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 const auto isLineMatch = [](const LineMetaDataContent *d, const QString &name, Line::Mode mode) {
112 return LineUtil::isSameLineNameStrict(lookupName(d->nameIdx), name) &&
113 (LineUtil::isCompatibleMode(LineMetaData(d).mode(), mode) ||
114 (LineUtil::isCompatibleBaseMode(LineMetaData(d).mode(), mode) && LineUtil::isHighlyIdentifyingName(name)));
115 };
116
117 // walk through the quad tree bottom up, looking for a tile containing the line we are looking for
118 OSM::ZTile tile(coord.z() >> (2 * minDepth), minDepth);
119 for (uint8_t d = minDepth; d <= maxDepth; ++d, tile = tile.parent()) {
120 // determining quad tree offsets for the current depth
121 const auto depthOffsetIt = std::lower_bound(std::begin(line_data_depthOffsets), std::end(line_data_depthOffsets), d);
122 if (depthOffsetIt == std::end(line_data_depthOffsets) || (*depthOffsetIt).depth != d) {
123 continue; // depth level isn't populated at all (yes, this can happen)
124 }
125 const auto treeBegin = std::begin(line_data_zquadtree) + (*depthOffsetIt).offset;
126 const auto treeEnd = (depthOffsetIt + 1) == std::end(line_data_depthOffsets) ?
127 std::end(line_data_zquadtree) :
128 std::begin(line_data_zquadtree) + (*(depthOffsetIt + 1)).offset;
129
130 // look up the tile for the given coordinate at depth d
131 const auto treeIt = std::lower_bound(treeBegin, treeEnd, tile.z);
132 if (treeIt == treeEnd || (*treeIt).z != tile.z) {
133 continue; // tile doesn't exist at this depth
134 }
135
136 // iterate over the bucket of this tile and look for the line
137 // we have to handle two cases: single lines and buckets of lines
138 if ((*treeIt).lineIdx >= line_data_count) {
139 auto bucketIt = line_data_bucketTable + (*treeIt).lineIdx - line_data_count;
140 while ((*bucketIt) != -1) {
141 const auto d = line_data + (*bucketIt);
142 if (isLineMatch(d, name, mode)) {
143 return LineMetaData(d);
144 }
145 ++bucketIt;
146 }
147 } else {
148 const auto d = line_data + (*treeIt).lineIdx;
149 if (isLineMatch(d, name, mode)) {
150 return LineMetaData(d);
151 }
152 }
153 }
154
155 return {};
156}
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 Sat Dec 21 2024 16:59:57 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.