Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgeojson.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2018 Julian Sherollari <jdotsh@gmail.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qgeojson_p.h"
6#include <qvariant.h>
7#include <qjsondocument.h>
8#include <qjsonobject.h>
9#include <qjsonvalue.h>
10#include <qjsonarray.h>
11#include <qgeocoordinate.h>
12#include <qgeocircle.h>
13#include <qgeopath.h>
14#include <qgeopolygon.h>
15#include <qtextstream.h>
16
18
19/*!
20 \namespace QGeoJson
21 \inmodule QtLocation
22 \internal
23
24 From Qt 6.7, QGeoJson is a private API. The replacement API is the GeoJsonData QML type.
25*/
26
27static QGeoCoordinate importPosition(const QVariant &position)
28{
29 QGeoCoordinate returnedCoordinates;
30 const QVariantList positionList = position.value<QVariantList>();
31 for (qsizetype i = 0; i < positionList.size(); ++i) { // Iterating Point coordinates arrays
32 switch (i) {
33 case 0:
34 returnedCoordinates.setLongitude(positionList.at(i).toDouble());
35 break;
36 case 1:
37 returnedCoordinates.setLatitude(positionList.at(i).toDouble());
38 break;
39 case 2:
40 returnedCoordinates.setAltitude(positionList.at(i).toDouble());
41 break;
42 default:
43 break;
44 }
45 }
46 return returnedCoordinates;
47}
48
49static QList<QGeoCoordinate> importArrayOfPositions(const QVariant &arrayOfPositions)
50{
51 QList<QGeoCoordinate> returnedCoordinates;
52 const QVariantList positionsList = arrayOfPositions.value<QVariantList>();
53 for (const auto &position : positionsList) // Iterating the LineString coordinates nested arrays
54 returnedCoordinates.append(importPosition(position)); // Populating the QList of coordinates
55 return returnedCoordinates;
56}
57
58static QList<QList<QGeoCoordinate>> importArrayOfArrayOfPositions(const QVariant &arrayOfArrayofPositions)
59{
60 QList<QList<QGeoCoordinate>> returnedCoordinates;
61 const QVariantList positionsList = arrayOfArrayofPositions.value<QVariantList>();
62 for (const auto &position : positionsList) // Iterating the Polygon coordinates nested arrays
63 returnedCoordinates << importArrayOfPositions(position);
64 return returnedCoordinates;
65}
66
67static QGeoCircle importPoint(const QVariantMap &inputMap)
68{
69 QGeoCircle returnedObject;
70 QGeoCoordinate center;
71 QVariant valueCoords = inputMap.value(QStringLiteral("coordinates"));
72 center = importPosition(valueCoords);
73 returnedObject.setCenter(center);
74 return returnedObject;
75}
76
77static QGeoPath importLineString(const QVariantMap &inputMap)
78{
79 QGeoPath returnedObject;
80 QList <QGeoCoordinate> coordinatesList;
81 const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates"));
82 coordinatesList = importArrayOfPositions(valueCoordinates);
83 returnedObject.setPath(coordinatesList);
84 return returnedObject;
85}
86
87static QGeoPolygon importPolygon(const QVariantMap &inputMap)
88{
89 QGeoPolygon returnedObject;
90 const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates"));
91 const QList<QList<QGeoCoordinate>> perimeters = importArrayOfArrayOfPositions(valueCoordinates);
92 for (qsizetype i = 0; i < perimeters.size(); ++i) { // Import an array of QList<QGeocoordinates>
93 if (i == 0)
94 returnedObject.setPerimeter(perimeters.at(i)); // External perimeter
95 else
96 returnedObject.addHole(perimeters.at(i)); // Inner perimeters
97 }
98 return returnedObject;
99}
100
101static QVariantList importMultiPoint(const QVariantMap &inputMap)
102{
103 QVariantList returnedObject;
104 const QVariantList coordinatesList = inputMap.value(QStringLiteral("coordinates")).value<QVariantList>();
105 QVariantMap singlePointMap;
106 QGeoCircle parsedPoint;
107 for (const auto &coordinate : coordinatesList) { // Iterating MultiPoint coordinates nasted arrays
108 parsedPoint.setCenter(importPosition(coordinate));
109 singlePointMap.insert(QStringLiteral("type"), QStringLiteral("Point"));
110 singlePointMap.insert(QStringLiteral("data"), QVariant::fromValue(parsedPoint));
111 returnedObject.append(QVariant::fromValue(singlePointMap));
112 }
113 return returnedObject;
114}
115
116static QVariantList importMultiLineString(const QVariantMap &inputMap)
117{
118 QVariantList returnedObject;
119 QGeoPath parsedLineString;
120 const QVariant listCoords = inputMap.value(QStringLiteral("coordinates"));
121 const QVariantList list = listCoords.value<QVariantList>();
122 QVariantMap singleLinestringMap;
123 for (int i = 0; i < list.size(); ++i) { // Iterating the MultiLineString coordinates nasted arrays using importArrayOfPositions
124 singleLinestringMap.clear();
125 const QList <QGeoCoordinate> coordinatesList = importArrayOfPositions(list.at(i));
126 singleLinestringMap.insert(QStringLiteral("type"), QStringLiteral("LineString"));
127 parsedLineString.setPath(coordinatesList);
128 singleLinestringMap.insert(QStringLiteral("data"), QVariant::fromValue(parsedLineString));
129 returnedObject.append(QVariant::fromValue(singleLinestringMap));
130 }
131 return returnedObject;
132}
133
134static QVariantList importMultiPolygon(const QVariantMap &inputMap)
135{
136 QVariantList returnedObject;
137 QGeoPolygon singlePoly;
138 QVariantMap singlePolygonMap;
139 const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates"));
140 const QVariantList list = valueCoordinates.value<QVariantList>();
141 for (int i = 0; i < list.size(); ++i) { // Iterating the MultiPolygon coordinates nasted arrays
142 singlePolygonMap.clear();
143 const QList<QList<QGeoCoordinate>> coordinatesList = importArrayOfArrayOfPositions(list.at(i));
144
145 for (int j = 0; j < coordinatesList.size(); ++j) {
146 if (j == 0)
147 singlePoly.setPerimeter(coordinatesList.at(j));
148 else
149 singlePoly.addHole(coordinatesList.at(j));
150 }
151 singlePolygonMap.insert(QStringLiteral("type"), QStringLiteral("Polygon"));
152 singlePolygonMap.insert(QStringLiteral("data"), QVariant::fromValue(singlePoly));
153 returnedObject.append(QVariant::fromValue(singlePolygonMap));
154 }
155 return returnedObject;
156}
157
158static QVariantMap importGeometry(const QVariantMap &inputMap); // Function prototype for a tail recursion
159
160static QVariantList importGeometryCollection(const QVariantMap &inputMap)
161{
162 QVariantList returnedObject;
163 const QVariant listGeometries = inputMap.value(QStringLiteral("geometries"));
164 const QVariantList list = listGeometries.value<QVariantList>(); // QVariantList of heterogeneous composition of the other geometry types
165 for (int i = 0; i < list.size(); ++i) {
166 QVariantMap geometryMap = list.at(i).value<QVariantMap>();
167 QVariantMap geoMap = importGeometry(geometryMap);
168 returnedObject.append(geoMap);
169 }
170 return returnedObject;
171}
172
173static QVariantMap importGeometry(const QVariantMap &inputMap)
174{
175 QVariantMap returnedObject;
176 QString geometryTypes[] = {
177 QStringLiteral("Point"),
178 QStringLiteral("MultiPoint"),
179 QStringLiteral("LineString"),
180 QStringLiteral("MultiLineString"),
181 QStringLiteral("Polygon"),
182 QStringLiteral("MultiPolygon"),
183 QStringLiteral("GeometryCollection")
184 };
185 enum geoTypeSwitch {
186 Point,
187 MultiPoint,
188 LineString,
189 MultiLineString,
190 Polygon,
191 MultiPolygon,
192 GeometryCollection
193 };
194 for (int i = 0; i<7; ++i) {
195 if (inputMap.value(QStringLiteral("type")).value<QString>() == geometryTypes[i]) {
196 switch (i) {
197 case Point: {
198 returnedObject.insert(QStringLiteral("type"), QStringLiteral("Point"));
199 returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importPoint(inputMap)));
200 break;
201 }
202 case MultiPoint: {
203 returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiPoint"));
204 returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiPoint(inputMap)));
205 break;
206 }
207 case LineString: {
208 returnedObject.insert(QStringLiteral("type"), QStringLiteral("LineString"));
209 returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importLineString(inputMap)));
210 break;
211 }
212 case MultiLineString: {
213 returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiLineString"));
214 returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiLineString(inputMap)));
215 break;
216 }
217 case Polygon: {
218 returnedObject.insert(QStringLiteral("type"), QStringLiteral("Polygon"));
219 returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importPolygon(inputMap)));
220 break;
221 }
222 case MultiPolygon: {
223 returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiPolygon"));
224 returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiPolygon(inputMap)));
225 break;
226 }
227 case GeometryCollection: {
228 returnedObject.insert(QStringLiteral("type"), QStringLiteral("GeometryCollection"));
229 returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importGeometryCollection(inputMap)));
230 break;
231 }
232 default:
233 break;
234 }
235 }
236 }
237 return returnedObject;
238}
239
240static QVariantList importFeatureCollection(const QVariantMap &inputMap)
241{
242 QVariantList returnedObject;
243 const QVariantList featuresList = inputMap.value(QStringLiteral("features")).value<QVariantList>();
244 for (int i = 0; i < featuresList.size(); ++i) {
245 QVariantMap inputFeatureMap = featuresList.at(i).value<QVariantMap>();
246 QVariantMap singleFeatureMap = importGeometry(inputFeatureMap.value(QStringLiteral("geometry")).value<QVariantMap>());
247 const QVariantMap importedProperties = inputFeatureMap.value(QStringLiteral("properties")).value<QVariantMap>();
248 singleFeatureMap.insert(QStringLiteral("properties"), importedProperties);
249 if (inputFeatureMap.contains(QStringLiteral("id"))) {
250 QVariant importedId = inputFeatureMap.value(QStringLiteral("id")).value<QVariant>();
251 singleFeatureMap.insert(QStringLiteral("id"), importedId);
252 }
253 returnedObject.append(singleFeatureMap);
254 }
255 return returnedObject;
256}
257
258static QJsonValue exportPosition(const QGeoCoordinate &obtainedCoordinates)
259{
260 QJsonValue geoLat = obtainedCoordinates.latitude();
261 QJsonValue geoLong = obtainedCoordinates.longitude();
262 QJsonArray array = {geoLong, geoLat};
263 QJsonValue geoAlt;
264 if (!qIsNaN(obtainedCoordinates.altitude())) {
265 geoAlt = obtainedCoordinates.altitude();
266 array.append(geoAlt);
267 }
268 QJsonValue geoArray = array;
269 return geoArray;
270}
271
272static QJsonValue exportArrayOfPositions(const QList<QGeoCoordinate> &obtainedCoordinatesList)
273{
274 QJsonValue lineCoordinates;
275 QJsonValue multiPosition;
276 QJsonArray arrayPosition;
277 for (int i = 0; i < obtainedCoordinatesList.size(); ++i) {
278 multiPosition = exportPosition(obtainedCoordinatesList.at(i));
279 arrayPosition.append(multiPosition);
280 }
281 lineCoordinates = arrayPosition;
282 return lineCoordinates;
283}
284
285static QJsonValue exportArrayOfArrayOfPositions(const QList<QList<QGeoCoordinate>> &obtainedCoordinates)
286{
287 QJsonValue lineCoordinates;
288 QJsonValue polyCoordinates;
289 QJsonArray arrayPath;
290 for (int i = 0; i < obtainedCoordinates.size(); ++i) {
291 lineCoordinates = exportArrayOfPositions(obtainedCoordinates.at(i));
292 arrayPath.append(lineCoordinates);
293 }
294 polyCoordinates = arrayPath;
295 return polyCoordinates;
296}
297
298static QJsonObject exportPoint(const QVariantMap &pointMap)
299{
300 QJsonObject parsedPoint;
301 QGeoCircle circle = pointMap.value(QStringLiteral("data")).value<QGeoCircle>();
302 parsedPoint.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Point")));
303 parsedPoint.insert(QStringLiteral("coordinates"), exportPosition(circle.center()));
304 return parsedPoint;
305}
306
307static QJsonObject exportLineString(const QVariantMap &lineStringMap)
308{
309 QJsonObject parsedLineString;
310 QList <QGeoCoordinate> linestringPath = lineStringMap.value(QStringLiteral("data")).value<QGeoPath>().path();
311 parsedLineString.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("LineString")));
312 parsedLineString.insert(QStringLiteral("coordinates"), exportArrayOfPositions(linestringPath));
313 return parsedLineString;
314}
315
316static QJsonObject exportPolygon(const QVariantMap &polygonMap)
317{
318 QVariant polygonVariant = polygonMap.value(QStringLiteral("data"));
319 QJsonObject parsedPolygon;
320 QJsonValue polyCoordinates;
321 QList<QList<QGeoCoordinate>> obtainedCoordinatesPoly;
322 QGeoPolygon parsedPoly = polygonVariant.value<QGeoPolygon>();
323 obtainedCoordinatesPoly << parsedPoly.perimeter();
324 if (parsedPoly.holesCount()!=0)
325 for (int i = 0; i < parsedPoly.holesCount(); ++i) {
326 obtainedCoordinatesPoly << parsedPoly.holePath(i);
327 }
328 polyCoordinates = exportArrayOfArrayOfPositions(obtainedCoordinatesPoly);
329 parsedPolygon.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Polygon")));
330 parsedPolygon.insert(QStringLiteral("coordinates"), polyCoordinates);
331 return parsedPolygon;
332}
333
334static QJsonObject exportMultiPoint(const QVariantMap &multiPointMap)
335{
336 QJsonObject parsedMultiPoint;
337 QList <QGeoCoordinate> obtainedCoordinatesMP;
338 QVariantList multiCircleVariantList = multiPointMap.value(QStringLiteral("data")).value<QVariantList>();
339 for (const QVariant &exCircleVariantMap: multiCircleVariantList) {
340 obtainedCoordinatesMP << exCircleVariantMap.value<QVariantMap>().value(QStringLiteral("data")).value<QGeoCircle>().center();
341 }
342 QJsonValue multiPosition = exportArrayOfPositions(obtainedCoordinatesMP);
343 parsedMultiPoint.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiPoint")));
344 parsedMultiPoint.insert(QStringLiteral("coordinates"), multiPosition);
345 return parsedMultiPoint;
346}
347
348static QJsonObject exportMultiLineString(const QVariantMap &multiLineStringMap)
349{
350 QJsonObject parsedMultiLineString;
351 QList<QList<QGeoCoordinate>> extractedCoordinatesValue;
352 QVariant multiPathVariant = multiLineStringMap.value(QStringLiteral("data"));
353 QVariantList multiPathList = multiPathVariant.value<QVariantList>();
354 for (int i = 0; i < multiPathList.size(); ++i) {
355 extractedCoordinatesValue << multiPathList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPath>().path();
356 }
357 QJsonValue exportedCoordinatesValue = exportArrayOfArrayOfPositions(extractedCoordinatesValue);
358 parsedMultiLineString.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiLineString")));
359 parsedMultiLineString.insert(QStringLiteral("coordinates"), exportedCoordinatesValue);
360 return parsedMultiLineString;
361}
362
363static QJsonObject exportMultiPolygon(const QVariantMap &multiPolygonMap)
364{
365 QJsonObject parsedMultiPolygon;
366 QJsonValue polyCoordinates;
367 QJsonArray parsedArrayPolygon;
368 QList<QList<QGeoCoordinate>> extractedCoordinatesValue;
369 QVariant multiPolygonVariant = multiPolygonMap.value(QStringLiteral("data"));
370 QVariantList multiPolygonList = multiPolygonVariant.value<QVariantList>();
371 int polyHoles = 0;
372 int currentHole;
373 for (int i = 0; i < multiPolygonList.size(); ++i) { // Start parsing Polygon list
374 extractedCoordinatesValue << multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().perimeter(); // Extract external polygon path
375 polyHoles = multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().holesCount();
376 if (polyHoles) // Check if the polygon has holes
377 for (currentHole = 0 ; currentHole < polyHoles; currentHole++)
378 extractedCoordinatesValue << multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().holePath(currentHole);
379 polyCoordinates = exportArrayOfArrayOfPositions(extractedCoordinatesValue); // Generates QJsonDocument compatible value
380 parsedArrayPolygon.append(polyCoordinates); // Adds one level of nesting in coordinates
381 extractedCoordinatesValue.clear(); // Clears the temporary polygon linear ring storage
382 }
383 QJsonValue exportedCoordinatesNodeValue = parsedArrayPolygon;
384 parsedMultiPolygon.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiPolygon")));
385 parsedMultiPolygon.insert(QStringLiteral("coordinates"), exportedCoordinatesNodeValue);
386 return parsedMultiPolygon;
387}
388
389static QJsonObject exportGeometry(const QVariantMap &geometryMap); // Function prototype
390
391static QJsonObject exportGeometryCollection(const QVariantMap &geometryCollection)
392{
393 QJsonObject parsed;
394 QJsonObject parsedGeometry;
395 QJsonValue valueGeometries;
396 QJsonArray parsedGeometries;
397 QVariantList geometriesList = geometryCollection.value(QStringLiteral("data")).value<QVariantList>();
398 for (int i = 0; i < geometriesList.size(); ++i) {
399 parsedGeometry = exportGeometry(geometriesList.at(i).value<QVariantMap>());
400 valueGeometries = parsedGeometry;
401 parsedGeometries.append(valueGeometries);
402 }
403 QJsonValue exportedGeometriesValue = parsedGeometries;
404 parsed.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("GeometryCollection")));
405 parsed.insert(QStringLiteral("geometries"), exportedGeometriesValue);
406 return parsed;
407}
408
409static QJsonObject exportGeometry(const QVariantMap &geometryMap)
410{
411 QJsonObject exportedGeometry;
412 if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("Point"))
413 exportedGeometry = exportPoint(geometryMap);
414 if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiPoint"))
415 exportedGeometry = exportMultiPoint(geometryMap);
416 if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("LineString"))
417 exportedGeometry = exportLineString(geometryMap);
418 if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiLineString"))
419 exportedGeometry = exportMultiLineString(geometryMap);
420 if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("Polygon"))
421 exportedGeometry = exportPolygon(geometryMap);
422 if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiPolygon"))
423 exportedGeometry = exportMultiPolygon(geometryMap);
424 if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("GeometryCollection"))
425 exportedGeometry = exportGeometryCollection(geometryMap);
426 return exportedGeometry;
427}
428
429static QJsonObject exportFeature(const QVariantMap &featureMap)
430{
431 QJsonObject exportedFeature;
432 QJsonValue geometryNodeValue = QJsonValue(exportGeometry(featureMap));
433 QJsonValue propertiesNodeValue = featureMap.value(QStringLiteral("properties")).value<QVariant>().toJsonValue();
434 QJsonValue idNodeValue = featureMap.value(QStringLiteral("id")).value<QVariant>().toJsonValue();
435 exportedFeature.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Feature")));
436 exportedFeature.insert(QStringLiteral("geometry"), geometryNodeValue);
437 exportedFeature.insert(QStringLiteral("properties"), propertiesNodeValue);
438 if (!idNodeValue.isNull()) // this value is optional
439 exportedFeature.insert(QStringLiteral("id"), idNodeValue);
440 return exportedFeature;
441}
442
443static QJsonObject exportFeatureCollection(const QVariantMap &featureCollection)
444{
445 QJsonObject exportedFeatureCollection;
446 QJsonArray featureArray;
447 QVariantList featureList = featureCollection.value(QStringLiteral("data")).value<QVariantList>();
448 for (int i = 0; i < featureList.size(); ++i) {
449 featureArray.append(QJsonValue(exportFeature(featureList.at(i).value<QVariantMap>())));
450 }
451 exportedFeatureCollection.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("FeatureCollection")));
452 exportedFeatureCollection.insert(QStringLiteral("features"), QJsonValue(featureArray) );
453 return exportedFeatureCollection;
454}
455
456namespace QGeoJson
457{
458
459/*!
460This method imports the \a geoJson document, expected to contain valid GeoJSON
461data, into a QVariantList structured like described in the section \l
462{Importing GeoJSON}.
463
464\note This method performs no validation on the input.
465
466\sa exportGeoJson
467*/
468QVariantList importGeoJson(const QJsonDocument &geoJson)
469{
470 QVariantList returnedList;
471 QJsonObject object = geoJson.object(); // Read json object from imported doc
472 QVariantMap rootGeoJsonObject = object.toVariantMap(); // Extraced map using Qt's API
473 QString geoType[] = {
474 QStringLiteral("Point"),
475 QStringLiteral("MultiPoint"),
476 QStringLiteral("LineString"),
477 QStringLiteral("MultiLineString"),
478 QStringLiteral("Polygon"),
479 QStringLiteral("MultiPolygon"),
480 QStringLiteral("GeometryCollection"),
481 QStringLiteral("Feature"),
482 QStringLiteral("FeatureCollection")
483 };
484 enum geoTypeSwitch {
485 Point,
486 MultiPoint,
487 LineString,
488 MultiLineString,
489 Polygon,
490 MultiPolygon,
491 GeometryCollection,
492 Feature,
493 FeatureCollection
494 };
495 QVariantMap parsedGeoJsonMap;
496
497 // Checking whether the JSON object has a "type" member
498 const QVariant keyVariant = rootGeoJsonObject.value(QStringLiteral("type"));
499 if (!keyVariant.isValid()) {
500 // Type check failed
501 }
502 QString valueType = keyVariant.value<QString>();
503
504 // Checking whether the "type" member has a GeoJSON admitted value
505 for (int i = 0; i < 9; ++i) {
506 if (valueType == geoType[i]) {
507 switch (i) {
508 case Point: {
509 QGeoCircle circle = importPoint(rootGeoJsonObject);
510 QVariant dataNodeValue = QVariant::fromValue(circle);
511 parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("Point"));
512 parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue);
513 break;
514 }
515 case MultiPoint: {
516 QVariantList multiCircle = importMultiPoint(rootGeoJsonObject);
517 QVariant dataNodeValue = QVariant::fromValue(multiCircle);
518 QList <QGeoCircle> testlist;
519 parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiPoint"));
520 parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue);
521 break;
522 }
523 case LineString: {
524 QGeoPath lineString = importLineString(rootGeoJsonObject);
525 QVariant dataNodeValue = QVariant::fromValue(lineString);
526 parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("LineString"));
527 parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue);
528 break;
529 }
530 case MultiLineString: {
531 QVariantList multiLineString = importMultiLineString(rootGeoJsonObject);
532 QVariant dataNodeValue = QVariant::fromValue(multiLineString);
533 parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiLineString"));
534 parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue);
535 break;
536 }
537 case Polygon: {
538 QGeoPolygon poly = importPolygon(rootGeoJsonObject);
539 QVariant dataNodeValue = QVariant::fromValue(poly);
540 parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("Polygon"));
541 parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue);
542 break;
543 }
544 case MultiPolygon: {
545 QVariantList multiPoly = importMultiPolygon(rootGeoJsonObject);
546 QVariant dataNodeValue = QVariant::fromValue(multiPoly);
547 parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiPolygon"));
548 parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue);
549 break;
550 }
551 // List of GeoJson geometry objects
552 case GeometryCollection: {
553 QVariantList multiGeo = importGeometryCollection(rootGeoJsonObject);
554 QVariant dataNodeValue = QVariant::fromValue(multiGeo);
555 parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("GeometryCollection"));
556 parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue);
557 break;
558 }
559 // Single GeoJson geometry object with properties
560 case Feature: {
561 parsedGeoJsonMap = importGeometry(rootGeoJsonObject.value(QStringLiteral("geometry")).value<QVariantMap>());
562 QVariantMap importedProperties = rootGeoJsonObject.value(QStringLiteral("properties")).value<QVariantMap>();
563 parsedGeoJsonMap.insert(QStringLiteral("properties"), importedProperties);
564 if (rootGeoJsonObject.contains(QStringLiteral("id"))){
565 QVariant importedId = rootGeoJsonObject.value(QStringLiteral("id")).value<QVariant>();
566 parsedGeoJsonMap.insert(QStringLiteral("id"), importedId);
567 }
568 break;
569 }
570 // Heterogeneous list of GeoJSON geometries with properties
571 case FeatureCollection: {
572 QVariantList featCollection = importFeatureCollection(rootGeoJsonObject);
573 QVariant dataNodeValue = QVariant::fromValue(featCollection);
574 parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("FeatureCollection"));
575 parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue);
576 break;
577 }
578 default:
579 break;
580 }
581 QVariant bboxNodeValue = rootGeoJsonObject.value(QStringLiteral("bbox"));
582 if (bboxNodeValue.isValid()) {
583 parsedGeoJsonMap.insert(QStringLiteral("bbox"), bboxNodeValue);
584 }
585 returnedList.append(parsedGeoJsonMap);
586 } else if (i >= 9) {
587 // Error
588 break;
589 }
590 }
591 return returnedList;
592}
593
594/*!
595This method exports the QVariantList \a geoData, expected to be structured like
596described in the section \l {Importing GeoJSON}, to a QJsonDocument containing
597the data converted to GeoJSON.
598
599\note This method performs no validation on the input.
600
601\sa importGeoJson
602*/
603QJsonDocument exportGeoJson(const QVariantList &geoData)
604{
605 if (geoData.isEmpty())
606 return QJsonDocument();
607 QVariantMap exportMap = geoData.at(0).value<QVariantMap>(); // Extracting the QVMap
608 QJsonObject newObject;
609 QJsonDocument newDocument;
610 if (exportMap.contains(QStringLiteral("properties"))) {
611 newObject = exportFeature(exportMap);
612 } else {
613 if (exportMap.value(QStringLiteral("type")) == QStringLiteral("Point")) // Check the value corresponding to the key "Point"
614 newObject = exportPoint(exportMap);
615 if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiPoint"))
616 newObject = exportMultiPoint(exportMap);
617 if (exportMap.value(QStringLiteral("type")) == QStringLiteral("LineString"))
618 newObject = exportLineString(exportMap);
619 if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiLineString"))
620 newObject = exportMultiLineString(exportMap);
621 if (exportMap.value(QStringLiteral("type")) == QStringLiteral("Polygon"))
622 newObject = exportPolygon(exportMap);
623 if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiPolygon"))
624 newObject = exportMultiPolygon(exportMap);
625 if (exportMap.value(QStringLiteral("type")) == QStringLiteral("GeometryCollection"))
626 newObject = exportGeometryCollection(exportMap);
627 if (exportMap.value(QStringLiteral("type")) == QStringLiteral("FeatureCollection"))
628 newObject = exportFeatureCollection(exportMap);
629 }
630 if (exportMap.contains((QStringLiteral("bbox")))) {
631 QJsonArray bboxArray;
632 QVariantList bboxList = exportMap.value(QStringLiteral("bbox")).value<QVariantList>();
633 for (int i = 0; i < bboxList.size(); ++i) {
634 bboxArray.append(QJsonValue(bboxList.at(i).value<double>()));
635 }
636 newObject.insert(QStringLiteral("bbox"), QJsonValue(bboxArray));
637 }
638 newDocument.setObject(newObject);
639 return newDocument;
640}
641
642// Functions for toString
643QTextStream &operator<<(QTextStream &stream, const QGeoCoordinate &crd)
644{
645 stream << "{ " << QString::number(crd.latitude(), 'f', 3) << ", "
646 << QString::number(crd.longitude(), 'f', 3) << ", "
647 << QString::number(crd.altitude(), 'f', 3) << " }";
648 return stream;
649}
650
651QTextStream &operator<<(QTextStream &stream, const QGeoShape &shape)
652{
653 switch (shape.type()) {
654 case QGeoShape::CircleType: {
655 QGeoCircle circle(shape);
656 stream << "QGeoCircle(" <<circle.center() << ", "<< QString::number(circle.radius()) << ")";
657 break;
658 }
659 case QGeoShape::PathType: {
660 QGeoPath path(shape);
661 stream << "QGeoPath(";
662 for (auto c: path.path())
663 stream << c << ", ";
664 stream << ")";
665 break;
666 }
667 case QGeoShape::PolygonType: {
668 QGeoPolygon poly(shape);
669 stream << "QGeoPolygon(";
670 for (auto c: poly.perimeter())
671 stream << c << ", ";
672 stream << ")";
673 break;
674 }
675 default:
676 stream << "QGeoShape(Unknown)";
677 break;
678 }
679 return stream;
680}
681
682
683static QString printQvariant(const QVariant v, int tabs = 0) {
684 static constexpr QStringView sTab(u" ");
685 QString sTabs;
686 QString res;
687 QTextStream stream(&res);
688 for (int i = 0; i< tabs; i++) {
689 sTabs += sTab;
690 }
691 if (v.typeId() == QMetaType::QVariantList) {
692 stream << sTabs << "[\n";
693 const QVariantList &l = v.toList();
694 for (int i = 0; i < l.size(); ++i)
695 stream << printQvariant(l.at(i), tabs + 1);
696 stream << sTabs << "]\n";
697 } else if (v.typeId() == QMetaType::QVariantMap) {
698 stream << sTabs << "{\n";
699 const QVariantList &l = v.toList();
700 const QVariantMap &map = v.toMap();
701
702 // Either one or the other are valid
703 if (!map.keys().isEmpty()) {
704 // Handle type first, to easy reading
705 if (map.contains(QStringLiteral("type"))) {
706 stream << sTabs << sTab << QStringLiteral("type") << " : "
707 << printQvariant(map[QStringLiteral("type")], tabs + 1).remove(QRegularExpression(QStringLiteral("^[ ]*")));
708 }
709 for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) {
710 if (iter.key() == QStringLiteral("type"))
711 continue;
712 stream << sTabs << sTab << iter.key() << " : " << printQvariant(iter.value(), tabs + 1).remove(QRegularExpression(QStringLiteral("^[ ]*")));
713 }
714 }
715 for (int i = 0; i < l.size(); ++i)
716 stream << printQvariant(l.at(i), tabs + 1);
717 stream << sTabs << "}\n";
718 } else {
719 stream << sTabs;
720 QGeoShape workigGeometry;
721 if ( v.canConvert<QGeoShape>()) {
722 workigGeometry = v.value<QGeoShape>();
723 if (workigGeometry.type() == QGeoShape::CircleType) {
724 QGeoCircle circle = v.value<QGeoCircle>();
725 stream << circle<< "\n";
726 } else if (workigGeometry.type() == QGeoShape::PathType) {
727 QGeoPath path = v.value<QGeoPath>();
728 stream << path<< "\n";
729 } else if (workigGeometry.type() == QGeoShape::PolygonType) {
730 QGeoPolygon polygon = v.value<QGeoPolygon>();
731 stream << polygon<< "\n";
732 }
733 } else {
734 if (v.isNull())
735 stream << "null\n";
736 else
737 stream << v.toString() << "\n";
738 }
739 }
740 return res;
741}
742
743/*!
744 This method accepts the QVariantList \a geoData, structured as described in
745 \l {Importing GeoJSON}, and returns a string containing the same data in a
746 readable form.
747*/
748QString toString(const QVariantList &geoData) {
749 if (geoData.isEmpty())
750 return QString();
751 return printQvariant(geoData.first(), 0);
752}
753
754} // namespace QGeoJson
755
756QT_END_NAMESPACE
\inmodule QtPositioning
Definition qgeocircle.h:15
\inmodule QtPositioning
\inmodule QtPositioning
Definition qgeopath.h:16
\inmodule QtPositioning
Definition qgeopolygon.h:16
QT_FORWARD_DECLARE_CLASS(QTextStream)
QTextStream & operator<<(QTextStream &stream, const QGeoCoordinate &crd)
Definition qgeojson.cpp:643
static QString printQvariant(const QVariant v, int tabs=0)
Definition qgeojson.cpp:683
QJsonDocument exportGeoJson(const QVariantList &geoData)
This method exports the QVariantList geoData, expected to be structured like described in the section...
Definition qgeojson.cpp:603
QVariantList importGeoJson(const QJsonDocument &geoJson)
This method imports the geoJson document, expected to contain valid GeoJSON data, into a QVariantList...
Definition qgeojson.cpp:468
QString toString(const QVariantList &geoData)
This method accepts the QVariantList geoData, structured as described in \l {Importing GeoJSON}...
Definition qgeojson.cpp:748
Combined button and popup list for selecting options.
static QJsonValue exportArrayOfPositions(const QList< QGeoCoordinate > &obtainedCoordinatesList)
Definition qgeojson.cpp:272
static QVariantList importMultiPoint(const QVariantMap &inputMap)
Definition qgeojson.cpp:101
static QList< QList< QGeoCoordinate > > importArrayOfArrayOfPositions(const QVariant &arrayOfArrayofPositions)
Definition qgeojson.cpp:58
static QVariantList importMultiPolygon(const QVariantMap &inputMap)
Definition qgeojson.cpp:134
static QJsonObject exportFeature(const QVariantMap &featureMap)
Definition qgeojson.cpp:429
static QVariantMap importGeometry(const QVariantMap &inputMap)
Definition qgeojson.cpp:173
static QJsonObject exportPoint(const QVariantMap &pointMap)
Definition qgeojson.cpp:298
static QGeoPolygon importPolygon(const QVariantMap &inputMap)
Definition qgeojson.cpp:87
static QJsonObject exportFeatureCollection(const QVariantMap &featureCollection)
Definition qgeojson.cpp:443
static QGeoCoordinate importPosition(const QVariant &position)
Definition qgeojson.cpp:27
static QGeoCircle importPoint(const QVariantMap &inputMap)
Definition qgeojson.cpp:67
static QVariantList importMultiLineString(const QVariantMap &inputMap)
Definition qgeojson.cpp:116
static QJsonObject exportMultiPolygon(const QVariantMap &multiPolygonMap)
Definition qgeojson.cpp:363
static QJsonObject exportGeometryCollection(const QVariantMap &geometryCollection)
Definition qgeojson.cpp:391
static QJsonObject exportMultiLineString(const QVariantMap &multiLineStringMap)
Definition qgeojson.cpp:348
static QVariantList importGeometryCollection(const QVariantMap &inputMap)
Definition qgeojson.cpp:160
static QJsonObject exportPolygon(const QVariantMap &polygonMap)
Definition qgeojson.cpp:316
static QJsonValue exportArrayOfArrayOfPositions(const QList< QList< QGeoCoordinate > > &obtainedCoordinates)
Definition qgeojson.cpp:285
static QGeoPath importLineString(const QVariantMap &inputMap)
Definition qgeojson.cpp:77
static QList< QGeoCoordinate > importArrayOfPositions(const QVariant &arrayOfPositions)
Definition qgeojson.cpp:49
static QJsonObject exportLineString(const QVariantMap &lineStringMap)
Definition qgeojson.cpp:307
static QJsonObject exportGeometry(const QVariantMap &geometryMap)
Definition qgeojson.cpp:409
static QJsonValue exportPosition(const QGeoCoordinate &obtainedCoordinates)
Definition qgeojson.cpp:258
static QVariantList importFeatureCollection(const QVariantMap &inputMap)
Definition qgeojson.cpp:240
static QJsonObject exportMultiPoint(const QVariantMap &multiPointMap)
Definition qgeojson.cpp:334
QList< QVariant > QVariantList
Definition qjsonarray.h:15