Geometry


Additional assembly information: Contents, Object Model Diagram
The Geometry namespace contains classes representing the different types of geometrical shapes (for example, points or polygons) and also operations that work on Geometry objects (for example, moving a Point or simplifying a Polygon). Geometries are used in vector data to represent the features in a spatially enabled table.
The Geometry namespace also contains classes representing geographical and projected coordinate systems, which help describe where a Geometry is located on the earth.

See the following sections for more information about this namespace:

Geometry classes

Some of the code examples in this topic assume the presence of two variables—a variable named "currentDisplay" that is set to the MapDisplay of the application, and a variable named "spatialTable" set to a table of spatial data.
The Geometry base class represents all types of geometrical shape, providing members that apply to all shape types, for example, you can get the center point (GetCenter) or the spatial extent (GetEnvelope) of any type of geometry. The CoordinateSystem property indicates how the shape of the geometry is georeferenced to real world coordinates; see the Coordinate systems and units of measurement section for more information about CoordinateSystems.
The following classes all inherit from this generic Geometry class and represent different specific types of geometrical shape:
  • Point—Single location in space, defined primarily by x and y coordinates and a Z property defining elevation. Points can be used to represent single geographical locations, such as addresses, oil wells, or vehicle locations.
  • Multipoint—Unordered collection of single locations in space. Multipoints can be used to represent geographical features that have multiple single locations but are related, for example, the multiple entrances to a single rabbit warren.
  • Polyline—Linear shapes used to represent linear geographical features such as roads, rivers, power lines, or water pipes. Polylines can be made of multiple paths with gaps between the different sections.
  • Polygon—Area shapes used to represent geographical features, such as countries, lakes, or land parcels. Polygons can be made of multiple rings, which define holes within the shape, or multiple sections of the shape.
  • Multipatch—Three-dimensional (3D) shapes, defined as a series of flat faces used to represent 3D structures, such as buildings or trees.
  • Envelope—Rectangular region with its sides orthogonal to its coordinate system, most commonly used to represent the minimum and maximum extent of coordinates in another geometry or in a spatially enabled table.
Point, multipoint, polyline, polygon, multipatch, and envelope are all specific types of geometry.

Geometries in ArcGIS Explorer

Geometry objects can be used to represent geographical features and are used throughout the system in a number of ways:
  • Returned from the Geometry column of a spatially enabled Table
  • Used as input to a spatial query of a Table using a Filter.
  • Define the shape and location of Graphic objects
A spatially enabled table can store points, multipoints, polylines, polygons, or multipatches in the Geometry column. Envelopes cannot be stored in the Geometry column.
See the following code example which uses a Point as input to the Search method of a spatial Table, then retrieves the Geometry of the first Row in the returned RowCollection:
[C#]
Point searchPt = currentDisplay.TrackPoint();
RowCollection foundFeatures = spatialTable.Search(new Filter(searchPt,
    FilterSearchOptions.Intersects));
Row foundFeature = foundFeatures.GetFirst();
if (foundFeature != null)
{
    Geometry foundGeom = foundFeature.Geometry;
}
[VB.NET]
Dim searchPt As Point = currentDisplay.TrackPoint()
Dim foundFeatures As RowCollection = spatialTable.Search(New Filter(searchPt, FilterSearchOptions.Intersects))
Dim foundFeature As Row = foundFeatures.GetFirst()
If Not foundFeature Is Nothing Then
    Dim foundGeom As Geometry = foundFeature.Geometry
End If
A point, multipoint, polyline, polygon, or envelope can be used for the geometry of a graphic; a multipatch cannot. The track methods (TrackPoint, TrackPolyline, TrackVector, and TrackPolygon) on the MapView class are commonly used as basic ways to return new geometries defined by the user interacting directly with the view.
See the following code example which demonstrates how you can add a new Graphic to the MapDisplay by using the TrackPoint, TrackPolyline and TrackPolygon methods:
[C#]
currentDisplay.Graphics.Add(new Graphic(currentDisplay.TrackPoint(),
                            Symbol.Marker.Pushpin.Yellow));
currentDisplay.Graphics.Add(new Graphic(currentDisplay.TrackPolyline(),
                            Symbol.Line.Solid.Yellow));
currentDisplay.Graphics.Add(new Graphic(currentDisplay.TrackPolygon(),
                            Symbol.Fill.SolidOutline.Yellow));
[VB.NET]
currentDisplay.Graphics.Add(New Graphic(currentDisplay.TrackPoint(), Symbol.Marker.Pushpin.Yellow))
currentDisplay.Graphics.Add(New Graphic(currentDisplay.TrackPolyline(), Symbol.Line.Solid.Yellow))
currentDisplay.Graphics.Add(New Graphic(currentDisplay.TrackPolygon(), Symbol.Fill.SolidOutline.Yellow))
These track methods are blocking calls—you cannot execute other code until the methods are completed; however, you can consider the alternative BeginTrackPoint, BeginTrackVector, BeginTrackPolyline, and BeginTrackPolygon methods if you need the more advanced functionality of asynchronous tracking.

Creating geometries and examining existing geometries

You can create instances of the Point, Multipoint, Polygon, Polyline, and Envelope classes to represent new shapes in ArcGIS Explorer. A Multipatch can only be returned from the Row.Geometry of a spatially enabled table connected to a multipatch data source. You cannot create instances of the Multipatch class or edit the shape of an existing Multipatch.
You can create and define instances of points, multipoints, polylines, polygons, and envelope; however, you cannot define new Multipatch geometries.

Creating and defining basic geometries

The Point and Envelope are the simplest types of geometry to define. To create and define a new Point or Envelope object, use the parameterized constructors to set the properties of the new object, as shown in the following code example:
[C#]
Point pt = new Point(48.867, 2.333);
Envelope env = new Envelope(48.5, 49.0, 48.6, 50.0);
[VB.NET]
Dim pt As Point = New Point(48.867, 2.333)
Dim env As Envelope = New Envelope(48.5, 49.0, 48.6, 50.0)
Alternatively, create and define a Point or Envelope by using the parameterless constructors and setting the appropriate properties once instantiated. If required, overloads are also available to specify elevation information (z).
You can define the location of a Point by setting the X, Y and optionally Z properties. The extent of an Envelope is defined by its XMin, XMax, YMin, YMax, and optionally ZMin and ZMax properties.
Polygon, Polyline, and Multipoint geometries are all defined by a series of points. The simplest way to build Polygon, Polyline, or Multipoint geometries from scratch is to create the object, then call the AddPoint method to define each new vertex of the shape. You can also call AddPoints to define multiple vertices in one method call, or use the parameterized constructors to define the whole shape if you already know all the vertices of the geometry. Geometries are constructed by value, which means any points you pass in to construct your shape are copied to the parent geometries.
The following code example shows using the AddPoint and AddPoints methods to define the shape of a new Polyline and Multipoint object:
[C#]
Polyline pline = new Polyline();
pline.AddPoint(new Point(0, 0));
pline.AddPoints(new Point[]
{
    new Point(0, 1), new Point(1, 1)
}

);

Multipoint mpoint = new Multipoint(new Point[]
{
    new Point(1, 1), new Point(2, 2)
}

);
[VB.NET]
Dim pline As Polyline = New Polyline()
pline.AddPoint(New Point(0, 0))
pline.AddPoints(New Point() { New Point(0, 1), New Point(1, 1) })

Dim mpoint As Multipoint = New Multipoint(New Point() { New Point(1, 1), New Point(2, 2) })
Polygons are the most complex type of shape to define because they should consist of closed rings where the last Point has the same location as the first. Calling the Close method adds a Point to an existing Polygon, if required, to ensure that the Polygon describes a closed ring.
See the following code example:
[C#]
Point[] points = new Point[]
{
    new Point(0, 0), new Point ...
};
Polygon poly = new Polygon(points);
poly.Close();
[VB.NET]
Dim points As Point() = New Point() { New Point(0, 0), New Point...}
Dim poly As Polygon = New Polygon(points)
poly.Close()
Again, use the overloads to specify elevation (Z) information for new points.
You can define the shape of a Polygon, Polyline, or Multipoint by copying in Point objects using the AddPoint or AddPoints methods, or by using the parameterized constructors.
By default, any geometry you create using constructors will have the WGS84 coordinate system (the same system as used by the 3D view in ArcGIS Explorer). You can change this by using the parameterized constructors, or by setting the CoordinateSystem property of an existing Geometry; note that changing the CoordinateSystem of a Geometry will not change any other spatial properties of the Geometry (the shape is not reprojected).
Existing Geometry objects returned from other methods (for example, Row.Geometry or MapDisplay.TrackPoint) will already have the CoordinateSystem property set appropriately.
When adding a Point to a Polygon, Polyline, or Multipoint, the CoordinateSystem of the added Point is ignored and the Point is assumed to be defined in the same coordinate system as the geometry to which it is being added, which allows your code to be more efficient when defining geometries in coordinate systems other than the default coordinate system.
For more information, see the Coordinate systems and units of measurement section in this topic.
The following sections in this topic discuss more advanced scenarios for creating and changing geometries:

Examining the locations of geometries

The locations of the simplest geometries, Point and Envelope, can be examined by using the same properties used to set the locations; the X and Y properties of Point, and the XMin, XMax, YMin, and YMax properties of the Envelope geometry. You can return a quick summary of these classes by calling the ToString methods.
See the following code example:
[C#]
Point pt = new Point( - 3.1603, 55.9494);
string ptDetails = pt.ToString(); // "Point: X = -3.1603 Y = 55.9494."

Envelope env = new Envelope(2, 2, 4, 4, 0, 1);
string envDetails = env.ToString(); 
                                 //"Envelope: XMin = 2 YMin = 2 XMax = 4 YMax = 4."
[VB.NET]
Dim pt As Point = New Point( -3.1603, 55.9494)
Dim ptDetails As String = pt.ToString() ' "Point: X = -3.1603 Y = 55.9494."

Dim env As Envelope = New Envelope(2, 2, 4, 4, 0, 1)
Dim envDetails As String = env.ToString() '"Envelope: XMin = 2 YMin = 2 XMax = 4 YMax = 4."
Polygons, polylines, and multipoints are shapes consisting of a number of vertices; the vertices are specified as Point objects and you can also retrieve each vertex as a Point object. Points are always retrieved by value (as copies of the actual point location); for example, on a Polyline, the GetPoint method allows you to get a copy of the Point at a specific index.
See the following code example which reports information about each point in an existing Multipoint object called mpoint:
[C#]
StringBuilder ptDetails = new StringBuilder();
for (int i = 0; i < mpoint.PointCount; i++)
{
    ptDetails.AppendLine(mpoint.GetPoint(i).ToString());
}
[VB.NET]
Dim ptDetails As StringBuilder = New StringBuilder()
For i As Integer = 0 To mpoint.PointCount(0) - 1
    ptDetails.AppendLine(mpoint.GetPoint(i).ToString())
Next i
The Polyline and Polygon classes have similar GetPoint methods; the PointCount member on these classes is an overloaded method instead of a property as these types can be multipart - see the sections on multipart geometries later in this topic for more information. This application programming interface (API) does not provide the ability to retrieve the individual vertices of a multipatch.
The locations of Points and Envelope, and the vertices of Multipoint, Polyline, and Polygon  objects can be investigated; however, the API does not provide the ability to investigate the parts or vertices of a Multipatch.

Changing geometries

The GeometryOperations class has a number of functions that apply a spatial operation to a geometry; these functions leave the input geometry unchanged and return a new geometry as the result.
A common use of the GeometryOperations.Union operation for envelopes is to create an Envelope representing the extent of multiple notes. The following code example adds a note to represent each row in the spatialTable table, and uses the Union method create a Viewpoint based on the unioned Envelope of all the geometries:
[C#]
RowCollection allRows = spatialTable.GetRows();
Folder newNoteFolder = new Folder();

IList < Envelope > allNotesExtents = new List < Envelope > ();
foreach (Row rw in allRows)
{
    Geometry newNoteGeom = rw.Geometry;
    allNotesExtents.Add(newNoteGeom.GetEnvelope());
    newNoteFolder.ChildItems.Add(new Note(rw.Values["FieldName"].ToString(),
                                 newNoteGeom));
}

Envelope extentUnion = GeometryOperations.Union(allNotesExtents);
newNoteFolder.Viewpoint = new Viewpoint(extentUnion);
currentDisplay.Map.ChildItems.Add(newNoteFolder);
[VB.NET]
Dim allRows As RowCollection = spatialTable.GetRows()
Dim newNoteFolder As Folder = New Folder()

Dim allNotesExtents As IList(Of Envelope) = New List(Of Envelope)()
For Each rw As Row In allRows
    Dim newNoteGeom As Geometry = rw.Geometry
    allNotesExtents.Add(newNoteGeom.GetEnvelope())
    newNoteFolder.ChildItems.Add(New Note(rw.Values("FieldName").ToString(), newNoteGeom))
Next rw

Dim extentUnion As Envelope = GeometryOperations.Union(allNotesExtents)
newNoteFolder.Viewpoint = New Viewpoint(extentUnion)
currentDisplay.Map.ChildItems.Add(newNoteFolder)
Alternatively, you can change the location of existing points and envelopes by directly updating the same properties you used to define the shape, or by using the overloaded SetCoordinates methods. See the following code example:
[C#]
// Alternative to using parameterized constructors is to specify the positions of point 
// and envelope using SetCoordinates after the objects are created.
Point pt = new Point();
pt.SetCoordinates(4.259, 55.858);

Envelope env = new Envelope();
env.SetCoordinates( - 1,  - 1, 1, 1);
[VB.NET]
' Alternative to using parameterized constructors is to specify the positions of point
' and envelope using SetCoordinates after the objects are created.
Dim pt As Point = New Point()
pt.SetCoordinates(4.259, 55.858)

Dim env As Envelope = New Envelope()
env.SetCoordinates( -1, -1, 1, 1)
Changing individual vertices of existing multipoints, polylines, and polygons can be done by using the overloaded InsertPoint, RemovePoint, and SetPoint methods, in addition to using AddPoint. Remember that points are set by value into multipoints, polylines, and polygons. The following code example demonstrates the use of a number of these members:
[C#]
Polyline pline = new Polyline(new Point[]
{
    new Point(0, 0), new Point(0, 1), new Point(1, 1)
}

);

// Add point to the end of the polyline.
pline.AddPoint(new Point(1, 2));

// Insert a point after the first and before the second existing vertices;
// the new vertex is at position 1.
pline.InsertPoint(1, new Point(0.5, 0.5));

// Change the first existing vertex.
pline.SetPoint(0, new Point(0, 0.5));

// Remove the third point, which in the zero-based set of points, is index 2.
pline.RemovePointAt(2);
[VB.NET]
Dim pline As Polyline = New Polyline(New Point() { New Point(0, 0), New Point(0, 1), New Point(1, 1) })

' Add point to the end of the polyline.
pline.AddPoint(New Point(1, 2))
'
Insert a point after the first And before the Second existing vertices;
' the new vertex is at position 1.
pline.InsertPoint(1, New Point(0.5, 0.5))

' Change the first existing vertex.
pline.SetPoint(0, New Point(0, 0.5))

' Remove the third point, which in the zero-based set of points, is index 2.
pline.RemovePointAt(2)
Again, use the overloads to specify elevation (Z) information. For code that updates geometry coordinates, see the Update Note geometry sample.
Notice that for methods which return or take in multiple Point objects, different Types from the System.Collections.Generic namespace are used. For example, the Multipoint.GetPoints method returns the points as an IList<Type>, indicating an ordered collection of points which can be accessed by index. However, methods which take in multiple Point objects generally accept the IEnumerable<Type>. To ensure the correct order of Points you should generally use an ordered list implementation to build these parameters; however by allowing the input as the more widely implemented IEnumerable<Type> allows you much more flexibility in the underlying class Type that you can pass in to the method.
Methods which return multiple points generally use System.Collections.Generic.IList<Type> to ensure points are ordered correctly. However methods which allow input of multiple points generally use System.Collections.Generic.IEnumerable<Type> as this allows much more flexibility in the underlying class Type you can pass in to the method.

For further information see:

Sample: Update Note geometry

Multipart geometries

So far, this topic has dealt with polylines and polygons consisting of a single contiguous set of vertices. However, polylines and polygons can optionally be defined as multiple sets of vertices, known as multipart geometries.
For polylines, each part is known as a path and forms a single continuous line; each path in the polyline can be disjoint from the other paths. For polygons, each part is known as a ring and forms a single closed shape. Rings can be contained within other rings, forming holes and islands in the polygon shape.
The methods you have used so far have not included parameters to specify the index of a path within a polyline or the index of a ring within a polygon. Overloads of the GetPoint, SetPoint, InsertPoint, RemovePoint, and AddPoint methods are available to handle specific parts of multipart geometries; other multipart-specific methods are also available.
A Polyline can be made of multiple paths and a Polygon can be made of multiple rings. These shapes are known as multipart geometries and overloaded methods are available to work with specific parts of the geometries.

Examining the locations of multipart geometries

You can determine the number of paths in a Polyline or rings in a Polygon by using the PathCount or RingCount properties respectively. Use the overloaded GetPoint methods to get a copy of the Point at a specific position in a specific path or ring. The following code example iterates through all of the points in a Polyline, multiPathLine, using the PathCount, PointCount and GetPoint members: 
[C#]
// Iterate through all points in all paths.
for (int i = 0; i < multiPathLine.PathCount; i++)
{
    for (int j = 0; j < multiPathLine.PointCount(i); j++)
    {
        multiPathLine.GetPoint(i, j);
    }
}
[VB.NET]
For i As Integer = 0 To multiPathLine.PathCount - 1 Step 1
    For j As Integer = 0 To multiPathLine.PointCount(i) - 1 Step 1
        Dim pt As Point = multiPathLine.GetPoint(i, j)
        System.Diagnostics.Debug.WriteLine(pt.ToString())
    Next
Next
Alternatively, refer to the GetPath, GetPaths, GetRing and GetRings methods which return enumerable generic lists of Points, as shown in the code example below.
[C#]
// Iterate through all points in all paths.
foreach (IList < Point > path in multiPathLine.GetPaths())
{
    foreach (Point pt in path)
    {
        System.Diagnostics.Debug.WriteLine(pt.ToString());
    }
}
[VB.NET]
' Iterate through all points in all paths.
For Each Path As IList(Of Point) In multiPathLine.GetPaths()
    For Each pt As Point In Path
        System.Diagnostics.Debug.WriteLine(pt.ToString())
    Next
Next

Changing multipart geometries

To add new paths to an existing multipart polyline, use the AddPath method; overloads are available to create an empty path, or to immediately populate the new path with the specified points. See the following code example:
[C#]
Polyline pline = new Polyline(new Point[]
{
    new Point(0, 0), new Point(0, 1), new Point(1, 1)
}

);

// Add a new path to a polyline, which has a single path already.
pline.AddPath(new Point[]
{
    new Point(2, 2), new Point(2, 1)
}

);

// Alternatively, add an empty path and add points to it afterwards.
pline.AddPath();
pline.AddPoint(new Point(3, 1));
pline.AddPoint(new Point(3, 2));
[VB.NET]
Dim pline As Polyline = New Polyline(New Point() { New Point(0, 0), New Point(0, 1), New Point(1, 1) })

' Add a new path to a polyline, which has a single path already.
pline.AddPath(New Point() { New Point(2, 2), New Point(2, 1)})

' Alternatively, add an empty path and add points to it afterwards.
pline.AddPath()
pline.AddPoint(New Point(3, 1))
pline.AddPoint(New Point(3, 2))
There are also methods to insert, set, and remove entire paths. You cannot add, insert, or set Points into paths that do not exist; if you try to do so, an InvalidOperationException is thrown. This is to preserve the integrity of multipart geometries. Members without path index parameters do not throw the InvalidOperationException when adding new Points to a new Polyline with zero paths; this allows novice users to add Points to a new empty Polyline without being concerned with the details of multipart geometry construction.
Similar conditions also apply to the ring related methods on polygon—AddRing, InsertRing, SetRing, RemoveRing, and the RingCount property. Be aware that paths and rings exist to create multipart geometries; if you only need to work with single part geometries, then simply use the methods without ring or path index parameters. 
Creating or editing multipart polygons can be complex; the direction of points within a ring (clockwise or counterclockwise) indicates if the ring forms the exterior or interior boundary of a part of a Polygon. This allows multipart polygons to represent donut and island cases. To ensure that a Polygon is constructed correctly, use the GeometryOperations.Simplify method. For more information, see the Simplification and geometrical correctness section in this topic.

Tracking multipart geometries

The tracking methods on MapView only allow the creation of single part polygons and polylines—a double-click completes the geometry. If you want to allow the user to track a multipart polyline for example, use multiple TrackPolyline calls in conjunction with the AddPath method. See the following code example:
[C#]
Polygon multipartPolygon = new Polygon();

Polygon firstRing = currentDisplay.TrackPolygon();
if (firstRing != null)
{
    multipartPolygon.AddRing(firstRing.GetRing(0));
}

Polygon secondRing = currentDisplay.TrackPolygon();
if (secondRing != null)
{
    multipartPolygon.AddRing(secondRing.GetRing(0));
}

multipartPolygon = GeometryOperations.Simplify(multipartPolygon);
[VB.NET]
Dim multipartPolygon As Polygon = New Polygon()
Dim firstRing As Polygon = currentDisplay.TrackPolygon()
If Not firstRing Is Nothing Then
    multipartPolygon.AddRing(firstRing.GetRing(0))
End If
Dim secondRing As Polygon = currentDisplay.TrackPolygon()
If Not secondRing Is Nothing Then
    multipartPolygon.AddRing(secondRing.GetRing(0))
End If
multipartPolygon = GeometryOperations.Simplify(multipartPolygon)
If you are using code to create a multipart polygon, instead of relying on the user to create interior rings in the correct orientation (counterclockwise) you can correct the orientation using simplification.

Simplification and geometrical correctness

Geometrical shapes have constraints on their shapes. For example, a Polygon object only represents a valid polygon shape if it has closed rings that clearly define the interior and exterior of the shape. If all constraints are met, a geometry is considered to be "simple." If not met, the geometry is "non-simple."
Geometries retrieved from a table based on a geodatabase will always be simple, as the geodatabase enforces simplicity when it is edited.
Geometrical simplicity is particularly important when looking at the spatial properties of a shape; for example, a non-simple Polygon might return an invalid value for its Area because the shape of the Polygon is not defined correctly; therefore, it cannot have a correct Area value. The GeometryOperations class provides a Simplify method that can be used to apply these rules to an input geometry, resulting in a new corrected copy of the geometry.
Some GeometryOperations always require geometries to be simple or they cannot proceed— for example, the Union operation relies on geometrical shapes to be valid and simple to calculate the shape's Union regions. In such cases, the GeometryOperations class ensures simplicity of inputs internally without the developer needing to perform this simplification; the input geometry is always left unchanged.
For more information about the rules of geometric simplicity, refer to ArcObjects API Library Reference on the ArcGIS Resource Center Web site (see the Simplify method on the ITopologicalOperator interface).

For further information see:

ArcObjects API for ArcGIS Desktop—Library Reference

2D and 3D geometries

ArcGIS Explorer can display using 2D or 3D mode. In 2D mode, any elevation information stored on a geometry is not used by the view. In 3D mode, shapes can be draped onto the elevation surface of the globe or alternatively, can be drawn by using the elevation information stored on the geometry.
The Point, Multipoint, Polyline, Polygon, and Envelope classes are essentially 2D shapes. Although each of these types can store z properties for locations, along with the x and y coordinates, they are generally considered to be 2D; setting a z-value is optional. You might find these shapes referred to elsewhere as "2.5D" indicating that they are somewhere between 2D and true 3D shapes.
Multipatches are the only "true" 3D geometries in ArcGIS Explorer. Multipatches cannot be used as the Geometry for Notes and are returned from the Geometry property of a row from a spatially enabled table connected to a multipatch data source (geodatabases and shapefiles can both store multipatch geometries). ArcGIS Explorer does not define new multipatches or investigate the constituent vericies or faces of existing multipatches.

Specifying the elevation of geometries in ArcGIS Explorer

Elevation information can be stored on geometries by using the Point.Z property, the Envelope.ZMin and Envelope.ZMax properties, or set in the parameterized constructors, as shown in the code example below which sets these properties.
See the following code example:
[C#]
Point pt = new Point(48.867, 2.333, 100);
Envelope env = new Envelope(48.5, 49.0, 0, 49.5, 50.0, 150);
[VB.NET]
Dim pt As Point = New Point(48.867, 2.333, 100)
Dim env As Envelope = New Envelope(48.5, 49.0, 0, 49.5, 50.0, 150)
Polygons, polylines, and multipoints are defined using Points, and elevation information for these types of geoemtry is stored in the Z properties of the individual Point objects that make up the shapes' vertices.
The Z property indicates height in meters. The default Z property is not a number (NaN). Geometries with NaN elevations can still display in 3D mode by being draped on or clamped to the globe surface. Whether a geometry is drawn using its actual elevation information is not determined at the geometry level but by the item using the geometry, for example the Note or Graphic.

Geometrical and spatial operations with elevation information

The Equals method, overridden on the Geometry classes, compares Z properties when checking object equality.
The functions available on GeometryOperations and the spatial searching available by using the Filter class, both operate in 2D space; Z properties are ignored.

Coordinate systems and units of measurement

Coordinate systems are mathematical models that describe how geometries are georeferenced to the surface of the earth and also define the unit of measurement used by the coordinates of a geometry. For more information, see Coordinate system concepts.
In ArcGIS Explorer, coordinate systems are represented by the CoordinateSystem class. The 3D mode in ArcGIS Explorer always uses the Web Mercator Aux Sphere geographical coordinate system; however the 2D mode may have different coordinate systems defined by the read-write MapDisplay.CoordinateSystem2D property.
Layers added to ArcGIS Explorer have a coordinate system (Layer.CoordinateSystem, Raster.CoordinateSystem, Table.CoordinateSystem), and a coordinate system is also associated with a Geometry by its CoordinateSystem property. By default, any new Geometry you create using constructors will have the WGS84 coordinate system (the same system as used by the 3D mode and the default for the 2D mode); you can change this by using the parameterized geometry constructors or by setting the property directly.
There are a number of ways to create a CoordinateSystem object to represent any of the many predefined systems supported by ArcGIS Explorer. The CoordinateSystem class contains a series of nested classes and static properties that return new CoordinateSystem objects. These nested type initializers allow you to logically navigate through a hierarchy of coordinate systems to find the one you require; this hierarchy is the same as the folder structure of projections you might find in other ArcGIS applications. Begin by browsing to the CoordinateSystem.ProjectedCoordinateSystem and CoordinateSystem.GeographicCoordinateSystem nested classes.
The following code example demonstrates using these nested type initializers to create projected and  geographic CoordinateSystem objects:
[C#]
CoordinateSystem bngPcs =
    CoordinateSystem.ProjectedCoordinateSystems.NationalGrids.Europe.BritishNationalGrid;
Point bngPt = new Point(bngPcs);

CoordinateSystem nzGcs =
    CoordinateSystem.GeographicCoordinateSystems.AustraliaNewZealand.NZGD2000;
Point nzPt = new Point();
nzPt.CoordinateSystem = nzGcs;
[VB.NET]
Dim bngPcs As CoordinateSystem = CoordinateSystem.ProjectedCoordinateSystems.NationalGrids.Europe.BritishNationalGridBritishNationalGrid
Dim bngPt As Point = New Point(bngPcs)

Dim nzGcs As CoordinateSystem = CoordinateSystem.GeographicCoordinateSystems.AustraliaNewZealand.NZGD2000
Dim nzPt As Point = New Point()
nzPt.CoordinateSystem = nzGcs
Alternatively, you can create a CoordinateSystem by specifying its unique identifier (if known) or by passing in the path to a .prj file (a format used to store the definition of a coordinate system). See the following code example which demonstrates both of these approaches:
[C#]
CoordinateSystem euroGcs = new CoordinateSystem(4231); // GCS_European_1987.
string[] prjFiles = System.IO.Directory.GetFiles(@"C:\Data\PRJs", "*.prj");
if (prjFiles.Length > 0)
{
    CoordinateSystem firstPrjFile = new CoordinateSystem(prjFiles[0]);
}
[VB.NET]
Dim euroGcs As CoordinateSystem = New CoordinateSystem(4231) ' GCS_European_1987.
Dim prjFiles As String() = System.IO.Directory.GetFiles("C:\Data\PRJs", "*.prj")
If prjFiles.Length > 0 Then
    Dim firstPrjFile As CoordinateSystem = New CoordinateSystem(prjFiles(0))
End If
Members on the CoordinateSystem class indicate the Type (geographic or projected), Id (unique identifier), Unit (see Units of measurement and converting measurements), and  Name. If the object represents a projected coordinate system,  BaseGeographicCoordinateSystem returns the underlying geographic CoordinateSystem upon which a projected system is based.
The Unit property of a CoordinateSystem returns a Unit object which indicates the units of measurement used by the system. A geographic coordinate system uses angular units; for example, the WGS84 coordinate system is a geographical coordinate system specifying coordinates in degrees. A projected coordinate system uses linear units; for example, the North American Datum of 1983 (NAD 1983) Maine East is a projected coordinate system specifying coordinates in meters. The coordinates of a geometry will be in the units of its CoordinateSystem (Geometry.CoordinateSytem).

Units of measurement and converting measurements

The Unit class represents a specific instance of a unit of measurement - either a linear, angular or area unit as indicated by the UnitType property.
The Unit class contains a number of nested classes and static properties which return new Unit objects representing any of the predefined units of measurement supported by ArcGIS Explorer. These nested type initializers includes most common units of measurement, for example, the linear units of meters, miles, and nautical miles, and the angular units of degrees, rads, and grads. Refer to the Unit.Angular, Unit.Linear and Unit.Area nested classes for more information.
Units can also be created by specifying a unique identifier, if known, in the Unit class constructors.
See the following code example which demonstrates both of these approaches:
[C#]
Unit mets = new Unit(9001); // International meter.
Unit degs = Unit.Angular.Degrees;
[VB.NET]
Dim mets As Unit = New Unit(9001) ' International meter.
Dim degs As Unit = Unit.Angular.Degrees
The Unit class also provides other measurement related functionality, in addition to indicating the name and type of the units represented. For example, you can use the GetPluralName and GetDisplayName methods to return strings representing the name of the unit in a user-friendly format, suitable for use in user interfaces (UIs). See the following code example which reports the name of the units used in the current MapDisplay:
[C#]
Unit currentDisplayUnit;
ESRI.ArcGISExplorer.Mapping.MapDisplay disp =
    ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay;
if (disp.DisplayMode == DisplayMode.Display2D)
{
    currentDisplayUnit = disp.CoordinateSystem2D.Unit;
}

else
{
    currentDisplayUnit =
        CoordinateSystem.GeographicCoordinateSystems.World.WGS1984.Unit;
}

MessageBox.Show("The view units are " + currentDisplayUnit.GetDisplayName
                (UnitNameOptions.Detailed));
[VB.NET]
Dim currentDisplayUnit As Unit
Dim disp As ESRI.ArcGISExplorer.Mapping.MapDisplay = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay
If disp.DisplayMode = DisplayMode.Display2D Then
    currentDisplayUnit = disp.CoordinateSystem2D.Unit
Else
    currentDisplayUnit = CoordinateSystem.GeographicCoordinateSystems.World.WGS1984.Unit
End If
MessageBox.Show("The view units are " & currentDisplayUnit.GetDisplayName(UnitNameOptions.Detailed))
The Unit class can also be used to convert measurements between two different linear or two different angular units, for example, converting miles to kilometers.
There is often no need to create new instances of the Unit class, as any existing CoordinateSystem has a Unit property. You can use this, for example, to convert a measurement from the units of a geometry into other units. For more information, see How to convert a measurement to a different unit

Problems using angular units as units of measurements

The Polyline.Length and Polygon.Area properties use the units of the CoordinateSystem to return their values, for example, length in meters or area in square meters. However, if using a geographic coordinate system (which has angular units), length and area are not coherent values. With angular units, 1 degree of latitude varies slightly, and 1 degree of longitude varies greatly between the equator and the poles. See the following example:
  • At the equator, 1 degree of latitude is 110.57 kilometers (68.7 miles).
  • At the poles, 1 degree of latitude is 111.69 kilometers (69.4 miles).
  • At the equator, 1 degree of longitude is 111.05 kilometers (69 miles).
  • At 60 degrees N latitude, 1 degree of longitude is 55.52 kilometers (34.5 miles) and at the poles, converges to 0 miles.
Therefore, to compare the length of two polylines representing two roads in different locations on the earth (for example to determine which was the shorter distance to drive), a distance in linear units would be required to obtain a comparable measurement.
For this reason, geometries with geographic coordinate systems (which use angular units) throw an exception from the Length and Area properties. Instead, you can use the GeodesicUtilities class, which provides functions to report the length and area of geometries, returning the measurement in linear units of your choice. See the following code example:
[C#]
string displayName = Unit.Linear.Meters.GetDisplayName(UnitNameOptions.Simple);

double polylineLength = GeodesicUtilities.Length(pline, Unit.Linear.Meters);
MessageBox.Show("The Polyine has a length of: " + polylineLength + displayName);

double polygonArea = GeodesicUtilities.Area(pgon, Unit.Area.SquareMeters);
MessageBox.Show("The Polygon has an area of: " + polygonArea + " square " +
                displayName);
[VB.NET]
Dim displayName As String = Unit.Linear.Meters.GetDisplayName(UnitNameOptions.Simple)

Dim polylineLength As Double = GeodesicUtilities.Length(pline, Unit.Linear.Meters)
MessageBox.Show("The Polyine has a length of: " & polylineLength & displayName)

Dim polygonArea As Double = GeodesicUtilities.Area(pgon, Unit.Area.SquareMeters)
MessageBox.Show("The Polygon has an area of: " & polygonArea & " square " & displayName)
This utility class is used inside the Measure tool in the ArcGIS Explorer application. Because Length and Area use the units of the CoordinateSystem, the conversion is not performed automatically within the length and area properties, as the units of the returned values would not then be clear.
This also affects other methods as follows:
  • SearchByDistance method on the table only allows you to specify a distance in linear units (search distances in angular units create egg-shaped buffers).
  • Unit.Convert method only allows conversion from angular-to-angular, linear-to-linear or area-to-area units of measurement.

See Also:

How to convert a measurement to a different unit
Coordinate system concepts
Sample: Update Note geometry