**Supported with:**

- Engine
- ArcGIS for Desktop Basic
- ArcGIS for Desktop Standard
- ArcGIS for Desktop Advanced
- Server

**Library dependencies:**Version, System, SystemUI

**Additional library information:**Contents, Object Model Diagram

The Geometry library provides vector representations for points, multipoints, polylines, polygons, and multipatches. Geometries are used by the geodatabase and graphic element systems to define the shapes of features and graphics. They supply operations that are used by the editor and map symbology systems to define and symbolize features. Spatial references describe where these geometries are located on the earth. They also define the resolution and valid values for the coordinates used by the geometries. Almost every system in ArcObjects uses geometries and spatial references in some way.

In addition, you can buffer sets of geometries robustly and efficiently using the BufferConstruction object. Finally, you can access common and useful geometric operations, such as projection and buffering, from any execution environment over the Internet using the GeometryServer Web service, or over a local area network (LAN) using the Web Application Developer Framework (ADF) and the GeometryServer proxy object.

To use geometries accurately, consistently, and predictably, you need to understand how geometries and spatial references work together.

Geometry objects are not meant to be extended by developers.

See the following sections for more information about this namespace:

- About geometry objects
- About spatial references and coordinate grids
- Using geometry objects
- GeometryServer
- BufferConstruction
- Using spatial reference objects
- Using transformation objects

### About geometry objects

In addition to the top level geometry objects (Points, Multipoints, Polylines, Polygons, and MultiPatches), Paths, Rings, Segments, TriangleStrips, TriangleFans, and Triangles serve as building blocks for polylines, polygons, and multipatches. Polylines contain paths; polygons contain rings; and multipatches contain triangle strips, triangle fans, triangles, and rings. Paths and rings are sequences of vertices connected by segments. A segment is a parametric function that defines the shape of the curve connecting its vertices. Segment types include CircularArc, Line, EllipticArc, and BezierCurve. In addition to the X and Y coordinates for each vertex in a geometry, these vertex attributes can be defined: M (measure), Z (elevation), and ID (foreign key). Envelopes describe the spatial extent of other geometries, and GeometryBags provide operations on collections of geometries.

Multipoint, polyline, polygon, and multipatch geometries have constraints on their shapes. For example, a polygon must have its interior clearly defined and separated from its exterior. When all constraints are satisfied, a geometry is said to be simple. When a constraint is violated, or it is not known if the constraint is met, the geometry is said to be non simple. The ITopologicalOperator, IPolygonN, and IPolylineN interfaces provide operations for testing and enforcing simplicity. The software development kit (SDK) documentation for the Simplify method of ITopologicalOperator describes these rules precisely.

Each vertex of a geometry, in addition to its X and Y coordinates, can have optional attributes, called vertex attributes. The Z vertex attribute is a double-precision value that can be used to represent heights or depths relative to a vertical coordinate system. The M vertex attribute, also called a measure, is a double-precision value that can be used to establish a linear reference system on a geometry (usually a polyline), such as exits along a highway. The ID vertex attribute, also called a point ID, is a signed integer that can be used as a foreign database key to associate additional information with each vertex such as survey measurements.

Vertex attributes can be added to or removed from any geometry at any time and in any combination. For example, a polyline can start out with no vertex attributes, have Zs added to it, have IDs added to it, then have its Zs removed. When a geometry is aware of its vertex attributes, those attributes are persisted as part of the geometry and are included in the output of topological operations that involve that geometry. If a geometry is not aware of its attributes, then those attributes are ignored when the geometry is persisted, and the attributes do not appear in the output of a topological operation involving that geometry. The attribute awareness of a geometry is controlled by the IZAware, IMAware, or IPointIDAware interface. The attribute values are not actually removed from a geometry if its awareness is disabled.

Geometries, especially segment types, have a rich set of methods for defining their location. For example, the IConstructCircularArc interface shows the different ways you can define a circular arc segment. Typically, interfaces or methods that include the word "construct" in their name use a set of input parameters (including other geometries) to completely define the target geometry. The inputs are not altered.

Top level geometries support the classical set-theoretic operations for generating new geometries including union, intersection, difference, and symmetric difference. These operations are exposed on the ITopologicalOperator interface and usually operate on a pair of geometries at a time. ITopologicalOperator.ConstructUnion can operate on more than two. New geometries are created to represent the results. Top level geometries also support the IRelationalOperator interface, which can perform a variety of tests on a pair of geometries such as disjoint, contains, and touches.

Both of these interfaces use the spatial reference associated with the input geometries when determining the answer. Two important properties of a spatial reference are its coordinate grid and its XY tolerance. Different values for these properties can cause the relational and topological operators to produce different results.

### About spatial references and coordinate grids

Geometries are georeferenced to the real world through a spatial reference. A spatial reference includes the coordinate system and several coordinate grids. A coordinate system includes information such as the unit of measure, the earth model used and, sometimes, how the data was projected. The coordinate grids are mathematical functions that define the XY, Z, and M resolution values and the corresponding domain extents. Each spatial reference also has a set of tolerance values. A geometry’s coordinates (or vertex attributes) must fall within the domain extent and be rounded to the resolution. The tolerance values are used by geometric operations that relate coordinates or compute new ones.

XY values can be georeferenced with a geographic or projected coordinate system. A geographic coordinate system (GCS) is defined by a datum, an angular unit of measure (usually degrees or grads), and a prime meridian. A projected coordinate system (PCS) consists of a linear unit of measure (usually meters or feet), a map projection, the specific parameters used by the map projection, and a GCS. A PCS or GCS can have a vertical coordinate system (VCS) as an optional property. A VCS georeferences Z values. A VCS includes either a geodetic or vertical datum, a linear unit of measure, an axis direction, and a vertical shift. Measure, or M, values do not have a coordinate system.

A spatial reference that includes an unknown coordinate system (UCS) includes a grid (domain extent) and a tolerance only. It is not possible to georeference a geometry associated with a UCS. If at all possible, you should not use a UCS. When a GCS or PCS is used, appropriate default XY domain extent, resolution, and tolerance values can be calculated. All grid and tolerance information for coordinates and attributes are associated with the PCS, GCS, or UCS. A VCS georeferences Z coordinates but does not have a well-defined default grid.

**For further information see:**

Understanding coordinate management in ArcGISHow to snap a point to a coordinate grid

Working with spatial references

### Using geometry objects

Some of the more widely used geometry objects are described in this section.

**GeometryEnvironment**

GeometryEnvironment provides a way of creating geometries from different inputs and setting or getting global variables for controlling the behavior of geometry methods. It also provides Java and .NET friendly versions of methods originally defined on other geometry objects (see the IGeometryBridge and IGeometryBridge2 interfaces). The GeometryEnvironment object is a singleton object, so calling new several times does not create a new object each time. Instead, it returns a reference to the existing GeometryEnvironment. See Interacting with singleton objects for details.

For additional information, see Working with GeometryEnvironment.

**Envelope**

For many applications, the coordinates of a geometry are treated as existing in a planar (Cartesian) coordinate space. An Envelope object is a rectangle with sides parallel to that space defining the spatial extent of a geometry. It can also describe the extent of the geometry’s Z and M vertex attributes. You can obtain copies of envelopes of other geometries or create envelopes directly. In the first case, the spatial reference of the envelope is the spatial reference of its defining geometry.

One way to use envelopes for geometric operations is explained in How to find the combined extent of two geometries.

**GeometryBag**

GeometryBag is a set of references to other geometry objects supporting the IGeometry interface. Objects of any level (Polyline, Polygon, MultiPatch, Multipoint, segments, and so on) can be added to GeometryBag via the IGeometryCollection interface. However, placing objects of different geometry types may not be suitable when using GeometryBag in some topological operations. For example, GeometryBag must contain strictly polygons, strictly polylines, or strictly envelopes when using it as a parameter to ITopologicalOperator.ConstructUnion. Also, Project and ProjectEx methods should not be applied to GeometryBag if it contains segments.

As with other geometries, a geometry bag has a spatial reference property. A geometry added to a bag will reference the same spatial reference as the bag. If the bag has no spatial reference, then neither will the added geometry after it is added to the bag. This is usually an error. Take care to define the spatial reference of the bag before adding geometries to it.

How to create a union of several polygons illustrates how to use GeometryBag to union a series of polygons, creating a single output geometry.

**Point**

A Point object is a two-dimensional point that can have M, Z, and ID attributes.

**Multipoint**

A Multipoint object is an ordered collection of points that can have M, Z, and ID attributes. The IPointCollection interface implemented by a Multipoint object provides direct access to its point elements. This is different from how IPointCollection behaves when that interface is used to provide access to the vertices of a polyline or polygon. In that case, you're working with copies of the points.

The following topics illustrate how to create a multipoint geometry:

**Polyline**

A Polyline object is an ordered collection of paths that can have M, Z, and ID attributes. The IPointCollection interface on Polyline manipulates copies of its vertices. Use the IGeometryCollection interface to directly access its paths and the ISegmentCollection interface to directly access its segments.

The IPointCollection and ISegmentCollection interfaces are also available on Path objects and are characterized the same way.

The polyline structure is shown in the following diagram:

Clothoid spirals are supported by construct piecewise linear approximation with the IConstructClothoid interface (new at ArcGIS 10).

Starting at ArcGIS 10, vertical segments in polylines are also supported. For more information, see Working with vertical polyline segments.

**Polygon**

A Polygon object is a collection of rings ordered by their containment relationship that can have M, Z, and ID attributes. Each ring is a collection of segments. The IPointCollection interface on Polygon and Ring manipulates copies of vertices. Use the IGeometryCollection and ISegmentCollection interfaces to access rings and segments directly.

The polygon structure is shown in the following diagram:

**Multipatch**

The multipatch geometry type was initially developed to address the needs for a three-dimensional (3D) polygon geometry type—unconstrained by two-dimensional (2D) validity rules. Without eliminating the constraints that rule out vertical walls, for example, representing extruded 2D lines and footprint-polygons for 3D visualization would not be possible. In addition to eliminating 2D constraints, multipatches provide more control over polygon face orientations and a better definition of polygon face interiors.

Multipatches also provide advanced geometric representations for 3D features. These complex 3D objects can be part of a Synthetic Landscape Model stored in a geodatabase. The target of these extensions is improved visualization quality.

Multipatches describe 3D geometries that can have multiple, textured surfaces. They can also store vertex normals, vertex ids, vertex measures, and several part-level attributes. You can create multipatches by importing data from a variety of different file formats (3D Studio Max .3ds files, OpenFlight .flt files, COLLADA .dae files, Sketchup .skp files, and VRML .wrl files). You can also create them programmatically in several different ways. Multipatches without textures, normals, or part attributes can be defined in a manner similar to building a polygon: create the parts, create a multipatch, then use the multipatch's IGeometryCollection interface to add the parts. Creating a multipatch with textures, normals, or part attributes requires the use of the GeneralMultiPatchCreator helper object (which requires an ArcGIS 3D Analyst license). To obtain information on normals and materials from an existing multipatch, use the IGeneralMultiPatchInfo interface.

The relationship between the objects used in multipatch construction is shown in the following graphic:

Multipatches support the IRelationalOperator3D interface, which contains the Disjoint3D method, and the IProximityOperator3D interface, which has methods for reporting the nearest distance from a query geometry to the multipatch and the nearest point on the multipatch from a query geometry. These interfaces treat multipatches as a collection of surfaces with no interior, so if you have a multipatch in the shape of a cube, and a point apparently inside that cube, the point will be classified as disjoint because it's not intersecting any of the cube's sides.

Multipatches contain multiple parts: triangle strips, triangle fans, triangles, and rings. Rings are the same Component Object Model (COM) object type as used in polygons but are unconstrained by 2D validity rules, so they can be vertical or have vertical segments. Each part in a multipatch has the following additional properties:

- Type—TriangleStrip, TriangleFan, Triangle, Outer Ring, and so on.
- Priority—Controls the drawing order of overlapping parts.
- An index into the array of materials (see the Material and textures section).

You can extrude polylines and polygons in various ways to define multipatches, or construct them explicitly (see the IConstructMultiPatch and IExtrude interfaces on the GeometryEnvironment singleton object). Multipatches can be stored as the geometry for a feature or used to symbolize points by drawing 3D models at the locations of the points. You can specify per-vertex normals to orient faces and provide more control over how multipatches are lit. Multipatches can contain materials (specifying color, texture, and transparency information) and texture coordinates that specify the placement of textures on each part. ArcScene provides style galleries containing multipatch models for 3D buildings (industrial and residential), trees, vehicles, street furniture, and other thematic categories.

You can compute the volume of a multipatch. The number will be meaningful if the multipatch is a closed surface (or has an opening that forms an implied lower face). You can compute the tessellated surface area using IArea3D. You can project a multipatch onto a plane (usually the xy plane). This operation is used to generate multipatch footprints when multipatches are operands to a spatial relation method. A ray can also be intersected with a multipatch.

**Triangle strip**

A triangle strip is a type of surface patch, defined by a collection of points that specify the triangle surfaces that comprise it. For a triangle strip with six points, the triangle surfaces are defined by points: (0, 1, 2), (2, 1, 3), (2, 3, 4), (4, 3, 5). The front side, or face, is established by orienting the first three vertices clockwise. See the following illustration:

**Triangle fan**

A triangle fan is a type of surface patch defined by a collection of points that specify the triangle surfaces that comprise it. Unlike a triangle strip, a triangle fan is comprised of a set of 3D triangles where the first point defines the apex or origin point and is included in all of the triangle surfaces. For a triangle fan with six points, the triangle surfaces are defined by points: (0, 1, 2), (0, 2, 3), (0, 3, 4), (0, 4, 5). The front side is established by orienting the first three vertices clockwise. See the following illustration:

**Triangle**

A triangle part is a type of surface patch used to construct a multipatch, defined by a collection of points that specify the triangle surfaces that comprise it. Each consecutive triplet of vertices defines a new triangle, and the vertex count must be a multiple of three. For a triangle part with six points, the triangle surfaces are defined by points: (0, 1, 2), (3, 4, 5). The front side of each triangle is established by orienting its vertices clockwise. See the following illustration:

**Rings (as used in multipatches)**

Rings are used in polygons and in multipatches. Rings in multipatches are not constrained by 2D validity rules, so you can use a multipatch containing vertically-oriented rings to represent vertical walls. A given ring does not have to be planar. That is, the vertices do not have to all lie in one plane. The interior of a non-planar ring is defined by how it is tessellated, which is currently done by the OpenGL utility library tessellator. A group of rings in a multipatch can define a surface with holes. A ring type is assigned to the ring immediately after it has been added to the multipatch as follows:

- Outer Ring—Exterior or outer ring of a multipatch surface (analogous to an outer ring in a polygon).

- Inner Ring—Interior or hole within a multipatch surface (analogous to an inner ring in a polygon).
- First Ring—First ring of a group of rings with an unspecified containment relation.
- Ring—Another ring of a group of rings with an unspecified containment relation.

The sequence typically consists of an Outer Ring, representing the outer boundary of the surface, followed by a number of Inner Rings representing holes. When the individual types of rings in a collection of rings representing a polygonal patch with holes are unknown, the sequence must start with First Ring, followed by a number of Rings. A sequence of Rings not preceded by a First Ring is treated as a sequence of Outer Rings without holes. In cases in which a multipatch is defined using Rings with no holes or interiors, the basic Ring role is used for convenience, although Outer Ring would work just as well. See the following illustration:

The following illustration shows a multipatch model of a building (note the use of texture, described in detail later). Five of the parts, forming a ring group, are highlighted in blue and gray. They are located on the closest building. The blue part is an Outer Ring. The gray parts are Inner Rings, constructed in the same plane as the Outer Ring.

Outer Ring and Inner Ring nomenclature is a more structured form of representing a surface than a First Ring and Ring series. The former explicitly defines that any Inner Ring that immediately follows an Outer Ring is a hole in the Outer Ring. In the sequence, "Inner" must always follow "Outer" or "Inner". Otherwise, it's an error. Anything other than "Inner" will stop the sequence for the Outer/Inner group.

**Surface normals in multipatches**

Each multipatch vertex can have a persistent surface normal associated with it. Without explicit, persistent surface normals, only flat shading of faces (individual triangles) is possible. With normals, lighting equations can be interpolated across faces to provide smoother shading. This might let you render smoothly curving surfaces using less geometric data.

**Materials and textures**

MultiPatches can store surface descriptions, called materials. A material adds detail to the multipatch’s appearance without increasing its geometric complexity. Each part can reference a material and each material can be referenced by more than one part. A material has a color, an overall transparency, and, optionally, a texture, which can have a transparent color or an alpha channel. Texture coordinates specify the placement of textures on each part. A texture is a raster image that is draped onto the surface of the multipatch. JPEG compressed raster files can be used.

In the context of a multipatch creator, material index and material type are synonymous and represent the index of a material within the multipatch used to symbolize a part. Parts within a multipatch can share materials.

Texture coordinates are pairs of floating point values associated with a vertex. The set of texture vertices associated with a multipatch tell the rendering system how to drape the texture. Texture coordinates are normally in the range [0,1]. Values larger than 1 cause the texture to be tiled along that coordinate axis.

The following pictures show the relationship between the texture data (left side); texture coordinates: (u, v) pairs, geometric coordinates (x, y, z) tuples; and the rendered multipatch model (right side). The origin of the texture coordinate system is the upper left corner.

Creating a multipatch that uses textures requires use of the GeometryMaterial COM object (3DAnalyst), an array of GeometryMaterials called a GeometryMaterialList and a GeneralMultiPatchCreator (3DAnalyst). The GeneralMultiPatchCreator assembles the material and geometry information into a multipatch shapefile buffer and then hydrates a multipatch from it. This process requires that all texture data is expanded in memory. MultiPatches themselves support shapefile buffers containing compressed texture data. Different multipatches cannot share texture data.

**For further information see:**

How to create a polylineHow to create a multipart polyline

How to create a polygon

How to build a polygon using segments and points

How to create a multipatch using a series of triangles

### GeometryServer

The GeometryServer object provides access to useful and powerful geometric operations, such as buffering and projection.

The following code example computes the area of a set of polygons obtained from an ArcGIS for Server map service. The polygons returned from the map service are defined in a geographic spatial reference. They are densified, projected to an equal area spatial reference, and their areas are then computed.

This code example also uses the SOAP application programming interface (API) to communicate over the Internet with the Web service.

For additional information on using more than one ArcGIS for Server Web Service in a single client application, refer to other parts of the Esri SOAP documentation. The Add Web Reference functionality available through the Visual Studio interface is not used. Instead, the wsdl.exe tool is invoked directly, using the /sharetypes option to combine WSDL documents from multiple Web services. The resulting source code file is then manually added to the C# .NET project.

The command used to generate the shared types proxies is as follows:

```
wsdl.exe /sharetypes /language:CS /namespace: ArcGISWebServices /out:.\ArcGISSOAP_SharedObjects.cs /protocol:SOAP http://geometria/arcgis/services/MapService/MapServer?wsdl http://geometria/arcgis/services/Geometry/GeometryServer?wsdl
```

See the .NET SDK documentation on wsdl.exe for additional information.

[C#] ```
// This C# example illustrates using a Geometry Service to compute the areas of polygons obtained
// from a Map Service.
using System;
using System.Collections.Generic;
using System.Text;
using ArcGISWebServices;
namespace GSClientTest
{
class Program
{
static void Main(string[] args)
{
ArcGISGeometryServer gs=new ArcGISGeometryServer();
gs.Url="http://geometria/arcgis/services/Geometry/GeometryServer";
ArcGISMapServer ms=new ArcGISMapServer();
ms.Url="http://geometria/arcgis/services/States/MapServer";
// Ask the "States" Map Service for all features in the first layer, which is assumed
// to be a polygon layer.
QueryFilter qf=new QueryFilter();
qf.SubFields="*";
RecordSet rs=ms.QueryFeatureData("Layers", 0, null);
// Find the geometry field in the returned record set, and get the spatial
// reference for the record set.
SpatialReference sr=null;
int iGeometry;
for (iGeometry=0; iGeometry < rs.Fields.FieldArray.Length; iGeometry++)
if (rs.Fields.FieldArray[iGeometry].Type ==
esriFieldType.esriFieldTypeGeometry)
{
Field f=rs.Fields.FieldArray[iGeometry];
sr=f.GeometryDef.SpatialReference;
break;
}
int j;
Geometry[] aG=new Geometry[rs.Records.Length];
for (j=0; j < rs.Records.Length; j++)
aG[j]=(Geometry)rs.Records[j].Values[iGeometry];
Geometry[] aGDens=gs.Densify(sr, aG, 0.1, false, 0.0);
// Project the geometries to an equal area projection to calculate their areas.
// The queried spatial reference (2163) is a US National Atlas Lambert
// Azimuthal Equal Area.
SpatialReference projSR=gs.FindSRByWKID(null, 2163, 0, true, true);
Geometry[] aGProj=gs.Project(sr, projSR, false, null, null, aGDens);
double[] lengths=new double[rs.Records.Length];
// Cast the array of geometries to an array of polygons.
Polygon[] aP=new Polygon[rs.Records.Length];
aGProj.CopyTo(aP, 0);
double[] areas=gs.GetAreasAndLengths(sr, aP, out lengths);
System.Console.WriteLine();
}
}
}
```

[VB.NET] ```
Module Module1
Sub Main()
Dim gs As ESRI.ArcGIS.Geometry.IGeometryServer
gs=New ESRI.ArcGIS.Geometry.GeometryServerImpl()
gs.Url="http://geometria/arcgis/services/Geometry/GeometryServer"
Dim ms As ESRI.ArcGIS.Carto.MapServer
ms=New ESRI.ArcGIS.Carto.MapServerClass()
ms.Url="http://geometria/arcgis/services/States/MapServer"
'Ask the "States" Map Service for all features in the first layer, which is assumed
'to be a polygon layer.
Dim qf As ESRI.ArcGIS.Geodatabase.IQueryFilter
qf=New ESRI.ArcGIS.Geodatabase.QueryFilter()
qf.SubFields="*"
Dim rs As ESRI.ArcGIS.Geodatabase.IRecordSet
rs=ms.QueryFeatureData("Layers", 0, Nothing)
'Find the geometry field in the returned record set, and get the spatial
'reference for the record set.
Dim sr As ESRI.ArcGIS.Geometry.ISpatialReference
sr=Nothing
Dim iGeometry As Integer
For iGeometry=0 To rs.Fields.FieldArray.Length - 1
If (rs.Fields.FieldArray(iGeometry).Type=ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeGeometry) Then
Dim f As ESRI.ArcGIS.Geodatabase.IField
f=rs.Fields.FieldArray(iGeometry)
sr=f.GeometryDef.SpatialReference
End If
Next iGeometry
Dim j As Integer
Dim aG(rs.Records.Length) As ESRI.ArcGIS.Geometry.IGeometry
For j=0 To rs.Records.Length
aG(j)=rs.Records(j).Values(iGeometry)
Next j
Dim aGDens As ESRI.ArcGIS.Geometry.IGeometryArray
aGDens=gs.Densify(sr, aG, 0.1, False, 0.0)
'Project the geometries to an equal area projection to calculate their areas
'The queried spatial reference (2163) is a US National Atlas Lambert
'Azimuthal Equal Area.
Dim projSR As ESRI.ArcGIS.Geometry.ISpatialReference
projSR=gs.FindSRByWKID(Nothing, 2163, 0, True, True)
Dim aGProj As ESRI.ArcGIS.Geometry.IGeometryArray
aGProj=gs.Project(sr, projSR, False, Nothing, Nothing, aGDens)
'Cast the array of geometries to an array of polygons.
Dim aP(rs.Records.Length) As ESRI.ArcGIS.Geometry.Polygon
aGProj.CopyTo(aP, 0)
Dim lengths As ESRI.ArcGIS.esriSystem.IDoubleArray
Dim areas As ESRI.ArcGIS.esriSystem.IDoubleArray
gs.GetAreasAndLengths(sr, aP, areas, lengths)
End Sub
End Module
```

### BufferConstruction

The BufferConstruction object implements an updated, highly robust geometric buffering operation. It is designed to process a large number of inputs without requiring that all inputs and outputs exist in main memory at the same time. It provides additional buffering options that are not possible with the current ArcObjects Buffer method. For example, geodesic buffers can be generated around points. Finally, it provides a compatibility operation that lets clients of the existing buffer operation use this object with minimal impact on their existing code. In fact, the simplest way to use the buffer construction object is as follows:

IBufferConstruction bc = new BufferConstruction();

Buffer = bc.Buffer(myInputGeometry, distance);

Buffer = bc.Buffer(myInputGeometry, distance);

The capabilities of the BufferConstruction object include the following:

- The IBufferConstructionProperties interface provides several new options for construction of geometric buffers.
- Polyline buffers can be constructed to the left or the right of the polyline.
- Polygon buffers can exclude the interior of the polygon.
- Curve segments can be added to the output buffers.
- Buffers can be dissolved together in places where they overlap.
- Separate polygons can be unioned for each non-overlapping portion of a buffer.
- True geodesic buffers can be generated around points that are in a GCS.
- Geometries of different types can be buffered together.
- Multiple buffers can be generated around the same set of inputs.
- In the context of a single buffering operation, different features can be buffered by different distances.

The buffer construction object requires the use of temporary files. They are placed in the directory identified by the pathname contained in the environment variable ARCTMPDIR. If the variable does not exist, the system TEMP location is used. Temporary files are removed at the end of a buffer operation.

### Using spatial reference objects

Some of the more widely used spatial reference objects are described in this section.

**SpatialReferenceEnvironment**

SpatialReferenceEnvironment is a singleton object used for creating, loading, and storing entire spatial references. Spatial references are often cloned and copied internally. Setting up SpatialReferenceEnvironment as a singleton object conserves resources and makes it less likely that a spatial reference will be deleted before it is no longer in use. SpatialReferenceEnvironment can also create predefined components used for building spatial references (projections, datums, prime meridians, and so on). You can also use it to convert between low and high precision spatial references.

The following topics include additional information on how to use SpatialReferenceEnvironment:

- Using the SpatialReferenceEnvironment
- Constructing a high- or low-precision spatial reference
- Converting between high- and low-precision spatial references
- How to import or export a spatial reference

**GeographicCoordinateSystem**

The GeographicCoordinateSystem object includes a name, angular unit of measure, datum (which includes a spheroid), and a prime meridian. It is a model of the earth in a 3D coordinate system. Latitude-longitude, or lat/lon, data is in a GCS. You can access the majority of the properties and methods through the IGeographicCoordinateSystem interface, with a few more properties available in IGeographicCoordinateSystem2. Although you probably won't need to create a custom GCS, the IGeographicCoordinateSystemEdit interface contains the Define and DefineEx methods if you do.

The following code example demonstrates how the DefineEx method can be used. It uses a SpatialReferenceFactory to create the Datum, PrimeMeridian, and Unit components.

[VCPP] ```
// Smart pointer variables used.
IDatumPtr ipDatum;
IPrimeMeridianPtr ipPrimeMeridian;
IUnitPtr ipUnit;
IAngularUnitPtr ipAngularUnit;
// Create the factory and the component parts.
ISpatialReferenceFactoryPtr ipFactory(CLSID_SpatialReferenceEnvironment);
ipFactory->CreateDatum(esriSRDatum_OSGB1936, &ipDatum);
ipFactory->CreatePrimeMeridian(esriSRPrimeM_Greenwich, &ipPrimeMeridian);
ipFactory->CreateUnit(esriSRUnit_Degree, &ipUnit);
IGeographicCoordinateSystemEditPtr ipGeoCSEdit(CLSID_GeographicCoordinateSystem)
;
IGeographicCoordinateSystemPtr ipGCS;
// Cast for the AngularUnit from the Unit.
// (This is achieved by the SmartPointers.)
ipAngularUnit=ipUnit;
// Make the string descriptions.
CComBSTR name(_T("User Defined Geographic Coordinate System"));
CComBSTR alias(_T("UserDefined"));
CComBSTR abbreviation(_T("User"));
CComBSTR remarks(_T("User Define GCS based on OSGB1936"));
CComBSTR useage(_T("Suitable for the UK"));
// Make the call.
HRESULT hr;
hr=ipGeoCSEdit->DefineEx(name, alias, abbreviation, remarks, useage, ipDatum,
ipPrimeMeridian, ipAngularUnit);
// Cast for the result.
ipGCS=ipGeoCSEdit;
```

[C#] ```
IDatum ipDatum;
IPrimeMeridian ipPrimeMeridian;
IUnit ipUnit;
IAngularUnit ipAngularUnit;
// Create the factory and the component parts.
ISpatialReferenceFactory ipFactory=new SpatialReferenceEnvironmentClass();
ipDatum=ipFactory.CreateDatum((int)esriSRDatumType.esriSRDatum_OSGB1936);
ipPrimeMeridian=ipFactory.CreatePrimeMeridian((int)
esriSRPrimeMType.esriSRPrimeM_Greenwich);
ipUnit=ipFactory.CreateUnit((int)esriSRUnitType.esriSRUnit_Degree);
IGeographicCoordinateSystemEdit ipGeoCSEdit=new GeographicCoordinateSystemClass();
// Cast for the AngularUnit from the Unit.
ipAngularUnit=ipUnit as IAngularUnit;
// Make the string descriptions.
string name="User Defined Geographic Coordinate System";
string alias="UserDefined";
string abbreviation="User";
string remarks="User Define GCS based on OSGB1936";
string useage="Suitable for the UK";
// Make the call.
ipGeoCSEdit.DefineEx(name, alias, abbreviation, remarks, useage, ipDatum,
ipPrimeMeridian, ipAngularUnit);
// Cast for the result.
IGeographicCoordinateSystem ipGCS=ipGeoCSEdit as IGeographicCoordinateSystem;
```

[VB.NET] ```
Dim ipDatum As ESRI.ArcGIS.Geometry.IDatum
Dim ipPrimeMeridian As ESRI.ArcGIS.Geometry.IPrimeMeridian
Dim ipUnit As ESRI.ArcGIS.Geometry.IUnit
Dim ipAngularUnit As ESRI.ArcGIS.Geometry.IAngularUnit
'Create the factory and the component parts.
Dim ipFactory As ESRI.ArcGIS.Geometry.ISpatialReferenceFactory
ipFactory=New ESRI.ArcGIS.Geometry.SpatialReferenceEnvironment()
ipDatum=ipFactory.CreateDatum(ESRI.ArcGIS.Geometry.esriSRDatumType.esriSRDatum_OSGB1936)
ipPrimeMeridian=ipFactory.CreatePrimeMeridian(ESRI.ArcGIS.Geometry.esriSRPrimeMType.esriSRPrimeM_Greenwich)
ipUnit=ipFactory.CreateUnit(ESRI.ArcGIS.Geometry.esriSRUnitType.esriSRUnit_Degree)
Dim ipGeoCSEdit As ESRI.ArcGIS.Geometry.IGeographicCoordinateSystemEdit
ipGeoCSEdit=New ESRI.ArcGIS.Geometry.GeographicCoordinateSystem()
'Cast for the AngularUnit from the Unit.
ipAngularUnit=ipUnit
'Make the string descriptions.
Dim Name As String, _alias As String, abbreviation As String, remarks As String, useage As String
Name="User Defined Geographic Coordinate System"
_alias="UserDefined"
abbreviation="User"
remarks="User Define GCS based on OSGB1936"
useage="Suitable for the UK"
'Make the call.
ipGeoCSEdit.DefineEx(Name, _alias, abbreviation, remarks, useage, ipDatum, ipPrimeMeridian, ipAngularUnit)
'Cast for the result.
Dim ipGCS As ESRI.ArcGIS.Geometry.IGeographicCoordinateSystem
ipGCS=ipGeoCSEdit
```

To access the hundreds of predefined GCSs, ISpatialReferenceFactory has the CreateGeographicCoordinateSystem method. The predefined GCSs are listed in the esriSRGeoCSType, esriSRGeoCS2Type, and esriSRGeoCS3Type enumerations. The parts of a GCS, such as the datum, angular unit, and prime meridian, are objects as well. All support ISpatialReference2 and ISpatialReferenceFactory. Use the predefined objects available in the various esriSR* enumerations.

The IGeographicCoordinateSystem2 interface supplies the AngularConversionFactor method, which returns a value that converts the units of measure between two GCSs.

The ExtentHint, LeftLongitude, and RightLongitude properties are interrelated. Usually, data in a GCS has longitude values between -180 and 180 if the unit of measure is degrees. Some datasets are designed to use a minimum longitude value of 0 or -360. The LeftLongitude property controls whether the data is considered as -360 to 0, -180 to 180, or 0 to 360. This is only pertinent when you’re inverse projecting projected coordinates for storage in a GCS-based feature class that has a non-standard longitude range. The ArcObjects framework usually deals with this detail for you.

The left longitude property is not considered when comparing two GCSs for equality.

GetHorizon returns a WKSEnvelope describing the extent of a GCS based on its unit of measure and LeftLongitude. This method can be used to define a standard coordinate grid for the GCS. It is used internally by the ISpatialReferenceResolution.ConstructFromHorizon method.

**ProjectedCoordinateSystem**

The ProjectedCoordinateSystem object includes a name, linear unit of measure, GCS, map projection, and any parameters required by the map projection. Using the term "projection" for a coordinate system is imprecise. Projection is the actual mathematical function. Transverse Mercator and Lambert Conformal Conic are map projections. Universal transverse Mercator (UTM) and State Plane are PCSs that are based on particular map projections. Each PCS must include a GCS. Map projection parameters can be linear, angular, or unitless. A unitless parameter includes scale factor and option. Angular parameters are the central meridian, standard parallels, and latitude of origin. Linear parameters are false easting and false northing. Use the GetDefaultParameters method on the IProjection interface to determine which parameters a particular map projection expects.

The parts of a PCS, such as the projection, linear unit, and GCS, are objects as well. All support ISpatialReference2 and ISpatialReferenceFactory. When defining a custom PCS, use the predefined objects available in the various esriSR* enumerations.

You can access the majority of the properties and methods through the IProjectedCoordinateSystem2 interface, although a few more properties are available in IProjectedCoordinateSystem3 and IProjectedCoordinateSystem4. The IProjectedCoordinateSystemEdit interface contains the Define method, which allows you to define a custom PCS. To access the hundreds of predefined PCSs, ISpatialReferenceFactory has the CreateProjectedCoordinateSystem method. The predefined PCSs are listed in the esriSRProjCSType, esriSRProjCS2Type, esriSRProjCS3Type, and esriSRProjCS4Type enumerations.

**VerticalCoordinateSystem**

The VerticalCoordinateSystem object includes a name, linear unit of measure, a vertical or geodetic (horizontal) datum, a direction, and optionally, a vertical shift. A VCS defines the origin of Z coordinate values. A common application is for Z values to represent elevations or depths, when Z values increase up (against the direction of gravity) or decrease down (in the direction of gravity), respectively. You can access the majority of the properties and methods through the IVerticalCoordinateSystem interface. Although you probably won't need to create a custom VCS, the IVerticalCoordinateSystemEdit interface contains the Define method if you do.

**For further information see:**

Working with spatial referencesCreating a custom geographic coordinate system

Creating a custom projected coordinate system

Creating a custom vertical coordinate system

### Using transformation objects

The transformation objects can be used to apply various linear coordinate transformations to top-level geometries (points, multipoints, polylines, and polygons). Typically, you create a particular kind of transformation object, define its properties, then pass it to the geometry being transformed to perform the transform on that geometry. Only occasionally will you need to extract the points from the geometry and transform them directly, or transform arrays of WKSPoints directly.

**AffineTransformation2D**

The AffineTransformation2D object is a 3x3 matrix that implements conformal (angle preserving) affine and general affine transformations. A minimum of two pairs of points are required to exactly define a conformal affine transformation. A 2D conformal transformation is also called a Helmert transformation. A minimum of three pairs of points are required to define a general affine transformation. Additional points are required to determine root mean square (RMS) error information for the transformation. One use for AffineTransformation2D is to register a paper map into a known coordinate system when digitizing.

**AffineTransformation3D**

The AffineTransformation3D obje4ct is a 4x4 matrix that supports definition of general affine transformations from control points. It does not determine conformal affine transformations.

**ProjectiveTransformation2D**

The ProjectiveTransformation2D object requires a minimum of four pairs of points to define the transformation. The projective transformation is only used to transform coordinates digitized directly off high altitude aerial photography or aerial photographs of relatively flat terrain assuming that there is no systematic distortion in the air photos. A projective transformation uses eight parameters.

**Geotransformation**

Moving your data between PCSs may also involve transforming GCSs. Because GCSs contain datums that are based on spheroids, a geographic transformation (geotransformation) also changes the underlying spheroid. Other frequently used terms for a geographic transformation include datum shift and geodetic transformation.

A geographic transformation is a mathematical operation that takes the coordinates of a point in one GCS and returns the coordinates of the same point in another GCS. There is also an inverse transformation to allow coordinates to be put back to the first coordinate system from the second. There are many different types of mathematical operations used to achieve this task.

**For further information see:**

How to perform an affine transformationUnderstanding geotransformations

Creating a predefined geotransformation