Learn how to find a route and directions with the route service A routing service is a service that uses network analysis and streets data to calculate the most effective path and turn-by-turn directions on a street network, optimize fleet routing and deliveries, find the closest facilities, calculate service areas, and more. It is hosted by Esri as the ArcGIS Routing service and can also be hosted in ArcGIS Enterprise. Learn more .

Map of Los Angeles with a blue route line and a turn-by-turn directions panel.

Routing is the process of finding the path from an origin An origin is a point that defines the start of a route. Learn more to a destination A destination is a point that defines the final stop in a route. Learn more in a street network. You can use the Routing service A routing service is a service that uses network analysis and streets data to calculate the most effective path and turn-by-turn directions on a street network, optimize fleet routing and deliveries, find the closest facilities, calculate service areas, and more. It is hosted by Esri as the ArcGIS Routing service and can also be hosted in ArcGIS Enterprise. Learn more to find routes A route is a polyline that defines the best path between two or more points in a street network. Learn more , get driving directions, calculate drive times, and solve complicated, multiple vehicle routing problems. To create a route, you typically define a set of stops (origin and one or more destinations) and use the service to find a route with directions. You can also use a number of additional parameters such as barriers and mode of travel to refine the results.

In this tutorial, you define an origin and destination by clicking on the map. These values are used to get a route and directions from the route service. The directions are also displayed on the map.

Prerequisites

Before starting this tutorial:

  1. You need an ArcGIS Location Platform or ArcGIS Online account.

  2. Your system meets the system requirements.

  3. The ArcGIS Maps SDK for Qt, version 300.1.0 or later is installed.

  4. The Qt 6.8.2 software development framework or later is installed.

Set up authentication

To access the secure ArcGIS location services ArcGIS Location Services, also referred to as Location Services, are services hosted by Esri that provide geospatial functionality for developing mapping applications. They include the ArcGIS Basemap Styles service, ArcGIS Static Basemap Tiles service, ArcGIS Static Maps service, ArcGIS Places service, ArcGIS Geocoding service, ArcGIS Routing service, ArcGIS GeoEnrichment service, and ArcGIS Elevation service. An ArcGIS Location Platform or ArcGIS Online account is required to use the services. Learn more used in this tutorial, you must implement API key authentication API key authentication is a type of authentication that uses an API key to authenticate requests to ArcGIS services and secure portal items. Learn more or user authentication User authentication is a type of authentication that allows users with an ArcGIS account to sign into an application and allow it to access ArcGIS content, services, and resources on their behalf. The typical authorization protocol used is OAuth2.0. Learn more using an ArcGIS Location Platform An ArcGIS Location Platform account, formerly known as an ArcGIS Developer account, is an identity associated with an ArcGIS Location Platform subscription. Learn more or an ArcGIS Online An ArcGIS Online account, also known as an ArcGIS Organization account, is an identity associated with an ArcGIS Online subscription. It can be used to access ArcGIS tools and develop applications with ArcGIS location services for an organization. Learn more account.

To complete this tutorial, click on the tab in the switcher below for your authentication type of choice, either API key authentication or User authentication.

Create a new API key access token An access token is an authorization string that provides access to secure ArcGIS content, data, and services. Its capabilities are determined by the privileges it supports. It is obtained by implementing API key authentication, User authentication, or App authentication. Learn more with privileges Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. Learn more to access the secure resources used in this tutorial.

  1. Complete the Create an API key tutorial and create an API key with the following privilege(s) Privileges are a set of permissions assigned to ArcGIS accounts, developer credentials, and applications that grant access to secure resources and functionality in ArcGIS. Learn more :

    • Privileges
      • Location services > Basemaps
      • Location services > Routing
  2. Copy and paste the API key access token into a safe location. It will be used in a later step.

Develop or Download

You have two options for completing this tutorial:

  1. Option 1: Develop the code or
  2. Option 2: Download the completed solution

Option 1: Develop the code

To start the tutorial, complete the Display a map tutorial. This creates a map to display the Santa Monica Mountains in California using the topographic basemap from the ArcGIS Basemap Styles service The ArcGIS Basemap Styles service, also referred to as the Basemap Styles service, is a location service that provides basemap styles and data for the world. It returns styles as Mapbox styles and web maps, and data as vector tiles and/or map tiles. It supports all of the styles in the ArcGIS Basemap style and Open Basemap style family. An ArcGIS Location Platform or ArcGIS Online account is required to use the service. Learn more .

Open a Qt Creator project

  1. Open the project you created by completing the Display a map tutorial.
  2. Continue with the following instructions to find a route and directions with the ArcGIS Routing service A routing service is a service that uses network analysis and streets data to calculate the most effective path and turn-by-turn directions on a street network, optimize fleet routing and deliveries, find the closest facilities, calculate service areas, and more. It is hosted by Esri as the ArcGIS Routing service and can also be hosted in ArcGIS Enterprise. Learn more .

Declare classes, functions, variables, enumerations and signals

  1. In the Display_a_map project, double click on Headers > Display_a_map.h to open the file. Add the four class declarations shown.

    Display_a_map.h
    namespace Esri::ArcGISRuntime {
    class Map;
    class MapQuickView;
    class Graphic;
    class GraphicsOverlay;
    class PictureMarkerSymbol;
    class RouteTask;
  2. Continuing in the Display_a_map.h file, create an enum to monitor user route selections and maintain the route builder status. This will be initialized in Display_a_map.cpp in a later step.

    Display_a_map.h
    class Graphic;
    class GraphicsOverlay;
    class PictureMarkerSymbol;
    class RouteTask;
    } // namespace Esri::ArcGISRuntime
    enum RouteBuilderStatus
    {
    NotStarted,
    SelectedStart,
    SelectedStartAndEnd,
    };
  3. Add an #include statement, class declaration, and a Meta Object Compiler (MOC) to add an include that exposes the QAbstractListModel.

    Display_a_map.h
    enum RouteBuilderStatus
    {
    NotStarted,
    SelectedStart,
    SelectedStartAndEnd,
    };
    #include <QObject>
    #include "RouteParameters.h"
    class QAbstractListModel;
    Q_MOC_INCLUDE("QAbstractListModel")
    Q_MOC_INCLUDE("MapQuickView.h")
  4. Use Q_PROPERTY to create a member variable m_directions.

    Display_a_map.h
    class Display_a_map : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(Esri::ArcGISRuntime::MapQuickView* mapView READ mapView WRITE setMapView NOTIFY mapViewChanged)
    Q_PROPERTY(QAbstractListModel* directions MEMBER m_directions NOTIFY directionsChanged)
  5. Add the following signal declaration; this will be used to prompt updates to route directions.

    Display_a_map.h
    public:
    explicit Display_a_map(QObject* parent = nullptr);
    ~Display_a_map() override;
    signals:
    void mapViewChanged();
    void directionsChanged();
  6. Declare the following private methods.

    Display_a_map.h
    private:
    Esri::ArcGISRuntime::MapQuickView* mapView() const;
    void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView);
    void setupViewpoint();
    void setupRouteTask();
    void findRoute();
    void resetState();
  7. Finally in the Display_a_map.h file, declare and initialize the following pointers, object, and enumeration. Then save the file.

    Display_a_map.h
    void setupRouteTask();
    void findRoute();
    void resetState();
    Esri::ArcGISRuntime::Map* m_map = nullptr;
    Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr;
    Esri::ArcGISRuntime::GraphicsOverlay* m_graphicsOverlay = nullptr;
    Esri::ArcGISRuntime::RouteTask* m_routeTask = nullptr;
    Esri::ArcGISRuntime::Graphic* m_startGraphic = nullptr;
    Esri::ArcGISRuntime::Graphic* m_endGraphic = nullptr;
    Esri::ArcGISRuntime::Graphic* m_lineGraphic = nullptr;
    QAbstractListModel* m_directions = nullptr;
    Esri::ArcGISRuntime::RouteParameters m_routeParameters;
    RouteBuilderStatus m_currentState;

Include header files to access needed classes

  1. In the Qt project, double click on Sources > Display_a_map.cpp to open the file. Add #include statements for the classes shown.

    Display_a_map.cpp
    #include "Display_a_map.h"
    #include "Map.h"
    #include "MapTypes.h"
    #include "MapQuickView.h"
    #include "Point.h"
    #include "Viewpoint.h"
    #include "SpatialReference.h"
    #include <QFuture>
    #include "DirectionManeuverListModel.h"
    #include "Graphic.h"
    #include "GraphicListModel.h"
    #include "GraphicsOverlay.h"
    #include "GraphicsOverlayListModel.h"
    #include "Polyline.h"
    #include "RouteTask.h"
    #include "RouteResult.h"
    #include "RouteParameters.h"
    #include "Route.h"
    #include "SimpleLineSymbol.h"
    #include "SimpleMarkerSymbol.h"
    #include "Stop.h"
    #include "Symbol.h"
    #include "SymbolTypes.h"
    #include <QGeoPositionInfoSource>
    #include <QList>
    #include <QUrl>
    #include <QUuid>

Update the constructor

  1. Continuing to edit the Display_a_map.cpp file, update the constructor as shown. Set BasemapStyle to ArcGISStreets and initialize the RouteBuilderStatus enumeration. Add an ending comma to the line for the m_map(new Map(BasemapStyle::ArcGISStreets, this)) member variable (yellow highlighted line) and add a new member variable for m_currentState(RouteBuilderStatus::NotStarted) (green highlighted line).

    Display_a_map.cpp
    Display_a_map::Display_a_map(QObject* parent /* = nullptr */):
    QObject(parent),
    m_map(new Map(BasemapStyle::ArcGISStreets, this)),
    m_currentState(RouteBuilderStatus::NotStarted)
  2. Call the setupRouteTask() method within the constructor. This will be populated in a later step.

    Display_a_map.cpp
    Display_a_map::Display_a_map(QObject* parent /* = nullptr */):
    QObject(parent),
    m_map(new Map(BasemapStyle::ArcGISStreets, this)),
    m_currentState(RouteBuilderStatus::NotStarted)
    {
    setupRouteTask();

Change the map’s view point

  1. Continuing to edit the Display_a_map.cpp file, in setupViewpoint() method change the 2 lines for the map’s Point and Viewpoint to place the map over over downtown Los Angeles (highlighted in yellow).

    Display_a_map.cpp
    MapQuickView* Display_a_map::mapView() const
    {
    return m_mapView;
    }
    void Display_a_map::setupViewpoint()
    {
    const Point center(-118.24532, 34.05398, SpatialReference::wgs84());
    const Viewpoint viewpoint(center, 144447.638572);

Change setupViewpoint() to respond to mouse clicks and find the route

  1. Continuing to edit the Display_a_map.cpp file, add a connect statement to setupViewpoint() to detect user mouse clicks, set and display point graphics, respond to the first and second click (using the switch statement), and call findRoute on the second mouse click.

    Display_a_map.cpp
    void Display_a_map::setupViewpoint()
    {
    const Point center(-118.24532, 34.05398, SpatialReference::wgs84());
    const Viewpoint viewpoint(center, 144447.638572);
    m_mapView->setViewpointAsync(viewpoint);
    connect(m_mapView, &MapQuickView::mouseClicked, this, [this](QMouseEvent& mouse)
    {
    const Point mapPoint = m_mapView->screenToLocation(mouse.position().x(), mouse.position().y());
    switch (m_currentState)
    {
    case RouteBuilderStatus::NotStarted:
    resetState();
    m_currentState = RouteBuilderStatus::SelectedStart;
    m_startGraphic->setGeometry(mapPoint);
    break;
    case RouteBuilderStatus::SelectedStart:
    m_currentState = RouteBuilderStatus::SelectedStartAndEnd;
    m_endGraphic->setGeometry(mapPoint);
    findRoute();
    break;
    case RouteBuilderStatus::SelectedStartAndEnd:
    // Ignore touches while routing is in progress
    break;
    }
    });

Create route graphics

  1. Continuing to edit the Display_a_map.cpp file, add code to setupViewpoint() to create the route’s starting point Graphic, determined by the user’s first mouse click. This consists of a SimpleLineSymbol, color blue, size 2, that outlines a SimpleMarkerSymbol, diamond shaped and orange in color. Create the route’s ending point Graphic, determined by the user’s second mouse click. This consists of a SimpleLineSymbol, color red, size 2, that outlines a SimpleMarkerSymbol, square shaped and green in color. Create a line Graphic connecting the route’s starting and ending points using a SimpleLineSymbol, color blue, size 4. Then append the starting point graphic, ending point graphic, and route line graphic to a GraphicsOverlay.

    Display_a_map.cpp
    case RouteBuilderStatus::SelectedStartAndEnd:
    // Ignore touches while routing is in progress
    break;
    }
    });
    m_graphicsOverlay = new GraphicsOverlay(this);
    m_mapView->graphicsOverlays()->append(m_graphicsOverlay);
    SimpleLineSymbol* startOutlineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("blue"), 2/*width*/, this);
    SimpleMarkerSymbol* startSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Diamond, QColor("orange"), 12/*width*/, this);
    startSymbol->setOutline(startOutlineSymbol);
    m_startGraphic = new Graphic(this);
    m_startGraphic->setSymbol(startSymbol);
    SimpleLineSymbol* endOutlineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("red"), 2/*width*/, this);
    SimpleMarkerSymbol* endSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::Square, QColor("green"), 12/*width*/, this);
    endSymbol->setOutline(endOutlineSymbol);
    m_endGraphic = new Graphic(this);
    m_endGraphic->setSymbol(endSymbol);
    SimpleLineSymbol* lineSymbol = new SimpleLineSymbol(SimpleLineSymbolStyle::Solid, QColor("blue"), 4/*width*/, this);
    m_lineGraphic = new Graphic(this);
    m_lineGraphic->setSymbol(lineSymbol);
    m_graphicsOverlay->graphics()->append(QList<Graphic*> {m_startGraphic, m_endGraphic, m_lineGraphic});
    }

Create the setRouteTask() method

A task makes a request to a service A service, also known as an ArcGIS service, is software that supports an ArcGIS REST API and provides geospatial functionality or data. A service can be hosted by Esri or in ArcGIS Enterprise. Learn more and returns the results. Use the RouteTask class to access a routing service A routing service is a service that uses network analysis and streets data to calculate the most effective path and turn-by-turn directions on a street network, optimize fleet routing and deliveries, find the closest facilities, calculate service areas, and more. It is hosted by Esri as the ArcGIS Routing service and can also be hosted in ArcGIS Enterprise. Learn more . Create a RouteTask with a string URL to reference the routing service.

  1. Continuing to edit the Display_a_map.cpp file, implement the setRouteTask() method. Point the RouteTask to an online service. Call the create default parameters async method obtain the route parameters.

    Display_a_map.cpp
    void Display_a_map::setupRouteTask()
    {
    // create the route task pointing to an online service
    m_routeTask = new RouteTask(QUrl("https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World"), this);
    // Create the default parameters which will load the route task implicitly.
    m_routeTask->createDefaultParametersAsync().then(this,[this](const RouteParameters& routeParameters)
    {
    // Store the resulting route parameters.
    m_routeParameters = routeParameters;
    });
    }

Create the findRoute() method

  1. Continuing to edit the Display_a_map.cpp file, implement the findRoute() method. Add code to first confirm that RouteTask has loaded and RouteParameters is not empty. Then set RouteParameters to return directions, and clear stops from previous routes. Then create Stop objects for the route from the geometries of the start and end graphics, and pass those to RouteParameters. Call solveRouteAsync(), passing in RouteParameters. With the route completed, set the route graphic’s geometry and reset RouteBuilderStatus to prepare for a new route task. Then display the route directions.

    Display_a_map.cpp
    void Display_a_map::findRoute()
    {
    if (m_routeTask->loadStatus() != LoadStatus::Loaded || m_routeParameters.isEmpty())
    return;
    // Set parameters to return directions.
    m_routeParameters.setReturnDirections(true);
    // Clear previous stops from the parameters.
    m_routeParameters.clearStops();
    // Set the stops to the parameters.
    const Stop stop1(Point(m_startGraphic->geometry()));
    const Stop stop2(Point(m_endGraphic->geometry()));
    m_routeParameters.setStops(QList<Stop> { stop1, stop2 });
    // Solve the route with the parameters.
    m_routeTask->solveRouteAsync(m_routeParameters).then(this,[this](const RouteResult& routeResult)
    {
    // Add the route graphic once the solve completes.
    const Route generatedRoute = routeResult.routes().at(0);
    m_lineGraphic->setGeometry(generatedRoute.routeGeometry());
    m_currentState = RouteBuilderStatus::NotStarted;
    // Set the direction maneuver list model.
    m_directions = generatedRoute.directionManeuvers(this);
    emit directionsChanged();
    });
    }

Create the resetState() method

This method resets all graphics and directions, and the RouteBuilderStatus enumeration. This happens at the beginning of every new route task.

  1. Continuing to edit the Display_a_map.cpp file, reset all graphics with empty Point objects, set m_directions to nullptr, and reset RouteBuilderStatus. Then save the file.

    Display_a_map.cpp
    void Display_a_map::resetState()
    {
    m_startGraphic->setGeometry(Point());
    m_endGraphic->setGeometry(Point());
    m_lineGraphic->setGeometry(Point());
    m_directions = nullptr;
    m_currentState = RouteBuilderStatus::NotStarted;
    }

Create the GUI

  1. In the Qt project, double click on Resources > qml\qml.qrc > /qml > Display_a_mapForm.qml to open the file. Add the following import.

    display_a_mapForm.qml
    import QtQuick
    import QtQuick.Controls
    import Esri.Display_a_map
    import QtQuick.Shapes
  2. Add the code highlighted below in green. This builds out the application GUI and displays the route and route directions.

    display_a_mapForm.qml
    // Declare the C++ instance which creates the map etc. and supply the view.
    Display_a_map {
    id: model
    mapView: view
    }
    // Create window for displaying the route directions.
    Rectangle {
    id: directionWindow
    anchors {
    right: parent.right
    top: parent.top
    margins: 5
    }
    radius: 5
    visible: model.directions
    width: Qt.platform.os === "ios" || Qt.platform.os === "android" ? 250 : 350
    height: parent.height / 2
    color: "#FBFBFB"
    clip: true
    ListView {
    id: directionsView
    anchors {
    fill: parent
    margins: 5
    }
    header: Component {
    Text {
    height: 40
    text: "Directions:"
    font.pixelSize: 22
    }
    }
    // Set the model to the DirectionManeuverListModel returned from the route.
    model: model.directions
    delegate: directionDelegate
    }
    }
    Component {
    id: directionDelegate
    Rectangle {
    id: rect
    width: parent.width
    height: textDirections.height
    color: directionWindow.color
    // separator for directions
    Shape {
    height: 2
    ShapePath {
    strokeWidth: 1
    strokeColor: "darkgrey"
    strokeStyle: ShapePath.SolidLine
    startX: 20; startY: 0
    PathLine { x: parent.width - 20 ; y: 0 }
    }
    }
    Text {
    id: textDirections
    text: qsTr("%1 (%2 miles)".arg(directionText).arg((length * 0.00062137).toFixed(2)))
    wrapMode: Text.WordWrap
    anchors {
    leftMargin: 5
    left: parent.left
    right: parent.right
    }
    }
    }
    }

Set developer credentials

For the final steps of this tutorial, click the tab below that corresponds to the authentication type (API key authentication or User authentication) that you chose when you completed the Display a map tutorial.

Be sure to also provide the same authentication (API key or user authentication Client ID/Redirect URL) that you used for the Display a map tutorial.

Set the API Key

  1. In the project Sources folder of Qt Creator, open the main.cpp file.

  2. Modify the code to set the accessToken using your API key access token (highlighted in yellow).

    main.cpp
    // The following methods grant an access token:
    // 1. User authentication: Grants a temporary access token associated with a user's ArcGIS account.
    // To generate a token, a user logs in to the app with an ArcGIS account that is part of an
    // organization in ArcGIS Online or ArcGIS Enterprise.
    // 2. API key authentication: Get a long-lived access token that gives your application access to
    // ArcGIS location services. Go to the tutorial at https://links.esri.com/create-an-api-key.
    // Copy the API Key access token.
    const QString accessToken = QString("");
    if (accessToken.isEmpty())
    {
    qWarning() << "Use of ArcGIS location services, such as the basemap styles service, requires" <<
    "you to authenticate with an ArcGIS account or set the API Key property.";
    }
    else
    {
    ArcGISRuntimeEnvironment::setApiKey(accessToken);
    }
  3. Save the main.cpp file.

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Press Ctrl + R to run the app.

The map should support two clicks to create an origin and destination point and then use the route service A routing service is a service that uses network analysis and streets data to calculate the most effective path and turn-by-turn directions on a street network, optimize fleet routing and deliveries, find the closest facilities, calculate service areas, and more. It is hosted by Esri as the ArcGIS Routing service and can also be hosted in ArcGIS Enterprise. Learn more to display the resulting route and turn-by-turn directions.

Alternatively, you can download the tutorial solution, as follows.

Option 2: Download the solution

  1. Click the Download solution link under Solution and unzip the file to a location on your machine.

  2. Open the .pro project file in Qt Creator.

Since the downloaded solution does not contain authentication credentials, you must add the developer credentials that you created in the Set up authentication section.

For the final steps of this tutorial, click the tab below that corresponds to the authentication type (API key authentication or User authentication) that you chose when you completed the Display a map tutorial.

Be sure to also provide the same authentication (API key or user authentication Client ID/Redirect URL) that you used for the Display a map tutorial.

Set the API Key

  1. In the project Sources folder of Qt Creator, open the main.cpp file.

  2. Modify the code to set the accessToken using your API key access token (highlighted in yellow).

    main.cpp
    // The following methods grant an access token:
    // 1. User authentication: Grants a temporary access token associated with a user's ArcGIS account.
    // To generate a token, a user logs in to the app with an ArcGIS account that is part of an
    // organization in ArcGIS Online or ArcGIS Enterprise.
    // 2. API key authentication: Get a long-lived access token that gives your application access to
    // ArcGIS location services. Go to the tutorial at https://links.esri.com/create-an-api-key.
    // Copy the API Key access token.
    const QString accessToken = QString("");
    if (accessToken.isEmpty())
    {
    qWarning() << "Use of ArcGIS location services, such as the basemap styles service, requires" <<
    "you to authenticate with an ArcGIS account or set the API Key property.";
    }
    else
    {
    ArcGISRuntimeEnvironment::setApiKey(accessToken);
    }
  3. Save main.cpp file.

Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.

Run the app

Press Ctrl + R to run the app.

The map should support two clicks to create an origin and destination point and then use the route service A routing service is a service that uses network analysis and streets data to calculate the most effective path and turn-by-turn directions on a street network, optimize fleet routing and deliveries, find the closest facilities, calculate service areas, and more. It is hosted by Esri as the ArcGIS Routing service and can also be hosted in ArcGIS Enterprise. Learn more to display the resulting route and turn-by-turn directions.

What’s next?

Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: