KPublicTransport

linemetadata.cpp
1/*
2 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "linemetadata.h"
8#include "linemetadata_data.cpp"
9#include "datatypes/lineutil_p.h"
10
11#include <osm/datatypes.h>
12#include <osm/ztile.h>
13
14#include <QColor>
15#include <QDebug>
16#include <QString>
17#include <QUrl>
18
19using namespace KPublicTransport;
20
21// ensure index storage space suffices
22// should this fail more space needs to be allocated in LineMetaDataContent
23static_assert(sizeof(line_name_stringtab) < (1 << 13));
24static_assert(sizeof(line_logo_stringtab) < (1 << 16));
25
26static QString lookupName(uint16_t index)
27{
28 return QString::fromUtf8(line_name_stringtab + index);
29}
30
31static QString lookupLogo(uint16_t index)
32{
33 return QString::fromUtf8(line_logo_stringtab + index);
34}
35
36LineMetaData::LineMetaData() = default;
37LineMetaData::LineMetaData(const LineMetaDataContent *dd)
38 : d(dd)
39{
40}
41
42LineMetaData::~LineMetaData() = default;
43LineMetaData::LineMetaData(const LineMetaData&) = default;
44LineMetaData& LineMetaData::operator=(const LineMetaData&) = default;
45
46bool LineMetaData::isNull() const
47{
48 return d == nullptr;
49}
50
51QString LineMetaData::name() const
52{
53 return lookupName(d->nameIdx);
54}
55
56QColor LineMetaData::color() const
57{
58 return d && d->color.argb() ? QColor(d->color.argb()) : QColor();
59}
60
61QUrl LineMetaData::logoUrl() const
62{
63 if (!d) {
64 return {};
65 }
66 const auto logoName = lookupLogo(d->logoIdx);
67 return logoName.isEmpty() ? QUrl() : QUrl(QLatin1String("https://commons.wikimedia.org/wiki/Special:Redirect/file/") + logoName);
68}
69
70Line::Mode LineMetaData::mode() const
71{
72 if (!d) {
73 return Line::Unknown;
74 }
75 switch (d->mode) {
76 case LineMetaDataContent::Tramway:
77 return Line::Tramway;
78 case LineMetaDataContent::RapidTransit:
79 return Line::RapidTransit;
80 case LineMetaDataContent::Subway:
81 return Line::Metro;
82 case LineMetaDataContent::LocalTrain:
83 return Line::LocalTrain;
84 case LineMetaDataContent::LongDistanceTrain:
85 return Line::LongDistanceTrain;
86 };
87 return Line::Unknown;
88}
89
90QUrl LineMetaData::modeLogoUrl() const
91{
92 if (!d) {
93 return {};
94 }
95 const auto logoName = lookupLogo(d->productLogoIdx);
96 return logoName.isEmpty() ? QUrl() : QUrl(QLatin1String("https://commons.wikimedia.org/wiki/Special:Redirect/file/") + logoName);
97}
98
99LineMetaData LineMetaData::find(double latitude, double longitude, const QString &name, Line::Mode mode)
100{
101 OSM::Coordinate coord(latitude, longitude);
102
103 // overall quad tree parameters
104 constexpr const auto depthCount = sizeof(line_data_depthOffsets) / sizeof(LineMetaDataQuadTreeDepthIndex);
105 static_assert(depthCount > 1, "quad tree depth information error");
106 constexpr const uint8_t maxDepth = line_data_depthOffsets[0].depth;
107 constexpr const uint8_t minDepth = line_data_depthOffsets[depthCount - 1].depth;
108 static_assert(maxDepth > minDepth, "quad tree depth error");
109 static_assert(minDepth > 1, "quad tree depth error");
110
111 // walk through the quad tree bottom up, looking for a tile containing the line we are looking for
112 OSM::ZTile tile(coord.z() >> (2 * minDepth), minDepth);
113 for (uint8_t d = minDepth; d <= maxDepth; ++d, tile = tile.parent()) {
114 // determining quad tree offsets for the current depth
115 const auto depthOffsetIt = std::lower_bound(std::begin(line_data_depthOffsets), std::end(line_data_depthOffsets), d);
116 if (depthOffsetIt == std::end(line_data_depthOffsets) || (*depthOffsetIt).depth != d) {
117 continue; // depth level isn't populated at all (yes, this can happen)
118 }
119 const auto treeBegin = std::begin(line_data_zquadtree) + (*depthOffsetIt).offset;
120 const auto treeEnd = (depthOffsetIt + 1) == std::end(line_data_depthOffsets) ?
121 std::end(line_data_zquadtree) :
122 std::begin(line_data_zquadtree) + (*(depthOffsetIt + 1)).offset;
123
124 // look up the tile for the given coordinate at depth d
125 const auto treeIt = std::lower_bound(treeBegin, treeEnd, tile.z);
126 if (treeIt == treeEnd || (*treeIt).z != tile.z) {
127 continue; // tile doesn't exist at this depth
128 }
129
130 // iterate over the bucket of this tile and look for the line
131 // we have to handle two cases: single lines and buckets of lines
132 if ((*treeIt).lineIdx >= line_data_count) {
133 auto bucketIt = line_data_bucketTable + (*treeIt).lineIdx - line_data_count;
134 while ((*bucketIt) != -1) {
135 const auto d = line_data + (*bucketIt);
136 if (LineUtil::isSameLineNameStrict(lookupName(d->nameIdx), name) && LineUtil::isCompatibleMode(LineMetaData(d).mode(), mode)) {
137 return LineMetaData(d);
138 }
139 ++bucketIt;
140 }
141 } else {
142 const auto d = line_data + (*treeIt).lineIdx;
143 if (LineUtil::isSameLineNameStrict(lookupName(d->nameIdx), name) && LineUtil::isCompatibleMode(LineMetaData(d).mode(), mode)) {
144 return LineMetaData(d);
145 }
146 }
147 }
148
149 return {};
150}
Static information about a public transport line.
static LineMetaData find(double latitude, double longitude, const QString &name, Line::Mode mode)
Attempts to find information about a line with the given name and a stop at the given coordinates.
Mode
Mode of transportation.
Definition line.h:27
constexpr uint64_t z() const
ZTile parent() const
Query operations and data types for accessing realtime public transport information from online servi...
QString fromUtf8(QByteArrayView str)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 17 2024 11:47:54 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.