Routes to the three closest facilities created with the routing service.
What is closest facility routing?
Closest facility routing is the process of finding one or more nearby facilities from incidents based on travel time or travel distance. Once you've found the closest facilities, you can display the best route to them and include the travel time, travel distance, and driving directions to each facility in multiple languages.
You can use closest facility routing to build applications that:
- Find the closest hospital to an accident.
- Dispatch the two closest police cars to a crime scene.
- Find the three closest fire stations that can respond to a fire incident within five minutes' drive time.
When finding the closest facilities, you can:
- Specify the number of nearby facilities to find.
- Set the direction of travel toward or away from facilities.
- Apply current traffic conditions to determine the best routes.
- Provide an impedance cutoff beyond which the service should not search for a facility. For instance, you can set up a closest facility service request to search for hospitals within 15 minutes drive time of the site of an accident. Any hospitals that take longer than 15 minutes to reach will not be included in the results.
- Perform multiple closest facility searches simultaneously. This means you can have multiple incidents and find the closest facility or facilities to each incident.
How closest facility routing works
The typical workflow for closest facility routing is to define:
- A set of locations from which to choose the nearest locations (facilities).
- One or more locations from which to start searching for the nearby locations (incidents).
- The type of travel for the analysis.
- The number of closest facilities to find per incident.
- Call the service to find the closest facilities and generate route and directions to each nearby facility.
URL requests
You can perform closest facility routing by making an HTTPS request to the closest facility service solve
operation or by using client APIs. Specify the facilities to search for, one or more incidents, and optionally, additional parameters to refine the operation. Some of most common parameters are described below.
Request limits
Limit | Direct | Job |
---|---|---|
Maximum number of incidents: | 100 | 5,000 |
Maximum number of facilities: | 100 | 5,000 |
Maximum number of facilities to find (per incident): | 10 | 100 |
Maximum transaction time: | 5 minutes | 60 minutes |
Maximum number of point barriers: | 250 | 250 |
Maximum number of street features intersected by polyline barriers: | 500 | 500 |
Maximum number of street features intersected by polygon barriers: | 2,000 | 2,000 |
Maximum straight-line distance for the walking travel mode: (If the straight-line distance between any incidents or facilities is greater than this limit, the analysis will fail when the walking restriction is used.) | 27 miles (43.45 kilometers) | 27 miles (43.45 kilometers) |
Force hierarchy beyond a straight-line distance of: (If the straight-line distance between any incidents or facilities is greater than the limit shown here, the analysis uses hierarchy, even if the travel mode defines not to use hierarchy.) | 50 miles (80.46 kilometers) | 50 miles (80.46 kilometers) |
Maximum snap tolerance: (If the distance between an input point and its nearest traversable street is greater than the distance specified here, the point is excluded from the analysis.) | 12.42 miles (20 kilometers) | 12.42 miles (20 kilometers) |
Maximum number of directions features that can be returned: | No limit | 1,000,000 |
Required parameters
Name | Description | Examples |
---|---|---|
f | The format of the data returned. | f=json f=pjson |
token | An API key or OAuth 2.0 access token. | token= |
Direct
Use for shorter transactions to find up to 10 facilities from 100 facilities and 100 incidents in less than 5 minutes.
https://route-api.arcgis.com/arcgis/rest/services/World/ClosestFacility/NAServer/ClosestFacility_World/solveClosestFacility?<parameters>
https://route.arcgis.com/arcgis/rest/services/World/ClosestFacility/NAServer/ClosestFacility_World/solveClosestFacility?<parameters>
Key parameters
Name (Direct) | Description | Examples |
---|---|---|
facilities | Set of locations from which to choose the nearest locations. | facilities=-117.190774,34.057301;-117.199781,34.06047 |
incidents | One or more locations from which to start searching for the nearby locations. | incidents=-117.195696,34.056503 |
travel | The mode of transportation such as driving a car or a truck or walking. | travel JSON Object |
default | The number of closest facilities to find per incident. | default |
default | The travel time or travel distance value at which to stop searching for facilities for a given incident. | default |
travel | Whether you want to search for the closest facility as measured from the incident to the facility or from the facility to the incident. | travel |
Additional parameters: Set additional constraints when finding closest facilities such as time
to use live traffic conditions or return
and directions
to generate driving directions to each nearby facility.
Job
Use for longer transactions to find up to 100 facilities from 5,000 facilities and 5,000 incidents in less than 60 minutes.
https://logistics.arcgis.com/arcgis/rest/services/World/ClosestFacility/GPServer/FindClosestFacilities/submitJob?<parameters>
Key parameters
Name (Direct) | Description | Examples |
---|---|---|
facilities | Set of locations from which to choose the nearest locations. | facilities={"features" |
incidents | One or more locations from which to start searching for the nearby locations. | incidents={"features" |
travel | The mode of transportation such as driving a car or a truck or walking. | travel JSON Object |
number | The number of closest facilities to find per incident. | number |
cutoff | The travel time or travel distance value at which to stop searching for facilities for a given incident. | cutoff=5 |
travel | Whether you want to search for the closest facility as measured from the incident to the facility or from the facility to the incident. | travel |
Additional parameters: Set additional constraints when finding closest facilities such as time
to use live traffic conditions or populate
and directions
to generate driving directions to each nearby facility.
Code examples
Direct: Find closest grocery stores
In this example, use the Closest facility service to find the three closest grocery stores from a start location and find the best routes to visit the stores.
To find the closest grocery stores, you need to define all grocery stores as facilities
, and a start location, for example an address or your current GPS location as incidents
. The default
value is set to 3 so that the service will find three closest grocery stores from the current location instead of one. You set return
to true
to get the best routes to the closest grocery stores. In order to determine which three grocery stores are nearest from the list of all available grocery stores, you should set the return
to true
so that you can correlate the chosen grocery stores from the returned facilities and routes.
The response contains the best routes to the three closest grocery stores as well as all the grocery stores provided as input. In order to find the three closest grocery stores, you can match the Facility
field in routes
with the Object
field in facilities
.
APIs
function findClosestFacility(startFeature, facilityFeatures) {
const params = new ClosestFacilityParameters({
incidents: new FeatureSet({
features: [startFeature],
}),
facilities: new FeatureSet({
features: facilityFeatures.toArray(),
}),
returnRoutes: true,
returnFacilities: true,
defaultTargetFacilityCount: 3,
});
const url = "https://route-api.arcgis.com/arcgis/rest/services/World/ClosestFacility/NAServer/ClosestFacility_World";
closestFacility.solve(url, params).then(
(results) => {
showRoutes(results.routes);
},
(error) => {
console.log(error.details);
}
);
}
REST API
curl https://route-api.arcgis.com/arcgis/rest/services/World/ClosestFacility/NAServer/ClosestFacility_World/solveClosestFacility? \
-d "f=json" \
-d "token=<ACCESS_TOKEN>" \
-d "facilities={'spatialReference':{'latestWkid':3857,'wkid':102100},'features':[{'geometry':{'x':-13656100.72194608,'y':5703897.952531632},'attributes':{'Name':'Downtown Grocery, 310 SW 4th Ave, Portland, OR, 97204, USA'}},{'geometry':{'x':-13657081.446659965,'y':5704279.273731899},'attributes':{'Name':'Whole Foods Market, 1210 NW Couch St, Portland, OR, 97209, USA'}},{'geometry':{'x':-13654900.697835328,'y':5704360.306582605},'attributes':{'Name':'Pacific Coast Fruit Company, 201 NE 2nd Ave, Portland, Oregon, 97232'}},{'geometry':{'x':-13654793.831124166,'y':5703907.485363393},'attributes':{'Name':'Nicky USA, 223 SE 3rd Ave, Portland, OR, 97214, USA'}},{'geometry':{'x':-13654829.453361219,'y':5703721.596977669},'attributes':{'Name':'Alexis Foods, 215 SE Stark St, Portland, OR, 97214, USA'}},{'geometry':{'x':-13654680.285243554,'y':5703712.064344136},'attributes':{'Name':'Sheridan Fruit Company, 408 SE Martin Luther King, Portland, OR, 97214, USA'}},{'geometry':{'x':-13654723.699844966,'y':5703513.470124055},'attributes':{'Name':'Graziano Food Services, 302 SE Washington St, Portland, OR, 97214, USA'}},{'geometry':{'x':-13654781.585980177,'y':5703484.872919755},'attributes':{'Name':'Rinella Produce, 231 SE Alder St, Portland, OR, 97214, USA'}}]}" \
-d "incidents={'spatialReference':{'latestWkid':3857,'wkid':102100},'features':[{'geometry':{'x':-13656119.041436872,'y':5703857.952531632},'attributes':{'Name':'322 SW 4th Ave, Portland, OR, 97204, USA'}}]}" \
-d "defaultTargetFacilityCount=3" \
-d "returnFacilities=true" \
-d "returnCFRoutes=true"
Job: Find closest fire stations
In this example, you will find the two fire stations that can provide the quickest response to a fire at a given address. You will also generate routes and driving directions for the firefighters.
All the fire stations in the neighborhood are specified as the facilities
parameter, and the location of the fire is specified as the incidents
parameter. To include the name of the fire station in the driving directions, you should specify Name
field in the facilities
. Because you want to model the fire engines traveling from the stations to the location of the fire, you specify Facility to Incident
as the value for the travel
parameter. You need to find the two closest fire stations within five minutes of the fire, so specify 2
as the value for the number
parameter and 5
as the value for the cutoff
parameter. You need to calculate the best routes that account for the current traffic conditions, so specify the current time in milliseconds since epoch as the time
parameter and specify Start Time
as the time
parameter. Specify populate
parameter in order to generate the driving directions.
APIs
# Connect to the closest facility service
api_key = "YOUR_ACCESS_TOKEN"
arcgis.GIS("https://www.arcgis.com", api_key=api_key)
# Call the closest facility service
result = arcgis.network.analysis.find_closest_facilities(facilities=facilities,
incidents=incidents,
number_of_facilities_to_find=2,
cutoff=5,
travel_direction="Facility to Incident",
time_of_day=datetime.datetime.utcnow(),
time_of_day_usage="Start Time",
populate_directions=True
)
print_result(result)
REST API
Unlike Direct request type which allows you to make a request and get back all the results in the response, when working with a Job request type, you need to follow a three step workflow:
- Make the
submit
request with the appropriate request parameters to get a job id.Job - Using the job id, check the job status to see if the job completed successfully.
- Use the job id to get one or more results.
curl https://logistics.arcgis.com/arcgis/rest/services/World/ClosestFacility/GPServer/FindClosestFacilities/submitJob? \
-d "f=json" \
-d "token=<ACCESS_TOKEN>" \
-d "facilities={'displayFieldName':'','fieldAliases':{'OBJECTID':'OBJECTID','Address':'Address','Name':'Name'},'geometryType':'esriGeometryPoint','spatialReference':{'wkid':2913,'latestWkid':2913},'fields':[{'name':'OBJECTID','type':'esriFieldTypeOID','alias':'OBJECTID'},{'name':'Address','type':'esriFieldTypeString','alias':'Address','length':38},{'name':'Name','type':'esriFieldTypeString','alias':'Name','length':255}],'features':[{'attributes':{'OBJECTID':1,'Address':'5247 N LOMBARD ST','Name':'Station 26 - Portsmouth/University Park'},'geometry':{'x':7633115.889,'y':706174.192}},{'attributes':{'OBJECTID':2,'Address':'8720 SW 30TH AVE','Name':'Station 18 - Multnomah Village'},'geometry':{'x':7635782.577,'y':662289.687}},{'attributes':{'OBJECTID':3,'Address':'5211 SE MALL ST','Name':'Station 25 - Woodstock'},'geometry':{'x':7661431,'y':672359.313}},{'attributes':{'OBJECTID':4,'Address':'7134 N MARYLAND AVE','Name':'Station 08 - Kenton'},'geometry':{'x':7643794.792,'y':703290.389}},{'attributes':{'OBJECTID':5,'Address':'511 SW COLLEGE ST','Name':'Station 04 - Portland State University'},'geometry':{'x':7642550.5,'y':679519.813}},{'attributes':{'OBJECTID':6,'Address':'1920 SW SPRING ST','Name':'Station 15 - Portland Heights'},'geometry':{'x':7638483.5,'y':679335.625}},{'attributes':{'OBJECTID':7,'Address':'7205 N ALTA AVE','Name':'Station 22 - St. Johns'},'geometry':{'x':7624439.852,'y':709314.646}},{'attributes':{'OBJECTID':8,'Address':'5540 NE SANDY BLVD','Name':'Station 28 - Rose City/Hollywood'},'geometry':{'x':7662615.362,'y':690552.356}},{'attributes':{'OBJECTID':9,'Address':'1500 SE 122ND AVE','Name':'Station 07 - Mill Park'},'geometry':{'x':7679927.014,'y':679567.305}},{'attributes':{'OBJECTID':10,'Address':'2915 SE 13TH PL','Name':'Station 23'},'geometry':{'x':7650264.798,'y':676428.937}},{'attributes':{'OBJECTID':11,'Address':'1905 NE KILLINGSWORTH ST','Name':'Station 14 - Alberta Park'},'geometry':{'x':7652607.5,'y':698666.187}},{'attributes':{'OBJECTID':12,'Address':'3130 NW SKYLINE BLVD','Name':'Station 27 - Forest Heights'},'geometry':{'x':7622995.190,'y':692838.978}},{'attributes':{'OBJECTID':13,'Address':'55 SW ASH ST','Name':' Station 01 - Old Town'},'geometry':{'x':7645808.735,'y':683815.505}},{'attributes':{'OBJECTID':14,'Address':'1715 SW SKYLINE BLVD','Name':'Station 16 - Sylvan'},'geometry':{'x':7628988.073,'y':680269.34}},{'attributes':{'OBJECTID':15,'Address':'3660 NW FRONT AVE','Name':'Station 06 - NW Industrial'},'geometry':{'x':7637036.822,'y':693920.006}},{'attributes':{'OBJECTID':16,'Address':'926 NE WEIDLER ST','Name':' Station 13 - Lloyd District'},'geometry':{'x':7649727.5,'y':688199.5}},{'attributes':{'OBJECTID':17,'Address':'2235 SE BYBEE BLVD','Name':'Station 20 - Sellwood/Moreland'},'geometry':{'x':7652687.5,'y':666304.5}},{'attributes':{'OBJECTID':18,'Address':'848 N TOMAHAWK ISLAND DR','Name':'Station 17 - Hayden Island'},'geometry':{'x':7645359.5,'y':715887.625}},{'attributes':{'OBJECTID':19,'Address':'4515 N MARYLAND AVE','Name':'Station 24 - Overlook/Swan Island'},'geometry':{'x':7643391.5,'y':696263.312}},{'attributes':{'OBJECTID':20,'Address':'13310 SE FOSTER RD','Name':'Station 29 - Powellhurst Fire Station'},'geometry':{'x':7682355,'y':666334.813}},{'attributes':{'OBJECTID':21,'Address':'1505 SW DEWITT ST','Name':'Station 05 - Hillsdale'},'geometry':{'x':7639618,'y':668875.813}},{'attributes':{'OBJECTID':22,'Address':'1706 SE CESAR E CHAVEZ BLVD','Name':'Station 09 - Hawthrone District'},'geometry':{'x':7658078.428,'y':679407.82}},{'attributes':{'OBJECTID':23,'Address':'4800 NE 122ND AVE','Name':'Station 02 - Parkrose'},'geometry':{'x':7680485.5,'y':695991.688}},{'attributes':{'OBJECTID':24,'Address':'1715 NW JOHNSON ST','Name':'Station 03 - Northwest Pearl District'},'geometry':{'x':7641263,'y':686484.063}},{'attributes':{'OBJECTID':25,'Address':'8645 NE SANDY BLVD','Name':'Station 12 - Sandy Blvd'},'geometry':{'x':7670903.955,'y':695130.753}},{'attributes':{'OBJECTID':26,'Address':'451 SW TAYLORS FERRY RD','Name':'Station 10 - Burlingame'},'geometry':{'x':7642023.5,'y':662635.312}},{'attributes':{'OBJECTID':27,'Address':'7301 E BURNSIDE ST','Name':'Station 19 - Mt. Tabor'},'geometry':{'x':7667098.674,'y':683759.966}},{'attributes':{'OBJECTID':28,'Address':'13313 NE SAN RAFAEL ST','Name':'Station 30 - Gateway'},'geometry':{'x':7683049.5,'y':688545.938}},{'attributes':{'OBJECTID':29,'Address':'5707 SE 92ND AVE','Name':'Station 11 - Lents'},'geometry':{'x':7671504,'y':668305.312}},{'attributes':{'OBJECTID':30,'Address':'5 SE MADISON ST','Name':'Station 21 - Eastbank/Hawthrone'},'geometry':{'x':7646356.982,'y':680651.469}},{'attributes':{'OBJECTID':31,'Address':'1927 SE 174TH AVE','Name':'Station 31 - Rockwood'},'geometry':{'x':7693238.495,'y':677792.48}}]}" \
-d "incidents={'displayFieldName':'','fieldAliases':{'OBJECTID':'OBJECTID','Name':'Name'},'geometryType':'esriGeometryPoint','spatialReference':{'wkid':2913,'latestWkid':2913},'fields':[{'name':'OBJECTID','type':'esriFieldTypeOID','alias':'OBJECTID'},{'name':'Name','type':'esriFieldTypeString','alias':'Name','length':500}],'features':[{'attributes':{'OBJECTID':1,'Name':'1020 SE 7th Ave, Portland, Oregon, 97214'},'geometry':{'x':7648955.177,'y':681403.651}}]}" \
-d "number_of_facilities_to_find=2" \
-d "cutoff=5" \
-d "travel_direction=Facility to Incident" \
-d "time_of_day=1611676800000" \
-d "time_of_day_usage=Start Time" \
-d "populate_directions=true"
Response (JSON)
{
"jobId": "j0c8bcdb041584d9f8e54243a23ea27f3",
"jobStatus": "esriJobSubmitted"
}