summaryrefslogtreecommitdiff
path: root/src/plugins/geoservices/osm
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@theqtcompany.com>2016-09-27 18:45:49 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2016-10-06 08:33:06 +0000
commita7c7a9bfc1f1d75f23f1e67ba3859e698e2e8965 (patch)
treebc7855bd5807a69a443f113038b74a19c5696108 /src/plugins/geoservices/osm
parent26b2f917861e63091cf97a5acba04d7b813c2fed (diff)
downloadqtlocation-a7c7a9bfc1f1d75f23f1e67ba3859e698e2e8965.tar.gz
Add OSRMv5 support in osm plugin
This patch adds support for the OSRMv5 protocol (the only one currently available on the OSRM demo server router.project.osrm.org). Support for the old v4 protocol is retained, in case of users who supply their own osm.routing.host parameter pointing at a self hosted OSRMv4 server. The support for OSRMv4 and v5 has been moved away from the osm plugin and into the location module because this should be used in the mapbox plugin in a subsequent patch (the routing support in the mapbox plugin currently uses the text direction coming from the server, which does not support i18n) Task-number: QTBUG-56119 Change-Id: Id30fd536c7fd434011795f643221f55becfc9e18 Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
Diffstat (limited to 'src/plugins/geoservices/osm')
-rw-r--r--src/plugins/geoservices/osm/qgeoroutereplyosm.cpp324
-rw-r--r--src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp31
-rw-r--r--src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h3
3 files changed, 35 insertions, 323 deletions
diff --git a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
index f704a714..81ada01d 100644
--- a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
+++ b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
@@ -32,207 +32,10 @@
****************************************************************************/
#include "qgeoroutereplyosm.h"
-
-#include <QtCore/QJsonDocument>
-#include <QtCore/QJsonObject>
-#include <QtCore/QJsonArray>
-#include <QtLocation/QGeoRouteSegment>
-#include <QtLocation/QGeoManeuver>
+#include "qgeoroutingmanagerengineosm.h"
QT_BEGIN_NAMESPACE
-static QList<QGeoCoordinate> parsePolyline(const QByteArray &data)
-{
- QList<QGeoCoordinate> path;
-
- bool parsingLatitude = true;
-
- int shift = 0;
- int value = 0;
-
- QGeoCoordinate coord(0, 0);
-
- for (int i = 0; i < data.length(); ++i) {
- unsigned char c = data.at(i) - 63;
-
- value |= (c & 0x1f) << shift;
- shift += 5;
-
- // another chunk
- if (c & 0x20)
- continue;
-
- int diff = (value & 1) ? ~(value >> 1) : (value >> 1);
-
- if (parsingLatitude) {
- coord.setLatitude(coord.latitude() + (double)diff/1e6);
- } else {
- coord.setLongitude(coord.longitude() + (double)diff/1e6);
- path.append(coord);
- }
-
- parsingLatitude = !parsingLatitude;
-
- value = 0;
- shift = 0;
- }
-
- return path;
-}
-
-static QGeoManeuver::InstructionDirection osrmInstructionDirection(const QString &instructionCode)
-{
- if (instructionCode == QLatin1String("0"))
- return QGeoManeuver::NoDirection;
- else if (instructionCode == QLatin1String("1"))
- return QGeoManeuver::DirectionForward;
- else if (instructionCode == QLatin1String("2"))
- return QGeoManeuver::DirectionBearRight;
- else if (instructionCode == QLatin1String("3"))
- return QGeoManeuver::DirectionRight;
- else if (instructionCode == QLatin1String("4"))
- return QGeoManeuver::DirectionHardRight;
- else if (instructionCode == QLatin1String("5"))
- return QGeoManeuver::DirectionUTurnLeft;
- else if (instructionCode == QLatin1String("6"))
- return QGeoManeuver::DirectionHardLeft;
- else if (instructionCode == QLatin1String("7"))
- return QGeoManeuver::DirectionLeft;
- else if (instructionCode == QLatin1String("8"))
- return QGeoManeuver::DirectionBearLeft;
- else if (instructionCode == QLatin1String("9"))
- return QGeoManeuver::NoDirection;
- else if (instructionCode == QLatin1String("10"))
- return QGeoManeuver::DirectionForward;
- else if (instructionCode == QLatin1String("11"))
- return QGeoManeuver::NoDirection;
- else if (instructionCode == QLatin1String("12"))
- return QGeoManeuver::NoDirection;
- else if (instructionCode == QLatin1String("13"))
- return QGeoManeuver::NoDirection;
- else if (instructionCode == QLatin1String("14"))
- return QGeoManeuver::NoDirection;
- else if (instructionCode == QLatin1String("15"))
- return QGeoManeuver::NoDirection;
- else
- return QGeoManeuver::NoDirection;
-}
-
-const QString osrmInstructionText(const QString &instructionCode, const QString &wayname)
-{
- if (instructionCode == QLatin1String("0")) {
- return QString();
- } else if (instructionCode == QLatin1String("1")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Go straight.");
- else
- return QGeoRouteReplyOsm::tr("Go straight onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("2")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Turn slightly right.");
- else
- return QGeoRouteReplyOsm::tr("Turn slightly right onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("3")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Turn right.");
- else
- return QGeoRouteReplyOsm::tr("Turn right onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("4")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Make a sharp right.");
- else
- return QGeoRouteReplyOsm::tr("Make a sharp right onto %1.").arg(wayname);
- }
- else if (instructionCode == QLatin1String("5")) {
- return QGeoRouteReplyOsm::tr("When it is safe to do so, perform a U-turn.");
- } else if (instructionCode == QLatin1String("6")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Make a sharp left.");
- else
- return QGeoRouteReplyOsm::tr("Make a sharp left onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("7")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Turn left.");
- else
- return QGeoRouteReplyOsm::tr("Turn left onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("8")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Turn slightly left.");
- else
- return QGeoRouteReplyOsm::tr("Turn slightly left onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("9")) {
- return QGeoRouteReplyOsm::tr("Reached waypoint.");
- } else if (instructionCode == QLatin1String("10")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Head on.");
- else
- return QGeoRouteReplyOsm::tr("Head onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11")) {
- return QGeoRouteReplyOsm::tr("Enter the roundabout.");
- } else if (instructionCode == QLatin1String("11-1")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the first exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the first exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11-2")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the second exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the second exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11-3")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the third exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the third exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11-4")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the fourth exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the fourth exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11-5")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the fifth exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the fifth exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11-6")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the sixth exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the sixth exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11-7")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the seventh exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the seventh exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11-8")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the eighth exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the eighth exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("11-9")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("At the roundabout take the ninth exit.");
- else
- return QGeoRouteReplyOsm::tr("At the roundabout take the ninth exit onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("12")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Leave the roundabout.");
- else
- return QGeoRouteReplyOsm::tr("Leave the roundabout onto %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("13")) {
- return QGeoRouteReplyOsm::tr("Stay on the roundabout.");
- } else if (instructionCode == QLatin1String("14")) {
- if (wayname.isEmpty())
- return QGeoRouteReplyOsm::tr("Start at the end of the street.");
- else
- return QGeoRouteReplyOsm::tr("Start at the end of %1.").arg(wayname);
- } else if (instructionCode == QLatin1String("15")) {
- return QGeoRouteReplyOsm::tr("You have reached your destination.");
- } else {
- return QGeoRouteReplyOsm::tr("Don't know what to say for '%1'").arg(instructionCode);
- }
-}
-
QGeoRouteReplyOsm::QGeoRouteReplyOsm(QNetworkReply *reply, const QGeoRouteRequest &request,
QObject *parent)
: QGeoRouteReply(request, parent), m_reply(reply)
@@ -259,70 +62,6 @@ void QGeoRouteReplyOsm::abort()
m_reply = 0;
}
-static QGeoRoute constructRoute(const QByteArray &geometry, const QJsonArray &instructions,
- const QJsonObject &summary)
-{
- QGeoRoute route;
-
- QList<QGeoCoordinate> path = parsePolyline(geometry);
-
- QGeoRouteSegment firstSegment;
- int firstPosition = -1;
-
- int segmentPathLengthCount = 0;
-
- for (int i = instructions.count() - 1; i >= 0; --i) {
- QJsonArray instruction = instructions.at(i).toArray();
-
- if (instruction.count() < 8) {
- qWarning("Instruction does not contain enough fields.");
- continue;
- }
-
- const QString instructionCode = instruction.at(0).toString();
- const QString wayname = instruction.at(1).toString();
- double segmentLength = instruction.at(2).toDouble();
- int position = instruction.at(3).toDouble();
- int time = instruction.at(4).toDouble();
- //const QString segmentLengthString = instruction.at(5).toString();
- //const QString direction = instruction.at(6).toString();
- //double azimuth = instruction.at(7).toDouble();
-
- QGeoRouteSegment segment;
- segment.setDistance(segmentLength);
-
- QGeoManeuver maneuver;
- maneuver.setDirection(osrmInstructionDirection(instructionCode));
- maneuver.setDistanceToNextInstruction(segmentLength);
- maneuver.setInstructionText(osrmInstructionText(instructionCode, wayname));
- maneuver.setPosition(path.at(position));
- maneuver.setTimeToNextInstruction(time);
-
- segment.setManeuver(maneuver);
-
- if (firstPosition == -1)
- segment.setPath(path.mid(position));
- else
- segment.setPath(path.mid(position, firstPosition - position));
-
- segmentPathLengthCount += segment.path().length();
-
- segment.setTravelTime(time);
-
- segment.setNextRouteSegment(firstSegment);
-
- firstSegment = segment;
- firstPosition = position;
- }
-
- route.setDistance(summary.value(QStringLiteral("total_distance")).toDouble());
- route.setTravelTime(summary.value(QStringLiteral("total_time")).toDouble());
- route.setFirstRouteSegment(firstSegment);
- route.setPath(path);
-
- return route;
-}
-
void QGeoRouteReplyOsm::networkReplyFinished()
{
if (!m_reply)
@@ -335,59 +74,26 @@ void QGeoRouteReplyOsm::networkReplyFinished()
return;
}
- QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll());
-
- if (document.isObject()) {
- QJsonObject object = document.object();
-
- //double version = object.value(QStringLiteral("version")).toDouble();
- int status = object.value(QStringLiteral("status")).toDouble();
- QString statusMessage = object.value(QStringLiteral("status_message")).toString();
-
- // status code 0 or 200 are case of success
- // status code is 207 if no route was found
- // an error occurred when trying to find a route
- if (0 != status && 200 != status) {
- setError(QGeoRouteReply::UnknownError, statusMessage);
- m_reply->deleteLater();
- m_reply = 0;
- return;
- }
-
- QJsonObject routeSummary = object.value(QStringLiteral("route_summary")).toObject();
-
- QByteArray routeGeometry =
- object.value(QStringLiteral("route_geometry")).toString().toLatin1();
-
- QJsonArray routeInstructions = object.value(QStringLiteral("route_instructions")).toArray();
-
- QGeoRoute route = constructRoute(routeGeometry, routeInstructions, routeSummary);
-
- QList<QGeoRoute> routes;
- routes.append(route);
+ if (m_reply->error() != QNetworkReply::NoError) {
+ setError(QGeoRouteReply::CommunicationError, m_reply->errorString());
+ m_reply->deleteLater();
+ m_reply = 0;
+ return;
+ }
- QJsonArray alternativeSummaries =
- object.value(QStringLiteral("alternative_summaries")).toArray();
- QJsonArray alternativeGeometries =
- object.value(QStringLiteral("alternative_geometries")).toArray();
- QJsonArray alternativeInstructions =
- object.value(QStringLiteral("alternative_instructions")).toArray();
+ QGeoRoutingManagerEngineOsm *engine = qobject_cast<QGeoRoutingManagerEngineOsm *>(parent());
+ const QGeoRouteParser *parser = engine->routeParser();
- if (alternativeSummaries.count() == alternativeGeometries.count() &&
- alternativeSummaries.count() == alternativeInstructions.count()) {
- for (int i = 0; i < alternativeSummaries.count(); ++i) {
- route = constructRoute(alternativeGeometries.at(i).toString().toLatin1(),
- alternativeInstructions.at(i).toArray(),
- alternativeSummaries.at(i).toObject());
- //routes.append(route);
- }
- }
+ QList<QGeoRoute> routes;
+ QString errorString;
+ QGeoRouteReply::Error error = parser->parseReply(routes, errorString, m_reply->readAll());
+ if (error == QGeoRouteReply::NoError) {
setRoutes(routes);
-
+ // setError(QGeoRouteReply::NoError, status); // can't do this, or NoError is emitted and does damages
setFinished(true);
} else {
- setError(QGeoRouteReply::ParseError, QStringLiteral("Couldn't parse json."));
+ setError(error, errorString);
}
m_reply->deleteLater();
diff --git a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp
index df3351c2..4e18049a 100644
--- a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp
+++ b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp
@@ -33,6 +33,8 @@
#include "qgeoroutingmanagerengineosm.h"
#include "qgeoroutereplyosm.h"
+#include "QtLocation/private/qgeorouteparserosrmv4_p.h"
+#include "QtLocation/private/qgeorouteparserosrmv5_p.h"
#include <QtCore/QUrlQuery>
@@ -51,7 +53,14 @@ QGeoRoutingManagerEngineOsm::QGeoRoutingManagerEngineOsm(const QVariantMap &para
if (parameters.contains(QStringLiteral("osm.routing.host")))
m_urlPrefix = parameters.value(QStringLiteral("osm.routing.host")).toString().toLatin1();
else
- m_urlPrefix = QStringLiteral("http://router.project-osrm.org/viaroute");
+ m_urlPrefix = QStringLiteral("http://router.project-osrm.org/route/v1/driving/");
+ // for v4 it was "http://router.project-osrm.org/viaroute"
+
+ if (parameters.contains(QStringLiteral("osm.routing.apiversion"))
+ && (parameters.value(QStringLiteral("osm.routing.apiversion")).toString().toLatin1() == QByteArray("v4")))
+ m_routeParser = new QGeoRouteParserOsrmV4(this);
+ else
+ m_routeParser = new QGeoRouteParserOsrmV5(this);
*error = QGeoServiceProvider::NoError;
errorString->clear();
@@ -64,20 +73,9 @@ QGeoRoutingManagerEngineOsm::~QGeoRoutingManagerEngineOsm()
QGeoRouteReply* QGeoRoutingManagerEngineOsm::calculateRoute(const QGeoRouteRequest &request)
{
QNetworkRequest networkRequest;
- networkRequest.setRawHeader("User-Agent", m_userAgent);
-
- QUrl url(m_urlPrefix);
- QUrlQuery query;
-
- query.addQueryItem(QStringLiteral("instructions"), QStringLiteral("true"));
+ networkRequest.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent);
- foreach (const QGeoCoordinate &c, request.waypoints()) {
- query.addQueryItem(QStringLiteral("loc"), QString::number(c.latitude()) + QLatin1Char(',') +
- QString::number(c.longitude()));
- }
-
- url.setQuery(query);
- networkRequest.setUrl(url);
+ networkRequest.setUrl(routeParser()->requestUrl(request, m_urlPrefix));
QNetworkReply *reply = m_networkManager->get(networkRequest);
@@ -90,6 +88,11 @@ QGeoRouteReply* QGeoRoutingManagerEngineOsm::calculateRoute(const QGeoRouteReque
return routeReply;
}
+const QGeoRouteParser *QGeoRoutingManagerEngineOsm::routeParser() const
+{
+ return m_routeParser;
+}
+
void QGeoRoutingManagerEngineOsm::replyFinished()
{
QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
diff --git a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h
index 618ef900..8ffba6e3 100644
--- a/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h
+++ b/src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.h
@@ -36,6 +36,7 @@
#include <QtLocation/QGeoServiceProvider>
#include <QtLocation/QGeoRoutingManagerEngine>
+#include <QtLocation/private/qgeorouteparser_p.h>
QT_BEGIN_NAMESPACE
@@ -52,6 +53,7 @@ public:
~QGeoRoutingManagerEngineOsm();
QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request);
+ const QGeoRouteParser *routeParser() const;
private Q_SLOTS:
void replyFinished();
@@ -59,6 +61,7 @@ private Q_SLOTS:
private:
QNetworkAccessManager *m_networkManager;
+ QGeoRouteParser *m_routeParser;
QByteArray m_userAgent;
QString m_urlPrefix;
};