Skip To Content

Find closest facility

In this topic

Closest facility analysis measures the cost of traveling on a network between incidents and facilities and determines which facilities are nearest (according to travel cost) for each incident. When finding closest facilities, you can specify how many to find for each incident and whether the direction of travel is toward or away from them. The ArcGIS Runtime SDK ClosestFacilityTask enables you to display the best routes between incidents and facilities, report their travel costs, and return driving directions.

Routes between incidents and the closest facility

Define closest facility parameters

When finding the closest facility, you use ClosestFacilityParameters to specify the required input incidents and facilities. You can also define preferences or constraints, like a cutoff cost beyond which the task will not search for facilities. For instance, you can set up a closest facility task to search for hospitals within a 15-minute drive of the site of an accident. Any hospitals that take longer than 15 minutes to reach are not included in the results. In this example, the hospitals are facilities, and the accident is the incident. You can also perform multiple closest facility analyses simultaneously. In other words, you can have multiple incidents and find the closest facility (or facilities) for each incident.

The following lists some of the available parameters you can specify for input to a closest facility task.

  • Facilities (required): points on the network that represent facilities.
  • Incidents (required): points on the network for which a nearest facility (or facilities) will be found.
  • Impedance attribute: the name of an attribute in the network dataset that describes impedance to travel (travel time, for example).
  • Route barriers: points, lines, or polygons that act as barriers to travel on the network.
  • Default cutoff: a maximum impedance (cost) to accumulate in search of a facility.
  • Travel direction: is travel from incident to facility or facility to incident.
  • Results to return: routes, directions, facilities, and incidents can be included with the results.
  • Result line type: the result route shapes - straight lines between incidents and facilities, the true shape of the route, true shape with measures, and so on.

The following example creates a new ClosestFacilityParameters and sets properties to define inputs and preferences for a find closest facilities task.

// build parameter values to use for a closest facility task
var findClosestFacilityParams = new ClosestFacilityParameters(); 

// specify the points that represent the facilities
findClosestFacilityParams.SetFacilities(facilitiesWgs);
// define the points that represent the features that need to find a facility ("incidents")
findClosestFacilityParams.SetIncidents(incidentsWgs);
// set the attribute that determines travel impedance along the route (speed limit, time, etc.)
findClosestFacilityParams.ImpedanceAttributeName = "TravelTime";
// define an output spatial reference to match the current map view
findClosestFacilityParams.OutSpatialReference = MyMapView.SpatialReference;
// set 10 (minutes) as the network cost cutoff (travel time) for finding a facility
findClosestFacilityParams.DefaultCutoff = 10.0;

The network service defines default values for many of these parameters. Instead of defining new parameters, you can get the default parameters from a ClosestFacilityTask. You can then make changes to any of the properties you would like to change.

// get the default parameters defined with the service (rather than creating them new)
var findClosestFacilityParams = await findClosestFacility.GetDefaultParametersAsync();

// define facilities and incidents
findClosestFacilityParams.SetFacilities(facilitiesWgs);
findClosestFacilityParams.SetIncidents(incidentsWgs);
// define an output spatial reference to match the current map view
findClosestFacilityParams.OutSpatialReference = MyMapView.SpatialReference;
Tip:

If no facilities are found when executing your closest facility task, take a closer look at the default cutoff value in the parameters. This is the value that defines the maximum travel cost to use when searching for facilities. If not defined for the service, the value will default to zero, which means a maximum cost (travel time, for example) of 0 will be used to search for facilities. Although a cutoff can be defined for individual incidents, the task uses the default value if it is smaller. To ensure the search works as expected, you may want to provide a larger value for the default cutoff.

Solving for closest facilities

You create a new ClosestFacilityTask by pointing it to an online network service that can solve for closest facilities. Create the input parameters as shown in the preceding section, add a set of input points to represent facilities on the network, and another to represent incidents. The result of solving the task will include information about nearby facilities for each incident, which may include a route, driving directions, and the travel cost (depending on how you defined the task parameters).

The following example uses an online network service for San Diego to find the closest facility for a set of incidents.

// base url to an online network service
var onlineNetworkService = "http://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/";
// append "ClosestFacility" to the base url to use closest facility functionality 
var closestFaclityService = onlineNetworkService + "ClosestFacility";

// create an Esri.ArcGISRuntime.Tasks.NetworkAnalyst.ClosestFacilityTask based on the url
var findClosestFacility = new ClosestFacilityTask(new Uri(closestFaclityService));

// build the parameter values to use for the task
var findClosestFacilityParams = new ClosestFacilityParameters(); 
// ... the attribute that determines travel impedance along the route (speed limit, time, etc.)
findClosestFacilityParams.ImpedanceAttributeName = "TravelTime";
// ... the points that represent the facilities
findClosestFacilityParams.SetFacilities(facilitiesWgs);
// ... the points that represent the features in search of a facility ("incidents")
findClosestFacilityParams.SetIncidents(incidentsWgs);
// ... the output spatial reference (match the current map view)
findClosestFacilityParams.OutSpatialReference = MyMapView.SpatialReference;
// ... the maximum impedance value (TravelTime) for searching on the network
findClosestFacilityParams.DefaultCutoff = 10.0;

try
{
    // solve the closest facility problem with these parameters
    var findClosestResult = await findClosestFacility.SolveAsync(findClosestFacilityParams);
    // process the results
				foreach (var route in findClosestResult.Routes)
    {
        var feature = route.RouteFeature;
        var directions = route.RouteDirections;
        var travelTime = route.TotalTime;
        // ... display route graphic, directions, travel time, etc. for each route
    }
}
catch (Exception ex)
{
    // Note: an exception is raised if no facilities are found for any of the incidents
    // (try increasing the default cutoff value or check the spatial reference of input points)
}
Caution:

An ArcGISWebException is thrown if no facilities are found for any of the input incidents. The exception message will indicate "Error code '400' : 'Unable to complete operation.'". You should trap for this exception and handle it appropriately, especially in situations where not finding closest facilities is an acceptable outcome.