Service Area Task
A Service Area task allows you to calculate areas that can be serviced (reached) from a given location using ArcGIS Network Analyst services.
A Network Analyst service contains one or more Network Analysis layers. ArcGIS provides different types of analysis layers, such as Route, Service Area, Closest Facility, etc depending upon the type of analysis to be performed. A Service Area task relies on a Service Area analysis layer.
Learn about creating Network Analyst services
Creating a Service Area task
To instantiate a Service Area task, you need to provide a URL to REST resource that represents a Service Area layer in a Network Analyst service. If the service is secured, you will also need to provide the credentials that can be used to access the service. The following code snippet shows how to create a Sevice Area task for the Service Area layer in the USA service on ArcGIS Online sample server.
NSURL* url = [NSURL URLWithString: @"http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Network/USA/NAServer/Service%20Area";
AGSServiceAreaTask* saTask = [[AGSServiceAreaTask alloc] initWithURL: url];
When you create the task, you need to ensure you take ownership of it. Otherwise, its memory might get deallocated before it has a chance to execute. If you instantiate the task using alloc as shown above , you automatically have ownership. However, if you instantiate the task using a convenience constructor, for instance serviceAreaTaskWithURL: , you explicitly need to take ownership by either sending it a retain message, or by assigning it to a property that will retain it.
When you are finished using the task, you should relinquish ownership so that its memory can be reclaimed. You do this either by sending the task a release message or by setting the corresponding property to nil.
Please refer to Apple's Memory Management Programming Guide for more information on how to manage object memory.
Preparing the input
You provide input to the Service Area task using an object of AGSServiceAreaTaskParameters class. You can instantiate a new AGSServiceAreaTaskParameters object and modify its properties to provide the input. But many times, you may want to calculate service areas using the defaults specified in the service. In such cases, you first need to invoke retrieveDefaultServiceAreaTaskParameters on AGSServiceAreaTask to get the default values. The default values are returned to the task's delegate as an AGSServiceAreaTaskParameters object via the serviceAreaTask:operation:didRetrieveDefaultServiceAreaTaskParameters: method.
The following sections describe some of the inputs you can provide to a Service Area task.
Impedance
Impedance specifies a cost that is used to constrain the service area. For example, impedance could be set to Time in order to calculate a service area that encompasses all accessible streets within that time interval. Or it could be set to Length to calculate a service area that encompassess all streets reachable within that distance. Impedances supported by the service are listed in the Services Directory under Network Dataset -> Network Attributes with a Usage Type of esriNAUTCost
In the example shown above, Length and Time are supported impedances. The following code snippets sets the impedance to Time .
AGSServiceAreaTaskParameters* params = ...;
params.impedanceAttributeName = @"Time";
Breaks
Breaks specify the quantity of the impedance to apply. They constrain the extent of the service area to be calculated. For example, if you apply breaks of 5, 10, and 15 when the impedance is set to Time, the service area will include all those streets than can be reached within 5, 10, and 15 minutes.
NSMutableArray* breaks = [[[NSMutableArray alloc] init] autorelease];
[breaks addObject:[NSNumber numberWithInt:5]];
[breaks addObject:[NSNumber numberWithInt:10]];
[breaks addObject:[NSNumber numberWithInt:15]];
params.defaultBreaks = breaks;
The breaks you specify in the defaultBreaks property are applied to all facilities that don't contain their own breaks. If you are computing service areas for a number of facilities in a batch, you can provide different breaks for each facility by setting their attributes accordingly.
Facilities
Facilities represent locations from which service areas need to be calculated. For eg, a fire station could be set as a facility to find which areas it can serve within a 10 minute service area. A hospital could be set as the facility to find out what proprotion of the population is within a 2 mile driving distance.
There are two ways to specify facilities:
Features
You can create an array of AGSFacilityGraphic objects representing facility features. You can then assign these features to the parameter object using setFacilitiesWithFeatures:. You need to minimally provide a name and a point geometry for each facility, but you can also provide additional attributes depending upon how the Service Area layer in the Network Analyst service is configured. These attributes are listed in the Network Analysis Classes -> Class Name:Facilities section of the Services Directory.
Attributes may be of type input, output, or both. Input attributes are specified by the client and are taken into consideration by the service while performing the analysis. For example, you can set breaks on each facility if you want to compute different service areas for different facilities. The attribute should have a name Breaks_<Impedance> where <impedance> is the value specified in the impedance property. For example, an attribute of name Breaks_Time with a value of "5 10 15" specifies service areas of 5, 10, and 15 mintues intervals. If the attribute is not specified, the defaultBreaks property is used to calculate service areas for the facility.
Output attributes are returned by the service along with the computed result when you enable returnFacilities on AGSServiceAreaTaskParameters. Output attributes provide additional information about facilities pertaining to the results.
Some attributes can be both Input and Output. These attributes are specified by the client but can be modified or overriden by the service.
Learn more about attributes supported by facility features.
The symbol and infoTemplateDelegate properties on AGSFacilityGraphic are relevant only if you add the facilities to a graphics layer in order to display them on a map. They are not used in the analysis.
Layer Definition
Apart from specifying facilities by-value (i.e providing the actual values for each feature as described above), you can also specify them by-reference. This is useful when you already have a set of well known or commonly used facilities stored along with the Network Analyst service. In such cases, the application does not need to know the actual details about each facility. All it needs to do is set up a layer definition specifiying which facilities should be included in the analysis.
A layer definition is represented by an object of the AGSNALayerDefinition class. You can use SQL statements and/or Spatial relationships to specify which faciliteis should be used in the analysis. For example, the following code snippets sets up a layer definition referencing features that fall within the City of Los Angeles and have a value of "Hospital" for the facility_type attribute.
AGSNALayerDefinition* layerDef = [[[AGSNALayerDefinition alloc] init] autorelease];
layerDef.layerName = @"<layer_in_the_service_containing_facilities>";
layerDef.where = @"facility_type = 'Hospital'";
layerDef.geometry = losangelesPolygon;
layerDef.spatialRelationship = AGSSpatialRelationshipContains ;
Once you have set up a layer definition identifying the features you wish to use, you can use it to specify facilities using setFacilitiesWithLayerDefinition:method on an AGSServiceAreaTaskParameters object.
[params setFacilitiesWithLayerDefinition: layerDef];
Restrictions
Restrictions allow you to place constraints on the analysis. For example, you can specify that the service area should avoid toll roads. If the analysis is for an emergency vehicle, you can specify that rules governing one-way streets should be relaxed. The restrictions supported by the service are listed in the Services Directory under Network Dataset -> Network Attributes with a Usage Type of esriNAUTRestriction
The following code snippet applies restrictions in order to avoid passenger ferries and toll roads.
params.restrictionAttributeNames = [NSArray arrayWithObjects:@"Avoid Ferries",@"Avoid Toll Roads",nil];
Barriers
Barriers represent ad-hoc restrictions that must be taken into consideration when calculating a service area. A barrier can specify a set of roads or a region that must be completely avoided. For example, a bridge that may be closed due to construction work. Some barriers may permit travel through them albeit at an added cost. For example, an accident on a freeway may temporarily slow down the traffic. This can be represented by a barrier that allows travel along the freeway but increases the travel time required.
Just as with facilities, there are two ways to specify barriers:
Features
You can create an array of AGSGraphic objects representing barrier features. You need to provide these features a geometry representing the location and shape of the barrier. The geometry can be a Point, Polyline, or a Polygon. You can then assign these barrier features to the parameter object using setPointBarriersWithFeatures:, setPolylineBarriersWithFeatures: , or setPolygonBarriersWithFeatures: depending upon the type of geometry that was assigned to the feature.
You need to create separate arrays for point, polyline, and polygon barriers.
A barrier can also have additional attributes depending upon how the Service Area layer in the Network Analyst service is configured. These attributes are listed in the Network Analysis Classes -> Class Name:Barriers, PolylineBarriers, PolygonBarriers section of the Services Directory. Attributes may be of type input (specified by the client), output (returned by the server), or both.
Layer Definition
Apart from specifying barriers by-value (i.e providing the actual values for each feature as described above), you can also specify barriers by-reference. This is useful when you already have a set of well known or commonly used barriers stored along with the Network Analyst service. For instance, the Transportation Department of a city could provide a Network Analyst service containing information about barriers representing the most recent traffic conditions, incidents, construction work, etc. In such cases, the application does not need to know the actual details about each barrier. All it needs to do is set up a layer definition specifiying which barriers should be included in the analysis.
Once you have a setup a layer definition identifying the features you wish to use, you can use it to specify barriers using setPointBarriersWithLayerDefinition:, setPolylineBarriersWithLayerDefinition:, or setPolygonBarriersWithLayerDefinition: methods on an AGSServiceAreaTaskParameters object
U-Turn policy
You can specify if U-turns are allowed everywhere (AGSNAUTurnAllowBacktrack), nowhere (AGSNAUTurnNoBacktrack), only at dead ends (AGSNAUTurnAtDeadEndsOnly), or only at intersections and dead ends (AGSNAUTurnAtDeadEndsAndIntersections). Allowing U-turns implies the vehicle can turn around at a junction and double back on the same street.
The following code snippet allows U-turns only at dead ends and intersections :
params.uTurns = AGSNAUTurnAtDeadEndsAndIntersections ;
Travel Direction
You can choose to create a service area by accumulating impedance in the direction away from or toward the facility. On a network with one-way restrictions and different impedances based on direction of travel, this would result in different service areas. The direction you should choose depends on the nature of your service area analysis. The service area for a pizza delivery store, for example, should be created away from the facility since pizzas are delivered from the store to the customer. Alternatively, a hospital should choose the opposite direction since the urgent part of the trip for an incoming patient is going to the hospital, not returning home afterwards.
params.travelDirection = AGSNATravelDirectionToFacility ;
Result options
Polygon options
You can choose to generate service areas as detailed or simplified polygons by setting the outputPolygons property on AGSServiceAreaTaskParameters. Detailed polygons take significantly longer to generate but more accurately represent the service area. Simplified polygons can be generated quickly and are reasonably accurate, except at the outer edges. If your data is of an urban area with a gridlike network, the difference between generalized and detailed polygons would be minimal. However, for mountain and rural roads, the detailed polygons may present significantly more accurate results than generalized polygons.
If you use more than one break for generating service areas, you can choose to create concentric service area polygons as disks or rings by setting the splitPolygonsAtBreaks property. Rings are created when you set the property to YES. Rings do not include the area of smaller breaks. This creates polygons going between consecutive breaks. Disks are polygons going from a facility to a break. If you create 5- and 10-minute service areas, then the 10-minute service area polygon will include the area under the 5-minute service area polygon as well as the area from the 5-minute to the 10-minute break.
If you include multiple facilities in the analysis, you can also choose to generate overlapping or non-overlapping polygons by setting the overlapPolygons property. You can also choose to join the polygons of multiple facilities that have the same break values by setting the mergeSimilarPolygonRanges property.
Line options
You can also choose to generate service areas as lines instead of, or in addition to, polygons by setting the outputLines property on AGSServiceAreaTaskParameters. Lines can be straight or true shape. Straight lines are based on " as the crow flies" directions whereas true shape lines follow the underlying transportation network.
Just as with polygons, you can choose to split lines that span multiple breaks by setting the splitLinesAtBreaks property. You can also choose to generate overlapping or non-overlapping lines by setting the overlapLines property.
Geometry options
You can request for the geometry of the service areas to be generalized by modifying the outputGeometryPrecision and outputGeometryPrecisionUnits properties on AGSServiceAreaTaskParameters. Generalizing a geometry removes vertices that add more detail beyond the precision you specify. Removing vertices makes the geometry smaller thus saving time needed to transfer the geometry over the network and also faster to draw as a map graphic.
You can also request the geometry to be projected into a coordinate system of your choice by setting the outSpatialReference property of AGSServiceAreaTaskParameters. This may be useful if the spatial reference of your map is different from the spatial reference of the service. If you do not specify an outSpatialReference , the geometries are returned in the spatial reference of the service by default.
Calculating service areas
Once you have set up the input parameters, calculating service areas is as simple as invoking solveServiceAreaWithParameters: on AGSServiceAreaTask and passing in the AGSServiceAreaTaskParameters object to use in the calculation.
NSOperation* op = [saTask solveServiceAreaWithParameters:params];
Retrieving results and Handling errors
The Service Area task informs its delegate when operations complete successfully or when errors are encountered. To get results from the task and to properly handle any errors, you must set one of your classes as the task's delegate. You do this by making your class (typically the view controller which uses the task) adopt the AGSServiceAreaTaskDelegate protocol.
@interface MyViewController : UIViewController <AGSServiceAreaTaskDelegate> {
...
}
An instance of your class must also be set as the task's delegate. This will allow the task to invoke methods on your class in response to operations that the task performs.
saTask.delegate = self;
Finally, your class should implement one ore more methods defined in the protocol which pertain to the operation being performed. There are a pair of methods for every type of operation - one for success and the other for failure. For instance, the delegate should implement serviceAreaTask:operation:didSolveServiceAreaWithResult: method for when the operation completes successfully. Results are passed to the delegate method as an AGSServiceAreaTaskResult object.
- (void) serviceAreaTask:(AGSServiceAreaTask*)serviceAreaTask operation:(NSOperation*)op didSolveServiceAreaWithResult:(AGSServiceAreaTaskResult*) serviceAreaTaskResult{
//process the results
}
An AGSServiceAreaTaskResult object represents the results of the operation. It contains
- An array of polygons and/or lines representing the service areas
- An array of graphics representing the facilities used in the analysis (if you enabled returnFacilities on AGSServiceAreaTaskParameters). Each graphic contains attributes that correspond to facility properties. These properties provide valuable information about the facility as it pertains to the computed service areas.
The AGSServiceAreaTaskResult object also contains an array of messages providing information about any warnings or errors encountered while calculating the service areas.
It is a good practice to inspect the messages, atleast during developement, as it could help troubleshoot any potential problems.
The delegate should also implement the serviceAreaTask:operation:didFailSolveWithError: method in order to be informed when an error is encountered. The error is passed into the method as an NSError object.
- (void) serviceAreaTask:(AGSServiceAreaTask*)serviceAreaTask operation:(NSOperation*)op didFailSolveWithError:(NSError*) error{
NSLog(@"Error: %@",error);
}