File indexing completed on 2024-12-08 07:18:53
0001 /* 0002 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "lineinfo.h" 0008 #include "../lib/datatypes/linecompare_p.h" 0009 0010 #include <QDebug> 0011 0012 enum { 0013 BoundingBoxSizeWarning = 12'000'000, // warning threshold for bbox sizes, in 1/1e7-th degree 0014 }; 0015 0016 LineInfo::LineInfo() = default; 0017 LineInfo::~LineInfo() = default; 0018 0019 bool LineInfo::isUseful(const LineInfo& info) 0020 { 0021 if (info.name.isEmpty()) 0022 return false; 0023 0024 switch (info.mode) { 0025 case Unknown: 0026 return false; 0027 case Train: 0028 case LongDistance: 0029 case LocalTrain: 0030 return !info.lineLogos.empty(); 0031 case RapidTransit: 0032 case Tram: 0033 case Subway: 0034 return info.color.isValid() || !info.lineLogos.isEmpty() || !info.productLogos.isEmpty(); 0035 } 0036 return false; 0037 } 0038 0039 static LineInfo::Mode lineModeStringToMode(const QByteArray &s) 0040 { 0041 if (s == "subway") { 0042 return LineInfo::Subway; 0043 } 0044 if (s == "tram") { 0045 return LineInfo::Tram; 0046 } 0047 if (s == "light_rail" || s == "commuter" || s == "suburban") { 0048 return LineInfo::RapidTransit; 0049 } 0050 if (s == "national" || s == "long_distance" || s == "international" || s == "high_speed") { 0051 return LineInfo::LongDistance; 0052 } 0053 if (s == "regional") { 0054 return LineInfo::LocalTrain; 0055 } 0056 return LineInfo::Unknown; 0057 } 0058 0059 LineInfo::Mode LineInfo::determineMode(const OSM::Relation &rel) 0060 { 0061 auto m = lineModeStringToMode(OSM::tagValue(rel, "route_master")); 0062 if (m != Unknown) return m; 0063 0064 m = lineModeStringToMode(OSM::tagValue(rel, "route")); 0065 if (m != Unknown) return m; 0066 0067 return std::max(lineModeStringToMode(OSM::tagValue(rel, "line")), 0068 std::max(lineModeStringToMode(OSM::tagValue(rel, "service")), 0069 lineModeStringToMode(OSM::tagValue(rel, "passenger")))); 0070 } 0071 0072 LineInfo LineInfo::fromRelation(const OSM::Relation &rel) 0073 { 0074 LineInfo info; 0075 info.relId = rel.id; 0076 0077 // check for under constructions or out-of-service tags 0078 const auto underConstruction = OSM::tagValue(rel, "construction"); 0079 if (underConstruction == "yes") { 0080 return info; 0081 } 0082 0083 info.name = QString::fromUtf8(OSM::tagValue(rel, "ref")).trimmed(); 0084 const auto colStr = OSM::tagValue(rel, "colour"); 0085 if (!colStr.isEmpty()) { 0086 info.color = QColor(QString::fromUtf8(colStr)); 0087 } 0088 info.wdId = Wikidata::Q(OSM::tagValue(rel, "wikidata")); 0089 info.mode = determineMode(rel); 0090 0091 info.bbox = rel.bbox; 0092 if (isUseful(info) && (info.bbox.width() > BoundingBoxSizeWarning || info.bbox.height() > BoundingBoxSizeWarning)) { 0093 qWarning() << "Suspicious bbox size:" << info.relId << info.name << info.bbox; 0094 } 0095 0096 return info; 0097 } 0098 0099 void LineInfo::merge(LineInfo &lhs, const LineInfo &rhs) 0100 { 0101 Q_ASSERT(!lhs.name.isEmpty()); 0102 if (!rhs.name.isEmpty() && !KPublicTransport::Internal::isSameLineName(lhs.name, rhs.name, KPublicTransport::Internal::StrictCompare)) { 0103 qDebug() << "OSM name conflict:" << lhs << rhs; 0104 } 0105 0106 if (lhs.color.isValid() && rhs.color.isValid() && lhs.color != rhs.color) { 0107 qWarning() << "OSM color conflict:" << lhs << rhs; 0108 } else if (rhs.color.isValid()) { 0109 lhs.color = rhs.color; 0110 } 0111 if (lhs.wdId.isValid() && rhs.wdId.isValid() && lhs.wdId != rhs.wdId) { 0112 qWarning() << "wikidata id conflict:" << lhs << rhs; 0113 } else if (rhs.wdId.isValid()) { 0114 lhs.wdId = rhs.wdId; 0115 } 0116 if (lhs.mode != Unknown && rhs.mode != Unknown && lhs.mode != rhs.mode) { 0117 qWarning() << "OSM mode conflict:" << lhs << rhs; 0118 } 0119 lhs.mode = std::max(lhs.mode, rhs.mode); 0120 lhs.bbox = OSM::unite(lhs.bbox, rhs.bbox); 0121 if (LineInfo::isUseful(lhs) && (lhs.bbox.width() > BoundingBoxSizeWarning || lhs.bbox.height() > BoundingBoxSizeWarning)) { 0122 qWarning() << "Suspicious bbox size after merging:" << lhs << rhs; 0123 } 0124 } 0125 0126 QDebug operator<<(QDebug debug, const LineInfo &info) 0127 { 0128 QDebugStateSaver saver(debug); 0129 debug.noquote().nospace() 0130 << info.name 0131 << " https://openstreetmap.org/relation/" << info.relId 0132 << " " << info.mode 0133 << (info.color.isValid() ? (QLatin1Char(' ') + info.color.name()) : QString()) 0134 << (info.wdId.isValid() ? QString(QLatin1Char(' ')) : QString()) << info.wdId 0135 << " " << info.bbox; 0136 return debug; 0137 }