Skip to content
View on GitHubSample viewer app

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

screenshot

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.setReturnPolygons(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

FindServiceAreasForMultipleFacilities.cppFindServiceAreasForMultipleFacilities.cppFindServiceAreasForMultipleFacilities.hFindServiceAreasForMultipleFacilities.qml
Use dark colors for code blocksCopy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 // [WriteFile Name=FindServiceAreasForMultipleFacilities, Category=Routing] // [Legal] // Copyright 2020 Esri. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // [Legal]  #ifdef PCH_BUILD #include "pch.hpp" #endif // PCH_BUILD  // sample headers #include "FindServiceAreasForMultipleFacilities.h"  // ArcGIS Maps SDK headers #include "Envelope.h" #include "Error.h" #include "ErrorException.h" #include "FeatureLayer.h" #include "Graphic.h" #include "GraphicListModel.h" #include "GraphicsOverlay.h" #include "GraphicsOverlayListModel.h" #include "LayerListModel.h" #include "Map.h" #include "MapQuickView.h" #include "MapTypes.h" #include "NetworkAnalystTypes.h" #include "PictureMarkerSymbol.h" #include "Polygon.h" #include "QueryParameters.h" #include "ServiceAreaFacility.h" #include "ServiceAreaParameters.h" #include "ServiceAreaPolygon.h" #include "ServiceAreaResult.h" #include "ServiceAreaTask.h" #include "ServiceFeatureTable.h" #include "SimpleFillSymbol.h" #include "SimpleRenderer.h" #include "SymbolTypes.h"  // Qt headers #include <QUrl> #include <QUuid>  using namespace Esri::ArcGISRuntime;  namespace { const QUrl url("https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/ArcGIS/rest/services/San_Diego_Facilities/FeatureServer/0"); const QUrl imageUrl("https://static.arcgis.com/images/Symbols/SafetyHealth/Hospital.png"); const QUrl serviceAreaTaskUrl("https://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/ServiceArea"); }  FindServiceAreasForMultipleFacilities::FindServiceAreasForMultipleFacilities(QObject* parent /* = nullptr */):  QObject(parent),  m_map(new Map(BasemapStyle::ArcGISLightGray, this)),  m_serviceAreasOverlay(new GraphicsOverlay(this)) {  // create fill symbols for rendering the results  m_fillSymbols.append(new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor(255, 166, 0, 66), this)); // translucent orange  m_fillSymbols.append(new SimpleFillSymbol(SimpleFillSymbolStyle::Solid, QColor(255, 0, 0, 66), this)); // translucent red   m_facilitiesTable = new ServiceFeatureTable(url, this);  m_facilitiesFeatureLayer = new FeatureLayer(m_facilitiesTable, this);   // create a symbol to display the facilities  PictureMarkerSymbol* facilitiesSymbol = new PictureMarkerSymbol(imageUrl, this);  facilitiesSymbol->setWidth(25);  facilitiesSymbol->setHeight(25);  m_facilitiesFeatureLayer->setRenderer(new SimpleRenderer(facilitiesSymbol, this));   // add the facilities feature layer to the map  m_map->operationalLayers()->append(m_facilitiesFeatureLayer); }  FindServiceAreasForMultipleFacilities::~FindServiceAreasForMultipleFacilities() = default;  void FindServiceAreasForMultipleFacilities::init() {  // Register the map view for QML  qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView");  qmlRegisterType<FindServiceAreasForMultipleFacilities>("Esri.Samples", 1, 0, "FindServiceAreasForMultipleFacilitiesSample"); }  MapQuickView* FindServiceAreasForMultipleFacilities::mapView() const {  return m_mapView; }  bool FindServiceAreasForMultipleFacilities::taskRunning() const {  return m_future.isRunning(); }  // Set the view (created in QML) void FindServiceAreasForMultipleFacilities::setMapView(MapQuickView* mapView) {  if (!mapView || mapView == m_mapView)  return;   m_mapView = mapView;   connect(m_facilitiesFeatureLayer, &FeatureLayer::doneLoading, this, [this](const Error& loadError)  {  if (!loadError.isEmpty())  {  qDebug() << loadError.message() << loadError.additionalMessage();  return;  }   // zoom to the full extent of the feature layer  int buffer = 100;  m_mapView->setViewpointGeometryAsync(m_facilitiesFeatureLayer->fullExtent(), buffer);   });   m_mapView->setMap(m_map);   m_mapView->graphicsOverlays()->append(m_serviceAreasOverlay);   emit mapViewChanged(); }  void FindServiceAreasForMultipleFacilities::connectServiceAreaTaskSignals() {  // once service area task is done loading, create default parameters  connect(m_serviceAreaTask, &ServiceAreaTask::doneLoading, this, [this](const Error& loadError)  {  if (!loadError.isEmpty())  {  qDebug() << loadError.message() << loadError.additionalMessage();  return;  }  m_serviceAreaTask->createDefaultParametersAsync().then(this, [this](ServiceAreaParameters serviceAreaParameters)  {  // once default parameters created, set parameters and solve  serviceAreaParameters.setPolygonDetail(ServiceAreaPolygonDetail::High);  serviceAreaParameters.setReturnPolygons(true);   QList<double> travelTimes = {1.0, 3.0};   // add service areas of 1 minute and 3 minutes travel time by car  serviceAreaParameters.setDefaultImpedanceCutoffs(travelTimes);   // create query parameters used to select all facilities from the feature table  QueryParameters queryParameters;  queryParameters.setWhereClause("1=1");   // add all facilities to the service area parameters  serviceAreaParameters.setFacilitiesWithFeatureTable(m_facilitiesTable, queryParameters);   m_future = m_serviceAreaTask->solveServiceAreaAsync(serviceAreaParameters);  m_future.then(this, [this](const ServiceAreaResult& serviceAreaResult)  {  emit taskRunningChanged();   // iterate through the facilities to get the service area polygons  for (int i = 0; i < serviceAreaResult.facilities().size(); ++i)  {  QList<ServiceAreaPolygon> serviceAreaPolygonList = serviceAreaResult.resultPolygons(i);  // create a graphic for each available polygon  for (int j = 0; j < serviceAreaPolygonList.size(); ++j)  {  m_serviceAreasOverlay->graphics()->append(new Graphic(serviceAreaPolygonList[j].geometry(), m_fillSymbols[j], this));  }  }  }).onFailed([](const ErrorException& e)  {  qWarning() << e.error().message();  });   if (!m_future.isValid())  qWarning() << "Furure not valid.";   });   emit taskRunningChanged();  }); }  void FindServiceAreasForMultipleFacilities::findServiceAreas() {  if (m_serviceAreaTask)  return;   m_serviceAreaTask = new ServiceAreaTask(serviceAreaTaskUrl, this);  connectServiceAreaTaskSignals();  m_serviceAreaTask->load(); }

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.