GeoGeometry Class

A geometry, as defined by GeoJSON and the Simple Features of the OGC: a GeoPoint, a GeoMultiPoint, a GeoLineString, a GeoMultiLineString, a GeoPolygon, a GeoMultiPolygon or a GeoGeometryCollection.

public abstract class GeoGeometry

Remarks

The geometries are immutable.

Properties

NameDescription
CrossesAntimeridianGets a value that indicates whether a line or a ring of the geometry has an edge that is meant to cross the 180th meridian: an edge whose ends are more than 180° of longitude apart, such as an edge from the longitude 179 to the longitude -179. The edges whose ends are both on the 180th meridian, such as the edges of a box around the whole world from -180 to 180, do not count.
IsEmptyGets a value that indicates whether the geometry has no position.
LabelPositionGets a position to label the geometry: the centroid of the exterior ring of its largest polygon (so the islands of a country do not pull it away), else the mean of the positions of its lines, else the mean of its points. The centroid is computed on the longitudes and latitudes, as on an equirectangular map. A ring with an edge that crosses the 180th meridian (see GeoGeometry.CrossesAntimeridian) and the positions on both sides of it are taken as they are on the globe, so the label does not move to the other side of the world. It is null for an empty geometry.
TypeGets the type of the geometry.

CrossesAntimeridian

GeoGeometry.cs

Gets a value that indicates whether a line or a ring of the geometry has an edge that is meant to cross the 180th meridian: an edge whose ends are more than 180° of longitude apart, such as an edge from the longitude 179 to the longitude -179. The edges whose ends are both on the 180th meridian, such as the edges of a box around the whole world from -180 to 180, do not count.

public bool CrossesAntimeridian { get; }

Property value

bool

Remarks

RFC 7946 wants such geometries split along the 180th meridian: the operations of this class draw the edge from 179 to -179 the long way, through the Greenwich meridian. Split them with GeoGeometry.SplitAtAntimeridian, or use GeoEdgeType.Geodesic edges.

Gets a value that indicates whether the geometry has no position.

public bool IsEmpty { get; }

Property value

bool

LabelPosition

GeoGeometry.cs

Gets a position to label the geometry: the centroid of the exterior ring of its largest polygon (so the islands of a country do not pull it away), else the mean of the positions of its lines, else the mean of its points. The centroid is computed on the longitudes and latitudes, as on an equirectangular map. A ring with an edge that crosses the 180th meridian (see GeoGeometry.CrossesAntimeridian) and the positions on both sides of it are taken as they are on the globe, so the label does not move to the other side of the world. It is null for an empty geometry.

public GeoPosition? LabelPosition { get; }

Property value

GeoPosition?

Type

Gets the type of the geometry.

public abstract GeoGeometryType Type { get; }

Property value

GeoGeometryType

Methods

NameDescription
Buffer(double, GeoBufferOptions?)Gets the area within a distance of the geometry, such as a zone around a position for a geofence or a corridor along a route.
Clip(GeoBounds)Cuts the geometry to a box: the parts of the points, lines and polygons that are inside it.
ConvexHull()Gets the smallest convex polygon that contains every position of the geometry.
Difference(GeoGeometry)Gets the area of this geometry that is outside another one.
Distance(GeoGeometry)Gets the shortest distance between this geometry and another one, on the WGS 84 ellipsoid.
GetBoundaryLines()Gets the rings of the polygons of the geometry as closed lines, such as the coastlines of land polygons.
GetBounds()Gets the smallest box that contains the geometry.
GetBounds(GeoEdgeType)Gets the smallest box that contains the geometry, whose edges are drawn as an edge type says.
GetPositions()Gets the positions of the geometry: every position of every point, line and ring, in order.
GetSimpleGeometries()Gets the simple geometries of the geometry: itself for a simple geometry, its parts for a multi-geometry or a collection, recursively.
Intersection(GeoGeometry)Gets the area that this geometry and another one have in common.
MakeValid()Repairs the polygons of the geometry: a ring that crosses itself or another ring of its polygon, a hole outside its exterior ring, rings in the wrong direction or repeated positions. Each polygon becomes the area its rings enclose an odd number of times (a bow-tie becomes two triangles), and a multi-polygon the union of the areas of its polygons. The exterior rings of the result turn counter-clockwise and its holes clockwise, as RFC 7946 wants them.
Simplify(double)Simplifies the lines and the rings of the geometry with the Douglas–Peucker algorithm: the positions that are closer than the tolerance to the line between the positions kept around them are removed. The simplified polygons are repaired with GeoGeometry.MakeValid, since removing positions can make a ring cross itself or another one.
SplitAtAntimeridian()Splits the lines and the polygons of the geometry along the 180th meridian, as RFC 7946 wants it, and moves every longitude to [-180, 180]. The edges that cross the 180th meridian (see GeoGeometry.CrossesAntimeridian) take the shortest way, and the longitudes greater than 180 or smaller than -180 go around the world.
Transform(CoordinateReferenceSystem, CoordinateReferenceSystem)Gets a geometry of the same type whose positions are converted from a coordinate reference system to another one, such as from Lambert 93 to the longitudes and latitudes of WGS 84.
Transform(Func<GeoPosition, GeoPosition>)Gets a geometry of the same type whose positions are transformed, such as positions in another coordinate system converted to longitudes and latitudes.
Union(GeoGeometry)Gets the union of the area of this geometry and of the area of another one.

Buffer(double, GeoBufferOptions?)

GeoGeometry.cs

Gets the area within a distance of the geometry, such as a zone around a position for a geofence or a corridor along a route.

public GeoGeometry? Buffer(double distance, GeoBufferOptions? options = null)

Parameters

distance double
The distance, in meters. A negative distance shrinks the polygons; the points and lines then have no buffer.
options GeoBufferOptions?
The shape of the joins and of the ends of the lines, or null for round ones.

Returns

GeoGeometry? The buffer, a GeoPolygon or a GeoMultiPolygon, or null when it is empty: a point or a line with a distance of 0 or less, or a polygon that shrinks to nothing.

Exceptions

ArgumentOutOfRangeException
distance is infinite or not a number.
InvalidOperationException
A coordinate of a polygon is not a number between -100,000 and 100,000.

Remarks

The positions at the distance are computed on the WGS 84 ellipsoid, and joined by edges straight in degrees: the circles are polygons of 4 × GeoBufferOptions.SegmentsPerQuarterCircle sides. The edges of the geometry are cut in pieces that span less than half a degree of latitude. The result is combined as by GeoGeometry.Union: its positions are on the grid of ten-millionths of a degree. A buffer that contains a pole is not handled, and one that crosses the 180th meridian has longitudes beyond 180 or -180.

Clip(GeoBounds)

GeoGeometry.cs

Cuts the geometry to a box: the parts of the points, lines and polygons that are inside it.

public GeoGeometry? Clip(GeoBounds bounds)

Parameters

bounds GeoBounds
The box.

Returns

GeoGeometry? The part of the geometry that is inside the box, or null when nothing is. The geometry itself when it is entirely inside. A line that leaves the box and comes back becomes a GeoMultiLineString. The polygons are cut as by GeoGeometry.Intersection. Where a line crosses the side of the box, the new position gets the altitude, the measure and the time interpolated between the positions around it, when both have one.

Exceptions

ArgumentException
The box is empty: its south side is north of its north side.

Remarks

A box whose west side is east of its east side crosses the 180th meridian (see GeoBounds.CrossesAntimeridian): the result is the part of the geometry east of its west side and the part west of its east side, as a multi-geometry. Split the geometries that cross the 180th meridian with GeoGeometry.SplitAtAntimeridian first.

ConvexHull()

GeoGeometry.cs

Gets the smallest convex polygon that contains every position of the geometry.

public GeoGeometry? ConvexHull()

Returns

GeoGeometry? The convex hull: a GeoPolygon whose exterior ring turns counter-clockwise, a GeoLineString between the two ends when the positions are on a line, a GeoPoint when they are all the same, or null for an empty geometry. The positions of the result are positions of the geometry.

Remarks

The hull is computed on the longitudes and latitudes, as on an equirectangular map: its edges are straight in degrees.

Difference(GeoGeometry)

GeoGeometry.cs

Gets the area of this geometry that is outside another one.

public GeoGeometry? Difference(GeoGeometry other)

Parameters

other GeoGeometry
The other geometry: a polygon, a multi-polygon or a collection of polygons.

Returns

GeoGeometry? The difference, or null when it is empty.

Exceptions

InvalidOperationException
This geometry is not a polygon, a multi-polygon or a collection of polygons.
ArgumentException
other is not a polygon, a multi-polygon or a collection of polygons.

Remarks

See GeoGeometry.Union for how the rings are read and what the result is made of.

Distance(GeoGeometry)

GeoGeometry.cs

Gets the shortest distance between this geometry and another one, on the WGS 84 ellipsoid.

public double? Distance(GeoGeometry other)

Parameters

other GeoGeometry
The other geometry.

Returns

double? The distance, in meters: 0 when the geometries meet, such as a point inside a polygon or two lines that cross. null when one of the geometries is empty. The altitudes are ignored.

Remarks

The edges are straight in degrees, as for the other operations, and the inside of the polygons is the inside as tested by GeoPolygon.Contains. The distance between the nearest positions is computed with the formulas of Vincenty, accurate to a millimeter, except for nearly antipodal positions, where it is the great-circle distance (within 0.5%). The nearest position of an edge is found to a fraction of a millimeter on edges of a few kilometers.

GetBoundaryLines()

GeoGeometry.cs

Gets the rings of the polygons of the geometry as closed lines, such as the coastlines of land polygons.

public IEnumerable<GeoLineString> GetBoundaryLines()

Returns

IEnumerable<GeoLineString> A line for each ring of each polygon, exterior rings and holes, in order. Nothing for points and lines.

GetBounds overloads

GetBounds()

GeoGeometry.cs

Gets the smallest box that contains the geometry.

public GeoBounds? GetBounds()
Returns

GeoBounds? The box, or null for an empty geometry.

Remarks

The box contains the positions, as the edges are straight in degrees (GeoEdgeType.Planar): it does not cross the 180th meridian.

GetBounds(GeoEdgeType)

GeoGeometry.cs

Gets the smallest box that contains the geometry, whose edges are drawn as an edge type says.

public GeoBounds? GetBounds(GeoEdgeType edgeType)
Parameters
edgeType GeoEdgeType
How the edges are drawn.
Returns

GeoBounds? The box, or null for an empty geometry. With GeoEdgeType.Planar, the box of GeoGeometry.GetBounds. With GeoEdgeType.Geodesic, the smallest box that contains the shortest great-circle arcs between the consecutive positions: it can cross the 180th meridian (its west side is east of its east side, as RFC 7946 allows), such as the box of a flight from Tokyo to San Francisco or of the parts of Fiji on both sides of the 180th meridian, and it goes past the latitudes of the positions where the arcs bend toward a pole. A ring that goes around a pole, such as the coast of Antarctica, gives a box that contains the pole and every longitude.

Exceptions
ArgumentOutOfRangeException
edgeType is not a value of GeoEdgeType.

GetPositions()

Gets the positions of the geometry: every position of every point, line and ring, in order.

public abstract IEnumerable<GeoPosition> GetPositions()

Returns

IEnumerable<GeoPosition> The positions.

GetSimpleGeometries()

GeoGeometry.cs

Gets the simple geometries of the geometry: itself for a simple geometry, its parts for a multi-geometry or a collection, recursively.

public IEnumerable<GeoGeometry> GetSimpleGeometries()

Returns

IEnumerable<GeoGeometry> The points, line strings and polygons of the geometry.

Intersection(GeoGeometry)

GeoGeometry.cs

Gets the area that this geometry and another one have in common.

public GeoGeometry? Intersection(GeoGeometry other)

Parameters

other GeoGeometry
The other geometry: a polygon, a multi-polygon or a collection of polygons.

Returns

GeoGeometry? The intersection, or null when it is empty.

Exceptions

InvalidOperationException
This geometry is not a polygon, a multi-polygon or a collection of polygons.
ArgumentException
other is not a polygon, a multi-polygon or a collection of polygons.

Remarks

See GeoGeometry.Union for how the rings are read and what the result is made of.

MakeValid()

GeoGeometry.cs

Repairs the polygons of the geometry: a ring that crosses itself or another ring of its polygon, a hole outside its exterior ring, rings in the wrong direction or repeated positions. Each polygon becomes the area its rings enclose an odd number of times (a bow-tie becomes two triangles), and a multi-polygon the union of the areas of its polygons. The exterior rings of the result turn counter-clockwise and its holes clockwise, as RFC 7946 wants them.

public GeoGeometry MakeValid()

Returns

GeoGeometry The repaired geometry: a polygon becomes a GeoPolygon, or a GeoMultiPolygon when it is cut in several parts. The positions of the polygons move to the nearest ten-millionth of a degree (about a centimeter), and lose their altitude, measure and time. The consecutive repeated positions of the lines (same coordinates and altitude) are removed, the first one being kept; the points are unchanged.

Exceptions

InvalidOperationException
A coordinate of a polygon is not a number between -100,000 and 100,000.

Remarks

The computation is exact on the grid of ten-millionths of a degree, as on an equirectangular map: the edges are straight in degrees.

Simplify(double)

GeoGeometry.cs

Simplifies the lines and the rings of the geometry with the Douglas–Peucker algorithm: the positions that are closer than the tolerance to the line between the positions kept around them are removed. The simplified polygons are repaired with GeoGeometry.MakeValid, since removing positions can make a ring cross itself or another one.

public GeoGeometry? Simplify(double tolerance)

Parameters

tolerance double
The largest distance between the geometry and its simplification, in degrees: 0.001° is about 100 meters.

Returns

GeoGeometry? The simplified geometry, or null when every line and ring collapses. The points are unchanged.

Exceptions

ArgumentOutOfRangeException
tolerance is negative, infinite or not a number.

SplitAtAntimeridian()

GeoGeometry.cs

Splits the lines and the polygons of the geometry along the 180th meridian, as RFC 7946 wants it, and moves every longitude to [-180, 180]. The edges that cross the 180th meridian (see GeoGeometry.CrossesAntimeridian) take the shortest way, and the longitudes greater than 180 or smaller than -180 go around the world.

public GeoGeometry SplitAtAntimeridian()

Returns

GeoGeometry The geometry itself when no edge crosses the 180th meridian and every longitude is in [-180, 180]. Otherwise, a line that crosses it becomes a GeoMultiLineString whose parts end and start on it, at the longitudes 180 and -180, and a polygon a GeoMultiPolygon with a polygon on each side. The points are moved, not split. The positions where a line crosses the meridian are interpolated as on an equirectangular map. A polygon is cut with GeoGeometry.Clip: the positions of a polygon that is cut move to the nearest ten-millionth of a degree and lose their altitude. A ring that goes around a pole, such as the coast of Antarctica, is closed through the pole it is nearest to.

Exceptions

InvalidOperationException
A coordinate of a polygon to split is not a number between -100,000 and 100,000.

Transform overloads

Transform(CoordinateReferenceSystem, CoordinateReferenceSystem)

GeoGeometry.cs

Gets a geometry of the same type whose positions are converted from a coordinate reference system to another one, such as from Lambert 93 to the longitudes and latitudes of WGS 84.

Parameters
source CoordinateReferenceSystem
The coordinate reference system of the positions of this geometry.
target CoordinateReferenceSystem
The coordinate reference system to convert the positions to, such as CoordinateReferenceSystem.Wgs84.
Returns

GeoGeometry The converted geometry.

Remarks

The positions are converted one by one: the edges between them are not curved to follow the projection.

Transform(Func<GeoPosition, GeoPosition>)

GeoGeometry.cs

Gets a geometry of the same type whose positions are transformed, such as positions in another coordinate system converted to longitudes and latitudes.

public GeoGeometry Transform(Func<GeoPosition, GeoPosition> transform)
Parameters
transform Func<GeoPosition, GeoPosition>
The function that transforms each position. Return position with { Longitude = ..., Latitude = ... } to keep its altitude, measure and time.
Returns

GeoGeometry The transformed geometry.

Union(GeoGeometry)

GeoGeometry.cs

Gets the union of the area of this geometry and of the area of another one.

public GeoGeometry? Union(GeoGeometry other)

Parameters

other GeoGeometry
The other geometry: a polygon, a multi-polygon or a collection of polygons.

Returns

GeoGeometry? The union, or null when it is empty.

Exceptions

InvalidOperationException
This geometry is not a polygon, a multi-polygon or a collection of polygons.
ArgumentException
other is not a polygon, a multi-polygon or a collection of polygons.

Remarks

The exterior ring of each polygon adds its area, and its holes remove theirs, whatever their direction: call GeoGeometry.MakeValid first on polygons whose rings cross. The result is a GeoPolygon or a GeoMultiPolygon whose positions are on the grid of ten-millionths of a degree.