| /**************************************************************************** |
| ** |
| ** Copyright (C) 2018 The Qt Company Ltd. |
| ** Copyright (C) 2018 Julian Sherollari <jdotsh@gmail.com> |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the QtCore module of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 3 requirements |
| ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 2.0 or (at your option) the GNU General |
| ** Public license version 3 or any later version approved by the KDE Free |
| ** Qt Foundation. The licenses are as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
| ** https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include "qgeojson_p.h" |
| #include <qjsonobject.h> |
| #include <qjsonvalue.h> |
| #include <qjsonarray.h> |
| #include <qgeocoordinate.h> |
| #include <qgeocircle.h> |
| #include <qgeopath.h> |
| #include <qgeopolygon.h> |
| #include <qtextstream.h> |
| |
| QT_BEGIN_NAMESPACE |
| |
| /*! \class QGeoJson |
| \inmodule QtLocation |
| \since 5.13 |
| |
| QGeoJson class can be used to convert between a GeoJSON document (see the |
| \l {https://en.wikipedia.org/wiki/GeoJSON} {Wikipedia page}, \l |
| {https://tools.ietf.org/html/rfc7946} {RFC}) and a \l |
| {http://doc.qt.io/qt-5/qvariant.html#QVariantList-typedef} {QVariantList} |
| of \l QVariantMap elements ready to be used as Model in a \l MapItemView. |
| WARNING! This private class is part of Qt labs, thus not stable API, it is |
| part of the experimental components of QtLocation. Until it is promoted to |
| public API, it may be subject to source and binary-breaking changes. |
| |
| \section2 Importing GeoJSON |
| |
| The importGeoJson() method accepts a \l |
| {http://doc.qt.io/qt-5/qjsondocument.html} {QJsonDocument} from which it |
| extracts a single \l {https://tools.ietf.org/html/rfc7159} {JSON} object, |
| since the GeoJSON RFC expects that a valid GeoJSON Document has in its root |
| a single JSON object. This method doesn't perform any validation on the |
| input. The importer returns a QVariantList containing a single QVariantMap. |
| This map has always at least 2 (key, value) pairs. The first one has \c |
| type as key, and the corresponding value is a string identifying the |
| GeoJSON type. This value can be one of the GeoJSON object types: \c Point, |
| \c MultiPoint, \c LineString, \c MultiLineString, \c Polygon, \c |
| MultiPolygon, \c GeometryCollection, \c FeatureCollection. The second pair |
| has \c data as key, and the corresponding value can be either a QGeoShape |
| or a list, depending on the GeoJSON type. The next section provides details |
| about this node. The \c Feature type is converted into the type of the |
| geometry contained within, with an additional (key, value) pair, where the |
| key is \c properties and the value is a \l QVariantMap. Thus, a feature Map |
| is distinguishable from the corresponding geometry, by looking for a \c |
| properties member. |
| |
| \section3 Structure of the data node |
| |
| For the single type geometry objects (\c Point, \c LineString, and \c |
| Polygon), the value corresponding to the \c data key is a QGeoShape: |
| |
| \list |
| \li When the type is \c Point, the data is a QGeoCircle with the point |
| coordinates stored in the center property. |
| |
| For example, the following GeoJSON document contains a \c Point |
| geometry: |
| |
| \code |
| { |
| "type" : "Point", |
| "data" : [60.0, 11.0] |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : Point |
| data : QGeoCircle({60.000, 11.000}, -1) |
| } |
| \endcode |
| |
| \li When the type is \c LineString the data ia a QGeoPath. |
| |
| For example, the following GeoJSON document contains a \c LineString |
| geometry: |
| |
| \code |
| { |
| "type" : "LineString", |
| "coordinates" : [[13.5, 43],[10.73, 59.92]] |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : LineString, |
| data : QGeoPath([{43.000, 13.500}, {59.920, 10.730}]) |
| } |
| \endcode |
| |
| \li When the type is \c Polygon, the data is a QGeoPolygon (holes are |
| supported). |
| |
| For example, the following GeoJSON document contains a \c Polygon |
| geometry: |
| |
| \code |
| { |
| "type" : "Polygon", |
| "coordinates" : [ |
| [[17.13, 51.11], |
| [30.54, 50.42], |
| [26.70, 58.36], |
| [17.13, 51.11]] |
| ], |
| "bbox" : [60, 60, -60, -60] |
| |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : Polygon |
| data : QGeoPolygon([{51.110, 17.130}, {50.420,30.540}, {58.360, 26.700}, {51.110, 17.130}]) |
| } |
| \endcode |
| |
| \endlist |
| |
| For the homogeneously typed multipart geometry objects (\c MultiPoint, \c |
| MultiLineString, \c MultiPolygon) the value corresponding to the \c data |
| key is a QVariantList. Each element of the list is a QVariantMap of one of |
| the above listed types. The elements in this list will be all of the same |
| GeoJSON type: |
| |
| \list |
| \li When the type is \c MultiPoint, the data is a List of Points. |
| |
| For example, the following GeoJSON document contains a \c MultiPoint |
| geometry: |
| |
| \code |
| { |
| "type" : "MultiPoint", |
| "coordinates" : [ |
| [11,60], |
| [5.5,60.3], |
| [5.7,58.90] |
| ] |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : MultiPoint |
| data : [ |
| { |
| type : Point |
| data : QGeoCircle({60.000, 11.000}, -1) |
| }, |
| { |
| type : Point |
| data : QGeoCircle({60.300, 5.500}, -1) |
| }, |
| { |
| type : Point |
| data : QGeoCircle({58.900, 5.700}, -1) |
| } |
| ] |
| } |
| \endcode |
| |
| \li When the type is \c MultiLineString, the data is a List of LineStrings. |
| |
| For example, the following GeoJSON document contains a \c MultiLineString |
| geometry: |
| |
| \code |
| { |
| "type" : "MultiLineString", |
| "coordinates" : [ |
| [[13.5, 43], [10.73, 59.92]], |
| [[9.15, 45], [-3.15, 58.90]] |
| ] |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : MultiLineString |
| data : [ |
| { |
| type : LineString |
| data : QGeoPath([{45.000, 9.150}, {58.900, -3.150}]) |
| }, |
| { |
| type : LineString |
| data : QGeoPath([{43.000, 13.500}, {59.920, 10.730}]) |
| } |
| ] |
| } |
| \endcode |
| |
| \li When the type is \c MultiPolygon, the data is a List of Polygons. |
| |
| For example, the following GeoJSON document contains a \c MultiPolygon |
| geometry: |
| |
| \code |
| { |
| "type" : "MultiPoint", |
| "coordinates" : [ |
| [11,60], |
| [5.5,60.3], |
| [5.7,58.90] |
| ] |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : MultiPoint |
| data : [ |
| { |
| type : Point |
| data : QGeoCircle({60.000, 11.000}, -1) |
| }, |
| { |
| type : Point |
| data : QGeoCircle({60.300, 5.500}, -1) |
| }, |
| { |
| type : Point |
| data : QGeoCircle({58.900, 5.700}, -1) |
| } |
| ] |
| } |
| \endcode |
| |
| \endlist |
| |
| The \c GeometryCollection is a heterogeneous composition of other geometry |
| types. In the resulting QVariantMap, the value of the \c data member is a |
| QVariantList populated by QVariantMaps of various geometries, including the |
| GeometryCollection itself. |
| |
| For example, the following \c GeometryCollection: |
| |
| \code |
| { |
| "type" : "GeometryCollection", |
| "geometries" : [ |
| { |
| "type" : "MultiPoint", |
| "coordinates" : [ |
| [11,60], [5.5,60.3], [5.7,58.90] |
| ] |
| }, |
| { |
| "type" : "MultiLineString", |
| "coordinates" : [ |
| [[13.5, 43], [10.73, 59.92]], |
| [[9.15, 45], [-3.15, 58.90]] |
| ] |
| }, |
| { |
| "type" : "MultiPolygon", |
| "coordinates" : [ |
| [ |
| [[17.13, 51.11], |
| [30.54, 50.42], |
| [26.74, 58.36], |
| [17.13, 51.11]] |
| ], |
| [ |
| [[19.84, 41.33], |
| [30.45, 49.26], |
| [17.07, 50.10], |
| [19.84, 41.33]] |
| ] |
| ] |
| } |
| ] |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : GeometryCollection |
| data : [ |
| { |
| type : MultiPolygon |
| data : [ |
| { |
| type : Polygon |
| data : QGeoPolygon([{41.330, 19.840}, {49.260, 30.450}, {50.100, 17.070}, {41.330, 19.840}]) |
| } |
| { |
| type : Polygon |
| data : QGeoPolygon([{51.110, 17.130}, {50.420, 30.540}, {58.360, 26.740}, {51.110, 17.130}]) |
| } |
| ] |
| } |
| { |
| type : MultiLineString |
| data : [ |
| { |
| type : LineString |
| data : QGeoPath([{45.000, 9.150}, {58.900, -3.150}]) |
| } |
| { |
| type : LineString |
| data : QGeoPath([{43.000, 13.500}, {59.920, 10.730}]) |
| } |
| ] |
| } |
| { |
| type : MultiPoint |
| data : [ |
| { |
| type : Point |
| data : QGeoCircle({58.900, 5.700}, -1) |
| }, |
| { |
| type : Point |
| data : QGeoCircle({60.300, 5.500}, -1) |
| }, |
| { |
| type : Point |
| data : QGeoCircle({60.000, 11.000}, -1) |
| } |
| ] |
| } |
| ] |
| } |
| \endcode |
| |
| The \c Feature object, which consists of one of the previous geometries |
| together with related attributes, is structured like one of the 7 above |
| mentioned geometry types, plus a \c properties member. The value of this |
| member is a QVariantMap. The only way to distinguish a Feature from the |
| included geometry is to check if a \c properties node is present in the |
| QVariantMap. |
| |
| For example, the following \c Feature: |
| |
| \code |
| { |
| "type" : "Feature", |
| "id" : "Poly", |
| "properties" : { |
| "text" : "This is a Feature with a Polygon" |
| }, |
| "geometry" : { |
| "type" : "Polygon", |
| "coordinates" : [ |
| [[17.13, 51.11], |
| [30.54, 50.42], |
| [26.70, 58.36], |
| [17.13, 51.11]], |
| [[23.46, 54.36], |
| [20.52, 51.91], |
| [28.25, 51.50], |
| [26.80, 54.36], |
| [23.46, 54.36]] |
| ] |
| } |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : Polygon |
| data : QGeoPolygon([{51.110, 17.130}, {50.420,30.540}, {58.360, 26.700}, {51.110, 17.130}]) |
| properties : {text : This is a Feature with a Polygon} |
| } |
| \endcode |
| |
| The \c FeatureCollection is a composition of Feature objects. The value of |
| the \c data member in a FeatureCollection is a QVariantList populated by |
| Feature type QVariantMaps. |
| |
| For example, the following \c FeatureCollection: |
| |
| \code |
| { |
| "type" : "FeatureCollection", |
| "features" : [ |
| { |
| "type" : "Feature", |
| "id" : "Poly", |
| "properties" : { |
| "text" : "This is a Feature with a Polygon" |
| }, |
| "geometry" : { |
| "type" : "Polygon", |
| "coordinates" : [ |
| [[17.13, 51.11], |
| [30.54, 50.42], |
| [26.70, 58.36], |
| [17.13, 51.11]], |
| [[23.46, 54.36], |
| [20.52, 51.91], |
| [28.25, 51.50], |
| [26.80, 54.36], |
| [23.46, 54.36]] |
| ] |
| } |
| }, |
| { |
| "type" : "Feature", |
| "id" : "MultiLine", |
| "properties" : { |
| "text" : "This is a Feature with a MultiLineString" |
| }, |
| "geometry" : { |
| "type" : "MultiLineString", |
| "coordinates" : [ |
| [[13.5, 43], [10.73, 59.92]], |
| [[9.15, 45], [-3.15, 58.90]] |
| ] |
| } |
| } |
| ] |
| } |
| \endcode |
| |
| it is converted to a QVariantMap with the following structure: |
| |
| \code |
| { |
| type : FeatureCollection |
| data : [ |
| { |
| type : MultiLineString |
| data : [ |
| { |
| type : LineString |
| data : QGeoPath([{45.000, 9.150}, {58.900, -3.150}]) |
| } |
| { |
| type : LineString |
| data : QGeoPath([{43.000, 13.500}, {59.920, 10.730}]) |
| } |
| ] |
| properties : {text : This is a Feature with a MultiLineString} |
| }, |
| { |
| type : Polygon |
| data : QGeoPolygon({51.110, 17.130}, {50.420, 30.540}, {58.360, 26.700}, {51.110, 17.130}) |
| properties : {text : This is a Feature with a Polygon} |
| } |
| ] |
| } |
| \endcode |
| |
| \section2 Exporting GeoJSON |
| |
| The exporter accepts the QVariantList returned by the \l {Importing GeoJSON} |
| {importer}, and returns a JSON document. The exporter is complementary to |
| the importer because it executes the inverse action. |
| |
| \section2 The toString function |
| |
| The \l toString outputs, for debugging purposes, the content of a |
| QVariantList structured like \l importGeoJson does, to a QString using a |
| prettyfied format. |
| */ |
| |
| static QGeoCoordinate importPosition(const QVariant &position) |
| { |
| QGeoCoordinate returnedCoordinates; |
| const QVariantList positionList = position.value<QVariantList>(); |
| for (int i = 0; i < positionList.size(); ++i) { // Iterating Point coordinates arrays |
| switch (i) { |
| case 0: |
| returnedCoordinates.setLongitude(positionList.at(i).toDouble()); |
| break; |
| case 1: |
| returnedCoordinates.setLatitude(positionList.at(i).toDouble()); |
| break; |
| case 2: |
| returnedCoordinates.setAltitude(positionList.at(i).toDouble()); |
| break; |
| default: |
| break; |
| } |
| } |
| return returnedCoordinates; |
| } |
| |
| static QList<QGeoCoordinate> importArrayOfPositions(const QVariant &arrayOfPositions) |
| { |
| QList <QGeoCoordinate> returnedCoordinates; |
| const QVariantList positionsList = arrayOfPositions.value<QVariantList>(); |
| QGeoCoordinate singlePosition; |
| for (int i = 0; i < positionsList.size(); ++i) { // Iterating the LineString coordinates nested arrays |
| singlePosition = importPosition((positionsList.at(i))); |
| returnedCoordinates.append(singlePosition); // Populating the QList of coordinates |
| } |
| return returnedCoordinates; |
| } |
| |
| static QList<QList<QGeoCoordinate>> importArrayOfArrayOfPositions(const QVariant &arrayOfArrayofPositions) |
| { |
| QList<QList<QGeoCoordinate>> returnedCoordinates; |
| const QVariantList positionsList = arrayOfArrayofPositions.value<QVariantList>(); |
| QList<QGeoCoordinate> arrayOfPositions; |
| for (int i = 0; i < positionsList.size(); ++i) { // Iterating the Polygon coordinates nested arrays |
| arrayOfPositions = importArrayOfPositions((positionsList.at(i))); |
| returnedCoordinates << arrayOfPositions; |
| } |
| return returnedCoordinates; |
| } |
| |
| static QGeoCircle importPoint(const QVariantMap &inputMap) |
| { |
| QGeoCircle returnedObject; |
| QGeoCoordinate center; |
| QVariant valueCoords = inputMap.value(QStringLiteral("coordinates")); |
| center = importPosition(valueCoords); |
| returnedObject.setCenter(center); |
| return returnedObject; |
| } |
| |
| static QGeoPath importLineString(const QVariantMap &inputMap) |
| { |
| QGeoPath returnedObject; |
| QList <QGeoCoordinate> coordinatesList; |
| const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates")); |
| coordinatesList = importArrayOfPositions(valueCoordinates); |
| returnedObject.setPath(coordinatesList); |
| return returnedObject; |
| } |
| |
| static QGeoPolygon importPolygon(const QVariantMap &inputMap) |
| { |
| QGeoPolygon returnedObject; |
| const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates")); |
| QList<QList<QGeoCoordinate>> perimeters = importArrayOfArrayOfPositions(valueCoordinates); |
| for (int i = 0; i < perimeters.size(); ++i) { // Import an array of QList<QGeocoordinates> |
| if (i == 0) |
| returnedObject.setPath(perimeters.at(i)); // External perimeter |
| else |
| returnedObject.addHole(perimeters.at(i)); // Inner perimeters |
| } |
| return returnedObject; |
| } |
| |
| static QVariantList importMultiPoint(const QVariantMap &inputMap) |
| { |
| QVariantList returnedObject; |
| const QVariantList coordinatesList = inputMap.value(QStringLiteral("coordinates")).value<QVariantList>(); |
| QVariantMap singlePointMap; |
| QGeoCircle parsedPoint; |
| for (int i = 0; i < coordinatesList.size(); ++i) { // Iterating MultiPoint coordinates nasted arrays |
| parsedPoint.setCenter(importPosition(coordinatesList.at(i))); |
| singlePointMap.insert(QStringLiteral("type"), QStringLiteral("Point")); |
| singlePointMap.insert(QStringLiteral("data"), QVariant::fromValue(parsedPoint)); |
| returnedObject.append(QVariant::fromValue(singlePointMap)); |
| } |
| return returnedObject; |
| } |
| |
| static QVariantList importMultiLineString(const QVariantMap &inputMap) |
| { |
| QVariantList returnedObject; |
| QGeoPath parsedLineString; |
| const QVariant listCoords = inputMap.value(QStringLiteral("coordinates")); |
| const QVariantList list = listCoords.value<QVariantList>(); |
| QVariantMap singleLinestringMap; |
| for (int i = 0; i < list.size(); ++i) { // Iterating the MultiLineString coordinates nasted arrays using importArrayOfPositions |
| singleLinestringMap.clear(); |
| const QList <QGeoCoordinate> coordinatesList = importArrayOfPositions(list.at(i)); |
| singleLinestringMap.insert(QStringLiteral("type"), QStringLiteral("LineString")); |
| parsedLineString.setPath(coordinatesList); |
| singleLinestringMap.insert(QStringLiteral("data"), QVariant::fromValue(parsedLineString)); |
| returnedObject.append(QVariant::fromValue(singleLinestringMap)); |
| } |
| return returnedObject; |
| } |
| |
| static QVariantList importMultiPolygon(const QVariantMap &inputMap) |
| { |
| QVariantList returnedObject; |
| QGeoPolygon singlePoly; |
| QVariantMap singlePolygonMap; |
| const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates")); |
| const QVariantList list = valueCoordinates.value<QVariantList>(); |
| for (int i = 0; i < list.size(); ++i) { // Iterating the MultiPolygon coordinates nasted arrays |
| singlePolygonMap.clear(); |
| const QList<QList<QGeoCoordinate>> coordinatesList = importArrayOfArrayOfPositions(list.at(i)); |
| |
| for (int j = 0; j < coordinatesList.size(); ++j) { |
| if (j == 0) |
| singlePoly.setPath(coordinatesList.at(j)); |
| else |
| singlePoly.addHole(coordinatesList.at(j)); |
| } |
| singlePolygonMap.insert(QStringLiteral("type"), QStringLiteral("Polygon")); |
| singlePolygonMap.insert(QStringLiteral("data"), QVariant::fromValue(singlePoly)); |
| returnedObject.append(QVariant::fromValue(singlePolygonMap)); |
| } |
| return returnedObject; |
| } |
| |
| static QVariantMap importGeometry(const QVariantMap &inputMap); // Function prototype for a tail recursion |
| |
| static QVariantList importGeometryCollection(const QVariantMap &inputMap) |
| { |
| QVariantList returnedObject; |
| const QVariant listGeometries = inputMap.value(QStringLiteral("geometries")); |
| const QVariantList list = listGeometries.value<QVariantList>(); // QVariantList of heterogeneous composition of the other geometry types |
| for (int i = 0; i < list.size(); ++i) { |
| QVariantMap geometryMap = list.at(i).value<QVariantMap>(); |
| QVariantMap geoMap = importGeometry(geometryMap); |
| returnedObject.append(geoMap); |
| } |
| return returnedObject; |
| } |
| |
| static QVariantMap importGeometry(const QVariantMap &inputMap) |
| { |
| QVariantMap returnedObject; |
| QString geometryTypes[] = { |
| QStringLiteral("Point"), |
| QStringLiteral("MultiPoint"), |
| QStringLiteral("LineString"), |
| QStringLiteral("MultiLineString"), |
| QStringLiteral("Polygon"), |
| QStringLiteral("MultiPolygon"), |
| QStringLiteral("GeometryCollection") |
| }; |
| enum geoTypeSwitch { |
| Point, |
| MultiPoint, |
| LineString, |
| MultiLineString, |
| Polygon, |
| MultiPolygon, |
| GeometryCollection |
| }; |
| for (int i = 0; i<7; ++i) { |
| if (inputMap.value(QStringLiteral("type")).value<QString>() == geometryTypes[i]) { |
| switch (i) { |
| case Point: { |
| returnedObject.insert(QStringLiteral("type"), QStringLiteral("Point")); |
| returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importPoint(inputMap))); |
| break; |
| } |
| case MultiPoint: { |
| returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiPoint")); |
| returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiPoint(inputMap))); |
| break; |
| } |
| case LineString: { |
| returnedObject.insert(QStringLiteral("type"), QStringLiteral("LineString")); |
| returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importLineString(inputMap))); |
| break; |
| } |
| case MultiLineString: { |
| returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiLineString")); |
| returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiLineString(inputMap))); |
| break; |
| } |
| case Polygon: { |
| returnedObject.insert(QStringLiteral("type"), QStringLiteral("Polygon")); |
| returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importPolygon(inputMap))); |
| break; |
| } |
| case MultiPolygon: { |
| returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiPolygon")); |
| returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiPolygon(inputMap))); |
| break; |
| } |
| case GeometryCollection: { |
| returnedObject.insert(QStringLiteral("type"), QStringLiteral("GeometryCollection")); |
| returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importGeometryCollection(inputMap))); |
| break; |
| } |
| default: |
| break; |
| } |
| } |
| } |
| return returnedObject; |
| } |
| |
| static QVariantList importFeatureCollection(const QVariantMap &inputMap) |
| { |
| QVariantList returnedObject; |
| const QVariantList featuresList = inputMap.value(QStringLiteral("features")).value<QVariantList>(); |
| for (int i = 0; i < featuresList.size(); ++i) { |
| QVariantMap inputFeatureMap = featuresList.at(i).value<QVariantMap>(); |
| QVariantMap singleFeatureMap = importGeometry(inputFeatureMap.value(QStringLiteral("geometry")).value<QVariantMap>()); |
| const QVariantMap importedProperties = inputFeatureMap.value(QStringLiteral("properties")).value<QVariantMap>(); |
| singleFeatureMap.insert(QStringLiteral("properties"), importedProperties); |
| if (inputFeatureMap.contains(QStringLiteral("id"))) { |
| QVariant importedId = inputFeatureMap.value(QStringLiteral("id")).value<QVariant>(); |
| singleFeatureMap.insert(QStringLiteral("id"), importedId); |
| } |
| returnedObject.append(singleFeatureMap); |
| } |
| return returnedObject; |
| } |
| |
| static QJsonValue exportPosition(const QGeoCoordinate &obtainedCoordinates) |
| { |
| QJsonValue geoLat = obtainedCoordinates.latitude(); |
| QJsonValue geoLong = obtainedCoordinates.longitude(); |
| QJsonArray array = {geoLong, geoLat}; |
| QJsonValue geoAlt; |
| if (!qIsNaN(obtainedCoordinates.altitude())) { |
| geoAlt = obtainedCoordinates.altitude(); |
| array.append(geoAlt); |
| } |
| QJsonValue geoArray = array; |
| return geoArray; |
| } |
| |
| static QJsonValue exportArrayOfPositions(const QList<QGeoCoordinate> &obtainedCoordinatesList) |
| { |
| QJsonValue lineCoordinates; |
| QJsonValue multiPosition; |
| QJsonArray arrayPosition; |
| for (int i = 0; i < obtainedCoordinatesList.size(); ++i) { |
| multiPosition = exportPosition(obtainedCoordinatesList.at(i)); |
| arrayPosition.append(multiPosition); |
| } |
| lineCoordinates = arrayPosition; |
| return lineCoordinates; |
| } |
| |
| static QJsonValue exportArrayOfArrayOfPositions(const QList<QList<QGeoCoordinate>> &obtainedCoordinates) |
| { |
| QJsonValue lineCoordinates; |
| QJsonValue polyCoordinates; |
| QJsonArray arrayPath; |
| for (int i = 0; i < obtainedCoordinates.size(); ++i) { |
| lineCoordinates = exportArrayOfPositions(obtainedCoordinates.at(i)); |
| arrayPath.append(lineCoordinates); |
| } |
| polyCoordinates = arrayPath; |
| return polyCoordinates; |
| } |
| |
| static QJsonObject exportPoint(const QVariantMap &pointMap) |
| { |
| QJsonObject parsedPoint; |
| QGeoCircle circle = pointMap.value(QStringLiteral("data")).value<QGeoCircle>(); |
| parsedPoint.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Point"))); |
| parsedPoint.insert(QStringLiteral("coordinates"), exportPosition(circle.center())); |
| return parsedPoint; |
| } |
| |
| static QJsonObject exportLineString(const QVariantMap &lineStringMap) |
| { |
| QJsonObject parsedLineString; |
| QList <QGeoCoordinate> linestringPath = lineStringMap.value(QStringLiteral("data")).value<QGeoPath>().path(); |
| parsedLineString.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("LineString"))); |
| parsedLineString.insert(QStringLiteral("coordinates"), exportArrayOfPositions(linestringPath)); |
| return parsedLineString; |
| } |
| |
| static QJsonObject exportPolygon(const QVariantMap &polygonMap) |
| { |
| QVariant polygonVariant = polygonMap.value(QStringLiteral("data")); |
| QJsonObject parsedPolygon; |
| QJsonValue polyCoordinates; |
| QList<QList<QGeoCoordinate>> obtainedCoordinatesPoly; |
| QGeoPolygon parsedPoly = polygonVariant.value<QGeoPolygon>(); |
| obtainedCoordinatesPoly << parsedPoly.path(); |
| if (parsedPoly.holesCount()!=0) |
| for (int i = 0; i < parsedPoly.holesCount(); ++i) { |
| obtainedCoordinatesPoly << parsedPoly.holePath(i); |
| } |
| polyCoordinates = exportArrayOfArrayOfPositions(obtainedCoordinatesPoly); |
| parsedPolygon.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Polygon"))); |
| parsedPolygon.insert(QStringLiteral("coordinates"), polyCoordinates); |
| return parsedPolygon; |
| } |
| |
| static QJsonObject exportMultiPoint(const QVariantMap &multiPointMap) |
| { |
| QJsonObject parsedMultiPoint; |
| QList <QGeoCoordinate> obtainedCoordinatesMP; |
| QVariantList multiCircleVariantList = multiPointMap.value(QStringLiteral("data")).value<QVariantList>(); |
| for (const QVariant &exCircleVariantMap: multiCircleVariantList) { |
| obtainedCoordinatesMP << exCircleVariantMap.value<QVariantMap>().value(QStringLiteral("data")).value<QGeoCircle>().center(); |
| } |
| QJsonValue multiPosition = exportArrayOfPositions(obtainedCoordinatesMP); |
| parsedMultiPoint.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiPoint"))); |
| parsedMultiPoint.insert(QStringLiteral("coordinates"), multiPosition); |
| return parsedMultiPoint; |
| } |
| |
| static QJsonObject exportMultiLineString(const QVariantMap &multiLineStringMap) |
| { |
| QJsonObject parsedMultiLineString; |
| QList<QList<QGeoCoordinate>> extractedCoordinatesValue; |
| QVariant multiPathVariant = multiLineStringMap.value(QStringLiteral("data")); |
| QVariantList multiPathList = multiPathVariant.value<QVariantList>(); |
| for (int i = 0; i < multiPathList.size(); ++i) { |
| extractedCoordinatesValue << multiPathList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPath>().path(); |
| } |
| QJsonValue exportedCoordinatesValue = exportArrayOfArrayOfPositions(extractedCoordinatesValue); |
| parsedMultiLineString.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiLineString"))); |
| parsedMultiLineString.insert(QStringLiteral("coordinates"), exportedCoordinatesValue); |
| return parsedMultiLineString; |
| } |
| |
| static QJsonObject exportMultiPolygon(const QVariantMap &multiPolygonMap) |
| { |
| QJsonObject parsedMultiPolygon; |
| QJsonValue polyCoordinates; |
| QJsonArray parsedArrayPolygon; |
| QList<QList<QGeoCoordinate>> extractedCoordinatesValue; |
| QVariant multiPolygonVariant = multiPolygonMap.value(QStringLiteral("data")); |
| QVariantList multiPolygonList = multiPolygonVariant.value<QVariantList>(); |
| int polyHoles = 0; |
| int currentHole; |
| for (int i = 0; i < multiPolygonList.size(); ++i) { // Start parsing Polygon list |
| extractedCoordinatesValue << multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().path(); // Extract external polygon path |
| polyHoles = multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().holesCount(); |
| if (polyHoles) // Check if the polygon has holes |
| for (currentHole = 0 ; currentHole < polyHoles; currentHole++) |
| extractedCoordinatesValue << multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().holePath(currentHole); |
| polyCoordinates = exportArrayOfArrayOfPositions(extractedCoordinatesValue); // Generates QJsonDocument compatible value |
| parsedArrayPolygon.append(polyCoordinates); // Adds one level of nesting in coordinates |
| extractedCoordinatesValue.clear(); // Clears the temporary polygon linear ring storage |
| } |
| QJsonValue exportedCoordinatesNodeValue = parsedArrayPolygon; |
| parsedMultiPolygon.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiPolygon"))); |
| parsedMultiPolygon.insert(QStringLiteral("coordinates"), exportedCoordinatesNodeValue); |
| return parsedMultiPolygon; |
| } |
| |
| static QJsonObject exportGeometry(const QVariantMap &geometryMap); // Function prototype |
| |
| static QJsonObject exportGeometryCollection(const QVariantMap &geometryCollection) |
| { |
| QJsonObject parsed; |
| QJsonObject parsedGeometry; |
| QJsonValue valueGeometries; |
| QJsonArray parsedGeometries; |
| QVariantList geometriesList = geometryCollection.value(QStringLiteral("data")).value<QVariantList>(); |
| for (int i = 0; i < geometriesList.size(); ++i) { |
| parsedGeometry = exportGeometry(geometriesList.at(i).value<QVariantMap>()); |
| valueGeometries = parsedGeometry; |
| parsedGeometries.append(valueGeometries); |
| } |
| QJsonValue exportedGeometriesValue = parsedGeometries; |
| parsed.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("GeometryCollection"))); |
| parsed.insert(QStringLiteral("geometries"), exportedGeometriesValue); |
| return parsed; |
| } |
| |
| static QJsonObject exportGeometry(const QVariantMap &geometryMap) |
| { |
| QJsonObject exportedGeometry; |
| if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("Point")) |
| exportedGeometry = exportPoint(geometryMap); |
| if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiPoint")) |
| exportedGeometry = exportMultiPoint(geometryMap); |
| if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("LineString")) |
| exportedGeometry = exportLineString(geometryMap); |
| if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiLineString")) |
| exportedGeometry = exportMultiLineString(geometryMap); |
| if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("Polygon")) |
| exportedGeometry = exportPolygon(geometryMap); |
| if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiPolygon")) |
| exportedGeometry = exportMultiPolygon(geometryMap); |
| if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("GeometryCollection")) |
| exportedGeometry = exportGeometryCollection(geometryMap); |
| return exportedGeometry; |
| } |
| |
| static QJsonObject exportFeature(const QVariantMap &featureMap) |
| { |
| QJsonObject exportedFeature; |
| QJsonValue geometryNodeValue = QJsonValue(exportGeometry(featureMap)); |
| QJsonValue propertiesNodeValue = featureMap.value(QStringLiteral("properties")).value<QVariant>().toJsonValue(); |
| QJsonValue idNodeValue = featureMap.value(QStringLiteral("id")).value<QVariant>().toJsonValue(); |
| exportedFeature.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Feature"))); |
| exportedFeature.insert(QStringLiteral("geometry"), geometryNodeValue); |
| exportedFeature.insert(QStringLiteral("properties"), propertiesNodeValue); |
| exportedFeature.insert(QStringLiteral("id"), idNodeValue); |
| return exportedFeature; |
| } |
| |
| static QJsonObject exportFeatureCollection(const QVariantMap &featureCollection) |
| { |
| QJsonObject exportedFeatureCollection; |
| QJsonArray featureArray; |
| QVariantList featureList = featureCollection.value(QStringLiteral("data")).value<QVariantList>(); |
| for (int i = 0; i < featureList.size(); ++i) { |
| featureArray.append(QJsonValue(exportFeature(featureList.at(i).value<QVariantMap>()))); |
| } |
| exportedFeatureCollection.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("FeatureCollection"))); |
| exportedFeatureCollection.insert(QStringLiteral("features"), QJsonValue(featureArray) ); |
| return exportedFeatureCollection; |
| } |
| |
| /*! |
| This method imports the \a geoJson document, expected to contain valid GeoJSON |
| data, into a QVariantList structured like described in the section \l |
| {Importing GeoJSON}. |
| |
| \note This method performs no validation on the input. |
| |
| \sa exportGeoJson |
| */ |
| QVariantList QGeoJson::importGeoJson(const QJsonDocument &geoJson) |
| { |
| QVariantList returnedList; |
| QJsonObject object = geoJson.object(); // Read json object from imported doc |
| QVariantMap rootGeoJsonObject = object.toVariantMap(); // Extraced map using Qt's API |
| QString geoType[] = { |
| QStringLiteral("Point"), |
| QStringLiteral("MultiPoint"), |
| QStringLiteral("LineString"), |
| QStringLiteral("MultiLineString"), |
| QStringLiteral("Polygon"), |
| QStringLiteral("MultiPolygon"), |
| QStringLiteral("GeometryCollection"), |
| QStringLiteral("Feature"), |
| QStringLiteral("FeatureCollection") |
| }; |
| enum geoTypeSwitch { |
| Point, |
| MultiPoint, |
| LineString, |
| MultiLineString, |
| Polygon, |
| MultiPolygon, |
| GeometryCollection, |
| Feature, |
| FeatureCollection |
| }; |
| QVariantMap parsedGeoJsonMap; |
| |
| // Checking whether the JSON object has a "type" member |
| const QVariant keyVariant = rootGeoJsonObject.value(QStringLiteral("type")); |
| if (keyVariant == QVariant::Invalid) { |
| // Type check failed |
| } |
| QString valueType = keyVariant.value<QString>(); |
| |
| // Checking whether the "type" member has a GeoJSON admitted value |
| for (int i = 0; i < 9; ++i) { |
| if (valueType == geoType[i]) { |
| switch (i) { |
| case Point: { |
| QGeoCircle circle = importPoint(rootGeoJsonObject); |
| QVariant dataNodeValue = QVariant::fromValue(circle); |
| parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("Point")); |
| parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); |
| break; |
| } |
| case MultiPoint: { |
| QVariantList multiCircle = importMultiPoint(rootGeoJsonObject); |
| QVariant dataNodeValue = QVariant::fromValue(multiCircle); |
| QList <QGeoCircle> testlist; |
| parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiPoint")); |
| parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); |
| break; |
| } |
| case LineString: { |
| QGeoPath lineString = importLineString(rootGeoJsonObject); |
| QVariant dataNodeValue = QVariant::fromValue(lineString); |
| parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("LineString")); |
| parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); |
| break; |
| } |
| case MultiLineString: { |
| QVariantList multiLineString = importMultiLineString(rootGeoJsonObject); |
| QVariant dataNodeValue = QVariant::fromValue(multiLineString); |
| parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiLineString")); |
| parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); |
| break; |
| } |
| case Polygon: { |
| QGeoPolygon poly = importPolygon(rootGeoJsonObject); |
| QVariant dataNodeValue = QVariant::fromValue(poly); |
| parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("Polygon")); |
| parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); |
| break; |
| } |
| case MultiPolygon: { |
| QVariantList multiPoly = importMultiPolygon(rootGeoJsonObject); |
| QVariant dataNodeValue = QVariant::fromValue(multiPoly); |
| parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiPolygon")); |
| parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); |
| break; |
| } |
| // List of GeoJson geometry objects |
| case GeometryCollection: { |
| QVariantList multiGeo = importGeometryCollection(rootGeoJsonObject); |
| QVariant dataNodeValue = QVariant::fromValue(multiGeo); |
| parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("GeometryCollection")); |
| parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); |
| break; |
| } |
| // Single GeoJson geometry object with properties |
| case Feature: { |
| parsedGeoJsonMap = importGeometry(rootGeoJsonObject.value(QStringLiteral("geometry")).value<QVariantMap>()); |
| QVariantMap importedProperties = rootGeoJsonObject.value(QStringLiteral("properties")).value<QVariantMap>(); |
| parsedGeoJsonMap.insert(QStringLiteral("properties"), importedProperties); |
| if (rootGeoJsonObject.contains(QStringLiteral("id"))){ |
| QVariant importedId = rootGeoJsonObject.value(QStringLiteral("id")).value<QVariant>(); |
| parsedGeoJsonMap.insert(QStringLiteral("id"), importedId); |
| } |
| break; |
| } |
| // Heterogeneous list of GeoJSON geometries with properties |
| case FeatureCollection: { |
| QVariantList featCollection = importFeatureCollection(rootGeoJsonObject); |
| QVariant dataNodeValue = QVariant::fromValue(featCollection); |
| parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("FeatureCollection")); |
| parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); |
| break; |
| } |
| default: |
| break; |
| } |
| QVariant bboxNodeValue = rootGeoJsonObject.value(QStringLiteral("bbox")); |
| if (bboxNodeValue != QVariant::Invalid) { |
| parsedGeoJsonMap.insert(QStringLiteral("bbox"), bboxNodeValue); |
| } |
| returnedList.append(parsedGeoJsonMap); |
| } else if (i >= 9) { |
| // Error |
| break; |
| } |
| } |
| return returnedList; |
| } |
| |
| /*! |
| This method exports the QVariantList \a geoData, expected to be structured like |
| described in the section \l {Importing GeoJSON}, to a QJsonDocument containing |
| the data converted to GeoJSON. |
| |
| \note This method performs no validation on the input. |
| |
| \sa importGeoJson |
| */ |
| QJsonDocument QGeoJson::exportGeoJson(const QVariantList &geoData) |
| { |
| QVariantMap exportMap = geoData.at(0).value<QVariantMap>(); // Extracting the QVMap |
| QJsonObject newObject; |
| QJsonDocument newDocument; |
| if (exportMap.contains(QStringLiteral("properties"))) { |
| newObject = exportFeature(exportMap); |
| } else { |
| if (exportMap.value(QStringLiteral("type")) == QStringLiteral("Point")) // Check the value corresponding to the key "Point" |
| newObject = exportPoint(exportMap); |
| if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiPoint")) |
| newObject = exportMultiPoint(exportMap); |
| if (exportMap.value(QStringLiteral("type")) == QStringLiteral("LineString")) |
| newObject = exportLineString(exportMap); |
| if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiLineString")) |
| newObject = exportMultiLineString(exportMap); |
| if (exportMap.value(QStringLiteral("type")) == QStringLiteral("Polygon")) |
| newObject = exportPolygon(exportMap); |
| if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiPolygon")) |
| newObject = exportMultiPolygon(exportMap); |
| if (exportMap.value(QStringLiteral("type")) == QStringLiteral("GeometryCollection")) |
| newObject = exportGeometryCollection(exportMap); |
| if (exportMap.value(QStringLiteral("type")) == QStringLiteral("FeatureCollection")) |
| newObject = exportFeatureCollection(exportMap); |
| } |
| if (exportMap.contains((QStringLiteral("bbox")))) { |
| QJsonArray bboxArray; |
| QVariantList bboxList = exportMap.value(QStringLiteral("bbox")).value<QVariantList>(); |
| for (int i = 0; i < bboxList.size(); ++i) { |
| bboxArray.append(QJsonValue(bboxList.at(i).value<double>())); |
| } |
| newObject.insert(QStringLiteral("bbox"), QJsonValue(bboxArray)); |
| } |
| newDocument.setObject(newObject); |
| return newDocument; |
| } |
| |
| // Functions for toString |
| QTextStream &operator << (QTextStream &stream, const QGeoCoordinate &crd) |
| { |
| stream << "{ " << QString::number(crd.latitude(), 'f', 3) << ", " |
| << QString::number(crd.longitude(), 'f', 3) << ", " |
| << QString::number(crd.altitude(), 'f', 3) << " }"; |
| return stream; |
| } |
| |
| QTextStream &operator << (QTextStream &stream, const QGeoShape &shape) |
| { |
| switch (shape.type()) { |
| case QGeoShape::CircleType: { |
| QGeoCircle circle(shape); |
| stream << "QGeoCircle(" <<circle.center() << ", "<< QString::number(circle.radius()) << ")"; |
| break; |
| } |
| case QGeoShape::PathType: { |
| QGeoPath path(shape); |
| stream << "QGeoPath("; |
| for (auto c: path.path()) |
| stream << c << ", "; |
| stream << ")"; |
| break; |
| } |
| case QGeoShape::PolygonType: { |
| QGeoPolygon poly(shape); |
| stream << "QGeoPolygon("; |
| for (auto c: poly.path()) |
| stream << c << ", "; |
| stream << ")"; |
| break; |
| } |
| default: |
| stream << "QGeoShape(Unknown)"; |
| break; |
| } |
| return stream; |
| } |
| |
| static const QString sTab = QStringLiteral(" "); |
| |
| QString printQvariant(const QVariant v, int tabs = 0) { |
| QString sTabs; |
| QString res; |
| QTextStream stream(&res); |
| for (int i = 0; i< tabs; i++) { |
| sTabs += sTab; |
| } |
| if (v.type() == QVariant::List) { |
| stream << sTabs << "[\n"; |
| const QVariantList &l = v.toList(); |
| for (int i = 0; i < l.size(); ++i) |
| stream << printQvariant(l.at(i), tabs + 1); |
| stream << sTabs << "]\n"; |
| } else if (v.type() == QVariant::Map) { |
| stream << sTabs << "{\n"; |
| const QVariantList &l = v.toList(); |
| const QVariantMap &map = v.toMap(); |
| |
| // Either one or the other are valid |
| if (!map.keys().isEmpty()) { |
| // Handle type first, to easy reading |
| if (map.contains(QStringLiteral("type"))) { |
| stream << sTabs << sTab << QStringLiteral("type") << " : " |
| << printQvariant(map[QStringLiteral("type")], tabs + 1).remove(QRegExp(QStringLiteral("^[ ]*")));; |
| } |
| for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) { |
| if (iter.key() == QStringLiteral("type")) |
| continue; |
| stream << sTabs << sTab << iter.key() << " : " << printQvariant(iter.value(), tabs + 1).remove(QRegExp(QStringLiteral("^[ ]*")));; |
| } |
| } |
| for (int i = 0; i < l.size(); ++i) |
| stream << printQvariant(l.at(i), tabs + 1); |
| stream << sTabs << "}\n"; |
| } else { |
| stream << sTabs; |
| QGeoShape workigGeometry; |
| if ( v.canConvert<QGeoShape>()) { |
| workigGeometry = v.value<QGeoShape>(); |
| if (workigGeometry.type() == QGeoShape::CircleType) { |
| QGeoCircle circle = v.value<QGeoCircle>(); |
| stream << circle<< "\n"; |
| } else if (workigGeometry.type() == QGeoShape::PathType) { |
| QGeoPath path = v.value<QGeoPath>(); |
| stream << path<< "\n"; |
| } else if (workigGeometry.type() == QGeoShape::PolygonType) { |
| QGeoPolygon polygon = v.value<QGeoPolygon>(); |
| stream << polygon<< "\n"; |
| } |
| } else { |
| if (v.isNull()) |
| stream << "null\n"; |
| else |
| stream << v.toString() << "\n"; |
| } |
| } |
| return res; |
| } |
| |
| /*! |
| This method accepts the QVariantList \a geoData, structured as described in |
| \l {Importing GeoJSON}, and returns a string containing the same data in a |
| readable form. |
| */ |
| QString QGeoJson::toString(const QVariantList &geoData) { |
| return printQvariant(geoData.first(), 0); |
| } |
| |
| QT_END_NAMESPACE |