diff options
Diffstat (limited to 'src/plugins/geoservices/esri/georoutejsonparser_esri.cpp')
-rw-r--r-- | src/plugins/geoservices/esri/georoutejsonparser_esri.cpp | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp b/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp new file mode 100644 index 00000000..30db48f0 --- /dev/null +++ b/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2013-2016 Esri <contracts@esri.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtLocation 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 "georoutejsonparser_esri.h" + +#include <QJsonArray> +#include <QGeoRectangle> +#include <QGeoManeuver> +#include <QGeoRouteSegment> + +QT_BEGIN_NAMESPACE + +// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/ + +static const QString kErrorMessage(QStringLiteral("Error %1: %2.")); +static const QString kErrorJson(QStringLiteral("Error: invalide JSON document.")); + +static const QString kErrorKey(QStringLiteral("error")); +static const QString kErrorCodeKey(QStringLiteral("code")); +static const QString kErrorMessageKey(QStringLiteral("message")); +static const QString kErrorDetailsKey(QStringLiteral("details")); +static const QString kDirectionsKey(QStringLiteral("directions")); +static const QString kRoutesKey(QStringLiteral("routes")); +static const QString kBarriersKey(QStringLiteral("barriers")); +static const QString kMessagesKey(QStringLiteral("messages")); +static const QString kDirectionsRouteIdKey(QStringLiteral("routeId")); +static const QString kDirectionsRouteNameKey(QStringLiteral("routeName")); +static const QString kDirectionsSummaryKey(QStringLiteral("summary")); +static const QString kDirectionsTotalLengthKey(QStringLiteral("totalLength")); +static const QString kDirectionsTotalTimeKey(QStringLiteral("totalTime")); +static const QString kDirectionsTotalDriveTimeKey(QStringLiteral("totalDriveTime")); +static const QString kDirectionsEnvelopeKey(QStringLiteral("envelope")); +static const QString kDirectionsEnvelopeXminKey(QStringLiteral("xmin")); +static const QString kDirectionsEnvelopeYminKey(QStringLiteral("ymin")); +static const QString kDirectionsEnvelopeXmaxKey(QStringLiteral("xmax")); +static const QString kDirectionsEnvelopeYmaxKey(QStringLiteral("ymax")); +static const QString kDirectionsFeaturesKey(QStringLiteral("features")); +static const QString kDirectionsFeaturesAttributesKey(QStringLiteral("attributes")); +static const QString kDirectionsFeaturesCompressedGeometryKey(QStringLiteral("compressedGeometry")); +static const QString kDirectionsFeaturesAttributesLengthKey(QStringLiteral("length")); +static const QString kDirectionsFeaturesAttributesTimeKey(QStringLiteral("time")); +static const QString kDirectionsFeaturesAttributesTextKey(QStringLiteral("text")); +static const QString kDirectionsFeaturesAttributesEtaKey(QStringLiteral("ETA")); +static const QString kDirectionsFeaturesAttributesManeuverTypeKey(QStringLiteral("maneuverType")); +static const QString kRoutesFeaturesKey(QStringLiteral("features")); +static const QString kRoutesFeaturesAttributesKey(QStringLiteral("attributes")); +static const QString kRoutesFeaturesObjectIdKey(QStringLiteral("ObjectID")); +static const QString kRoutesFeaturesGeometryKey(QStringLiteral("geometry")); +static const QString kRoutesFeaturesGeometryPathsKey(QStringLiteral("paths")); + +GeoRouteJsonParserEsri::GeoRouteJsonParserEsri(const QJsonDocument &document) +{ + if (!document.isObject()) + { + m_error = kErrorJson; + return; + } + + m_json = document.object(); + if (m_json.contains(kErrorKey)) + { + QJsonObject error = m_json.value(kErrorKey).toObject(); + int code = error.value(kErrorCodeKey).toInt(); + QString message = error.value(kErrorMessageKey).toString(); + + m_error = kErrorMessage.arg(code).arg(message); + return; + } + + parseDirections(); + parseRoutes(); +} + +QList<QGeoRoute> GeoRouteJsonParserEsri::routes() const +{ + return m_routes.values(); +} + +bool GeoRouteJsonParserEsri::isValid() const +{ + return (m_error.isEmpty()); +} + +QString GeoRouteJsonParserEsri::errorString() const +{ + return m_error; +} + +void GeoRouteJsonParserEsri::parseDirections() +{ + QJsonArray directions = m_json.value(kDirectionsKey).toArray(); + foreach (const QJsonValue &direction, directions) + parseDirection(direction.toObject()); +} + +void GeoRouteJsonParserEsri::parseDirection(const QJsonObject &direction) +{ + QGeoRoute &geoRoute = m_routes[direction.value(kDirectionsRouteIdKey).toInt()]; + + // parse summary + geoRoute.setRouteId(direction.value(kDirectionsRouteNameKey).toString()); + + QJsonObject summary = direction.value(kDirectionsSummaryKey).toObject(); + geoRoute.setDistance(summary.value(kDirectionsTotalLengthKey).toDouble()); + + geoRoute.setTravelTime(summary.value(kDirectionsTotalTimeKey).toDouble() * 60); + // default units is minutes, see directionsTimeAttributeName param + + geoRoute.setTravelMode(QGeoRouteRequest::CarTravel); + // default request is time for car, see directionsTimeAttributeName param + + QJsonObject enveloppe = summary.value(kDirectionsEnvelopeKey).toObject(); + + QGeoCoordinate topLeft(enveloppe.value(kDirectionsEnvelopeXminKey).toDouble(), + enveloppe.value(kDirectionsEnvelopeYmaxKey).toDouble()); + QGeoCoordinate bottomRight(enveloppe.value(kDirectionsEnvelopeXmaxKey).toDouble(), + enveloppe.value(kDirectionsEnvelopeYminKey).toDouble()); + geoRoute.setBounds(QGeoRectangle(topLeft, bottomRight)); + + // parse features + QJsonArray features = direction.value(kDirectionsFeaturesKey).toArray(); + + static const QMap<QString, QGeoManeuver::InstructionDirection> esriDirectionsManeuverTypes + { + { QStringLiteral("esriDMTUnknown"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTStop"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTStraight"), QGeoManeuver::DirectionForward }, + { QStringLiteral("esriDMTBearLeft"), QGeoManeuver::DirectionBearLeft }, + { QStringLiteral("esriDMTBearRight"), QGeoManeuver::DirectionBearRight }, + { QStringLiteral("esriDMTTurnLeft"), QGeoManeuver::DirectionLeft }, + { QStringLiteral("esriDMTTurnRight"), QGeoManeuver::DirectionRight }, + { QStringLiteral("esriDMTSharpLeft"), QGeoManeuver::DirectionLightLeft }, + { QStringLiteral("esriDMTSharpRight"), QGeoManeuver::DirectionLightRight }, + { QStringLiteral("esriDMTUTurn"), QGeoManeuver::DirectionUTurnRight }, + { QStringLiteral("esriDMTFerry"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTRoundabout"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTHighwayMerge"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTHighwayExit"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTHighwayChange"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTForkCenter"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTForkLeft"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTForkRight"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTDepart"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTTripItem"), QGeoManeuver::NoDirection }, + { QStringLiteral("esriDMTEndOfFerry"), QGeoManeuver::NoDirection } + }; + + QGeoRouteSegment firstSegment; + for (int i = features.size() - 1; i >= 0; --i) + { + QJsonObject feature = features.at(i).toObject(); + QJsonObject attributes = feature.value(kDirectionsFeaturesAttributesKey).toObject(); + + QGeoRouteSegment segment; + double length = attributes.value(kDirectionsFeaturesAttributesLengthKey).toDouble(); + segment.setDistance(length); + + double time = attributes.value(kDirectionsFeaturesAttributesTimeKey).toDouble() * 60; + // default units is minutes, see directionsTimeAttributeName param + segment.setTravelTime(time); + + QGeoManeuver maneuver; + QString type = attributes.value(kDirectionsFeaturesAttributesManeuverTypeKey).toString(); + maneuver.setDirection(esriDirectionsManeuverTypes.value(type)); + + maneuver.setInstructionText(attributes.value(kDirectionsFeaturesAttributesTextKey).toString() + "."); + maneuver.setDistanceToNextInstruction(length); + maneuver.setTimeToNextInstruction(time); + + segment.setManeuver(maneuver); + + segment.setNextRouteSegment(firstSegment); + firstSegment = segment; + } + geoRoute.setFirstRouteSegment(firstSegment); +} + +void GeoRouteJsonParserEsri::parseRoutes() +{ + QJsonObject routes = m_json.value(kRoutesKey).toObject(); + QJsonArray features = routes.value(kRoutesFeaturesKey).toArray(); + foreach (const QJsonValue &feature, features) + parseRoute(feature.toObject()); +} + +void GeoRouteJsonParserEsri::parseRoute(const QJsonObject &route) +{ + QJsonObject attributes = route.value(kRoutesFeaturesAttributesKey).toObject(); + QGeoRoute &geoRoute = m_routes[attributes.value(kRoutesFeaturesObjectIdKey).toInt()]; + + QJsonObject geometry = route.value(kRoutesFeaturesGeometryKey).toObject(); + QJsonArray paths = geometry.value(kRoutesFeaturesGeometryPathsKey).toArray(); + + if (!paths.isEmpty()) + { + QList<QGeoCoordinate> geoCoordinates; + foreach (const QJsonValue &value, paths.first().toArray()) // only first polyline? + { + QJsonArray geoCoordinate = value.toArray(); + if (geoCoordinate.size() == 2) // ignore 3rd coordinate + { + geoCoordinates.append(QGeoCoordinate(geoCoordinate[1].toDouble(), + geoCoordinate[0].toDouble())); + } + } + geoRoute.setPath(geoCoordinates); + } +} + +QT_END_NAMESPACE |