Geometries represent real-world objects by defining a shape at a specific geographic location. They are used throughout the API to represent the shapes of features and graphics, layer extents, viewpoints, and GPS locations. They are also used as inputs and outputs of spatial analysis and geoprocessing operations, and to measure distances and areas, among other uses.

The AGSGeometry class provides functionality common to all types of geometry. AGSPoint, AGSMultipoint, AGSPolyline, AGSPolygon, and AGSEnvelope all inherit from AGSGeometry, and represent different types of shapes.

The following are common geometry characteristics:

- Geometries have a spatial reference indicating the coordinate system used by its coordinates.
- Geometries can be empty, indicating that they have no specific location or shape.
- Geometries can have z-values and/or m-values.
- Geometries can be converted to and from JSON to be persisted or to be exchanged directly with REST services.

## Geometries are immutable

Most geometries are created and not changed for their lifetime. Examples include features created to be stored in a geodatabase or read from a non-editable layer, and features returned from tasks such as a spatial query, geocode operation, network trace, or geoprocessing task. Immutable geometries (geometries that cannot be changed) offer some important benefits to your app. They are inherently thread-safe, they help prevent inadvertent changes, and they allow for certain performance optimizations.

While immutable geometries appear to present problems for editing existing geometries, those problems are solved by using geometry builders. Geometry builders are designed to represent the state of a geometry under construction while allowing modifications, thus enabling editing workflows. Apple's Foundation framework follows a similar pattern of having separate mutable and immutable versions. Examples of these include NSDictionary, NSArray, NSData, and so on.

## Envelope

AGSEnvelope geometries represent rectangular shapes with sides that are parallel with the x or y axis of the coordinate system. Most commonly, they represent the spatial extent of layers or other geometries, or define areas of interest for tasks. They can be used as the geometry of graphics and in many geometry operations, although they cannot be used as the geometry of features.

New instances of AGSEnvelope are defined by specifying a minimum and maximum x-coordinate and minimum and maximum y-coordinate, and a AGSSpatialReference. Optionally, a minimum and maximum z-value can be specified to define the depth of the envelope.

```
// Create an Envelope using the minimum and maximum x,y coordinates and a Spatial Reference
let envelope = AGSEnvelope(xMin: -123.0, yMin: 33.5, xMax: -101.0, yMax: 48.0, spatialReference: AGSSpatialReference.wgs84())
```

Another way to define an envelope is by using two points. The minimum and maximum x,y coordinates are calculated from the two points.

```
// Create a Point using x,y coordinates and a Spatial Reference
let point1 = AGSPoint(x: -122, y: 34.5, spatialReference: AGSSpatialReference.wgs84())
let point2 = AGSPoint(x: -121, y: 35.5, spatialReference: AGSSpatialReference.wgs84())
// Create an Envelope by passing in two points
let envelope = AGSEnvelope(min: point1, max: point2)
```

## Point

AGSPoint geometries represent a single point, place, or location such as a geocoded house address in a neighborhood or the location of a water meter in a water utility network. Larger geographic entities such as cities can be represented as points on small-scale maps. Points can be used as the geometry of features and graphics and are often used to help construct other geometries. They are also used in AGSViewpoints.

Points store a single set of x,y coordinates that represent the coordinates of a location (longitude and latitude for example), and a AGSSpatialReference. Optionally, a z-value (representing things such as elevation for example) can also be included. Instances of AGSPoint can be created using constructors, which define the full geometry in a single call.

```
// Create a Point using x,y coordinates and a Spatial Reference
let point1 = AGSPoint(x: -122, y: 34.5, spatialReference: AGSSpatialReference.wgs84())
// Create a Point using x,y,z coordinates and a Spatial Reference
let point2 = AGSPoint(x: 34, y: -117, z: 414, spatialReference: AGSSpatialReference.wgs84())
```

##### Caution:

Remember when working with AGSPoint instances that have a geographic spatial reference, the x-coordinate is the longitude (east or west), and the y-coordinate is the latitude (north or south). When geographic coordinates are represented in strings, they are generally written using the form "(latitude, longitude)", where the y-coordinate comes before the x-coordinate. Latitude values south of the equator and longitude values west of the prime meridian are expressed as negative numbers.

You can use AGSCoordinateFormatter to convert a latitude, longitude formatted string directly to a AGSPoint, and also return a latitude, longitude formatted string from an existing AGSPoint. Other coordinate notations, such as Military Grid Reference System (MGRS) and United States National Grid (USNG) are also supported.

## Multipoint

AGSMultipoint geometries represent an ordered collection of points. They can be used as the geometry of features and graphics, or as input or output of geometry operations. For features that consist of a very large number of points that share the same set of attribute values, multipoints may be more efficient to store and analyze in a geodatabase compared to using multiple point features. LIDAR is an example of data that may use multipoints.

Multipoints are composed of a single read-only collection of AGSPoints. To build a AGSMultipoint, create an AGSMultipointBuilder, add points, and the geometry will return an AGSMultipoint.

```
// Create a MultipointBuilder and add Points
let multiPointBuilder = AGSMultipointBuilder(spatialReference: AGSSpatialReference.wgs84())
multiPointBuilder.points.addPointWith(x: -121, y: 38)
multiPointBuilder.points.addPointWith(x: -122, y: 47)
multiPointBuilder.points.addPointWith(x: -123, y: 44)
multiPointBuilder.points.addPointWith(x: -119, y: 39)
// Pass the Geometry from the MultipointBuilder to the MultiPoint
let multiPoint = multiPointBuilder.toGeometry()
```

To access each AGSPoint in an existing AGSMultipoint, iterate over the read only AGSPointCollection returned from points property.

```
let multiPoint = multiPointBuilder.toGeometry()
let points = multiPoint.points
for i in 0...points.count-1 {
print("Point x= ", points[i].x, " y= ", points[i].y)
}
```

Use the AGSMultipointBuilder to modify an existing multipoint.

## Polyline

AGSPolyline geometries represent the shape and location of linear features, for example, a street in a road network or a pipeline in an oil refinery. They can be used as the geometry of features and graphics, or as input or output of tasks or geoprocessing operations, such as the output of a network trace.

Polylines are composed of a series of connected segments, where each segment defines a continuous line between a start and an end point. You can also work with polylines by using point-based helper methods.

Create a AGSPolyline using an AGSPolylineBuilder. Add points, and this will create a series of straight AGSLineSegments connecting the points you specified.

```
// Create a Polyline Builder and add Points
let polylineBuilder = AGSPolylineBuilder(spatialReference: AGSSpatialReference.wgs84())
polylineBuilder.addPointWith(x: -121, y: 38)
polylineBuilder.addPointWith(x: -122, y: 47)
polylineBuilder.addPointWith(x: -123, y: 44)
polylineBuilder.addPointWith(x: -124, y: 46)
polylineBuilder.addPointWith(x: -125, y: 33)
let polyLine = polylineBuilder.toGeometry()
```

Polylines can have multiple parts. Each part is a series of connected segments, but the parts can be disjoint from each other, for example, in a polyline representing a discontinuous highway that has an unfinished section. Parts can also intersect at one or more vertices, for example, in a polyline representing a river and its tributaries. The AGSPolyline class inherits from AGSMultipart, which provides members for iterating through the segments and points of each part in a AGSPolyline.

To modify an existing polyline, use AGSPolylineBuilder.

## Polygon

AGSPolygon geometries represent the shape and location of areas, for example, a country or a lake. They can be used as the geometry of features and graphics, or as input or output of tasks or geoprocessing operations, such as the output of a drive-time analysis or a buffer operation.

Polygons are similar to polylines in that they are also composed of a series of connected segments. However, polygons define closed areas, so the end point of the last segment is always in the same location as the start point of the first segment, forming a closed boundary. As with polylines, you can work with the vertices of the segments of a polygon by using point-based helper methods.

To build an AGSPolygon, create an AGSPolygonBuilder and add points in the correct order around the polygon's perimeter. Next, use the toGeometry method to provide the AGSPolygon.

```
// Create a Polygon Builder and add Points
let polygonBuilder = AGSPolygonBuilder(spatialReference: AGSSpatialReference.wgs84())
polygonBuilder.addPointWith(x: -121, y: 38)
polygonBuilder.addPointWith(x: -122, y: 47)
polygonBuilder.addPointWith(x: -123, y: 44)
polygonBuilder.addPointWith(x: -124, y: 46)
polygonBuilder.addPointWith(x: -125, y: 33)
let polygon = polygonBuilder.toGeometry()
```

##### Tip:

When defining a polygon, there is no need to explicitly close it by repeating the start point as the last point. Polygons are always drawn as enclosed areas by ArcGIS Runtime. However, you may need to simplify a geometry to store it in a geodatabase.

To modify an existing polygon, use a AGSPolygonBuilder.

Similar to polylines, polygons can have multiple parts but have different rules than those for multipart polylines. Each part of a multipart polygon is a series of connected segments forming a closed ring. Each part must not cross any other part but may lie completely inside or outside another part. For example, a polygon representing the state of Hawaii would comprise eight disjoint parts, one representing each island. A polygon representing the country of South Africa, which completely surrounds the enclave of Lesotho, would comprise two parts, one contained inside the other. The AGSPolygon class also inherits from AGSMultipart.

## Multipart (Polygon and Polyline)

AGSPolygon and AGSPolyline inherit from AGSMultipart, which in turn inherits from AGSGeometry. Multipart provides access to the geometry's AGSPartCollection. Each AGSPart in the collection is a collection of AGSSegment objects. You can iterate through the segments or points in each part.

```
let polyLine = polylineBuilder.toGeometry()
let parts = polyLine.parts
// iterate each Part of a Polyline
for i in 0...parts.count-1 {
let part = parts[i]
// iterate each Segment in the Part
for k in 0...part.segmentCount-1 {
let segment = part.segment(at: k)
print(segment.startPoint.x)
print(segment.endPoint.x)
}
}
```

You can iterate through the points that represent the vertices in all the parts.

```
let parts = polyLine.parts
// iterate each Part of a Polyline
for i in 0...parts.count-1 {
let part = parts[i]
// iterate each Point in the Part
for j in 0...part.points.count-1 {
print("Point x= ", part.points[j].x, " y= ", part.points[j].y)
}
}
```

In the same way as AGSPolygons and AGSPolylines are immutable, the collections returned from AGSMultipart are also immutable—AGSPartCollection, AGSPart, and AGSPointCollection. However, when creating polygons and polylines, you use the mutable equivalents—AGSMutablePartCollection, AGSMutablePart, and AGSMutablePointCollection. Point-based helper methods are available on both the mutable and immutable classes.

### Segments

A segment describes a continuous line between a start location and an end location. Every part in a multipart geometry is a collection of AGSSegments where the end of one segment is at exactly the same location as the start of the following segment. The ArcGIS system supports both straight and curved segments, but at the current release, only straight AGSLineSegments are supported in ArcGIS Runtime SDK. Multipart geometries can be composed from and decomposed into segments if required; until true curves are supported fully, using point-based methods offers equal functionality.

Because a single location is shared by adjacent segments, a single AGSPoint object is used to represent the shared location when you iterate through the points in a part. As a result, when iterating through the points in a part of a polyline, there will be one more AGSPoint than the number of AGSSegments in that same part.

```
let parts = polyLine.parts
// iterate each Part of a Polyline
for i in 0...parts.count-1 {
let part = parts[i]
print(part.pointCount)
print(part.segmentCount)
}
```

Similar to the geometries they comprise, AGSSegments are immutable.

## Other aspects of geometries

### Spatial references

The meaning of the coordinates in a geometry is determined by the geometry's spatial reference. The vertices and spatial reference together allow your app to translate a real-world object from its location on the Earth to its location on your map.

In some cases, a geometry's spatial reference may not be set. Graphics that do not have a spatial reference are drawn using the same spatial reference as the AGSMapView in which they are drawn. When using a geometry builder to create a polyline or polygon geometry from point geometries, you don't need to set the spatial reference of every point before you add it to the builder, as it will be assigned the spatial reference of the builder it's added to. In most other cases, such as when using a geometry in geometry operations or when editing a feature table, the geometry's spatial reference must be set.

### Projection, topological, and other operations

Changing the coordinates of a geometry to have the same shape and location represented using a different spatial reference is known as "projection" or sometimes as "reprojection". Because geometries are immutable, they do not have any member methods that project, transform, or otherwise modify their content.

The AGSGeometryEngine class provides a wide range of methods that read the content of geometries and modify that content to create new geometries. There are methods to project, rotate, move, cut, densify, and generalize geometries. When creating geometries using locations from the screen, and the map is a wraparound map, you may also need to consider normalizing a geometry before you save it to a geodatabase or use it in tasks or other operations.

Use the AGSGeometryEngine class to project geometries to a different spatial reference.

```
let oldPoint = AGSPoint(x: -121, y: 38, spatialReference: AGSSpatialReference.wgs84())
let newPoint = AGSGeometryEngine.projectGeometry(oldPoint, to: AGSSpatialReference.webMercator()) as! AGSPoint
```

### Converting to and from JSON

Geometries can be serialized and de-serialized to and from JSON. The ArcGIS REST API documentation describes the JSON representation of geometry objects. You can use this encoding and decoding mechanism to exchange geometries with REST Web services or to store them in text files.

```
// convert a Polygon to a JSON representation
let polygonJSON = (try? polygon1.toJSON()) as? NSDictionary
// create a new Polygon from JSON
let polygon2 = (try? AGSPolygon.fromJSON(polygonJSON!)) as! AGSPolygon
```

Converting to or from JSON can add points to multipart geometries if the geometry has insufficient points to construct a segment.

### Z-values and 3D

Geometries can have z-values, indicating values along the z-axis, which is orthogonal to both the x-axis and y-axis. Z-values can indicate height above or depth below a surface, or an absolute elevation. For example, z-values are used to draw the locations of geometries in SceneViews. Note that geometries are not considered true 3D shapes and are draped onto surfaces in the view, or in some cases, drawn in a single plane by using z-values. Z-values are stored on AGSPoints and AGSEnvelopes. Therefore, because AGSMultipoints, AGSPolylines, and AGSPolygons are created from AGSPoints, all types of geometry can have z-values.

Whether or not a geometry has z-values is determined when the geometry is created; if you use a method that has a z-value parameter, the new geometry will have z-values (the geometry's hasZ will be true). If you create geometries using constructors that take z-value parameters, or if you pass into the constructor points or segments that have z-values, the new geometry will have z-values. A geometry with z-values is sometimes known as a z-aware geometry.

It may be that not all vertices in your geometry have a z-value defined. NaN is a valid z-value used to indicate an unknown z-value. However, the default z-value is zero. It is important to note that when you get z-values from a geometry that does not have z-values, the default value of zero is returned. Check the hasZ property to determine whether a z-value of zero means that there are no z-values in the geometry or that the z-value in the geometry's coordinates really is zero.

See Editing geometries for more information about editing workflows with respect to z-values.

### M-values

M-values are used in linear referencing scenarios, and like z-values, every geometry can optionally store m-values. The default m-value is NaN. If an m-value is specified as a parameter when a geometry is created, the new geometry will have m-values (the geometry's hasM will be true). Note that when you get m-values back from a geometry, the default value of NaN (different than the default for z-values) is returned for vertices that do not have m-values. A geometry with m-values is sometimes known as an m-aware geometry. See Editing geometries for more information about editing workflows and m-values.