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