Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for Qt

Find service areas for multiple facilities

Sample Viewer View Sample on GitHub

Find the service areas of several facilities from a feature service.

Use case

A city taxi company may calculate service areas around their vehicle lots to identify gaps in coverage. Alternatively, they may want to ensure overlaps where a high volume of passengers requires redundant facilities, such as near an airport.

How to use the sample

Click 'Find service areas' to calculate and display the service area of each facility (hospital) on the map. The polygons displayed around each facility represent the facility's service area: the red area is within 1 minute travel time from the hospital by car, whilst orange is within 3 minutes by car. All service areas are semi-transparent to show where they overlap.

How it works

  1. Create a new ServiceAreaTask from a network service.
  2. Create default ServiceAreaParameters from the service area task.
  3. Set the parameters ServiceAreaParameters.returnPolygons = true to return polygons of all service areas.
  4. Define QueryParameters that retrieve all Facility items from a ServiceFeatureTable. Add the facilities to the service area parameters using the query parameters, serviceAreaParameters.SetFacilitiesWithFeatureTable(facilitiesTable, queryParameters).
  5. Get the ServiceAreaResult by solving the service area task using the parameters.
  6. For each facility, get any ServiceAreaPolygons that were returned, serviceAreaResult.resultPolygons(facilityIndex).
  7. Display the service area polygons as Graphics in a GraphicsOverlay on the MapView.

Relevant API

  • ServiceAreaParameters
  • ServiceAreaPolygon
  • ServiceAreaResult
  • ServiceAreaTask

About the data

This sample uses a street map of San Diego, in combination with a feature service with facilities (used here to represent hospitals). Additionally a street network is used on the server for calculating the service area.

Tags

facilities, feature service, impedance, network analysis, service area, travel time

Sample Code

import QtQuick 2.6
import Esri.ArcGISRuntime 100.9
import QtQuick.Layouts 1.11
import QtQuick.Controls 2.2

Rectangle {
    id: rootRectangle
    clip: true
    width: 800
    height: 600

    property url featureTableUrl: "https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/ArcGIS/rest/services/San_Diego_Facilities/FeatureServer/0"
    property url imageUrl: "https://static.arcgis.com/images/Symbols/SafetyHealth/Hospital.png"
    property url serviceTaskAreaUrl: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/ServiceArea"
    property list<SimpleFillSymbol> fillSymbols: [
        SimpleFillSymbol {
            style: Enums.SimpleFillSymbolStyleSolid
            color: "#66FFA500"
            outline: null
        },
        SimpleFillSymbol {
            style: Enums.SimpleFillSymbolStyleSolid
            color: "#66FF0000"
        }
    ]

    MapView {
        id: mapView
        anchors.fill: parent

        GraphicsOverlay {
            id: serviceAreasOverlay
        }

        Map {
            BasemapLightGrayCanvas {}

            // create query parameters used to select all facilities from the feature table
            QueryParameters {
                id: queryParameters
                whereClause: "1=1"
            }

            FeatureLayer {
                featureTable: ServiceFeatureTable {
                    id: featureTable
                    url: featureTableUrl
                }
                onLoadStatusChanged: {
                    if(loadStatus === Enums.LoadStatusLoaded) {
                        mapView.setViewpointGeometryAndPadding(fullExtent, 100);
                    }
                }
                onErrorChanged: {
                    console.warn(error.message);
                }

                renderer: SimpleRenderer {
                    PictureMarkerSymbol {
                        url: imageUrl
                        height: 25
                        width: 25
                    }
                }
            }

            ServiceAreaTask {
                id: serviceAreaTask
                url: serviceTaskAreaUrl

                Component.onCompleted: {
                    load();
                }

                onErrorChanged: {
                    console.warn(error.message);
                }

                onLoadStatusChanged: {
                    if (loadStatus === Enums.LoadStatusLoaded) {
                        createDefaultParameters();
                    }
                }

                onCreateDefaultParametersStatusChanged: {
                    if (createDefaultParametersStatus === Enums.TaskStatusCompleted) {
                        createDefaultParametersResult.polygonDetail = Enums.ServiceAreaPolygonDetailHigh;
                        createDefaultParametersResult.returnPolygons = true;

                        // add service areas of 1 minute and 3 minutes travel time by car
                        createDefaultParametersResult.defaultImpedanceCutoffs = [1.0, 3.0];
                        createDefaultParametersResult.setFacilitiesWithFeatureTable(featureTable, queryParameters);
                    }
                }

                onSolveServiceAreaStatusChanged: {
                    if (solveServiceAreaStatus === Enums.TaskStatusCompleted) {
                        // iterate through the facilities to get the service area polygons
                        for (let i = 0; i < solveServiceAreaResult.facilities.length; i++) {
                            const serviceAreaPolygonList = solveServiceAreaResult.resultPolygons(i);
                            //create a graphic for each available polygon
                            for (let j = 0; j < serviceAreaPolygonList.length; j++) {
                                serviceAreasOverlay.graphics.append(ArcGISRuntimeEnvironment.createObject("Graphic", {geometry: serviceAreaPolygonList[j].geometry, symbol: fillSymbols[j]}));
                            }
                        }
                    }
                }
            }
        }

        RowLayout {
            anchors {
                left: parent.left
                top: parent.top
            }

            Button {
                Layout.fillWidth: true
                Layout.fillHeight: true
                text: "Find service areas"
                onClicked: {
                    enabled = false;
                    serviceAreaTask.solveServiceArea(serviceAreaTask.createDefaultParametersResult)
                }
            }
        }
    }

    BusyIndicator {
        anchors.centerIn: parent
        visible: true
        running: serviceAreaTask.solveServiceAreaStatus === Enums.TaskStatusInProgress
    }
}