# GeometryEngine

Performs geometric operations such as spatial relationship tests, reprojections, shape manipulations, topological query and analysis operations on Geometry objects. Capabilities include:

GeometryEngine generally operates in two dimensions; operations do not account for z-values unless documented as such for a specific method (for example GeometryEngine.projectOrNull(Geometry, SpatialReference) transforms z-values in some cases).

GeometryEngine provides both planar (Euclidean) and geodetic versions of many operations. Be aware that methods named with only the operation are the planar versions (GeometryEngine.bufferOrNull(Geometry, Double), for example), while the geodetic equivalent has "Geodetic" appended to the name (for example GeometryEngine.bufferGeodeticOrNull(Geometry, Double, LinearUnit, Double, GeodeticCurveType)).

Planar methods are suitable for data with a projected coordinate system, especially for local, large-scale areas. Geodetic methods are better suited to data with a geographic spatial reference (see SpatialReference.isGeographic), especially for large-area, small-scale use.

200.1.0

## Functions

fun area(geometry: Geometry): Double

Calculates the area of the given geometry. This planar measurement uses 2D Cartesian mathematics to compute the area. It is based upon the SpatialReference of the input geometry. If the input geometry does not use an 'area preserving' spatial reference, the result can be inaccurate. You have two options available to calculate a more accurate result:

fun areaGeodetic(geometry: Geometry, unit: AreaUnit?, curveType: GeodeticCurveType): Double

Calculates the geodesic area of the given geometry using a geodetic curve. The term Geodesic[https://developers.arcgis.com/documentation/glossary/geodesic/] means calculating the shortest distance between two points on a sphere. Using geodesic algorithms to calculate distances provides a highly accurate way to obtain length and area of measurements of geographic features. The geodesic algorithm uses the concept of the great circle[https://developers.arcgis.com/documentation/glossary/great-circle/] to obtain the shortest route between two points along the Earth’s surface. The area measurement obtained via this method is typically superior to that returned by the GeometryEngine.area(Geometry) method, which provides a planar measurement[https://developers.arcgis.com/documentation/glossary/planar-measurement/] that can introduce distortion depending on the SpatialReference the geometry is in.

Calculates the boundary of the given geometry. For Point - returns an empty geometry. Points have no boundary. For Multipoint - returns an empty geometry. Points have no boundary. For Polyline - returns a multipoint containing the end points of the polyline's parts. For Polygon - returns a polyline describing its outer and inner rings.

fun bufferGeodeticOrNull(geometry: Geometry, distance: Double, distanceUnit: LinearUnit?, maxDeviation: Double, curveType: GeodeticCurveType): Polygon?

Creates a buffer polygon at the specified distance around the given geometry, calculated using a geodetic curve. Geodesic buffers account for the actual shape of the Earth. Distances are calculated between points on a curved surface (the geoid) as opposed to points on a flat surface (the Cartesian plane).

fun bufferOrNull(geometry: Geometry, distance: Double): Polygon?

Creates a buffer polygon at the specified distance around the given geometry. This is a planar buffer operation. Use GeometryEngine.bufferGeodeticOrNull(Geometry, Double, LinearUnit, Double, GeodeticCurveType) to produce geodetic buffers. This planar measurement uses 2D Cartesian mathematics to compute the buffer area. It is based upon the SpatialReference of the input geometry. If the input geometry does not use an 'area preserving' spatial reference, the result can be inaccurate. You have two options available to calculate a more accurate result:

fun clipOrNull(geometry: Geometry, envelope: Envelope): Geometry?

Constructs the portion of a geometry that intersects an envelope. If the Geometry intersects the Envelope, the portion of the Geometry contained within the Envelope is returned. If no part of the Geometry lies within the Envelope, an empty Geometry is returned. If the Geometry lies completely within the Envelope, the entire Geometry is returned.

Returns an Envelope representing the minimum extent that encloses all geometries in the given collection. The given geometries must have consistent spatial references.

fun combineExtentsOrNull(geometry1: Geometry, geometry2: Geometry): Envelope?

Returns an Envelope representing the minimum extent that encloses both geometry1 and geometry2. The given geometries must have consistent spatial references.

fun contains(geometry1: Geometry, geometry2: Geometry): Boolean

Tests if geometry1 contains geometry2. This spatial relationship test is based on the Dimensionally Extended 9 Intersection Model (DE-9IM) developed by Clementini, et al., and is discussed further in the web pages: DE-9IM[https://en.wikipedia.org/wiki/DE-9IM] and https://developers.arcgis.com/documentation/mapping-apis-and-services/spatial-analysis/geometry-analysis/spatial-relationship/.

Calculates the minimum bounding geometry (convex hull) that completely encloses the given geometry. The convex hull is the minimal bounding geometry that encloses the input geometry, such that all outer angles are convex. If you imagine a rubber band stretched around the input geometry, the rubber band takes the shape of the convex hull.

fun createPointAlongOrNull(polyline: Polyline, distance: Double): Point?

Return the point at the given distance along the line. If distance is less than or equal to zero, the point returned is coincident with the start of the line. If distance is greater than or equal to the line's length, the point returned is coincident with the end of the line. If the line has multiple parts, and the distance falls exactly on a boundary between two parts, the returned point will be coincident with either the end of one part or the start of the next, but which one is undetermined.

fun <T : Geometry> createWithM(geometry: T, m: Double?): T

Return a copy of a geometry with the supplied m-value. If the given geometry already has m-values, they are replaced within the resulting geometry by the supplied value. The resulting geometry has Geometry.hasM true. If the m-value supplied is null, then the geometry's m-value will be removed, and the resulting geometry has Geometry.hasM false.

fun <T : Geometry> createWithZ(geometry: T, z: Double?): T

Return a copy of a geometry with the supplied z-coordinate. If the given geometry already has z-coordinates, they are replaced within the resulting geometry by the supplied value. The resulting geometry has Geometry.hasZ true. If the z-coordinate supplied is null, then the geometry's z-coordinate will be removed, and the resulting geometry has Geometry.hasZ false.

fun <T : Geometry> createWithZAndM(geometry: T, z: Double?, m: Double?): T

Return a copy of a geometry with the supplied z-coordinate and m-value. If the given geometry already has z-coordinates or m-values, they are replaced in the resulting geometry by the supplied values. The resulting geometry has both Geometry.getHasZ() and Geometry.getHasM() true. If the z-coordinate supplied is null, then the geometry's z-coordinate will be removed, and the resulting geometry has Geometry.hasZ false. If the m-value supplied is null, then the geometry's m-value will be removed, and the resulting geometry has Geometry.hasM false.

fun crosses(geometry1: Geometry, geometry2: Geometry): Boolean

Test is geometry1 crosses geometry2. Two polylines cross if their intersection contains only points, and at least one of the points of intersection is internal to both polylines. A polyline and polygon cross if a connected part of the polyline is partly inside and partly outside the polygon. A polyline and polygon cross if they share a polyline in common on the interior of the polygon, which is not equal to the entire polyline. The target and join features must be either polylines or polygons.

fun densifyGeodeticOrNull(geometry: Geometry, maxSegmentLength: Double, lengthUnit: LinearUnit?, curveType: GeodeticCurveType): Geometry?

Densifies the input geometry by creating additional vertices along the geometry, using a geodesic curve.

fun densifyOrNull(geometry: Geometry, maxSegmentLength: Double): Geometry?

Densifies the input geometry by inserting additional vertices along the geometry at an interval defined by maxSegmentLength. Additional vertices are not inserted on segments of the input Envelope, Polygon, or Polyline that are shorter than maxSegmentLength.

fun differenceOrNull(geometry1: Geometry, geometry2: Geometry): Geometry?

Constructs the set-theoretic difference between two geometries. This method returns a geometry consisting of the parts of geometry1 that are not in geometry2. It performs a spatial subtraction from the two input geometries. The order of the two input geometry arguments produces different results if they are switched. Think of the difference equation as:

fun disjoint(geometry1: Geometry, geometry2: Geometry): Boolean

Tests if the two geometries are disjoint. Geometries are disjoint if their boundaries or interiors do not intersect.

fun distanceGeodeticOrNull(point1: Point, point2: Point, distanceUnit: LinearUnit?, azimuthUnit: AngularUnit?, curveType: GeodeticCurveType): GeodeticDistanceResult?

Calculates the geodesic distance between two given points and calculates the azimuth at both points for the geodesic curve that connects the points.

fun distanceOrNull(geometry1: Geometry, geometry2: Geometry): Double?

Calculates the simple planar (Euclidean) distance between two geometries. This planar measurement uses 2D Cartesian mathematics to compute the distance. It is based upon the SpatialReference of the input geometries. If the input geometries do not use an 'distance preserving' spatial reference, the result can be inaccurate. You have two options available to calculate a more accurate result:

Constructs a geodesic ellipse centered on a specific point. Constructs a geodesic ellipse centered on the specified point. It returns a piecewise approximation of a geodesic ellipse (or geodesic circle, if GeodesicEllipseParameters.semiAxis1Length = GeodesicEllipseParameters.semiAxis2Length) consisting of LineSegment objects.

fun equals(geometry1: Geometry, geometry2: Geometry): Boolean

Tests if two geometries are equal The geometries are equal if they have the same spatial reference systems, geometry type, points and occupy the same space. For a more strict comparison of the two geometries use Geometry.equals(Geometry).

fun extend(polyline: Polyline, extender: Polyline, extendOptions: Set<GeometryExtendOptions>): Polyline?

Extends a polyline using a polyline as the extender using the type of extension specified with extendOptions. The output polyline has the first and last segment of each path extended to the extender if the segments can be interpolated to intersect the extender. In the case that the segments can be extended to multiple segments of the extender, the shortest extension is chosen. Only end points for paths that are not shared by the end points of other paths are extended. If the polyline cannot be extended by the input extender, then null is returned.

fun fractionAlong(line: Polyline, point: Point, tolerance: Double): Double

Finds the location on the line nearest the input point, expressed as the fraction along the line's total geodesic length, if the point is within the specified distance from the closest location on the line. The line and point must have consistent spatial references. Supports true curves.

fun generalizeOrNull(geometry: Geometry, maxDeviation: Double, removeDegenerateParts: Boolean): Geometry?

Generalizes the given geometry by removing vertices based on the Douglas-Poiker algorithm. Point and Multipoint geometries are left unchanged. Envelope is converted to a Polygon and then generalized.

fun intersectionOrNull(geometry1: Geometry, geometry2: Geometry): Geometry?

Calculates the intersection of two geometries. The result has the same dimensionality as the lower dimensionality of the two intersecting geometries. If there is no intersection with this dimensionality, returns an empty geometry. For example, the intersection of two polygons (geometries with area, so they have dimensionality of 2) or, say, a polygon and an envelope (also an area) is a polygon. Similarly, the intersection of a polyline (a line, so dimensionality of 1) and another polyline is always a polyline. Therefore when computing the intersection of polylines, this function does not return points where they cross, but rather lines of overlap. If there are no lines of overlap, an empty polyline is returned even if the input lines cross. To obtain all intersections, irrespective of dimensionality, see GeometryEngine.tryIntersections(Geometry, Geometry).

fun intersects(geometry1: Geometry, geometry2: Geometry): Boolean

Tests if two geometries intersect each other. A geometry intersects another geometry if it shares any portion of its geometry with the other geometry feature. If either geometry contain, is within, crosses, touches, or overlaps the other geometry, they intersect.

fun isSimple(geometry: Geometry): Boolean

Test if the geometry is topologically simple. Point geometry is always simple.

Calculates an interior point for the given polygon. This point can be used by clients to place a label for the polygon. Supports true curves.

fun length(geometry: Geometry): Double

Calculates the length of the given geometry. This planar measurement uses 2D Cartesian mathematics to compute the length. It is based upon the SpatialReference of the input geometry. If the input geometry is not using an 'distance preserving' spatial reference, the result can be inaccurate. You have two options available to calculate a more accurate result:

fun lengthGeodetic(geometry: Geometry, lengthUnit: LinearUnit?, curveType: GeodeticCurveType): Double

Calculates the geodesic length of the geometry. Supports true curves, calculating the result by densifying curves.

fun move(geometry: Geometry, deltaX: Double, deltaY: Double): Geometry

Moves the provided geometry by the specified distances along the x-axis and y-axis. Planar measurements of distance can be extremely inaccurate if using an unsuitable spatial reference. Ensure that you understand the potential for error with the geometry's spatial reference. If you need to calculate more accurate results, consider using a different spatial reference. For input geometries with a geographic spatial reference, consider projecting to an appropriate projected coordinate system before attempting to move them, as the distance represented by angular units of measure will differ depending on the geometry's location on the earth. See Spatial references[https://developers.arcgis.com/documentation/spatial-references/] for more information.

Determines the nearest point in the input geometry to the input point using a simple planar measurement. Input geometry of type Envelope is not supported. To find the nearest coordinate on an Envelope, convert it to a Polygon first using GeometryEngine.boundaryOrNull(Geometry).

fun nearestCoordinateGeodetic(geometry: Geometry, point: Point, maxDeviation: Double, deviationUnit: LinearUnit?): ProximityResult?

Determines the nearest point in the input geometry to the input point, by using a shape preserving geodesic approximation of the input geometry. All geometry types are supported for the geometry parameter.

fun nearestVertex(geometry: Geometry, point: Point): ProximityResult?

Returns a ProximityResult that describes the nearest vertex in the input geometry to the input point. Input geometry of type Envelope is not supported. To find the nearest vertex on an Envelope, convert it to a Polygon first.

Normalizes the input geometry so that it does not intersect the antimeridian. This may be necessary when wrap around is enabled on the map. Normalization is used when a geometry intersects the minimum or maximum meridian of the spatial reference, or when the geometry is completely outside of the meridian range. You may wish to use this method to normalize geometries before passing them to methods that require coordinates within the spatial reference domain, for example geodatabase editing methods or geocoding services.

fun offsetOrNull(geometry: Geometry, distance: Double, offsetType: GeometryOffsetType, bevelRatio: Double, flattenError: Double): Geometry?

Creates an offset version of the input geometry. The offset operation creates a geometry that is a constant distance from the input geometry. It is similar to buffering, but produces a one-sided result. If distance 0, then the offset geometry is constructed to the right of the input geometry, otherwise it is constructed to the left. For a simple polygon, the orientation of outer rings is clockwise and for inner rings it is counterclockwise. So the "right side" of a simple polygon is always its inside. The bevelRatio is multiplied by the offset distance and the result determines how far a mitered offset intersection can be from the input curve before it is beveled.

fun overlaps(geometry1: Geometry, geometry2: Geometry): Boolean

Tests if two geometries overlap. Two geometries overlap when they have the same dimension and when their intersection result is a geometry of the same dimension. If the intersection result is a geometry with a lesser dimension than the input geometries, the method returns false. For example, two input polygons must return a polygon to overlap. If two polygons intersect each other at exactly one point, then no overlap has occurred because the intersection result is a point, whose dimension is zero.

fun <T : Geometry> projectOrNull(geometry: T, spatialReference: SpatialReference): T?

Projects the given geometry from its current spatial reference system into the given spatial reference system. A default best-choice DatumTransformation is applied to the project operation. To control the specific transformation used, use the GeometryEngine.project(Geometry, SpatialReference, DatumTransformation) overload.

fun <T : Geometry> projectOrNull(geometry: T, outputSpatialReference: SpatialReference, datumTransformation: DatumTransformation?): T?

Projects the given geometry from its current spatial reference system into the given output spatial reference system, applying the datum transformation provided. Use this overload to project a geometry if the difference between the input geometry's SpatialReference and the outputSpatialReference involves a change of datum, and you do not wish to use the default datum transformation used by GeometryEngine.project(Geometry, SpatialReference).

fun relate(geometry1: Geometry, geometry2: Geometry, relation: String): Boolean

Test if the two geometries are related using a custom relation. You can test for a custom spatial relationship by defining your own relation. For example, you can create a relation that tests if two geometries intersect and touch.

fun reshape(geometry: Multipart, reshaper: Polyline): Multipart?

Reshape polygons or polylines with a single path polyline. Performs the reshape operation on a polygon or polyline using a single path polyline as the reshaper. The output geometry takes the shape of the Multi_path where it first intersects the reshaper to the last intersection. The first and last intersection points of the reshaper are chosen closest to the end points of the reshaper in the case that multiple intersections are found. For polygons, only individual paths can be reshaped. However, polylines can be reshaped across paths. If the geometry cannot be reshaped by the input reshaper, then null is returned.

fun rotate(geometry: Geometry, angle: Double, origin: Point? = null): Geometry

Rotates the geometry by the specified angle of rotation around the provided origin point. The angle of rotation is used in the form of the modulo of 360 degrees; for example rotating by 540 degrees is equivalent to rotating the geometry by 180 degrees. A positive value corresponds to a counterclockwise rotation.

fun scale(geometry: Geometry, scaleX: Double, scaleY: Double, origin: Point? = null): Geometry

Scales the given geometry by the specified factors from the specified origin point. If the origin Point has a different SpatialReference than that of the geometry parameter, the point will be reprojected before the geometry is scaled, using the default transformation.

Constructs a geodesic sector defined by a geodesic arc and 2 radii. Creates a sector as a polygon, polyline, or multipoint geometry. A geodesic sector is defined by a geodesic elliptical arc and two radii extending from the center point of the arc to the points where they each intersect the arc. The arc is a portion of an ellipse. The ellipse is defined by a center point, the lengths of its semi-major and semi-minor axes, and the direction of its semi-major axis. The first radius of the sector is defined by the start direction angle relative to the direction of the semi-major axis. The second radius is the sum of the start direction and the sector angle.

fun <T : Geometry> simplifyOrNull(geometry: T): T?

Simplifies the given geometry to make it topologically consistent according to its geometry type. Supports true curves.

fun symmetricDifferenceOrNull(geometry1: Geometry, geometry2: Geometry): Geometry?

Calculates the symmetric difference (exclusive or) of the two geometries. Symmetric difference obtains those parts of the two input geometries that do not overlap. If you want to perform a more atomic-level difference operation where the spatial subtraction of two input geometries might look different if the order of the geometries were switched, consider using GeometryEngine.differenceOrNull(Geometry, Geometry).

fun touches(geometry1: Geometry, geometry2: Geometry): Boolean

Test if the two geometries have at least one boundary point in common, but no interior points. This spatial relationship test is based on the Dimensionally Extended 9 Intersection Model (DE-9IM) developed by Clementini, et al., and is discussed further in the web pages: DE-9IM[https://en.wikipedia.org/wiki/DE-9IM] and https://developers.arcgis.com/documentation/mapping-apis-and-services/spatial-analysis/geometry-analysis/spatial-relationship/.

fun tryAutoComplete(existingBoundaries: Iterable<Polygon>, newBoundaries: Iterable<Polyline>): List<Polygon>

Fills the closed gaps between polygons using polygon boundaries and polylines as the boundary for the new polygons. The new polygons are created in the closed empty areas bounded by the edges of the existing polygon boundaries and the new boundary polylines. The newly created polygons do not overlap any existing polygons or polylines, and the boundary of a new polygon must contain at least one edge from the polylines. Only polygons that intersect the input polylines participate in the operation, so it makes sense to prefilter the input accordingly.

fun tryBuffer(geometries: Iterable<Geometry>, distances: Iterable<Double>, unionResult: Boolean): List<Polygon>

Creates a buffer or buffers relative to the given collection of geometries. This is a planar buffer operation. Use GeometryEngine.bufferGeodeticOrNull(Geometry, Double, LinearUnit, Double, GeodeticCurveType) to produce geodetic buffers. This planar measurement uses 2D Cartesian mathematics to compute the buffer areas. It is based upon the SpatialReference of the input geometries. If the input geometries do not use an 'area preserving' spatial reference, the results can be inaccurate. You have two options available to calculate a more accurate results:

fun tryBufferGeodetic(geometries: Iterable<Geometry>, distances: Iterable<Double>, distanceUnit: LinearUnit?, maxDeviation: Double, curveType: GeodeticCurveType, unionResult: Boolean): List<Polygon>

Creates and returns a geodesic buffer or buffers relative to the given collection of geometries. Geodesic buffers account for the actual shape of the Earth. Distances are calculated between points on a curved surface (the geoid) as opposed to points on a flat surface (the Cartesian plane).

fun tryConvexHull(geometries: Iterable<Geometry>, merge: Boolean): List<Geometry>

Calculates the minimum bounding geometry (convex hull) for the geometries in the given collection. The geometries must have consistent spatial references. If merge is true, returns a single convex hull that encloses all the geometries in the collection as a single geometry in an array. If merge is false, returns the minimum bounding geometry that completely encloses each of the geometries in the given collection as an array of geometries. If geometries is empty, returns an empty array. Returns null on error.

fun tryCut(geometry: Geometry, cutter: Polyline): List<Geometry>

Cuts the 'geometry' into parts with the 'cutter' Polyline. When a Polyline or Polygon is cut, it is split where it intersects the cutter Polyline. The cut parts are output as a collection of geometries. All left cuts are grouped together in the first Geometry, all right cuts are grouped in the second Geometry, any uncut parts are output as separate geometries.

fun tryIntersections(geometry1: Geometry, geometry2: Geometry): List<Geometry>

Calculates the intersection of two geometries. The returned collection contains one geometry of each dimension for which there are intersections. For example, if both inputs are polylines, the collection contains at most two geometries: the first a multipoint containing the points at which the lines cross, and the second a polyline containing the lines of overlap. If a crossing point lies within a line of overlap, only the line of overlap is present. The result set is not self-intersecting. If there are no crossing points or there are no lines of overlap, the respective geometry is not present in the returned collection. If the input geometries do not intersect, the resulting collection is empty. The table below shows, for each combination of pairs of input geometry types, the types of geometry that are contained within the returned collection if there are intersections of that type.

fun tryMoveGeodetic(pointCollection: Iterable<Point>, distance: Double, distanceUnit: LinearUnit?, azimuth: Double, azimuthUnit: AngularUnit?, curveType: GeodeticCurveType): List<Point>

Moves each point in the point collection in a specified direction by a geodesic distance. Each point in the input collection of points must use the same spatial reference. The returned collection is in the same order as the input, but with new points at their destination locations. Specifying a negative distance moves points in the opposite direction from azimuth.