KPublicTransport

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

KDE's Doxygen guidelines are available online.