Geometry Operations
Geometry Objects are an excellent way to visualize the shapes and locations of elements on a map. However you might want to do more than simply display geometric shapes. For example, you may want to measure the area of a polygon representing a lake or district. Perhaps you have multiple geometries, and you want to know their relationship to one another. The API includes two ways to perform geometric operations on your geometry objects.
Geometry Engine
The geometry engine performs geometric operations, such as measuring distance, determining spatial relationships, and altering geometries all locally on the device. The geometry engine is a singleton class much like UIApplication. A singleton is a class for which there exists only a single instantiated object. Thus, each time you call defaultGeometryEngine you are returned a reference to the same instance.
AGSGeometryEngine *geometryEngine = [AGSGeometryEngine defaultGeometryEngine]
Measuring Distance
Often we want to know the length or area of a geometry. We may want to know the length of a river or the area of a county. There are a number of different ways to measure length and area using the Geometry Engine. You can measure simple distances and areas using the lengthOfGeometry: and areaOfGeometry: methods.
double length = [geometryEngine lengthOfGeometry:polyline];
double area = [geometryEngine areaOfGeometry:polygon
However if you are measuring large areas or distances that need to take into account the curvature of the earth. You should use methods such as geodesicLengthOfGeometry: inUnit: and shapePreservingAreaOfGeometry: inUnit:.
Spatial Relationships
When you have multiple geometries on a map you may want to know their relationship to each other. For example, you may want to know if a polyline representing a creek crosses through a polygon representing your property. Given two geometry objects the geometry engine can tell you whether a given spatial relationship is true of those geometries.
There are seven basic relationships the Geometry Engine support
- Contains
- Crosses
- Disjoint
- Intersects
- Overlaps
- Touches
- Within
For each spatial relationship there is a method, which returns a Boolean value indicating whether that relationship is true of the two geometries. For spatial relationships that are true of one geometry but not the other, such as Within or Contains, the Geometry Engine will consider the order of the geometries entered.
// Returns TRUE if geometry1 contains geometry2
BOOL contains = [geometryEngine geometry: geometry1 containsGeometry: geometry2];
Modifying Geometry Objects based on Topological Relationships
Geometry objects can also be modified in a number of different ways. When any of these operations are called a new geometry is returned with the modifications made.
There are ten operations supported in total.
- Buffer
- Clip
- Cut
- Densify
- Difference
- Offset
- Intersection
- Symmetric Difference
- Simplify
- Union
AGSGeometry *modifiedGeometry = [geometry unionGeometries:geometries];
Projecting to Different Spatial References
There may be times when you want to migrate geometries on a map with one spatial reference to another map, with a completely different spatial reference. The geometry engine allows you to do this with a simple method call. Like modifying geometry objects, the instance of the geometry object passed in is not actually changed, rather a new geometry object is returned.
// Spatial Reference you want to project to
AGSSpatialReference *sr = [AGSSpatialReference spatialReferenceWithWKID:4326];
AGSGeometry *newGeometry = [geometryEngine projectGeometry:oldGeometry toSpatialReference:sr];
Geometry Service Task
There may be some cases where the geometry engine does not provide support for all the operations you want to do. For example, if you want to perform a convex hull operation, or project to a very uncommon spatial reference that is not supported by the Geometry Engine. Refer to this document for a list of spatial reference systems supported by the engine.
In such cases you can use the geometry service task. The device must be able to connect to the network to perform a geometry service task. The geometry service task takes a URL to a geometry service e.g. http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer
AGSGeometryServiceTask *serviceTask = [AGSGeometryServiceTask geometryServiceTaskWithURL:serviceTaskURL ];
serviceTask.delegate = self;
Once you create an instance of a service task, you must set the class that will receive its results to be its delegate. Usually this is just self. This class must implement the geometry service class protocol. After an operation is performed it provides its results in its respective return method, or provides and error through its failure method.
-(void)geometryServiceTask:(AGSGeometryServiceTask*)geometryServiceTask
operation: (NSOperation*)op
didReturnConvexHullGeometry:(AGSGeometry*)geometry {
// Do something with geometry
}
- (void)geometryServiceTask:(AGSGeometryServiceTask*)geometryServiceTask
operation: (NSOperation*)op
didFailConvexHullWithError: (NSError*)error {
NSLog(@”Failed with error: %@”, error);
}