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
georoutejsonparser_esri.cpp
Go to the documentation of this file.
1// Copyright (C) 2013-2018 Esri <contracts@esri.com>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QJsonArray>
7#include <QGeoRectangle>
8#include <QGeoManeuver>
9#include <QGeoRouteSegment>
10
12
13// JSON reference:
14// https://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
15
16static const QString kErrorMessage(QStringLiteral("Error %1: %2."));
17static const QString kErrorJson(QStringLiteral("Error: invalide JSON document."));
18
19static const QString kErrorKey(QStringLiteral("error"));
20static const QString kErrorCodeKey(QStringLiteral("code"));
21static const QString kErrorMessageKey(QStringLiteral("message"));
22static const QString kErrorDetailsKey(QStringLiteral("details"));
23static const QString kDirectionsKey(QStringLiteral("directions"));
24static const QString kRoutesKey(QStringLiteral("routes"));
25static const QString kBarriersKey(QStringLiteral("barriers"));
26static const QString kMessagesKey(QStringLiteral("messages"));
27static const QString kDirectionsRouteIdKey(QStringLiteral("routeId"));
28static const QString kDirectionsRouteNameKey(QStringLiteral("routeName"));
29static const QString kDirectionsSummaryKey(QStringLiteral("summary"));
30static const QString kDirectionsTotalLengthKey(QStringLiteral("totalLength"));
31static const QString kDirectionsTotalTimeKey(QStringLiteral("totalTime"));
32static const QString kDirectionsTotalDriveTimeKey(QStringLiteral("totalDriveTime"));
33static const QString kDirectionsEnvelopeKey(QStringLiteral("envelope"));
34static const QString kDirectionsEnvelopeXminKey(QStringLiteral("xmin"));
35static const QString kDirectionsEnvelopeYminKey(QStringLiteral("ymin"));
36static const QString kDirectionsEnvelopeXmaxKey(QStringLiteral("xmax"));
37static const QString kDirectionsEnvelopeYmaxKey(QStringLiteral("ymax"));
38static const QString kDirectionsFeaturesKey(QStringLiteral("features"));
39static const QString kDirectionsFeaturesAttributesKey(QStringLiteral("attributes"));
40static const QString kDirectionsFeaturesCompressedGeometryKey(QStringLiteral("compressedGeometry"));
41static const QString kDirectionsFeaturesAttributesLengthKey(QStringLiteral("length"));
42static const QString kDirectionsFeaturesAttributesTimeKey(QStringLiteral("time"));
43static const QString kDirectionsFeaturesAttributesTextKey(QStringLiteral("text"));
44static const QString kDirectionsFeaturesAttributesEtaKey(QStringLiteral("ETA"));
45static const QString kDirectionsFeaturesAttributesManeuverTypeKey(QStringLiteral("maneuverType"));
46static const QString kRoutesFeaturesKey(QStringLiteral("features"));
47static const QString kRoutesFeaturesAttributesKey(QStringLiteral("attributes"));
48static const QString kRoutesFeaturesObjectIdKey(QStringLiteral("ObjectID"));
49static const QString kRoutesFeaturesGeometryKey(QStringLiteral("geometry"));
50static const QString kRoutesFeaturesGeometryPathsKey(QStringLiteral("paths"));
51
52GeoRouteJsonParserEsri::GeoRouteJsonParserEsri(const QJsonDocument &document)
53{
54 if (!document.isObject())
55 {
56 m_error = kErrorJson;
57 return;
58 }
59
60 m_json = document.object();
61 if (m_json.contains(kErrorKey))
62 {
63 QJsonObject error = m_json.value(kErrorKey).toObject();
64 int code = error.value(kErrorCodeKey).toInt();
65 QString message = error.value(kErrorMessageKey).toString();
66
67 m_error = kErrorMessage.arg(code).arg(message);
68 return;
69 }
70
71 parseDirections();
72 parseRoutes();
73}
74
75QList<QGeoRoute> GeoRouteJsonParserEsri::routes() const
76{
77 return m_routes.values();
78}
79
80bool GeoRouteJsonParserEsri::isValid() const
81{
82 return (m_error.isEmpty());
83}
84
85QString GeoRouteJsonParserEsri::errorString() const
86{
87 return m_error;
88}
89
90void GeoRouteJsonParserEsri::parseDirections()
91{
92 QJsonArray directions = m_json.value(kDirectionsKey).toArray();
93 for (const QJsonValueRef direction : directions)
94 parseDirection(direction.toObject());
95}
96
97void GeoRouteJsonParserEsri::parseDirection(const QJsonObject &direction)
98{
99 QGeoRoute &geoRoute = m_routes[direction.value(kDirectionsRouteIdKey).toInt()];
100
101 // parse summary
102 geoRoute.setRouteId(direction.value(kDirectionsRouteNameKey).toString());
103
104 QJsonObject summary = direction.value(kDirectionsSummaryKey).toObject();
105 geoRoute.setDistance(summary.value(kDirectionsTotalLengthKey).toDouble());
106
107 geoRoute.setTravelTime(summary.value(kDirectionsTotalTimeKey).toDouble() * 60);
108 // default units is minutes, see directionsTimeAttributeName param
109
110 geoRoute.setTravelMode(QGeoRouteRequest::CarTravel);
111 // default request is time for car, see directionsTimeAttributeName param
112
113 QJsonObject enveloppe = summary.value(kDirectionsEnvelopeKey).toObject();
114
115 QGeoCoordinate topLeft(enveloppe.value(kDirectionsEnvelopeXminKey).toDouble(),
116 enveloppe.value(kDirectionsEnvelopeYmaxKey).toDouble());
117 QGeoCoordinate bottomRight(enveloppe.value(kDirectionsEnvelopeXmaxKey).toDouble(),
118 enveloppe.value(kDirectionsEnvelopeYminKey).toDouble());
119 geoRoute.setBounds(QGeoRectangle(topLeft, bottomRight));
120
121 // parse features
122 QJsonArray features = direction.value(kDirectionsFeaturesKey).toArray();
123
124 static const QMap<QString, QGeoManeuver::InstructionDirection> esriDirectionsManeuverTypes
125 {
126 { QStringLiteral("esriDMTUnknown"), QGeoManeuver::NoDirection },
127 { QStringLiteral("esriDMTStop"), QGeoManeuver::NoDirection },
128 { QStringLiteral("esriDMTStraight"), QGeoManeuver::DirectionForward },
129 { QStringLiteral("esriDMTBearLeft"), QGeoManeuver::DirectionBearLeft },
130 { QStringLiteral("esriDMTBearRight"), QGeoManeuver::DirectionBearRight },
131 { QStringLiteral("esriDMTTurnLeft"), QGeoManeuver::DirectionLeft },
132 { QStringLiteral("esriDMTTurnRight"), QGeoManeuver::DirectionRight },
133 { QStringLiteral("esriDMTSharpLeft"), QGeoManeuver::DirectionLightLeft },
134 { QStringLiteral("esriDMTSharpRight"), QGeoManeuver::DirectionLightRight },
135 { QStringLiteral("esriDMTUTurn"), QGeoManeuver::DirectionUTurnRight },
136 { QStringLiteral("esriDMTFerry"), QGeoManeuver::NoDirection },
137 { QStringLiteral("esriDMTRoundabout"), QGeoManeuver::NoDirection },
138 { QStringLiteral("esriDMTHighwayMerge"), QGeoManeuver::NoDirection },
139 { QStringLiteral("esriDMTHighwayExit"), QGeoManeuver::NoDirection },
140 { QStringLiteral("esriDMTHighwayChange"), QGeoManeuver::NoDirection },
141 { QStringLiteral("esriDMTForkCenter"), QGeoManeuver::NoDirection },
142 { QStringLiteral("esriDMTForkLeft"), QGeoManeuver::NoDirection },
143 { QStringLiteral("esriDMTForkRight"), QGeoManeuver::NoDirection },
144 { QStringLiteral("esriDMTDepart"), QGeoManeuver::NoDirection },
145 { QStringLiteral("esriDMTTripItem"), QGeoManeuver::NoDirection },
146 { QStringLiteral("esriDMTEndOfFerry"), QGeoManeuver::NoDirection }
147 };
148
149 QGeoRouteSegment firstSegment;
150 for (qsizetype i = features.size() - 1; i >= 0; --i)
151 {
152 QJsonObject feature = features.at(i).toObject();
153 QJsonObject attributes = feature.value(kDirectionsFeaturesAttributesKey).toObject();
154
155 QGeoRouteSegment segment;
156 double length = attributes.value(kDirectionsFeaturesAttributesLengthKey).toDouble();
157 segment.setDistance(length);
158
159 double time = attributes.value(kDirectionsFeaturesAttributesTimeKey).toDouble() * 60;
160 // default units is minutes, see directionsTimeAttributeName param
161 segment.setTravelTime(time);
162
163 QGeoManeuver maneuver;
164 QString type = attributes.value(kDirectionsFeaturesAttributesManeuverTypeKey).toString();
165 maneuver.setDirection(esriDirectionsManeuverTypes.value(type));
166
167 maneuver.setInstructionText(attributes.value(kDirectionsFeaturesAttributesTextKey).toString() + ".");
168 maneuver.setDistanceToNextInstruction(length);
169 maneuver.setTimeToNextInstruction(time);
170
171 segment.setManeuver(maneuver);
172
173 segment.setNextRouteSegment(firstSegment);
174 firstSegment = segment;
175 }
176 geoRoute.setFirstRouteSegment(firstSegment);
177}
178
179void GeoRouteJsonParserEsri::parseRoutes()
180{
181 QJsonObject routes = m_json.value(kRoutesKey).toObject();
182 QJsonArray features = routes.value(kRoutesFeaturesKey).toArray();
183 for (const QJsonValueRef feature : features)
184 parseRoute(feature.toObject());
185}
186
187void GeoRouteJsonParserEsri::parseRoute(const QJsonObject &route)
188{
189 QJsonObject attributes = route.value(kRoutesFeaturesAttributesKey).toObject();
190 QGeoRoute &geoRoute = m_routes[attributes.value(kRoutesFeaturesObjectIdKey).toInt()];
191
192 QJsonObject geometry = route.value(kRoutesFeaturesGeometryKey).toObject();
193 QJsonArray paths = geometry.value(kRoutesFeaturesGeometryPathsKey).toArray();
194
195 if (!paths.isEmpty())
196 {
197 QList<QGeoCoordinate> geoCoordinates;
198 for (const QJsonValueRef value : paths.first().toArray()) // only first polyline?
199 {
200 QJsonArray geoCoordinate = value.toArray();
201 if (geoCoordinate.size() == 2) // ignore 3rd coordinate
202 {
203 geoCoordinates.append(QGeoCoordinate(geoCoordinate[1].toDouble(),
204 geoCoordinate[0].toDouble()));
205 }
206 }
207 geoRoute.setPath(geoCoordinates);
208 }
209}
210
211QT_END_NAMESPACE
static const QString kErrorCodeKey(QStringLiteral("code"))
static const QString kDirectionsFeaturesAttributesManeuverTypeKey(QStringLiteral("maneuverType"))
static const QString kDirectionsFeaturesAttributesTextKey(QStringLiteral("text"))
static const QString kRoutesFeaturesAttributesKey(QStringLiteral("attributes"))
static const QString kErrorKey(QStringLiteral("error"))
static const QString kMessagesKey(QStringLiteral("messages"))
static const QString kDirectionsSummaryKey(QStringLiteral("summary"))
static const QString kDirectionsKey(QStringLiteral("directions"))
static const QString kDirectionsEnvelopeYmaxKey(QStringLiteral("ymax"))
static const QString kBarriersKey(QStringLiteral("barriers"))
static const QString kDirectionsFeaturesAttributesTimeKey(QStringLiteral("time"))
static const QString kRoutesKey(QStringLiteral("routes"))
static const QString kDirectionsRouteNameKey(QStringLiteral("routeName"))
static const QString kDirectionsFeaturesAttributesKey(QStringLiteral("attributes"))
static const QString kDirectionsFeaturesCompressedGeometryKey(QStringLiteral("compressedGeometry"))
static const QString kDirectionsFeaturesAttributesEtaKey(QStringLiteral("ETA"))
static const QString kDirectionsEnvelopeXmaxKey(QStringLiteral("xmax"))
static const QString kDirectionsRouteIdKey(QStringLiteral("routeId"))
static const QString kErrorJson(QStringLiteral("Error: invalide JSON document."))
static const QString kDirectionsEnvelopeYminKey(QStringLiteral("ymin"))
static const QString kRoutesFeaturesObjectIdKey(QStringLiteral("ObjectID"))
static const QString kDirectionsEnvelopeKey(QStringLiteral("envelope"))
static const QString kDirectionsTotalTimeKey(QStringLiteral("totalTime"))
static const QString kDirectionsFeaturesAttributesLengthKey(QStringLiteral("length"))
static const QString kRoutesFeaturesKey(QStringLiteral("features"))
static const QString kRoutesFeaturesGeometryKey(QStringLiteral("geometry"))
static const QString kDirectionsFeaturesKey(QStringLiteral("features"))
static const QString kErrorMessageKey(QStringLiteral("message"))
static const QString kDirectionsTotalLengthKey(QStringLiteral("totalLength"))
static const QString kDirectionsEnvelopeXminKey(QStringLiteral("xmin"))
static QT_BEGIN_NAMESPACE const QString kErrorMessage(QStringLiteral("Error %1: %2."))
static const QString kErrorDetailsKey(QStringLiteral("details"))
static const QString kDirectionsTotalDriveTimeKey(QStringLiteral("totalDriveTime"))
static const QString kRoutesFeaturesGeometryPathsKey(QStringLiteral("paths"))