File indexing completed on 2024-05-12 04:42:47
0001 /* 0002 SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "geojson_p.h" 0008 0009 #include <QJsonArray> 0010 #include <QJsonObject> 0011 #include <QPointF> 0012 #include <QPolygonF> 0013 0014 using namespace KPublicTransport; 0015 0016 static QPointF readPointCoordinates(const QJsonArray &coords) 0017 { 0018 if (coords.size() != 2) { 0019 return {}; 0020 } 0021 0022 return {coords.at(0).toDouble(), coords.at(1).toDouble()}; 0023 } 0024 0025 QPointF GeoJson::readPoint(const QJsonObject &obj) 0026 { 0027 const auto type = obj.value(QLatin1String("type")).toString(); 0028 if (type != QLatin1String("Point")) { 0029 return {}; 0030 } 0031 0032 const auto coordinates = obj.value(QLatin1String("coordinates")).toArray(); 0033 return readPointCoordinates(coordinates); 0034 } 0035 0036 static QPolygonF readPolygonCoordinates(const QJsonArray &coords) 0037 { 0038 QPolygonF poly; 0039 poly.reserve(coords.size()); 0040 for (const auto &pointV : coords) { 0041 const auto point = pointV.toArray(); 0042 poly.push_back(readPointCoordinates(point)); 0043 } 0044 return poly; 0045 } 0046 0047 static QPolygonF readOuterPolygonCoordinates(const QJsonArray &coordinates) 0048 { 0049 if (coordinates.empty()) { 0050 return {}; 0051 } 0052 return readPolygonCoordinates(coordinates.at(0).toArray()); 0053 } 0054 0055 QPolygonF GeoJson::readLineString(const QJsonObject &obj) 0056 { 0057 const auto type = obj.value(QLatin1String("type")).toString(); 0058 if (type != QLatin1String("LineString")) { 0059 return {}; 0060 } 0061 0062 const auto coordinates = obj.value(QLatin1String("coordinates")).toArray(); 0063 return readPolygonCoordinates(coordinates); 0064 } 0065 0066 QPolygonF GeoJson::readOuterPolygon(const QJsonObject &obj) 0067 { 0068 const auto type = obj.value(QLatin1String("type")).toString(); 0069 if (type == QLatin1String("Polygon")) { 0070 return readOuterPolygonCoordinates(obj.value(QLatin1String("coordinates")).toArray()); 0071 } else if (type == QLatin1String("MultiPolygon")) { 0072 const auto coordinates = obj.value(QLatin1String("coordinates")).toArray(); 0073 QPolygonF poly; 0074 for (const auto &polyV : coordinates) { 0075 auto subPoly = readOuterPolygonCoordinates(polyV.toArray()); 0076 poly = poly.empty() ? std::move(subPoly) : poly.united(subPoly); 0077 } 0078 return poly; 0079 } 0080 0081 return {}; 0082 } 0083 0084 std::vector<QPolygonF> GeoJson::readOuterPolygons(const QJsonObject &obj) 0085 { 0086 const auto type = obj.value(QLatin1String("type")).toString(); 0087 if (type == QLatin1String("Polygon")) { 0088 return {readOuterPolygonCoordinates(obj.value(QLatin1String("coordinates")).toArray())}; 0089 } else if (type == QLatin1String("MultiPolygon")) { 0090 const auto coordinates = obj.value(QLatin1String("coordinates")).toArray(); 0091 std::vector<QPolygonF> polys; 0092 polys.reserve(coordinates.size()); 0093 for (const auto &polyV : coordinates) { 0094 polys.push_back(readOuterPolygonCoordinates(polyV.toArray())); 0095 } 0096 return polys; 0097 } 0098 0099 return {}; 0100 } 0101 0102 static QJsonArray writePoint(const QPointF &p) 0103 { 0104 return QJsonArray({ p.x(), p.y() }); 0105 } 0106 0107 QJsonObject GeoJson::writeLineString(const QPolygonF &lineString) 0108 { 0109 QJsonObject obj; 0110 obj.insert(QLatin1String("type"), QLatin1String("LineString")); 0111 0112 QJsonArray coords; 0113 for (const auto &p : lineString) { 0114 coords.push_back(writePoint(p)); 0115 } 0116 obj.insert(QLatin1String("coordinates"), coords); 0117 return obj; 0118 } 0119 0120 QJsonObject GeoJson::writePolygon(const QPolygonF &polygon) 0121 { 0122 QJsonObject obj; 0123 obj.insert(QLatin1String("type"), QLatin1String("Polygon")); 0124 0125 QJsonArray coords; 0126 for (const auto &p : polygon) { 0127 coords.push_back(writePoint(p)); 0128 } 0129 QJsonArray polyArray; 0130 polyArray.push_back(coords); 0131 obj.insert(QLatin1String("coordinates"), polyArray); 0132 return obj; 0133 } 0134 0135 QJsonObject GeoJson::writePolygons(const std::vector<QPolygonF> &polygons) 0136 { 0137 if (polygons.empty()) { 0138 return {}; 0139 } 0140 if (polygons.size() == 1) { 0141 return writePolygon(polygons[0]); 0142 } 0143 0144 QJsonObject obj; 0145 obj.insert(QLatin1String("type"), QLatin1String("MultiPolygon")); 0146 0147 QJsonArray multiPolys; 0148 for (const auto &polygon : polygons) { 0149 QJsonArray coords; 0150 for (const auto &p : polygon) { 0151 coords.push_back(writePoint(p)); 0152 } 0153 QJsonArray polyArray; 0154 polyArray.push_back(coords); 0155 multiPolys.push_back(polyArray); 0156 } 0157 obj.insert(QLatin1String("coordinates"), multiPolys); 0158 return obj; 0159 }