Skip to content

ProSnippets GeometryEngine

UmaHarano edited this page Nov 12, 2025 · 1 revision
Language:              C#  
Subject:               GeometryEngine  
Contributor:           ArcGIS Pro SDK Team <[email protected]>  
Organization:          Esri, http://www.esri.com  
Date:                  11/7/2025  
ArcGIS Pro:            3.6  
Visual Studio:         2022  

GeometryEngine functions

Accelerate Geometries

// Use acceleration to speed up relational operations.  Accelerate your source geometry only if you are going to test many other geometries against it. 
  // Acceleration is applicable for polylines and polygons only. Note that accelerated geometries take more memory so if you aren't going to get any
  // benefit from accelerating it, don't do it. 

  // The performance of the following GeometryEngine functions are the only ones which can be improved with an accelerated geometry.
  //    GeometryEngine.Instance.Contains
  //    GeometryEngine.Instance.Crosses
  //    GeometryEngine.Instance.Disjoint
  //    GeometryEngine.Instance.Disjoint3D
  //    GeometryEngine.Instance.Equals
  //    GeometryEngine.Instance.Intersects
  //    GeometryEngine.Instance.Relate
  //    GeometryEngine.Instance.Touches
  //    GeometryEngine.Instance.Within


  // Note: Needs QueuedTask to run
  {
    // accelerate the geometry to test
    var acceleratedPoly = GeometryEngine.Instance.AccelerateForRelationalOperations(polygon);

    // loop through all the geometries to test against
    foreach (var testPolygon in testPolygons)
    {
      bool contains = GeometryEngine.Instance.Contains(acceleratedPoly, testPolygon);
      bool within = GeometryEngine.Instance.Within(acceleratedPoly, testPolygon);
      bool crosses = GeometryEngine.Instance.Crosses(acceleratedPoly, testPolygon);

      // do something with the results...
    }
  }

Determine area of a polygon

var g1 = PolygonBuilderEx.FromJson("{\"rings\": [ [ [0, 0], [10, 0], [10, 10], [0, 10] ] ] }");
  double d = GeometryEngine.Instance.Area(g1);
  // d = -100.0         //negative due to wrong ring orientation
  d = GeometryEngine.Instance.Area(GeometryEngine.Instance.SimplifyAsFeature(g1));
  // d = 100.0        // feature has been simplifed; ring orientation is correct

Determine the boundary of a multi-part Polygon

// create a donut polygon.  Must use the PolygonBuilderEx object

  List<Coordinate2D> outerPts =
  [
    new Coordinate2D(10.0, 10.0),
    new Coordinate2D(10.0, 20.0),
    new Coordinate2D(20.0, 20.0),
    new Coordinate2D(20.0, 10.0),
  ];

  List<Coordinate2D> innerPts =
  [
    new Coordinate2D(13.0, 13.0),
    new Coordinate2D(17.0, 13.0),
    new Coordinate2D(17.0, 17.0),
    new Coordinate2D(13.0, 17.0),
  ];

  Polygon donut = null;

  // add the outer points
  PolygonBuilderEx pb = new(outerPts);
  // add the inner points (note they are defined anticlockwise)
  pb.AddPart(innerPts);
  // get the polygon
  donut = pb.ToGeometry();

  // get the boundary 
  Geometry g = GeometryEngine.Instance.Boundary(donut);
  Polyline boundary = g as Polyline;

  // use the boundary...

Buffer a MapPoint

// buffer a point
  MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 1.0, SpatialReferences.WGS84);
  Geometry ptBuffer = GeometryEngine.Instance.Buffer(pt, 5.0);
  Polygon buffer = ptBuffer as Polygon;

Buffer a Circular Arc

// create the circular arc
  MapPoint fromPt = MapPointBuilderEx.CreateMapPoint(2, 1);
  MapPoint toPt = MapPointBuilderEx.CreateMapPoint(1, 2);
  Coordinate2D interiorPt = new(1 + Math.Sqrt(2) / 2, 1 + Math.Sqrt(2) / 2);

  EllipticArcSegment circularArc = EllipticArcBuilderEx.CreateCircularArc(fromPt, toPt, interiorPt);

  // buffer the arc
  polyline = PolylineBuilderEx.CreatePolyline(circularArc);
  Geometry lineBuffer = GeometryEngine.Instance.Buffer(polyline, 10);

Buffer multiple MapPoints

// creates a buffer around each MapPoint

  List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
    MapPointBuilderEx.CreateMapPoint(1.0, 2.0),
    MapPointBuilderEx.CreateMapPoint(2.0, 2.0),
    MapPointBuilderEx.CreateMapPoint(2.0, 1.0),
  ];

  Geometry ptsBuffer = GeometryEngine.Instance.Buffer(pts, 0.25);
  Polygon bufferResult = ptsBuffer as Polygon;      // bufferResult will have 4 parts

Buffer many different Geometry Types

List<Coordinate2D> coords =
  [
    new Coordinate2D(1, 2), new Coordinate2D(3, 4), new Coordinate2D(4, 2),
    new Coordinate2D(5, 6), new Coordinate2D(7, 8), new Coordinate2D(8, 4),
    new Coordinate2D(9, 10), new Coordinate2D(11, 12), new Coordinate2D(12, 8),
    new Coordinate2D(10, 8), new Coordinate2D(12, 12), new Coordinate2D(14, 10)
  ];

  List<Geometry> manyGeometries =
  [
    MapPointBuilderEx.CreateMapPoint(coords[9]),
    PolylineBuilderEx.CreatePolyline([coords[0], coords[1], coords[2]], SpatialReferences.WGS84),
    PolylineBuilderEx.CreatePolyline([coords[3], coords[4], coords[5]]),
    PolygonBuilderEx.CreatePolygon([coords[6], coords[7], coords[8]])
  ];

  Geometry manyGeomBuffer = GeometryEngine.Instance.Buffer(manyGeometries, 0.25);

Interpolate Z values on a polyline

List<Coordinate3D> coords2 =
[
  new Coordinate3D(0, 0, 0),
  new Coordinate3D(0, 1000, double.NaN),
  new Coordinate3D(1000, 1000, 50),
  new Coordinate3D(1000, 1000, 76),
  new Coordinate3D(0, 1000, double.NaN),
  new Coordinate3D(0, 0, 0)
];

  SpatialReference sr = SpatialReferences.WebMercator;

  polyline = PolylineBuilderEx.CreatePolyline(coords2, sr);

  // polyline.HasZ = true
  // polyline.Points[1].HasZ = true
  // polyline.Points[1].Z  = NaN   
  // polyline.Points[4].HasZ = true
  // polyline.Points[4].Z  = NaN   

  Polyline polylineNoNaNZs = GeometryEngine.Instance.CalculateNonSimpleZs(polyline, 0) as Polyline;

  // polylineNoNaNZs.Points[1].HasZ = true
  // polylineNoNaNZs.Points[1].Z = 25  (halfway between 0 and 50)
  // polylineNoNaNZs.Points[4].HasZ = true
  // polylineNoNaNZs.Points[4].Z = 38  (halfway between 76 and 0)

Interpolate M values on a polygon

List<MapPoint> coords =
  [
    MapPointBuilderEx.CreateMapPoint(0, 0, 0, 0),
    MapPointBuilderEx.CreateMapPoint(0, 1000),
    MapPointBuilderEx.CreateMapPoint(1000, 1000, 10, 50)
  ];

  SpatialReference sr = SpatialReferences.WebMercator;

  polygon = PolygonBuilderEx.CreatePolygon(coords, sr);

  // polygon.HasM = true
  // polygon.Points[1].HasM = true
  // polygon.Points[1].M = NaN

  Polygon polygonNoNaNMs = GeometryEngine.Instance.CalculateNonSimpleMs(polygon, 0) as Polygon;

  // polygonNoNaNMs.Points[1].HasM = true
  // polygonNoNaNMs.Points[1].M = 25  (halfway between 0 and 50)

Center an envelope around X,Y

Envelope env = EnvelopeBuilderEx.CreateEnvelope(1.0, 1.0, 5.0, 5.0);
  Envelope centered = GeometryEngine.Instance.CenterAt(env, 2.0, 2.0);

  // centered.Center.X = 2.0
  // centered.Center.Y = 2.0
  // centered.XMin = 0
  // centered.YMin = 0
  // centered.XMax = 4
  // centered.YMax = 4

  centered = env.CenterAt(4.0, 3.0);
  // centered.Center.X == 4.0
  // centered.Center.Y == 3.0
  // centered.XMin == 2.0
  // centered.YMin == 1.0
  // centered.XMax == 6.0
  // centered.YMax == 5.0

Find the centroid of geometries

// simple polygon
  List<Coordinate2D> list2D =
  [
    new Coordinate2D(0, 0),
    new Coordinate2D(0, 2),
    new Coordinate2D(2, 2),
    new Coordinate2D(2, 0),
  ];

  polygon = PolygonBuilderEx.CreatePolygon(list2D, SpatialReferences.WGS84);

  // verify it is simple
  bool isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polygon);
  // find the centroid
  MapPoint centroid = GeometryEngine.Instance.Centroid(polygon);
  // centroid.X = 1
  // centroid.Y = 1

  // map Point
  MapPoint pt1 = MapPointBuilderEx.CreateMapPoint(1, 2, 3, 4, SpatialReferences.WGS84);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(5, 2, double.NaN, 7);

  // pt1.HasZ = true
  // pt1.HasM = true
  centroid = GeometryEngine.Instance.Centroid(pt1);
  // centroid.HasZ = true
  // centroid.HasM = true
  // pt1.IsEqual(centroid) = true

  // multipoint
  List<MapPoint> list = [pt1, pt2];
  Multipoint multipoint = MultipointBuilderEx.CreateMultipoint(list);
  // multipoint.HasZ = true
  // multipoint.HasM = true

  centroid = GeometryEngine.Instance.Centroid(multipoint);
  // centroid.X = 3
  // centroid.Y = 2
  // centroid.HasZ = false
  // centroid.HasM = false

Clip a Polyline

// clip a polyline by an envelope

  Envelope env = EnvelopeBuilderEx.CreateEnvelope(2.0, 2.0, 4.0, 4.0);
  LineSegment line = LineBuilderEx.CreateLineSegment(new Coordinate2D(0, 3), new Coordinate2D(5.0, 3.0));
  polyline = PolylineBuilderEx.CreatePolyline(line);

  Geometry clipGeom = GeometryEngine.Instance.Clip(polyline, env);

Clip a Polyline by a Polygon

// clip a polyline by a polygon

  List<Coordinate2D> list =
  [
    new Coordinate2D(1.0, 1.0),
    new Coordinate2D(1.0, 4.0),
    new Coordinate2D(4.0, 4.0),
    new Coordinate2D(4.0, 1.0),
  ];

  polygon = PolygonBuilderEx.CreatePolygon(list, SpatialReferences.WGS84);

  LineSegment crossingLine = LineBuilderEx.CreateLineSegment(MapPointBuilderEx.CreateMapPoint(0, 3), MapPointBuilderEx.CreateMapPoint(5.0, 3.0));
  Polyline p = PolylineBuilderEx.CreatePolyline(crossingLine);
  Geometry geometry = GeometryEngine.Instance.Clip(p, polygon.Extent);

Construct a geodetic line with specified distance and azimuth

var sr = SpatialReferenceBuilder.CreateSpatialReference(4326);
  var mapPoint = MapPointBuilderEx.CreateMapPoint(15, 60, sr);

  // calculate
  var polylineGeodetic = GeometryEngine.Instance.ConstructGeodeticLineFromDistance(GeodeticCurveType.Loxodrome, mapPoint, 5000000, 45, null, CurveDensifyMethod.ByLength, 300000);

Construct a geodetic line connecting points

var sr = SpatialReferenceBuilder.CreateSpatialReference(4326);

  var pt1 = MapPointBuilderEx.CreateMapPoint(60, 180, sr);
  var pt2 = MapPointBuilderEx.CreateMapPoint(60, 0, sr);

  // densify by length
  var gl = GeometryEngine.Instance.ConstructGeodeticLineFromPoints(GeodeticCurveType.Geodesic, pt1, pt2, null, CurveDensifyMethod.ByLength, -3.356);

  // densify by deviation
  gl = GeometryEngine.Instance.ConstructGeodeticLineFromPoints(GeodeticCurveType.Geodesic, pt1, pt2, null, CurveDensifyMethod.ByDeviation, -0.0026);

Construct a Point at a distance and angle from an existing Point

MapPoint inPoint = MapPointBuilderEx.CreateMapPoint(3, 4);
  double angle = 0;
  double distance = 10;

  MapPoint outPoint = GeometryEngine.Instance.ConstructPointFromAngleDistance(inPoint, angle, distance);
  // outPoint.X = 13
  // outPoint.Y = 4

  SpatialReference sr = SpatialReferences.WGS84;
  inPoint = MapPointBuilderEx.CreateMapPoint(0, 0, sr);
  angle = Math.PI;
  distance = 1;

  outPoint = GeometryEngine.Instance.ConstructPointFromAngleDistance(inPoint, angle, distance, sr);
  // outPoint.X = -1
  // outPoint.Y = 0

Construct a Polygon from a set of Polylines

List<Coordinate2D> firstLinePts = [new Coordinate2D(1.0, 1.0), new Coordinate2D(1.0, 4.0)];

  List<Coordinate2D> secondLinePts = [new Coordinate2D(4.0, 4.0), new Coordinate2D(4.0, 1.0)];

  List<Coordinate2D> thirdLinePts = [new Coordinate2D(0.0, 2.0), new Coordinate2D(5.0, 2.0)];

  List<Coordinate2D> fourthLinePts = [new Coordinate2D(0.0, 3.0), new Coordinate2D(5.0, 3.0)];

  // build the polylines
  List<Polyline> polylines =
  [
    PolylineBuilderEx.CreatePolyline(firstLinePts),
PolylineBuilderEx.CreatePolyline(secondLinePts),
PolylineBuilderEx.CreatePolyline(thirdLinePts),
PolylineBuilderEx.CreatePolyline(fourthLinePts),
      ];

  // construct polygons from the polylines
  var polygons = GeometryEngine.Instance.ConstructPolygonsFromPolylines(polylines);

  // polygons.Count = 1
  // polygon coordinates are (1.0, 2.0), (1.0, 3.0), (4.0, 3.0), (4.0, 2.0)

Polygon contains MapPoints, Polylines, Polygons

// build a polygon      
  List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
MapPointBuilderEx.CreateMapPoint(1.0, 2.0),
MapPointBuilderEx.CreateMapPoint(2.0, 2.0),
MapPointBuilderEx.CreateMapPoint(2.0, 1.0),
      ];

  Polygon poly = PolygonBuilderEx.CreatePolygon(pts);

  // test if an inner point is contained
  MapPoint innerPt = MapPointBuilderEx.CreateMapPoint(1.5, 1.5);
  bool contains = GeometryEngine.Instance.Contains(poly, innerPt);   // contains = true

  // test a point on a boundary
  contains = GeometryEngine.Instance.Contains(poly, poly.Points[0]);     // contains = false

  // test an interior line
  MapPoint innerPt2 = MapPointBuilderEx.CreateMapPoint(1.25, 1.75);
  List<MapPoint> innerLinePts = [innerPt, innerPt2];

  // test an inner polyline
  polyline = PolylineBuilderEx.CreatePolyline(innerLinePts);
  contains = GeometryEngine.Instance.Contains(poly, polyline);   // contains = true

  // test a line that crosses the boundary
  MapPoint outerPt = MapPointBuilderEx.CreateMapPoint(3, 1.5);
  List<MapPoint> crossingLinePts = [innerPt, outerPt];

  polyline = PolylineBuilderEx.CreatePolyline(crossingLinePts);
  contains = GeometryEngine.Instance.Contains(poly, polyline);     // contains = false

  // test a polygon in polygon
  Envelope env = EnvelopeBuilderEx.CreateEnvelope(innerPt, innerPt2);
  contains = GeometryEngine.Instance.Contains(poly, env);      // contains = true

Determine convex hull

//
  // convex hull around a point - returns a point
  //

  MapPoint pt = MapPointBuilderEx.CreateMapPoint(2.0, 2.0);
  Geometry hull = GeometryEngine.Instance.ConvexHull(pt);
  MapPoint hullPt = hull as MapPoint;
  // nullPt.X = 2
  // hullPt.Y = 2


  List<MapPoint> list =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
MapPointBuilderEx.CreateMapPoint(1.0, 2.0),
MapPointBuilderEx.CreateMapPoint(2.0, 2.0),
MapPointBuilderEx.CreateMapPoint(2.0, 1.0),
      ];

  //
  // convex hull around a multipoint - returns a polygon
  //

  // build a multiPoint
  Multipoint multiPoint = MultipointBuilderEx.CreateMultipoint(list);

  hull = GeometryEngine.Instance.ConvexHull(multiPoint);
  Polygon hullPoly = hull as Polygon;
  // hullPoly.Area = 1
  // hullPoly.PointCount = 5

  // 
  // convex hull around a line - returns a polyline or polygon
  // 

  List<MapPoint> polylineList = [MapPointBuilderEx.CreateMapPoint(1.0, 1.0), MapPointBuilderEx.CreateMapPoint(2.0, 2.0)];

  // 2 point straight line
  polyline = PolylineBuilderEx.CreatePolyline(polylineList);
  hull = GeometryEngine.Instance.ConvexHull(polyline);
  Polyline hullPolyline = hull as Polyline;
  // hullPolyline.Length = Math.Sqrt(2)
  // hullPolyline.PointCount = 2

  // 3 point angular line
  polylineList.Add(MapPointBuilderEx.CreateMapPoint(2.0, 1.0));
  polyline = PolylineBuilderEx.CreatePolyline(polylineList);
  hull = GeometryEngine.Instance.ConvexHull(polyline);
  hullPoly = hull as Polygon;
  // hullPoly.Length = 2 + Math.Sqrt(2)
  // hullPoly.Area = 0.5
  // hullPoly.PointCount = 4

  //
  // convex hull around a polygon - returns a polygon
  //

  // simple polygon
  Polygon poly = PolygonBuilderEx.CreatePolygon(list);
  hull = GeometryEngine.Instance.ConvexHull(poly);
  hullPoly = hull as Polygon;

  // hullPoly.Length = 4.0
  // hullPoly.Area = 1.0
  // hullPoly.PointCount = 5

  // polygon with concave angles
  List<MapPoint> funkyList =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
MapPointBuilderEx.CreateMapPoint(1.5, 1.5),
MapPointBuilderEx.CreateMapPoint(1.0, 2.0),
MapPointBuilderEx.CreateMapPoint(2.0, 2.0),
MapPointBuilderEx.CreateMapPoint(1.5, 1.5),
MapPointBuilderEx.CreateMapPoint(2.0, 1.0),
MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
      ];

  Polygon funkyPoly = PolygonBuilderEx.CreatePolygon(funkyList);
  hull = GeometryEngine.Instance.ConvexHull(funkyPoly);
  hullPoly = hull as Polygon;
  // hullPoly.Length = 4.0
  // hullPoly.Area = 1.0
  // hullPoly.PointCount = 5
  // hullPoly.Points[0] = 1.0, 1.0
  // hullPoly.Points[1] = 1.0, 2.0
  // hullPoly.Points[2] = 2.0, 2.0
  // hullPoly.Points[3] = 2.0, 1.0
  // hullPoly.Points[4] = 1.0, 1.0

Determine if two geometries cross

//
  // pt on pt
  //

  MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 1.0);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(2.0, 2.0);

  bool crosses = GeometryEngine.Instance.Crosses(pt, pt2);         // crosses = false
  crosses = GeometryEngine.Instance.Crosses(pt, pt);               // crosses = false

  // 
  // pt and line
  // 

  List<MapPoint> list =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
MapPointBuilderEx.CreateMapPoint(3.0, 3.0),
MapPointBuilderEx.CreateMapPoint(5.0, 1.0),
      ];

  Polyline line1 = PolylineBuilderEx.CreatePolyline(list);
  crosses = GeometryEngine.Instance.Crosses(line1, pt2);           // crosses = false
  crosses = GeometryEngine.Instance.Crosses(pt2, line1);           // crosses = false
                                                                   // end pt of line
  crosses = GeometryEngine.Instance.Crosses(line1, pt);            // crosses = false

  //
  // pt and polygon
  //
  List<MapPoint> polyPts =
  [
    MapPointBuilderEx.CreateMapPoint(3.0, 2.0),
MapPointBuilderEx.CreateMapPoint(3.0, 6.0),
MapPointBuilderEx.CreateMapPoint(6.0, 6.0),
MapPointBuilderEx.CreateMapPoint(6.0, 2.0),
      ];

  Polygon poly1 = PolygonBuilderEx.CreatePolygon(polyPts);
  crosses = GeometryEngine.Instance.Crosses(poly1, pt);              // crosses = false
  crosses = GeometryEngine.Instance.Crosses(pt, poly1);              // crosses = false

  // 
  // line and line
  //
  List<MapPoint> list2 =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 3.0),
MapPointBuilderEx.CreateMapPoint(3.0, 1.0),
MapPointBuilderEx.CreateMapPoint(5.0, 3.0),
      ];

  Polyline line2 = PolylineBuilderEx.CreatePolyline(list2);
  crosses = GeometryEngine.Instance.Crosses(line1, line2);           // crosses = true

  //
  // line and polygon
  //
  crosses = GeometryEngine.Instance.Crosses(poly1, line1);           // crosses = true

  //
  // polygon and polygon
  //
  Envelope env = EnvelopeBuilderEx.CreateEnvelope(MapPointBuilderEx.CreateMapPoint(1.0, 1.0), MapPointBuilderEx.CreateMapPoint(4, 4));
  Polygon poly2 = PolygonBuilderEx.CreatePolygon(env);
  crosses = GeometryEngine.Instance.Crosses(poly1, poly2);           // crosses = false

Cut a geometry with a polyline

SpatialReference sr = SpatialReferences.WGS84;

  List<MapPoint> list =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, sr),
MapPointBuilderEx.CreateMapPoint(1.0, 4.0, sr),
MapPointBuilderEx.CreateMapPoint(4.0, 4.0, sr),
MapPointBuilderEx.CreateMapPoint(4.0, 1.0, sr),
      ];

  List<Geometry> cutGeometries;

  LineSegment line = LineBuilderEx.CreateLineSegment(MapPointBuilderEx.CreateMapPoint(0, 0, sr), MapPointBuilderEx.CreateMapPoint(3, 6, sr));
  Polyline cutter = PolylineBuilderEx.CreatePolyline(line);

  // polyline
  polyline = PolylineBuilderEx.CreatePolyline(list);
  bool isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polyline);
  cutGeometries = GeometryEngine.Instance.Cut(polyline, cutter) as List<Geometry>;

  Polyline leftPolyline = cutGeometries[0] as Polyline;
  Polyline rightPolyline = cutGeometries[1] as Polyline;

  // leftPolyline.Points[0] = 1, 2
  // leftPolyline.Points[1] = 1, 4
  // leftPolyline.Points[2] = 2, 4

  // rightPolyline.Points.Count = 5
  // rightPolyline.Parts.Count = 2

  ReadOnlySegmentCollection segments0 = rightPolyline.Parts[0];
  // segments0[0].StartCoordinate = 1, 1
  // segments0[0].EndCoordinate = 1, 2

  ReadOnlySegmentCollection segments1 = rightPolyline.Parts[1];
  // segments1.Count = 2
  // segments1[0].StartCoordinate = 2, 4
  // segments1[0].EndCoordinate = 4, 4
  // segments1[1].StartCoordinate = 4, 4
  // segments1[1].EndCoordinate = 4, 1

  // polygon 
  polygon = PolygonBuilderEx.CreatePolygon(list);
  isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polygon);
  cutGeometries = GeometryEngine.Instance.Cut(polygon, cutter) as List<Geometry>;

Densify by Length

// densify a line segment
  MapPoint startPt = MapPointBuilderEx.CreateMapPoint(1.0, 1.0);
  MapPoint endPt = MapPointBuilderEx.CreateMapPoint(1, 21);
  LineSegment line = LineBuilderEx.CreateLineSegment(startPt, endPt);
  polyline = PolylineBuilderEx.CreatePolyline(line);

  Geometry geom = GeometryEngine.Instance.DensifyByLength(polyline, 2);
  Polyline result = geom as Polyline;

  // densify a circular arc
  MapPoint fromPt = MapPointBuilderEx.CreateMapPoint(2, 1);
  MapPoint toPt = MapPointBuilderEx.CreateMapPoint(1, 2);
  Coordinate2D interiorPt = new(1 + Math.Sqrt(2) / 2, 1 + Math.Sqrt(2) / 2);

  EllipticArcBuilderEx cab = new(fromPt, toPt, interiorPt);
  EllipticArcSegment circularArc = cab.ToSegment();
  polyline = PolylineBuilderEx.CreatePolyline(circularArc);
  geom = GeometryEngine.Instance.DensifyByLength(polyline, 2);
  result = geom as Polyline;

Difference between two Polygons

List<MapPoint> polyPts =
  [
    MapPointBuilderEx.CreateMapPoint(3.0, 2.0),
MapPointBuilderEx.CreateMapPoint(3.0, 6.0),
MapPointBuilderEx.CreateMapPoint(6.0, 6.0),
MapPointBuilderEx.CreateMapPoint(6.0, 2.0),
      ];

  Polygon poly1 = PolygonBuilderEx.CreatePolygon(polyPts);

  Envelope env = EnvelopeBuilderEx.CreateEnvelope(MapPointBuilderEx.CreateMapPoint(1.0, 1.0), MapPointBuilderEx.CreateMapPoint(4, 4));
  Polygon poly2 = PolygonBuilderEx.CreatePolygon(env);

  Geometry result = GeometryEngine.Instance.Difference(poly1, poly2);
  Polygon polyResult = result as Polygon;
  // polyResult.Area = 10.0

  result = GeometryEngine.Instance.Difference(poly2, poly1);
  polyResult = result as Polygon;
  // polyResult.Area = 7.0

Determine if two Geometries are disjoint

//
  // pt on pt
  //

  MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 1.0);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(2.0, 2.5);

  bool disjoint = GeometryEngine.Instance.Disjoint(pt, pt2);       // result is true

  MultipointBuilderEx mpb = new();
  mpb.AddPoint(pt);
  mpb.AddPoint(pt2);
  Multipoint multiPoint = mpb.ToGeometry();

  disjoint = GeometryEngine.Instance.Disjoint(multiPoint, pt);     // result is false

  // 
  // pt and line
  // 

  List<MapPoint> list =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
MapPointBuilderEx.CreateMapPoint(3.0, 3.0),
MapPointBuilderEx.CreateMapPoint(5.0, 1.0),
      ];

  Polyline line1 = PolylineBuilderEx.CreatePolyline(list);
  disjoint = GeometryEngine.Instance.Disjoint(line1, pt2);       // result is true

  disjoint = GeometryEngine.Instance.Disjoint(pt2, line1);       // result is true

  // end pt of line
  disjoint = GeometryEngine.Instance.Disjoint(line1, pt);        // result is false

  //
  // pt and polygon
  //
  List<MapPoint> polyPts =
  [
    MapPointBuilderEx.CreateMapPoint(3.0, 2.0),
MapPointBuilderEx.CreateMapPoint(3.0, 6.0),
MapPointBuilderEx.CreateMapPoint(6.0, 6.0),
MapPointBuilderEx.CreateMapPoint(6.0, 2.0),
      ];

  Polygon poly1 = PolygonBuilderEx.CreatePolygon(polyPts);
  disjoint = GeometryEngine.Instance.Disjoint(poly1, pt);          // result is true
  disjoint = GeometryEngine.Instance.Disjoint(pt, poly1);          // result is true

  // 
  // line and line
  //

  List<MapPoint> list2 =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 3.0),
MapPointBuilderEx.CreateMapPoint(3.0, 1.0),
MapPointBuilderEx.CreateMapPoint(5.0, 3.0),
      ];

  Polyline line2 = PolylineBuilderEx.CreatePolyline(list2);
  disjoint = GeometryEngine.Instance.Disjoint(line1, line2);         // result is false

  //
  // line and polygon
  //
  disjoint = GeometryEngine.Instance.Disjoint(poly1, line1);         // result is false
  disjoint = GeometryEngine.Instance.Disjoint(line1, poly1);         // result is false

  //
  // polygon and polygon
  //
  Envelope env = EnvelopeBuilderEx.CreateEnvelope(MapPointBuilderEx.CreateMapPoint(1.0, 1.0), MapPointBuilderEx.CreateMapPoint(4, 4));
  Polygon poly2 = PolygonBuilderEx.CreatePolygon(env);

  disjoint = GeometryEngine.Instance.Disjoint(poly1, poly2);         // result is false


  // disjoint3D

  SpatialReference sr = SpatialReferences.WGS84;

  MapPoint pt3D_1 = MapPointBuilderEx.CreateMapPoint(1, 1, 1, sr);
  MapPoint pt3D_2 = MapPointBuilderEx.CreateMapPoint(2, 2, 2, sr);
  MapPoint pt3D_3 = MapPointBuilderEx.CreateMapPoint(1, 1, 2, sr);

  MultipointBuilderEx mpbEx = new();
  mpbEx.AddPoint(pt3D_1);
  mpbEx.AddPoint(pt3D_2);
  mpbEx.HasZ = true;

  multiPoint = mpbEx.ToGeometry();
  disjoint = GeometryEngine.Instance.Disjoint3D(multiPoint, pt3D_2);     // disjoint = false
  disjoint = GeometryEngine.Instance.Disjoint3D(multiPoint, pt3D_3);     // disjoint = true

Determine distance between two Geometries

MapPoint pt1 = MapPointBuilderEx.CreateMapPoint(1.0, 1.0);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(2.0, 2.0);
  MapPoint pt3 = MapPointBuilderEx.CreateMapPoint(4.0, 2.0);

  //
  // pt and pt 
  //
  double d = GeometryEngine.Instance.Distance(pt1, pt2);         // d = Math.Sqrt(2)

  //
  // pt and multipoint
  //
  List<MapPoint> multiPts = [pt2, pt3];
  Multipoint multiPoint = MultipointBuilderEx.CreateMultipoint(multiPts);
  d = GeometryEngine.Instance.Distance(pt1, multiPoint);         // d = Math.Sqrt(2)

  //
  // pt and envelope
  //
  Envelope env = EnvelopeBuilderEx.CreateEnvelope(pt1, pt2);
  d = GeometryEngine.Instance.Distance(pt1, env);                // d = 0

  //
  // pt and polyline
  //
  List<MapPoint> polylinePts = [MapPointBuilderEx.CreateMapPoint(2.0, 1.0), pt2];
  polyline = PolylineBuilderEx.CreatePolyline(polylinePts);

  d = GeometryEngine.Instance.Distance(pt1, polyline);             // d = 1.0

  //
  // pt and polygon
  //
  Envelope env2 = EnvelopeBuilderEx.CreateEnvelope(MapPointBuilderEx.CreateMapPoint(3.0, 3.0), MapPointBuilderEx.CreateMapPoint(5.0, 5.0));
  Polygon poly = PolygonBuilderEx.CreatePolygon(env2);
  d = GeometryEngine.Instance.Distance(pt1, poly);                 // d = Math.Sqrt(8)

  //
  // envelope and polyline
  //
  d = GeometryEngine.Instance.Distance(env, polyline);             // d = 0

  //
  // polyline and polyline
  //
  List<MapPoint> polylineList = [MapPointBuilderEx.CreateMapPoint(4, 3), MapPointBuilderEx.CreateMapPoint(4, 4)];
  Polyline polyline2 = PolylineBuilderEx.CreatePolyline(polylineList);

  d = GeometryEngine.Instance.Distance(polyline, polyline2);           // d = Math.Sqrt(5)


  //
  // polygon and polygon
  //
  Polygon poly2 = PolygonBuilderEx.CreatePolygon(env);
  d = GeometryEngine.Instance.Distance(poly, poly2);                 // d = Math.Sqrt(2)

Determine 3D distance between two Geometries

// between points 
  MapPoint pt1 = MapPointBuilderEx.CreateMapPoint(1, 1, 1);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(2, 2, 2);
  MapPoint pt3 = MapPointBuilderEx.CreateMapPoint(10, 2, 1);

  // pt1 to pt2
  double d = GeometryEngine.Instance.Distance3D(pt1, pt2);        // d = Math.Sqrt(3)

  // pt1 to pt3
  d = GeometryEngine.Instance.Distance3D(pt1, pt3);        // d = Math.Sqrt(82)

  // pt2 to pt3
  d = GeometryEngine.Instance.Distance3D(pt2, pt3);        // d = Math.Sqrt(65)

  // intersecting lines

  List<MapPoint> list =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, 1.0),
    MapPointBuilderEx.CreateMapPoint(3.0, 3.0, 1.0),
    MapPointBuilderEx.CreateMapPoint(5.0, 1.0, 1.0),
  ];

  Polyline line1 = PolylineBuilderEx.CreatePolyline(list);

  List<MapPoint> list2 =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 3.0, 1.0),
    MapPointBuilderEx.CreateMapPoint(3.0, 1.0, 1.0),
    MapPointBuilderEx.CreateMapPoint(5.0, 3.0, 1.0),
  ];

  Polyline line2 = PolylineBuilderEx.CreatePolyline(list2);

  bool intersects = GeometryEngine.Instance.Intersects(line1, line2);    // intersects = true
  d = GeometryEngine.Instance.Distance3D(line1, line2);                  // d = 0   (distance is 0 when geomtries intersect)

Expand envelopes

Envelope env = EnvelopeBuilderEx.CreateEnvelope(100.0, 100.0, 500.0, 500.0);
  // env.HasZ = false

  Envelope result = GeometryEngine.Instance.Expand(env, 0.5, 0.5, true);
  // result.Center = 300, 300
  // result.XMin = 200
  // result.YMin = 200
  // result.XMax = 400
  // result.YMax = 400

  result = GeometryEngine.Instance.Expand(env, 100, 200, false);
  // result.Center = 300, 300
  // result.XMin = 0
  // result.YMin = -100
  // result.XMax = 600
  // result.YMax = 700

  try
  {
    // expand in 3 dimensions
    result = GeometryEngine.Instance.Expand(env, 0.5, 0.5, 0.5, true);
  }
  catch (InvalidOperationException)
  {
    // the geometry is not Z-Aware
  }

  // expand a 3d envelope
  MapPoint pt1 = MapPointBuilderEx.CreateMapPoint(100, 100, 100);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(200, 200, 200);

  env = EnvelopeBuilderEx.CreateEnvelope(pt1, pt2);
  // env.HasZ = true

  result = GeometryEngine.Instance.Expand(env, 0.5, 0.5, 0.5, true);

  // result.Center = 150, 150, 150
  // result.XMin = 125
  // result.YMin = 125
  // result.ZMin = 125
  // result.XMax = 175
  // result.YMax = 175
  // result.ZMax = 175

Extend a polyline

// build a polyline
  polyline = PolylineBuilderEx.CreatePolyline(
  [
    MapPointBuilderEx.CreateMapPoint(1, 1, 10, 20),
    MapPointBuilderEx.CreateMapPoint(0, 0, 10, 20),
    MapPointBuilderEx.CreateMapPoint(1, -1, 10, 20)
  ]);

  // build the extender line
  var extender = PolylineBuilderEx.CreatePolyline(
  [
    MapPointBuilderEx.CreateMapPoint(2, 2),
    MapPointBuilderEx.CreateMapPoint(2, -2),
  ]);

  // extend
  var result = GeometryEngine.Instance.Extend(polyline, extender, ExtendFlags.KeepEndAttributes);
  Polyline extendedLine = result as Polyline;
  // result.Parts[0].Points[0] = 2, 2, 10, 20
  // result.parts[0].Points[1] = 1, 1, 10, 20
  // result.Parts[0].Points[2] = 0, 0, 10, 20
  // result.Parts[0].Points[3] = 1, -1, 10, 20
  // result.Parts[0].Points[4] = 2, -2, 10, 20

  // change the flags
  result = GeometryEngine.Instance.Extend(polyline, extender, ExtendFlags.NoEndAttributes);
  extendedLine = result as Polyline;
  // result.Parts[0].Points[0] = 2, 2, 0
  // result.parts[0].Points[1] = 1, 1, 10, 20
  // result.Parts[0].Points[2] = 0, 0, 10, 20
  // result.Parts[0].Points[3] = 1, -1, 10, 20
  // result.Parts[0].Points[4] = 2, -2, 0

  // extend
  result = GeometryEngine.Instance.Extend(polyline, extender, ExtendFlags.KeepEndAttributes | ExtendFlags.NoExtendAtTo);
  extendedLine = result as Polyline;
  // result.Parts[0].Points[0] = 2, 2, 10, 20
  // result.parts[0].Points[1] = 1, 1, 10, 20
  // result.Parts[0].Points[2] = 0, 0, 10, 20
  // result.Parts[0].Points[3] = 1, -1, 10, 20

  // extend with no intersection 

  polyline = PolylineBuilderEx.CreatePolyline(
  [
    MapPointBuilderEx.CreateMapPoint(1, 1),
    MapPointBuilderEx.CreateMapPoint(3, 1)
  ]);

  extender = PolylineBuilderEx.CreatePolyline(
  [
    MapPointBuilderEx.CreateMapPoint(1, 4),
    MapPointBuilderEx.CreateMapPoint(3, 4)
  ]);

  result = GeometryEngine.Instance.Extend(polyline, extender, ExtendFlags.Default);
  // result = null

  result = GeometryEngine.Instance.Extend(polyline, extender, ExtendFlags.KeepEndAttributes | ExtendFlags.NoExtendAtTo);

  // Use the result ...

Generalize

Polyline generalizedPolyline = GeometryEngine.Instance.Generalize(polylineWithZ, 200) as Polyline;
  // generalizedPolyline.HasZ = true

  Polygon generalized3DPolyline = GeometryEngine.Instance.Generalize3D(polylineWithZ, 200) as Polygon;
  // generalized3DPolyline.HasZ = true

  // note that generalized3DPolyline and generalizedPolyline will have different definitions
  //  i.e generalizedPolyline.IsEqual(generalized3DPolyline) = false

Calculate the Geodesic Area of a polygon

polygon = PolygonBuilderEx.CreatePolygon(
  [
    MapPointBuilderEx.CreateMapPoint(-10018754.1713946, 10018754.1713946),
    MapPointBuilderEx.CreateMapPoint(10018754.1713946, 10018754.1713946),
    MapPointBuilderEx.CreateMapPoint(10018754.1713946, -10018754.1713946),
    MapPointBuilderEx.CreateMapPoint(-10018754.1713946, -10018754.1713946)
  ], SpatialReferences.WebMercator);
  var area = GeometryEngine.Instance.GeodesicArea(polygon);

  // area is close to 255032810857732.31

  area = GeometryEngine.Instance.GeodesicArea(polygon, AreaUnit.SquareKilometers);
  // area is close to 255032810.85953,

Create a buffer polygon at the specified geodesic distance

// buffer a point
  MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 1.0, SpatialReferences.WGS84);
  Polygon outPolygon = GeometryEngine.Instance.GeodesicBuffer(pt, 5) as Polygon;

  double delta = SpatialReferences.WGS84.XYTolerance * 2 * Math.Sqrt(2);
  ReadOnlyPointCollection points = outPolygon.Points;
  foreach (MapPoint p in points)
  {
    double d = GeometryEngine.Instance.GeodesicDistance(pt, p);
    // d = 5 (+- delta)
  }

  // specify a unit for the distance
  outPolygon = GeometryEngine.Instance.GeodesicBuffer(pt, 5000, LinearUnit.Millimeters) as Polygon;

  // buffer of 0 distance produces an empty geometry
  Geometry g = GeometryEngine.Instance.GeodesicBuffer(pt, 0);
  // g.IsEmpty = true

  // buffer many points
  List<MapPoint> list =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, SpatialReferences.WGS84),
MapPointBuilderEx.CreateMapPoint(10.0, 20.0),
MapPointBuilderEx.CreateMapPoint(40.0, 40.0),
MapPointBuilderEx.CreateMapPoint(60.0, 60.0),
      ];

  outPolygon = GeometryEngine.Instance.GeodesicBuffer(list, 10000) as Polygon;
  // outPolygon.PartCount = 4

  // buffer different geometry types
  List<Coordinate2D> coords =
  [
    new Coordinate2D(1, 2), new Coordinate2D(10, 20), new Coordinate2D(20, 30),
new Coordinate2D(50, 60), new Coordinate2D(70, 80), new Coordinate2D(80, 40),
new Coordinate2D(90, 10), new Coordinate2D(110, 15), new Coordinate2D(120, 30),
new Coordinate2D(10, 40), new Coordinate2D(-10, 40), new Coordinate2D(-10, 50)
  ];

  List<Geometry> manyGeometries =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, SpatialReferences.WGS84),
PolylineBuilderEx.CreatePolyline([coords[0], coords[1], coords[2]], SpatialReferences.WGS84),
PolylineBuilderEx.CreatePolyline([coords[3], coords[4], coords[5]]),
PolygonBuilderEx.CreatePolygon([coords[9], coords[10], coords[11]])
  ];

  outPolygon = GeometryEngine.Instance.GeodesicBuffer(manyGeometries, 20000) as Polygon;

  // specify unit types
  outPolygon = GeometryEngine.Instance.GeodesicBuffer(manyGeometries, 20, LinearUnit.Miles) as Polygon;

Determine geodesic distance between two Geometries

var point1 = MapPointBuilderEx.CreateMapPoint(-170, 45, SpatialReferences.WGS84);
  var point2 = MapPointBuilderEx.CreateMapPoint(170, 45, SpatialReferences.WGS84);

  var distances_meters = GeometryEngine.Instance.GeodesicDistance(point1, point2);
  // distance is approximately 1572912.2066940258 in meters

  var distance_feet = GeometryEngine.Instance.GeodesicDistance(point1, point2, LinearUnit.Feet);
  // distance is approximately  5160473.11904786 in feet

GeodesicEllipse

GeodesicEllipseParameter param = new()
  {
    AxisDirection = 4 * Math.PI / 3,
    Center = new Coordinate2D(-120, 60),
    LinearUnit = LinearUnit.Meters,
    OutGeometryType = GeometryType.Polyline,
    SemiAxis1Length = 6500000,
    SemiAxis2Length = 1500000,
    VertexCount = 800
  };

  Geometry geometry = GeometryEngine.Instance.GeodesicEllipse(param, SpatialReferences.WGS84);
  // geometry.IsEmpty = false

  polyline = geometry as Polyline;
  // polyline.PointCount = 801
  // polyline.PartCount = 1

Determine geodesic length of a line

polyline = PolylineBuilderEx.CreatePolyline(
  [
      MapPointBuilderEx.CreateMapPoint(-10018754.1713946, 10018754.1713946),
  MapPointBuilderEx.CreateMapPoint(10018754.1713946, 10018754.1713946)
  ], SpatialReferences.WebMercator);

  var length = GeometryEngine.Instance.GeodesicLength(polyline);
  // length is approx 5243784.5551844323 in meters

  length = GeometryEngine.Instance.GeodesicLength(polyline, LinearUnit.Miles);
  // length is approx 3258.33666089067 in miles

  var polyline2 = GeometryEngine.Instance.Project(polyline, SpatialReferences.WGS84);
  length = GeometryEngine.Instance.GeodesicLength(polyline2);
  // length is approx 5243784.55518443 in meters after projecting

GeodesicSector

GeodesicSectorParameter param = new()
  {
    ArcVertexCount = 50,
    AxisDirection = Math.PI / 4,
    Center = new Coordinate2D(0, 0),
    LinearUnit = LinearUnit.Meters,
    OutGeometryType = GeometryType.Polygon,
    RadiusVertexCount = 10,
    SectorAngle = 5 * Math.PI / 3,
    SemiAxis1Length = 100000,
    SemiAxis2Length = 20000,
    StartDirection = 11 * Math.PI / 6
  };

  Geometry geometry = GeometryEngine.Instance.GeodesicSector(param, SpatialReferences.WGS84);
  // geometry.IsEmpty = false

  polygon = geometry as Polygon;
  // polygon.PointCount = 68
  // polygon.PartCount = 1

GeodeticDensifyByDeviation - polyline

List<Coordinate2D> coords =
  [
    new Coordinate2D(-80, 0),
new Coordinate2D(-20, 60),
new Coordinate2D(40, 20),
new Coordinate2D(0, -20),
new Coordinate2D(-80, 0)
  ];

  SpatialReference sr = SpatialReferences.WGS84;

  // create a polyline
  polyline = PolylineBuilderEx.CreatePolyline(coords, sr);

  // densify in km
  Polyline geodesicPolyline = GeometryEngine.Instance.GeodeticDensifyByDeviation(polyline, 200, LinearUnit.Kilometers, GeodeticCurveType.Geodesic) as Polyline;
  // densify in m
  geodesicPolyline = GeometryEngine.Instance.GeodeticDensifyByDeviation(polyline, 200, LinearUnit.Meters, GeodeticCurveType.Geodesic) as Polyline;

  // Change curve type to Loxodrome
  Polyline loxodromePolyline = GeometryEngine.Instance.GeodeticDensifyByDeviation(polyline, 200, LinearUnit.Meters, GeodeticCurveType.Loxodrome) as Polyline;

GeodeticDensifyByLength - polygon

List<Coordinate2D> coords =
  [
    new Coordinate2D(-80, 0),
new Coordinate2D(-20, 60),
new Coordinate2D(40, 20),
new Coordinate2D(0, -20),
new Coordinate2D(-80, 0)
  ];

  SpatialReference sr = SpatialReferences.WGS84;

  // create a polygon
  polygon = PolygonBuilderEx.CreatePolygon(coords, sr);

  // get the geodesic lengths of the polygon segments
  ReadOnlySegmentCollection segments = polygon.Parts[0];
  List<double> geoLengths = new(segments.Count);
  foreach (Segment s in segments)
  {
    Polyline line = PolylineBuilderEx.CreatePolyline(s, sr);
    double geoLen = GeometryEngine.Instance.GeodesicLength(line);
    geoLengths.Add(geoLen);
  }

  // find the max length
  geoLengths.Sort();
  double maxLen = geoLengths[^1];

  // densify the polygon (in meters)
  Polygon densifiedPoly = GeometryEngine.Instance.GeodeticDensifyByLength(polygon, maxLen, LinearUnit.Meters, GeodeticCurveType.Geodesic) as Polygon;

  // densify the polygon (in km)
  double maxSegmentLength = maxLen / 10000;
  densifiedPoly = GeometryEngine.Instance.GeodeticDensifyByLength(polygon, maxSegmentLength, LinearUnit.Kilometers, GeodeticCurveType.Geodesic) as Polygon;

Calculate geodetic distance, azimuth between two points

SpatialReference sr = SpatialReferences.WGS84;

  MapPoint p1 = MapPointBuilderEx.CreateMapPoint(111, 55, sr);
  MapPoint p2 = MapPointBuilderEx.CreateMapPoint(95.5845, 64.2285, sr);

  double distance;

  distance = GeometryEngine.Instance.GeodeticDistanceAndAzimuth(p1, p2, GeodeticCurveType.Geodesic, out double az12, out double az21);
  // distance - 1339728.0303777338
  // az12 - 326.235780421405
  // az21 - 132.87425637913955

  distance = GeometryEngine.Instance.GeodeticDistanceAndAzimuth(p1, p2, GeodeticCurveType.Loxodrome, out az12, out az21);
  // distance - 1342745.9687172563
  // az12 - 319.966400332104
  // az21- 139.96640033210397

  distance = GeometryEngine.Instance.GeodeticDistanceAndAzimuth(p1, p2, GeodeticCurveType.GreatElliptic, out az12, out az21);
  // distance - 1339728.038837946
  // az12 - 326.22479262335418
  // az21 - 132.88558894347742

  MapPoint p3 = MapPointBuilderEx.CreateMapPoint(0, 0, sr);
  MapPoint p4 = MapPointBuilderEx.CreateMapPoint(1, 0, sr);

  distance = GeometryEngine.Instance.GeodeticDistanceAndAzimuth(p3, p4, GeodeticCurveType.Geodesic, out az12, out az21);
  // distance - 111319.49079327342
  // az12 - 90
  // az21 - 270

  distance = GeometryEngine.Instance.GeodeticDistanceAndAzimuth(p3, p4, GeodeticCurveType.Geodesic, LinearUnit.Miles, out az12, out az21);
  // distance - 69.1707247134693
  // az12 - 90
  // az21 - 270

Perform Geodetic Move on a set of MapPoints

SpatialReference sr = SpatialReferences.WebMercator;
  var points = new[] { MapPointBuilderEx.CreateMapPoint(0, 0, sr) };
  double distance = 10;
  double azimuth = Math.PI / 2;
  var resultPoints = GeometryEngine.Instance.GeodeticMove(points, sr, distance, LinearUnit.Meters, azimuth, GeodeticCurveType.Geodesic);

  // resultPoints.First().X = 10
  // resultPoints.First().Y = 0
  // resultPoints.First().SpatialReference.Wkid = sr.Wkid

  // Change LinearUnit to Miles
  resultPoints = GeometryEngine.Instance.GeodeticMove(points, sr, distance, LinearUnit.Miles, azimuth, GeodeticCurveType.Geodesic);
  // resultPoints.First().X = 16093.44
  // resultPoints.First().Y = 0

  // Change curve type
  resultPoints = GeometryEngine.Instance.GeodeticMove(points, sr, distance, LinearUnit.Miles, azimuth, GeodeticCurveType.Loxodrome);
  // resultPoints.First().X = 16093.44
  // resultPoints.First().Y = 0

Retrieve coordinate systems

// get all the geographic coordinate systems
  IReadOnlyList<CoordinateSystemListEntry> gcs_list = GeometryEngine.Instance.GetPredefinedCoordinateSystemList(CoordinateSystemFilter.GeographicCoordinateSystem);

  // get the projected coordinate systems
  IReadOnlyList<CoordinateSystemListEntry> proj_list = GeometryEngine.Instance.GetPredefinedCoordinateSystemList(CoordinateSystemFilter.ProjectedCoordinateSystem);

  // get the vertical coordinate systems
  IReadOnlyList<CoordinateSystemListEntry> vert_list = GeometryEngine.Instance.GetPredefinedCoordinateSystemList(CoordinateSystemFilter.VerticalCoordinateSystem);

  // get geographic and projected coordinate systems
  IReadOnlyList<CoordinateSystemListEntry> combined_list = GeometryEngine.Instance.GetPredefinedCoordinateSystemList(CoordinateSystemFilter.GeographicCoordinateSystem | CoordinateSystemFilter.ProjectedCoordinateSystem);

  // investigate one of the entries
  CoordinateSystemListEntry entry = gcs_list[0];
  int wkid = entry.Wkid;
  string category = entry.Category;
  string name = entry.Name;

Retrieve system geographic transformations

// a geographic transformation is the definition of how to project from one spatial reference to another
  IReadOnlyList<GeographicTransformationListEntry> list = GeometryEngine.Instance.GetPredefinedGeographicTransformationList();

  // a GeographicTransformationListEntry consists of Name, Wkid, the From SpatialReference Wkid, the To SpatialReference Wkid
  GeographicTransformationListEntry entry = list[0];

  int fromWkid = entry.FromSRWkid;
  int toWkid = entry.ToSRWkid;
  int wkid = entry.Wkid;
  string name = entry.Name;

Get Sub-curve of a polyline or polygon

SpatialReference sr = SpatialReferences.WGS84;

  List<Coordinate2D> coords =
  [
    new Coordinate2D(-111, 72),
  new Coordinate2D(-108, 68),
  new Coordinate2D(-114, 68)
  ];

  polyline = PolylineBuilderEx.CreatePolyline(coords, sr);

  Polyline subCurve = GeometryEngine.Instance.GetSubCurve(polyline, 0, 5, AsRatioOrLength.AsLength);
  // subCurve.PartCount = 1
  // subCurve.PointCount = 2

  ReadOnlyPointCollection points = subCurve.Points;
  // points[0] = -111, 72
  // points[1] = -108, 68

  subCurve = GeometryEngine.Instance.GetSubCurve(polyline, 0, 0.5, AsRatioOrLength.AsRatio);
  // subCurve.PointCount = 3

  points = subCurve.Points;
  // points[0] = -111, 72
  // points[1] = -108, 68
  // points[2] = -108.5, 68

  List<Coordinate3D> coords3D =
  [
    new Coordinate3D(0, 0, 0),
  new Coordinate3D(0, 1, 1),
  new Coordinate3D(1, 1, 2),
  new Coordinate3D(1, 0, 3)
  ];

  polygon = PolygonBuilderEx.CreatePolygon(coords3D, sr);

  subCurve = GeometryEngine.Instance.GetSubCurve3D(polygon, 0, 1, AsRatioOrLength.AsLength);
  // subCurve.HasZ = true

  points = subCurve.Points;
  // points.Count = 2
  // points[0] = 0, 0, 0
  // points[1] = 0, 0.70710678118654746, 0.70710678118654746

GraphicBuffer

// mitered join and butt caps
  SpatialReference sr = SpatialReferenceBuilder.CreateSpatialReference(102010);
  List<Coordinate2D> coords =
  [
      new Coordinate2D(1400,6200),
  new Coordinate2D(1600,6300),
  new Coordinate2D(1800,6200)
  ];

  polyline = PolylineBuilderEx.CreatePolyline(coords, sr);

  polygon = GeometryEngine.Instance.GraphicBuffer(polyline, 50, LineJoinType.Miter, LineCapType.Butt, 10, 0, -1) as Polygon;

  // bevelled join and round caps
  Envelope envelope = EnvelopeBuilderEx.CreateEnvelope(0, 0, 10000, 10000, SpatialReferences.WebMercator);

  Polygon outPolygon = GeometryEngine.Instance.GraphicBuffer(envelope, 1000, LineJoinType.Bevel, LineCapType.Round, 4, 0, 96) as Polygon;

GraphicBuffer Many

// round join and round caps
  MapPoint point1 = MapPointBuilderEx.CreateMapPoint(0, 0);
  MapPoint point2 = MapPointBuilderEx.CreateMapPoint(1, 1, SpatialReferences.WGS84);
  MapPoint point3 = MapPointBuilderEx.CreateMapPoint(1000000, 1200000, SpatialReferences.WebMercator);
  List<MapPoint> points = [point1, point2, point3];

  IReadOnlyList<Geometry> geometries = GeometryEngine.Instance.GraphicBuffer(points, 5, LineJoinType.Round, LineCapType.Round, 0, 0, 3000);

Intersection between two Polylines

// determine intersection between two polylines

  List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
  MapPointBuilderEx.CreateMapPoint(3.0, 3.0),
  MapPointBuilderEx.CreateMapPoint(5.0, 1.0),
];

  Polyline line1 = PolylineBuilderEx.CreatePolyline(pts);

  List<MapPoint> pts2 =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 3.0),
  MapPointBuilderEx.CreateMapPoint(3.0, 1.0),
  MapPointBuilderEx.CreateMapPoint(5.0, 3.0),
];

  Polyline line2 = PolylineBuilderEx.CreatePolyline(pts2);

  bool intersects = GeometryEngine.Instance.Intersects(line1, line2);    // intersects = true
  Geometry g = GeometryEngine.Instance.Intersection(line1, line2, GeometryDimensionType.EsriGeometry0Dimension);
  Multipoint resultMultipoint = g as Multipoint;

  // result is a multiPoint that intersects at (2,2) and (4,2)

Intersection between two Polygons

// determine intersection between two polygons

  Envelope env1 = EnvelopeBuilderEx.CreateEnvelope(new Coordinate2D(3.0, 2.0), new Coordinate2D(6.0, 6.0));
  Polygon poly1 = PolygonBuilderEx.CreatePolygon(env1);

  Envelope env2 = EnvelopeBuilderEx.CreateEnvelope(new Coordinate2D(1.0, 1.0), new Coordinate2D(4.0, 4.0));
  Polygon poly2 = PolygonBuilderEx.CreatePolygon(env2);

  Polygon polyResult = GeometryEngine.Instance.Intersection(poly1, poly2) as Polygon;

Determine label point for a Polygon

// create a polygon
  List<Coordinate2D> list2D =
  [
    new Coordinate2D(1.0, 1.0),
    new Coordinate2D(1.0, 2.0),
    new Coordinate2D(2.0, 2.0),
    new Coordinate2D(2.0, 1.0),
  ];

  polygon = PolygonBuilderEx.CreatePolygon(list2D);
  bool isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polygon);
  MapPoint pt = GeometryEngine.Instance.LabelPoint(polygon);

Determine Length, Length3D of line

MapPoint c1 = MapPointBuilderEx.CreateMapPoint(1, 2, 3);
  MapPoint c2 = MapPointBuilderEx.CreateMapPoint(4, 2, 4);

  // line segment
  LineSegment line = LineBuilderEx.CreateLineSegment(c1, c2);
  double len = line.Length;     // = 3
  double len3D = line.Length3D;   // = Math.Sqrt(10)

  // polyline
  Polyline p = PolylineBuilderEx.CreatePolyline(line);
  double p_len = p.Length;        // = len = 3
  double p_len3D = p.Length3D;    // = len3D = Math.Sqrt(10)

  double ge_len = GeometryEngine.Instance.Length(p);      // = p_len = len = 3
  double ge_len3d = GeometryEngine.Instance.Length3D(p);    // = p_len3D = len3D = Math.Sqrt(10)

Get the minimum and maximum M values - GetMinMaxM

string json = "{\"hasM\":true,\"rings\":[[[-3000,-2000,10],[-2000,-2000,15],[-1000,-2000,20],[0,-2000,0],[1000,-2000,-20],[2000,-2000,-30],[3000,-2000,10],[4000,-2000,5]]],\"spatialReference\":{\"wkid\":3857}}";
  polygon = PolygonBuilderEx.FromJson(json);

  GeometryEngine.Instance.GetMinMaxM(polygon, out double minM, out double maxM);
  // minM = -30 
  // maxM = 20

  json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,10],[-2000,-2000,null],[-1000,-2000,null]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  GeometryEngine.Instance.GetMinMaxM(polyline, out minM, out maxM);
  // minM = 10
  // maxM = 10

  json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,null],[-2000,-2000,null],[-1000,-2000,null]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  GeometryEngine.Instance.GetMinMaxM(polyline, out minM, out maxM);
  // minM = double.Nan
  // maxM = double.Nan

Determine whether Ms are monotonic and whether ascending or descending - GetMMonotonic

string json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,10],[-2000,-2000,15],[-1000,-2000,20]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  MonotonicType monotonic = GeometryEngine.Instance.GetMMonotonic(polyline);
  // monotonic = Monotonic.Ascending

  json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,10],[-2000,-2000,5],[-1000,-2000,0]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  monotonic = GeometryEngine.Instance.GetMMonotonic(polyline);
  // monotonic = Monotonic.Descending

  json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,10],[-2000,-2000,15],[-1000,-2000,0]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  monotonic = GeometryEngine.Instance.GetMMonotonic(polyline);
  // monotonic = Monotonic.NotMonotonic

Get a multipoint corresponding to the locations where the specified M values occur along the geometry - GetPointsAtM

string json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,10],[-2000,-2000,15],[-1000,-2000,20],[0,-2000,0],[1000,-2000,20],[2000,-2000,30],[3000,-2000,10],[4000,-2000,5]]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);

  Multipoint multipoint = GeometryEngine.Instance.GetPointsAtM(polyline, 10, 500);
  // multiPoint.PointCount = 4
  // multipoint.Points[0]  X= -3000, Y= -2500  M= 10
  // multipoint.Points[1]  X= -500, Y= -2500  M= 10
  // multipoint.Points[2]  X= 500, Y= -2500  M= 10
  // multipoint.Points[3]  X= 3000, Y= -2500  M= 10

Get a polyline corresponding to the subcurves between specified M values - GetSubCurveBetweenMs

string json = "{\"hasM\":true,\"paths\":[[[-2000,0,1],[-1000,1000,2],[-1000,0,3],[1000,1000,4],[2000,1000,5],[2000,2000,6],[3000,2000,7],[4000,0,8]]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);

  Polyline subCurve = GeometryEngine.Instance.GetSubCurveBetweenMs(polyline, 2, 6);
  // subCurve.PointCount = 5
  // subCurve.Points[0]  X= --1000, Y= 1000 M= 2
  // subCurve.Points[1]  X= --1000, Y= 0  M= 3
  // subCurve.Points[2]  X= 1000, Y= 1000  M= 4
  // subCurve.Points[3]  X= 2000, Y= -1000  M= 5
  // subCurve.Points[4]  X= 2000, Y= -2000  M= 6

  subCurve = GeometryEngine.Instance.GetSubCurveBetweenMs(polyline, double.NaN, 5);
  // subCurve.PointCount = 0
  // subCurve.IsEmpty = true

Get line segments corresponding to the normal at the locations where the specified M values occur along the geometry - GetNormalsAtM

IList<MapPoint> inPoints =
  [
    MapPointBuilderEx.CreateMapPoint(-3000, -2000, 0, 100),
MapPointBuilderEx.CreateMapPoint(-3000, 0, 0, 200),
MapPointBuilderEx.CreateMapPoint(-1000, 0, 0, 300),
MapPointBuilderEx.CreateMapPoint(-1000, 2000, 0, 100),
MapPointBuilderEx.CreateMapPoint(3000, 2000, 0, 200),
MapPointBuilderEx.CreateMapPoint(3000, 0, 0, 300),
MapPointBuilderEx.CreateMapPoint(1000, 0, 0, 100),
MapPointBuilderEx.CreateMapPoint(1000, -2000, 0, 200),
MapPointBuilderEx.CreateMapPoint(-3000, -2000, 0, 300)
  ];

  polygon = PolygonBuilderEx.CreatePolygon(inPoints);
  // polygon.HasM = true

  polyline = GeometryEngine.Instance.GetNormalsAtM(polygon, 150, 100);
  // polyline.PartCount = 5
  // polyline.PointCount = 10
  // polyline.HasM = false

  ReadOnlyPartCollection parts = polyline.Parts;
  ReadOnlySegmentCollection segments = parts[0];
  LineSegment line = segments[0] as LineSegment;
  // line.StartCoordinate = (-3000, -1000)
  // line.EndCoordinate = (-2900, -1000)

  segments = parts[1];
  line = segments[0] as LineSegment;
  // line.StartCoordinate = (-1000, 1500)
  // line.EndCoordinate = (-900, 1500)

  segments = parts[2];
  line = segments[0] as LineSegment;
  // line.StartCoordinate = (1000, 2000)
  // line.EndCoordinate = (1000, 1900)

  segments = parts[3];
  line = segments[0] as LineSegment;
  // line.StartCoordinate = (1500, 0)
  // line.EndCoordinate = (1500, 100)

  segments = parts[4];
  line = segments[0] as LineSegment;
  // line.StartCoordinate = (1000, -1000)
  // line.EndCoordinate = (900, -1000)

Get the M values at the specified distance along the multipart

string json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,-3],[-2000,-2000,-2]],[[-2000,-2000,1],[-2000,1000,2]]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);

  // polyline has 2 parts

  GeometryEngine.Instance.GetMsAtDistance(polyline, 0, AsRatioOrLength.AsLength, out double m1, out double m2);
  // m1 = -3
  // m2 = NaN

  GeometryEngine.Instance.GetMsAtDistance(polyline, 500, AsRatioOrLength.AsLength, out m1, out m2);
  // m1 = -2.5
  // m2 = NaN

  GeometryEngine.Instance.GetMsAtDistance(polyline, 1000, AsRatioOrLength.AsLength, out m1, out m2);
  // m1 = -2
  // m2 = 1     // m2 has a value because distance 1000 is at the end of the first part, beginning of the second part

Insert M value at the given distance - InsertMAtDistance

string json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,-3],[-2000,-2000,-2],[-1000,-2000,null]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  // A point already exists at the given distance
  double m = -1;
  double distance = 2000;
  bool createNewPart = false;
  Polyline outputPolyline = GeometryEngine.Instance.InsertMAtDistance(polyline, m, distance, AsRatioOrLength.AsLength, createNewPart, out bool splitHappened, out int partIndex, out int segmentIndex) as Polyline;

  // splitHappened = false, partIndex = 0, segmentIndex = 2
  // outputPolyline.Points[2].M = -1

  json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,-3],[-2000,-2000,-2],[-1000,-2000,-1]],[[0,0,0],[0,1000,0],[0,2000,2]]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);

  // A point already exists at the given distance, but createNewPart = true
  m = 1;
  distance = 3000;
  createNewPart = true;
  outputPolyline = GeometryEngine.Instance.InsertMAtDistance(polyline, m, distance, AsRatioOrLength.AsLength, createNewPart, out splitHappened, out partIndex, out segmentIndex) as Polyline;
  string outputJson = outputPolyline.ToJson();

  // splitHappened = true, partIndex = 2, segmentIndex = 0
  // outputJson = {"hasM":true,"paths":[[[-3000,-2000,-3],[-2000,-2000,-2],[-1000,-2000,-1]],[[0,0,0],[0,1000,1]],[[0,1000,1],[0,2000,2]]]}}
  // A new part has been created and the M values for outputPolyline.Points[4] and outputPolyline.Points[5] have been modified

  // A point does not exist at the given distance
  m = 1;
  distance = 3500;
  createNewPart = false;
  outputPolyline = GeometryEngine.Instance.InsertMAtDistance(polyline, m, distance, AsRatioOrLength.AsLength, createNewPart, out splitHappened, out partIndex, out segmentIndex) as Polyline;
  outputJson = outputPolyline.ToJson();

  // splitHappened = true even though createNewPart = false because a new point was created
  // partIndex = 1, segmentIndex = 2
  // outputJson = {"hasM":true,"paths":[[[-3000,-2000,-3],[-2000,-2000,-2],[-1000,-2000,-1]],[[0,0,0],[0,1000,0],[0,1500,1],[0,2000,2]]]}
  // A new point has been inserted (0, 1500, 1) by interpolating the X and Y coordinates and M value set to the input M value.

Calibrate M values using M values from input points - CalibrateByMs

string json = "{\"hasM\":true,\"paths\":[[[0,0,-1],[1,0,0],[1,1,1],[1,2,2],[3,1,3],[5,3,4],[9,5,5],[7,6,6]]],\"spatialReference\":{\"wkid\":4326}}";
  polyline = PolylineBuilderEx.FromJson(json);

  // Interpolate using points (0, 0, 17), (1, 0, 42), (7, 6, 18) 
  List<MapPoint> updatePoints = new(3);
  MapPointBuilderEx builder = new(0, 0)
  {
    M = 17
  };
  updatePoints.Add(builder.ToGeometry() as MapPoint);

  builder.X = 1;
  builder.M = 42;
  updatePoints.Add(builder.ToGeometry() as MapPoint);

  builder.X = 7;
  builder.Y = 6;
  builder.M = 18;
  updatePoints.Add(builder.ToGeometry() as MapPoint);

  // Calibrate all the points in the polyline
  double cutOffDistance = polyline.Length;

  Polyline updatedPolyline = GeometryEngine.Instance.CalibrateByMs(polyline, updatePoints, UpdateMMethod.Interpolate, cutOffDistance) as Polyline;
  // The points in the updated polyline are
  // (0, 0, 17 ), ( 1, 0, 42 ), ( 1, 1, 38 ), ( 1, 2, 34 ), ( 3, 1, 30 ), ( 5, 3, 26 ), ( 9, 5, 22 ), ( 7, 6, 18 )

  // ExtrapolateBefore using points (1, 2, 42), (9, 5, 18)
  builder.X = 1;
  builder.Y = 2;
  builder.M = 42;
  updatePoints[0] = builder.ToGeometry() as MapPoint;

  builder.X = 9;
  builder.Y = 5;
  builder.M = 18;
  updatePoints[1] = builder.ToGeometry() as MapPoint;

  updatePoints.RemoveAt(2);

  updatedPolyline = GeometryEngine.Instance.CalibrateByMs(polyline, updatePoints, UpdateMMethod.ExtrapolateBefore, cutOffDistance) as Polyline;
  // The points in the updated polyline are
  // ( 0, 0, 66 ), ( 1, 0, 58 ), ( 1, 1, 50 ), ( 1, 2, 42 ), ( 3, 1, 3 ), ( 5, 3, 4 ), ( 9, 5, 18 ), ( 7, 6, 6 )

  // ExtrapolateAfter using points (0, 0, 17), (1, 2, 42)
  builder.X = 0;
  builder.Y = 0;
  builder.M = 17;
  updatePoints.Insert(0, builder.ToGeometry() as MapPoint);

  updatePoints.RemoveAt(2);

  updatedPolyline = GeometryEngine.Instance.CalibrateByMs(polyline, updatePoints, UpdateMMethod.ExtrapolateAfter, cutOffDistance) as Polyline;
  // The points in the updated polyline are
  // ( 0, 0, 17 ), ( 1, 0, 0 ), ( 1, 1, 1 ), ( 1, 2, 42 ), ( 3, 1, 50.333333333333333 ), ( 5, 3, 58.666666666666671 ), ( 9, 5, 67 ), ( 7, 6, 75.333333333333343 )

  // ExtrapolateAfter and Interpolate using points (0, 0, 17), (1, 2, 42)
  updatedPolyline = GeometryEngine.Instance.CalibrateByMs(polyline, updatePoints, UpdateMMethod.ExtrapolateAfter | UpdateMMethod.Interpolate, cutOffDistance) as Polyline;
  // The points in the updated polyline are
  // (0,0,17),(1,0,25.333333333333336),(1,1,33.666666666666671),(1,2,42),(3,1,50.333333333333336),(5,3,58.666666666666671),(9,5,67),(7,6,75.333333333333343)

Calibrate M-values using segment lengths and M values from input points - CalibrateMsByDistance

List<MapPoint> points = [];

  MapPointBuilderEx pointBuilder = new(0, 0)
  {
    HasM = true,
    M = 0
  };
  points.Add(pointBuilder.ToGeometry());

  pointBuilder.SetValues(0, 8);
  pointBuilder.M = 12;
  points.Add(pointBuilder.ToGeometry());

  pointBuilder.SetValues(0, 18);
  pointBuilder.M = 10;
  points.Add(pointBuilder.ToGeometry());

  pointBuilder.SetValues(0, 28);
  pointBuilder.M = 14;
  points.Add(pointBuilder.ToGeometry());

  pointBuilder.SetValues(0, 32);
  pointBuilder.M = 20;
  points.Add(pointBuilder.ToGeometry());

  pointBuilder.SetValues(0, 38);
  pointBuilder.M = 26;
  points.Add(pointBuilder.ToGeometry());

  pointBuilder.SetValues(0, 50);
  pointBuilder.M = 30;
  points.Add(pointBuilder.ToGeometry());

  polyline = PolylineBuilderEx.CreatePolyline(points, AttributeFlags.HasM);
  // The points in the polyline are (0, 0, 0), (0, 8, 12), (0, 18, 10), (0, 28, 14), (0, 32, 20), (0, 38, 26), (0, 50, 30)

  // Calibrate Ms using points (0, 8, 15), (0, 28, 30), (0, 38, 20)
  points.Clear();
  pointBuilder.SetValues(0, 8);
  pointBuilder.M = 15;
  points.Add(pointBuilder.ToGeometry());

  pointBuilder.SetValues(0, 28);
  pointBuilder.M = 30;
  points.Add(pointBuilder.ToGeometry());

  pointBuilder.SetValues(0, 38);
  pointBuilder.M = 20;
  points.Add(pointBuilder.ToGeometry());

  double cutOffDistance = polyline.Length;

  // ExtrapolateBefore
  Polyline updatedPolyline = GeometryEngine.Instance.CalibrateMsByDistance(polyline, points, UpdateMMethod.ExtrapolateBefore, true, cutOffDistance) as Polyline;
  // The points in the updated polyline are
  // (0, 0, 9), (0, 8, 15), (0, 18, 10), (0, 28, 30), (0, 32, 20), (0, 38, 20), (0, 50, 30)

  // Interpolate
  updatedPolyline = GeometryEngine.Instance.CalibrateMsByDistance(polyline, points, UpdateMMethod.Interpolate, true, cutOffDistance) as Polyline;
  // The points in the updated polyline are
  // (0, 0, 0), (0, 8, 15), (0, 18, 22.5), (0, 28, 30), (0, 32, 26), (0, 38, 20), (0, 50, 30)

  // ExtrapolateAfter
  updatedPolyline = GeometryEngine.Instance.CalibrateMsByDistance(polyline, points, UpdateMMethod.ExtrapolateAfter, true, cutOffDistance) as Polyline;
  // The points in the updated polyline are
  // (0, 0, 0), (0, 8, 15), (0, 18, 10), (0, 28, 30), (0, 32, 20), (0, 38, 20), (0, 50, 8)

  // ExtrapolateBefore and Interpolate and ExtrapolateAfter
  updatedPolyline = GeometryEngine.Instance.CalibrateMsByDistance(polyline, points, UpdateMMethod.ExtrapolateAfter, true, cutOffDistance) as Polyline;
  // The points in the updated polyline are
  // (0, 0, 9), (0, 8, 15), (0, 18, 22.5), (0, 28, 30), (0, 32, 26), (0, 38, 20), (0, 50, 8)

Set all the M-values to NaN - DropMs

string json = "{\"hasM\":true,\"paths\":[[[-4,2,1],[-4,5,2],[-2,5,3],[-2,7,4],[2,7,5]],[[4,1,-1],[2,1,-2],[2,-2,-3],[-3,-2,-4],[-3,0,-5]]]}}";
  polyline = PolylineBuilderEx.FromJson(json);
  Polyline outputPolyline = GeometryEngine.Instance.DropMs(polyline) as Polyline;
  // outputPolyline.HasM = true. Every M-value is NaN.
  // outputPolyline.ToJson() = {"hasM":true,"paths":[[[-4,2,null],[-4,5,null],[-2,5,null],[-2,7,null],[2,7,null]],[[4,1,-null],[2,1,null],[2,-2,null],[-3,-2,null],[-3,0,null]]]}

Extrapolate M-values based on a range defined by part and vertex indices - ExtrapolateMs

string json = "{\"hasM\":true,\"paths\":[[[2,0,50],[2,1,40],[3,1,30],[3,5,60],[7,5,12],[7,1,20],[9,1,28],[9,3,10]]],\"spatialReference\":{\"wkid\":4326}}";
  polyline = PolylineBuilderEx.FromJson(json);

  // Extrapolate M-values from part 0, point 3 to part 0, point 5
  Polyline outPolyline = GeometryEngine.Instance.ExtrapolateMs(polyline, ExtrapolateMMethod.ExtrapolateBefore, 0, 3, 0, 5) as Polyline;
  // The points in outPolyline are (x, y, m):
  // ( 2, 0, 90 ), ( 2, 1, 85 ), ( 3, 1, 80 ), ( 3, 5, 60 ), ( 7, 5, 12 ), ( 7, 1, 20 ), ( 9, 1, 28 ), ( 9, 3, 10 )

  json = "{\"hasM\":true,\"paths\":[[[2,0,50],[2,1,40],[3,1,30],[3,5,60],[7,5,12],[7,1,20],[9,1,28],[9,3,10]],[[5,-4,-10],[5,-2,-40],[10,-2,-60],[10,-6,-50],[8,-6,-40],[8,-4,-80],[6,-4,-90]]],\"spatialReference\":{\"wkid\":4326}}";
  polyline = PolylineBuilderEx.FromJson(json);

  // Extrapolate M-values from part 0, point 5 to part1, point 1
  outPolyline = GeometryEngine.Instance.ExtrapolateMs(polyline, ExtrapolateMMethod.ExtrapolateAfter, 0, 5, 1, 1) as Polyline;
  // The points in part 0 of outPolyline don't change. They are (x, y, m):
  // ( 2, 0, 50 ), ( 2, 1, 40 ), ( 3, 1, 30 ), ( 3, 5, 60 ), ( 7, 5, 12 ), ( 7, 1, 20 ), ( 9, 1, 28 ), ( 9, 3, 10 )

  // The points in part 1 of outPolyline are (x, y, m):
  // ( 5, -4, -10 ), ( 5, -2, -40 ), ( 10, -2, -90 ), ( 10, -6, -130 ), ( 8, -6, -150 ), ( 8, -4, -170 ), ( 6, -4, -190 )

Get a list of distances along the multipart at points with the specified M-value - GetDistancesAtM

string json = "{\"hasM\":true,\"paths\":[[[-4,1,1],[-4,3,2],[-2,3,3],[-2,5,1]],[[3,5,1],[3,2,2],[6,2,3],[6,-2,2]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  // Get the distances as length measured from the start of the multipart
  IReadOnlyList<double> distances = GeometryEngine.Instance.GetDistancesAtM(polyline, AsRatioOrLength.AsLength, 2);
  // distances.Count = 4
  // distances[0] = 2 measured to the point (-4, 3, 2)
  // distances[1] = 5 measured to the point (-2, 4, 2). Its M-value is interpolated from the segment (-2, 3, 3) -> (-2, 5, 1)
  // distances[2] = 9 measured to the point (3, 2, 2) 
  // distances[3] = 16 measured to the point (6, -2, 2)

  // Get the distances as a ratio of the distance measured from the start of the multipart and the total length of the multipart
  distances = GeometryEngine.Instance.GetDistancesAtM(polyline, AsRatioOrLength.AsRatio, 2);
  // distances.Count = 4;
  // distances are { 0.125, 0.3125, 0.5625, 1 }

Get a polyline and other details corresponding to the subcurves between the specified M-values GetSubCurveBetweenMsEx

string json = "{\"hasM\":true,\"paths\":[[[-2000,0,1],[-1000,1000,-1],[-1000,0,3],[1000,1000,4],[2000,1000,5],[2000,2000,6],[3000,2000,7],[4000,0,8]]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);

  // Get the subcurve between M-values 2 and 6
  Polyline subCurve = GeometryEngine.Instance.GetSubCurveBetweenMsEx(polyline, 2, 6, out MSubCurveRelation fromDetail, out MSubCurveRelation toDetail);
  // The subcurve has one part and five points. The subcurve points are (x, y, m):
  // (-1000, 250, 2), (-1000, 0, 3), (1000, 1000, 4), (2000, 1000, 5), (2000, 2000, 6)
  // fromDetail = toDetail = MSubCurveRelation.MBetweenMinMax

  // Get the subcurve between M-values -2 and 3.5
  subCurve = GeometryEngine.Instance.GetSubCurveBetweenMsEx(polyline, -2, 3.5, out fromDetail, out toDetail);
  // The subcurve has two parts and five points.
  // The subcurve points in part 0 are (x, y, m): (-1000, 1000, -1), (-2000, 0, 1)
  // The subcurve points in part 1 are (x, y, m): (-1000, 1000, -1), (-1000, 0, 3), (0, 500, 3.5)
  // fromDetail = MSubCurveRelation.MBelowMin, toDetail = MSubCurveRelation.MBetweenMinMax

Get a combination of monotonicity values that describes all trends in the M-values over the length of the multipart - GetMMonotonicity

string json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,10],[-2000,-2000,5],[-1000,-2000,0]]]}";
  polyline = PolylineBuilderEx.FromJson(json);
  Monotonicity monotonicity = GeometryEngine.Instance.GetMMonotonicity(polyline);
  // monotonicity = Monotonicity.ValueDecreases

  // Create a polygon from the polyline
  polygon = PolygonBuilderEx.CreatePolygon(polyline);
  monotonicity = GeometryEngine.Instance.GetMMonotonicity(polygon);
  // monotonicity = ValueIncreases | ValueDecreases

  json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,10],[-2000,-2000,10],[-1000,-2000,10]]]}";
  polyline = PolylineBuilderEx.FromJson(json);
  monotonicity = GeometryEngine.Instance.GetMMonotonicity(polygon);
  // monotonicity = Monotonicity.ValueLevel

  json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,null],[-2000,-2000,5],[-1000,-2000,10]]]}";
  polyline = PolylineBuilderEx.FromJson(json);
  monotonicity = GeometryEngine.Instance.GetMMonotonicity(polyline);
  // monotonicity = ValueIncreases | ValueEmpty

  // Create an empty polyline
  Polyline emptyPolyline = PolylineBuilderEx.FromJson("{\"hasM\":true,\"paths\":[]}");
  monotonicity = GeometryEngine.Instance.GetMMonotonicity(emptyPolyline);
  // monotonicity = Monotonicity.None

Generates M-values by linear interpolation over a range of points - InterpolateMsBetween

string json = "{\"hasM\":true,\"paths\":[[[0,0,-1],[1,0,0],[1,1,1],[1,2,2],[3,1,3],[5,3,4],[9,5,5],[7,6,6]]],\"spatialReference\":{\"wkid\":4326}}";
  polyline = PolylineBuilderEx.FromJson(json);

  // Interpolate between points 2 and 6
  Polyline outPolyline = GeometryEngine.Instance.InterpolateMsBetween(polyline, 0, 2, 0, 6) as Polyline;
  // The points of the output polyline are
  // (0, 0, -1), (1, 0, 0), (1, 1, 1), (1, 2, 1.3796279833912741), (3, 1, 2.2285019604153242), (5, 3, 3.3022520459518998), (9, 5, 5), (7, 6, 6)

Determine if all the M-values are numbers - IsMSimple

Coordinate2D[] coords = [new Coordinate2D(-2, 2), new Coordinate2D(3, 5), new Coordinate2D(7, 2)];
  polyline = PolylineBuilderEx.CreatePolyline(coords); // polyline.HasM = false
  bool isMSimple = GeometryEngine.Instance.IsMSimple(polyline); // isMSimple = false

  PolylineBuilderEx polylineBuilder = new(polyline)
  {
    HasM = true
  };
  polyline = polylineBuilder.ToGeometry();
  isMSimple = GeometryEngine.Instance.IsMSimple(polyline); // isMSimple = false

  MapPoint point1 = MapPointBuilderEx.CreateMapPoint(-2, 2, -1, 1);
  MapPoint point2 = MapPointBuilderEx.CreateMapPoint(3, 5, -2, 2);
  MapPoint[] points = [point1, point2];
  polyline = PolylineBuilderEx.CreatePolyline(points, AttributeFlags.HasM);
  isMSimple = GeometryEngine.Instance.IsMSimple(polyline); // isMSimple = true

Multiply all M-values by a factor - MultiplyMs

// Create a multipoint and multiply M-values by 6
  Coordinate2D[] coords = [ new Coordinate2D(-4, 4), new Coordinate2D(-1, 1), new Coordinate2D(2, 6),
new Coordinate2D(-8, 2), new Coordinate2D(5, -3), new Coordinate2D(7, 2), new Coordinate2D(5, 3), new Coordinate2D(3, -1) ];

  double[] ms = [1, 2, 3, 4, 5, 6, 7, 8];

  MultipointBuilderEx builder = new(coords)
  {
    Ms = ms,
    HasM = true
  };
  Multipoint multipoint = builder.ToGeometry();

  Multipoint outMultipoint = GeometryEngine.Instance.MultiplyMs(multipoint, 6) as Multipoint;
  // The xy-values of the points in outMultipoint are the same as the points in the input multipoint.
  // The M-values in outMultipoint are { 6, 12, 18, 24, 30, 36, 42, 48 }

Add an offset value to each of the M-values - OffsetMs

// Create a polyline and add an offset of 2 to each of the M-values
  MapPointBuilderEx pointBuilder = new(0, 0)
  {
    M = 1
  };
  MapPoint point1 = pointBuilder.ToGeometry();

  pointBuilder.SetValues(2, 2);
  pointBuilder.M = 3;
  MapPoint point2 = pointBuilder.ToGeometry();

  polyline = PolylineBuilderEx.CreatePolyline([point1, point2], AttributeFlags.HasM); ;

  Polyline outPolyline = GeometryEngine.Instance.OffsetMs(polyline, 2) as Polyline;
  // The xy-values of the points in outPolyline are the same as the points in the input polyline.
  // The M-values in outPolyline are { 3, 5 }

  // Create an envelope and add an offset of 25 to each of the M-values
  EnvelopeBuilderEx envelopeBuilder = new(-5, 1, 2, 4)
  {
    MMin = 10,
    MMax = 20
  };
  Envelope envelope = envelopeBuilder.ToGeometry();

  Envelope outEnvelope = GeometryEngine.Instance.OffsetMs(envelope, 25) as Envelope;
  // The xy-values of the points in outEnvelope are the same as the points in the input envelope.
  // outEnvelope.MMin = 35, outEnvelope.MMax = 45

  // Add a negative offset to the M-values of the envelope
  outEnvelope = GeometryEngine.Instance.OffsetMs(envelope, -10) as Envelope;
  // The xy-values of the points in outEnvelope are the same as the points in the input envelope.
  // outEnvelope.MMin = 0, outEnvelope.MMax = 10

Reorient a polyline such that all M-values are non-decreasing, if possible - OrientByMs

string json = "{\"hasM\":true,\"paths\":[[[0,0,1],[0,1,0],[1,1,-1],[1,0,-2]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  Polyline outputPolyline = GeometryEngine.Instance.OrientByMs(polyline);
  // The points of outputPolyline are (x, y, m): (1, 0, -2), (1, 1, -1), (0, 1, 0), (0, 0, 1)

  // M-values of second part is not monotonic, so it won't change. The first part will change.
  json = "{\"hasM\":true,\"paths\":[[[0,0,1],[0,1,0],[1,1,-1],[1,0,-2]],[[5,4,6],[6,4,5],[8,6,7]]]}";
  polyline = PolylineBuilderEx.FromJson(json);
  outputPolyline = GeometryEngine.Instance.OrientByMs(polyline);
  // The points of part 0 of outputPolyline are (x, y, m): (1, 0, -2), (1, 1, -1), (0, 1, 0), (0, 0, 1)
  // The points of part 1 of outputPolyline are (x, y, m): (5, 4, 6), (6, 4, 5), (8, 6, 7)

Get the first and last defined M-values in a polyline - QueryFirstLastM

string json = "{\"hasM\":true,\"paths\":[[[5,4,6],[6,4,5],[8,6,7]],[[0,0,1],[0,1,0],[1,1,-1],[1,0,-2]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  GeometryEngine.Instance.QueryFirstLastM(polyline, out double firstM, out double lastM);
  // firstM = 6, lastM = -2

  json = "{\"hasM\":true,\"paths\":[[[5,4,null],[6,4,5],[8,6,7]],[[0,0,1],[0,1,0],[1,1,-1],[1,0,null]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  GeometryEngine.Instance.QueryFirstLastM(polyline, out firstM, out lastM);
  // firstM = 5, lastM = -1

  json = "{\"hasM\":true,\"paths\":[[[5,4,null],[6,4,null],[8,6,null]],[[0,0,null],[0,1,null],[1,1,null],[1,0,null]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  GeometryEngine.Instance.QueryFirstLastM(polyline, out firstM, out lastM);
  // firstM and lastM are NaN

  json = "{\"hasM\":true,\"paths\":[]}";
  polyline = PolylineBuilderEx.FromJson(json);

  GeometryEngine.Instance.QueryFirstLastM(polyline, out firstM, out lastM);
  // firstM and lastM are NaN

Reverse the order of the M-values along a multipart - ReverseMs

string json = "{\"hasM\":true,\"paths\":[[[5,4,6],[6,4,5],[8,6,7]]],\"spatialReference\":{\"wkid\":4326}}";
  polyline = PolylineBuilderEx.FromJson(json);
  Polyline outputPolyline = GeometryEngine.Instance.ReverseMs(polyline) as Polyline;
  // The xy-coordinates in outputPolyline are not changed. 
  // The M-values in outputPolyline are: { 7, 5, 6 }

Set Ms at the beginning and end of the geometry and interpolate M-values between the two values - SetAndInterpolateMsBetween

string json = "{\"hasM\":true,\"paths\":[[[-3000,-2000],[-2000,-2000],[-1000,-2000],[0,-2000],[1000,-2000],[2000,-2000],[3000,-2000],[4000,-2000]]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);

  Polyline outPolyline = GeometryEngine.Instance.SetAndInterpolateMsBetween(polyline, 100, 800) as Polyline;
  ReadOnlyPointCollection outPoints = outPolyline.Points;
  // outPoints M values are { 100, 200, 300, 400, 500, 600, 700, 800 };

Set the M-values to the cumulative length of the start of the multipart - SetMsAtDistance

string json = "{\"hasM\":true,\"paths\":[[[-3000,-2000,1],[-2000,-2000,2],[-1000,-2000,3],[0,-2000,null],[1000,-2000,4],[2000,-2000,5],[3000,-2000,10],[4000,-2000,11],[5000,-2000,12],[6000,-2000,13],[7000,-2000,14]]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);

  Polyline outPolyline = GeometryEngine.Instance.SetMsAsDistance(polyline, AsRatioOrLength.AsLength) as Polyline;
  // The xy-coordinates don't change. 
  // The M-values of the vertices in outPolyline are (x, y, m): 
  // { 0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000 }

  json = "{\"hasM\":true,\"rings\":[[[0,0],[0,3000],[4000,3000],[4000,0],[0,0]]],\"spatialReference\":{\"wkid\":3857}}";
  polygon = PolygonBuilderEx.FromJson(json);

  Polygon outPolygon = GeometryEngine.Instance.SetMsAsDistance(polygon, AsRatioOrLength.AsLength) as Polygon;
  // The M-values of the vertices in outPolygon are (x, y, m): { 0, 3000, 7000, 10000, 14000 };

Set the M-values of the vertices as scaled and offset distances measured along a polyline - SetMsAsDistance

string json = "{\"hasM\":true,\"paths\":[[[0,0,1],[3,0,2],[3,6,3],[7,6,4]]],\"spatialReference\":{\"wkid\":4326}}";
  polyline = PolylineBuilderEx.FromJson(json);
  Coordinate2D origin = new(0, 0);

  Polyline outputPolyline = GeometryEngine.Instance.SetMsAsDistance(polyline, origin, 0.5, 1, true) as Polyline;
  // The xy-coordinates of the polyline don't change.
  // The points of outputPolyline are (x, y, m): 
  // (0, 0, 1), (3, 0, 2.5), (3, 6, 5.5), (7, 6, 7.5)

  // Measurements will start at the end of the polyline, point (7, 6)
  origin = new Coordinate2D(4, 6);

  outputPolyline = GeometryEngine.Instance.SetMsAsDistance(polyline, origin, 0.5, 1, true) as Polyline;
  // The points of outputPolyline are (x, y, m): 
  // (0, 0, 7.5), (3, 0, 6), (3, 6, 3), (7, 6, 1)

Snap the M-values to the M-precision of the spatial reference - SnapMsToSpatialReference

SpatialReference sr = SpatialReferences.WebMercator;  // precision = 1 / MScale = 0.0001

  // MapPoint
  MapPointBuilderEx pointBuilder = new(3, 4, sr)
  {
    M = 5.00006
  };
  MapPoint point = pointBuilder.ToGeometry();
  MapPoint outputPoint = GeometryEngine.Instance.SnapMsToSpatialReference(point) as MapPoint;
  // outputPoint.M = 5.0001

  // Multipoint
  MapPointBuilderEx mapPointBuilderEx = new(-3, -4, sr)
  {
    M = -5.000007
  };
  pointBuilder = mapPointBuilderEx;
  MapPoint point2 = pointBuilder.ToGeometry();
  Multipoint multipoint = MultipointBuilderEx.CreateMultipoint([point, point2], AttributeFlags.HasM, sr);
  Multipoint outputMultipoint = GeometryEngine.Instance.SnapMsToSpatialReference(multipoint) as Multipoint;
  // outputMultipoint.Points[0].M = 5.0001, outputMultipoint.Points[1].M = -5

  // Polyline
  string json = "{\"hasM\":true,\"paths\":[[[3,2,10.00065],[3,4,15.000325],[5,4,20],[5,2,15.000325],[3,2,10.00065]]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);
  Polyline outputPolyline = GeometryEngine.Instance.SnapMsToSpatialReference(polyline) as Polyline;
  // The M-values for the vertices in outputPolyline are { 10.0007, 15.0003, 20, 15.0003, 10.0007 }

Set the M-values of the vertices as scaled and offset M distances measured along a polyline - UpdateAllMsByMs

string json = "{\"hasM\":true,\"paths\":[[[-8,2,1],[-8,5,8],[-5,5,0],[-5,7,12]],[[3,2,20],[7,2,30],[7,4,10],[13,4,5]]]}";
  polyline = PolylineBuilderEx.FromJson(json);
  Coordinate2D origin = new(-5, 6);

  Polyline outputPolyline = GeometryEngine.Instance.UpdateAllMsByMs(polyline, origin, 1, 0, true);
  // The xy-coordinates don't change. 
  // The M-values of the vertices in part 0 of outputPolyline are { 27, 20, 12, 0 }
  // The M-values of the vertices in part 1 of outputPolyline are { 27, 37, 57, 62 }

  outputPolyline = GeometryEngine.Instance.UpdateAllMsByMs(polyline, origin, 2, 4, true);
  // The M-values of the vertices in part 0 of outputPolyline are { 58, 44, 28, 4 }
  // The M-values of the vertices in part 1 of outputPolyline are { 58, 78, 118, 128 }

Update M-values along the shortest path between the specified vertices - UpdateMsByDistance

string json = "{\"hasM\":true,\"paths\":[[[-8,2,1],[-8,5,8],[-5,5,0],[-5,7,12]]],\"spatialReference\":{\"wkid\":4326}}";
  polyline = PolylineBuilderEx.FromJson(json);

  Polyline outputPolyline = GeometryEngine.Instance.UpdateMsByDistance(polyline, 0, 0, 0, 2, 10, 20, UpdateMMethod.Interpolate, true);
  // The xy-coordinates don't change.
  // The M-values of the vertices in outputPolyline are { 10, 15, 20, 12 }

  json = "{\"hasM\":true,\"paths\":[[[-8,2,1],[-8,5,8],[-5,5,0],[-5,7,12]],[[3,2,20],[7,2,30],[7,4,10],[13,4,5]]]}";
  polyline = PolylineBuilderEx.FromJson(json);

  outputPolyline = GeometryEngine.Instance.UpdateMsByDistance(polyline, 0, 2, 1, 1, 10, 20, UpdateMMethod.ExtrapolateBefore, true);
  // The M-values of the vertices in part 0 of outputPolyline are { -5, 2.5, 10, 5 }
  // The M-values of the vertices in part 1 of outputPolyline are { 20, 20, 10, 5 }

Update M-values with the interpolation ratio determined by existing M-values and the input M-values - UpdateMsByMs

string json = "{\"hasM\":true,\"paths\":[[[-8,2,1],[-8,5,8],[-5,5,0],[-5,7,12]]],\"spatialReference\":{\"wkid\":4326}}";
  polyline = PolylineBuilderEx.FromJson(json);

  Polyline outputPolyline = GeometryEngine.Instance.UpdateMsByMs(polyline, 0, 1, 0, 3, -2, 14, UpdateMMethod.Interpolate);
  // The xy-coordinates don't change.
  // The M-values of the vertices in outputPolyline are (x, y, m): { 1, -2, 30, 14 }

Move a MapPoint

MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 3.0);
  MapPoint ptResult = GeometryEngine.Instance.Move(pt, -3.5, 2.5) as MapPoint;
  // ptResult is (-2.5, 5.5)

Move a z-aware MapPoint

MapPoint zPt = MapPointBuilderEx.CreateMapPoint(1.0, 3.0, 2.0);
  MapPoint zPtResult = GeometryEngine.Instance.Move(zPt, 4, 0.25, 0.5) as MapPoint;
  // zPtResult is (5.0, 3.25, 2.5);

Move a Polyline

List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, 3.0),
MapPointBuilderEx.CreateMapPoint(3.0, 3.0, 3.0),
MapPointBuilderEx.CreateMapPoint(3, 2, 3.0),
MapPointBuilderEx.CreateMapPoint(4.0, 2.0, 3.0),
      ];

  polyline = PolylineBuilderEx.CreatePolyline(pts);

  Geometry geometry = GeometryEngine.Instance.Move(polyline, 3, 2);
  Polyline polylineResult = geometry as Polyline;
  // polylineResult.Points[0] = 4.0, 3.0, 3.0
  // polylineResult.Points[1] = 6.0, 5.0, 3.0
  // polylineResult.Points[2] = 6.0, 4.0, 3.0
  // polylineResult.Points[3] = 7.0, 4.0, 3.0

MovePointAlongLine

LineSegment line = LineBuilderEx.CreateLineSegment(MapPointBuilderEx.CreateMapPoint(0, 3), MapPointBuilderEx.CreateMapPoint(5.0, 3.0));
  polyline = PolylineBuilderEx.CreatePolyline(line);
  bool simple = GeometryEngine.Instance.IsSimpleAsFeature(polyline);

  // ratio = false
  MapPoint pt = GeometryEngine.Instance.MovePointAlongLine(polyline, 1.0, false, 0.0, SegmentExtensionType.NoExtension);
  // pt = 1.0, 3.0

  pt = GeometryEngine.Instance.MovePointAlongLine(polyline, 1.0, false, -1.0, SegmentExtensionType.NoExtension);
  // pt = 1.0, 4.0

  pt = GeometryEngine.Instance.MovePointAlongLine(polyline, 1.0, false, 2.0, SegmentExtensionType.NoExtension);
  // pt = 1.0, 1.0

  // ratio = true
  pt = GeometryEngine.Instance.MovePointAlongLine(polyline, 0.5, true, 0, SegmentExtensionType.NoExtension);
  // pt = 2.5, 3.0

  // move past the line
  pt = GeometryEngine.Instance.MovePointAlongLine(polyline, 7, false, 0, SegmentExtensionType.NoExtension);
  // pt = 5.0, 3.0

  // move past the line with extension at "to" point
  pt = GeometryEngine.Instance.MovePointAlongLine(polyline, 7, false, 0, SegmentExtensionType.ExtendEmbeddedAtTo);
  // pt = 7.0, 3.0

  // negative distance with extension at "from" point
  pt = GeometryEngine.Instance.MovePointAlongLine(polyline, -2, false, 0, SegmentExtensionType.ExtendEmbeddedAtFrom);
  // pt = -2.0, 3.0

  // ratio = true
  pt = GeometryEngine.Instance.MovePointAlongLine(polyline, 0.5, true, 0, SegmentExtensionType.NoExtension);
  // pt = 2.5, 3.0

  // line with Z
  List<Coordinate3D> coords3D = [new Coordinate3D(0, 0, 0), new Coordinate3D(1113195, 1118890, 5000)];
  Polyline polylineZ = PolylineBuilderEx.CreatePolyline(coords3D, SpatialReferences.WebMercator);
  // polylineZ.HasZ = true

  // ratio = true, no offset
  pt = GeometryEngine.Instance.MovePointAlongLine(polylineZ, 0.5, true, 0, SegmentExtensionType.NoExtension);
  // pt.X = 556597.5
  // pt.Y = 559445
  // pt.Z = 2500

  // ratio = true, past the line with "to" extension, no offset
  pt = GeometryEngine.Instance.MovePointAlongLine(polylineZ, 1.5, true, 0, SegmentExtensionType.ExtendEmbeddedAtTo);
  // pt.X = 1669792.5
  // pt.Y = 1678335
  // pt.Z = 7500

  // ratio = true, negative distance past the line with no extension, no offset
  pt = GeometryEngine.Instance.MovePointAlongLine(polylineZ, -1.5, true, 0, SegmentExtensionType.NoExtension);
  // pt.X = 0
  // pt.Y = 0
  // pt.Z = -7500

  // polyline with Z but 2d distance = 0
  MapPoint pt3 = MapPointBuilderEx.CreateMapPoint(5, 5, 0);
  MapPoint pt4 = MapPointBuilderEx.CreateMapPoint(5, 5, 10);
  List<MapPoint> pts = [pt3, pt4];

  polyline = PolylineBuilderEx.CreatePolyline(pts);
  // polyline.HasZ = true
  // polyline.Length3D = 10
  // polyline.Length = 0

  MapPoint result = GeometryEngine.Instance.MovePointAlongLine(polyline, 2, false, 0, SegmentExtensionType.NoExtension);
  // result = 5, 5, 2

  // polyline with length2d = 0 and length3d = 0
  MapPoint pt5 = MapPointBuilderEx.CreateMapPoint(5, 5, 10);
  MapPoint pt6 = MapPointBuilderEx.CreateMapPoint(5, 5, 10);
  pts.Clear();
  pts.Add(pt5);
  pts.Add(pt6);

  polyline = PolylineBuilderEx.CreatePolyline(pts);
  // polyline.HasZ = true
  // polyline.Length3D = 0
  // polyline.Length = 0

  result = GeometryEngine.Instance.MovePointAlongLine(polyline, 3, true, 0, SegmentExtensionType.NoExtension);
  // result = 5, 5, 10

  result = GeometryEngine.Instance.MovePointAlongLine(polyline, 3, true, 0, SegmentExtensionType.ExtendEmbeddedAtFrom);
  // result = 5, 5, 10

  // polyline with Z and M
  List<MapPoint> inputPoints =
  [
      MapPointBuilderEx.CreateMapPoint(1, 2, 3, 4),
    MapPointBuilderEx.CreateMapPoint(1, 2, 33, 44),
];

  Polyline polylineZM = PolylineBuilderEx.CreatePolyline(inputPoints, SpatialReferences.WGS84);
  // polylineZM.HasZ = true
  // polylineZM.HasM = true

  // ratio = true, no offset
  MapPoint pointAlong = GeometryEngine.Instance.MovePointAlongLine(polylineZM, 0.5, true, 0, SegmentExtensionType.NoExtension);
  // pointAlong = 1, 2, 18, 24

  // ratio = true with offset
  pointAlong = GeometryEngine.Instance.MovePointAlongLine(polylineZM, 0.2, true, 2.23606797749979, SegmentExtensionType.NoExtension);
  // pointAlong = 1, 2, 9, 12

Separate components of a geometry into single component geometries

List<Coordinate2D> coords2D =
  [
    new Coordinate2D(0, 0),
  new Coordinate2D(1, 4),
  new Coordinate2D(2, 7),
  new Coordinate2D(-10, 3)
  ];

  Multipoint multipoint = MultipointBuilderEx.CreateMultipoint(coords2D, SpatialReferences.WGS84);

  IReadOnlyList<Geometry> result = GeometryEngine.Instance.MultipartToSinglePart(multipoint);
  // result.Count = 4, 

  // 'explode' a multipart polygon
  result = GeometryEngine.Instance.MultipartToSinglePart(multipartPolygon);

  // create a bag of geometries
  polygon = PolygonBuilderEx.CreatePolygon(coords2D, SpatialReferences.WGS84);
  var bag = GeometryBagBuilderEx.CreateGeometryBag([multipoint, polygon]);
  // bag.PartCount = =2

  result = GeometryEngine.Instance.MultipartToSinglePart(bag);
  // result.Count == 2
  // result[0] is MultiPoint
  // result[1] is Polygon

Nearest Point versus Nearest Vertex

SpatialReference sr = SpatialReferences.WGS84;
  MapPoint pt = MapPointBuilderEx.CreateMapPoint(5, 5, sr);

  List<Coordinate2D> coords =
  [
    new Coordinate2D(10, 1),
  new Coordinate2D(10, -4),
  new Coordinate2D(0, -4),
  new Coordinate2D(0, 1),
  new Coordinate2D(10, 1)
  ];

  polygon = PolygonBuilderEx.CreatePolygon(coords);

  // find the nearest point in the polygon geometry to the pt
  ProximityResult result = GeometryEngine.Instance.NearestPoint(polygon, pt);
  // result.Point = 5, 1
  // result.SegmentIndex = 3
  // result.PartIndex = 0
  // result.PointIndex = null
  //result.Distance = 4
  //result.RightSide = false

  // find the nearest vertex in the polgyon geometry to the pt
  result = GeometryEngine.Instance.NearestVertex(polygon, pt);
  // result.Point = 10, 1
  // result.PointIndex = 0
  // result.SegmentIndex = null
  // result.PartIndex = 0
  // result.Distance = Math.Sqrt(41)
  // result.RightSide = false

Determine Nearest Point in 3D

MapPoint pt1 = MapPointBuilderEx.CreateMapPoint(1, 1, 1);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(2, 2, 2);
  MapPoint pt3 = MapPointBuilderEx.CreateMapPoint(10, 2, 1);

  //
  // test pt1 to pt2
  //
  ProximityResult result = GeometryEngine.Instance.NearestPoint3D(pt1, pt2);
  // result.Point = 1,1,1
  // result.Distance = Math.Sqrt(3)
  // result.SegmentIndex = null
  // result.PartIndex = 0
  // result.PointIndex = 0
  // result.RightSide = false

  // 
  // multipoint built from pt1, pt2.   should be closer to pt2
  // 
  Multipoint multipoint = MultipointBuilderEx.CreateMultipoint([pt1, pt2]);
  result = GeometryEngine.Instance.NearestPoint3D(multipoint, pt3);
  // result.Point = 2, 2, 2
  // result.Distance = Math.Sqrt(65)
  // result.SegmentIndex = null
  // result.PartIndex = 1
  // result.PointIndex = 1
  // result.RightSide = false

Calculate a geometry offset from the source

List<MapPoint> linePts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, SpatialReferences.WGS84),
MapPointBuilderEx.CreateMapPoint(10.0, 1.0, SpatialReferences.WGS84),
      ];

  polyline = PolylineBuilderEx.CreatePolyline(linePts);

  Geometry g = GeometryEngine.Instance.Offset(polyline, 10, OffsetType.Square, 0);
  Polyline gResult = g as Polyline;
  // gResult.PointCount = 2
  // gResult.Points[0] = (1, -9)
  // gResult.Points[1] = (10, -9)

  g = GeometryEngine.Instance.Offset(polyline, -10, OffsetType.Round, 0.5);
  gResult = g as Polyline;
  // gResult.PointCount = 2
  // gResult.Points[0] = (1, -11
  // gResult.Points[1] = (10, 11)

  //
  // elliptic arc curve
  //
  Coordinate2D fromPt = new(2, 1);
  Coordinate2D toPt = new(1, 2);
  Coordinate2D interiorPt = new(1 + Math.Sqrt(2) / 2, 1 + Math.Sqrt(2) / 2);

  EllipticArcSegment circularArc = EllipticArcBuilderEx.CreateCircularArc(fromPt.ToMapPoint(), toPt.ToMapPoint(), interiorPt);

  polyline = PolylineBuilderEx.CreatePolyline(circularArc);
  g = GeometryEngine.Instance.Offset(polyline, -0.25, OffsetType.Miter, 0.5);
  gResult = g as Polyline;

  g = GeometryEngine.Instance.Offset(polyline, 0.25, OffsetType.Bevel, 0.5);
  gResult = g as Polyline;

  //
  //  offset for a polygon
  //
  List<MapPoint> list =
  [
    MapPointBuilderEx.CreateMapPoint(10.0, 10.0, SpatialReferences.WGS84),
  MapPointBuilderEx.CreateMapPoint(10.0, 20.0, SpatialReferences.WGS84),
  MapPointBuilderEx.CreateMapPoint(20.0, 20.0, SpatialReferences.WGS84),
  MapPointBuilderEx.CreateMapPoint(20.0, 10.0, SpatialReferences.WGS84),
];

  polygon = PolygonBuilderEx.CreatePolygon(list);

  g = GeometryEngine.Instance.Offset(polygon, 2, OffsetType.Square, 0);
  Polygon gPolygon = g as Polygon;

  g = GeometryEngine.Instance.Offset(polygon, -2, OffsetType.Round, 0.3);
  gPolygon = g as Polygon;

  g = GeometryEngine.Instance.Offset(polygon, -0.5, OffsetType.Miter, 0.6);
  gPolygon = g as Polygon;

Determine if geometries overlap

MapPoint pt1 = MapPointBuilderEx.CreateMapPoint(1.5, 1.5);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(1.25, 1.75);
  MapPoint pt3 = MapPointBuilderEx.CreateMapPoint(3, 1.5);
  MapPoint pt4 = MapPointBuilderEx.CreateMapPoint(1.5, 2);

  //
  // point and point overlap
  //
  bool overlaps = GeometryEngine.Instance.Overlaps(pt1, pt2);        // overlaps = false
  overlaps = GeometryEngine.Instance.Overlaps(pt1, pt1);             // overlaps = false
                                                                     // Two geometries overlap if the region of their intersection is of the same dimension as the geometries involved and 
                                                                     // is not equivalent to either of the geometries.  

  List<MapPoint> pts = [pt1, pt2, pt3];

  List<MapPoint> pts2 = [pt2, pt3, pt4];

  //
  // pt and line overlap
  //
  polyline = PolylineBuilderEx.CreatePolyline(pts);
  bool isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polyline);         // isSimple = true
  overlaps = GeometryEngine.Instance.Overlaps(polyline, pt1);                  // overlaps = false

  //
  // line and line
  //
  Polyline polyline2 = PolylineBuilderEx.CreatePolyline(pts2);
  isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polyline2);             // isSimple = true
  overlaps = GeometryEngine.Instance.Overlaps(polyline, polyline2);            // overlaps = true

Project from WGS84 to WebMercator

MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 3.0, SpatialReferences.WGS84);
  Geometry result = GeometryEngine.Instance.Project(pt, SpatialReferences.WebMercator);
  MapPoint projectedPt = result as MapPoint;

Project from WGS84

// create the polygon
  List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, SpatialReferences.WGS84),
  MapPointBuilderEx.CreateMapPoint(1.0, 2.0, SpatialReferences.WGS84),
  MapPointBuilderEx.CreateMapPoint(2.0, 2.0, SpatialReferences.WGS84),
  MapPointBuilderEx.CreateMapPoint(2.0, 1.0, SpatialReferences.WGS84),
];

  polygon = PolygonBuilderEx.CreatePolygon(pts);
  // ensure it is simple
  bool isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polygon);

  // create the spatial reference to project to
  SpatialReference northPole = SpatialReferenceBuilder.CreateSpatialReference(102018);   // north pole stereographic 

  // project
  Geometry geometry = GeometryEngine.Instance.Project(polygon, northPole);

QueryNormal

string json = "{\"curvePaths\":[[[-13046586.8335,4036570.6796000004]," +
                "{\"c\":[[-13046645.107099999,4037152.5873000026]," +
                "[-13046132.776277589,4036932.1325614937]]}]],\"spatialReference\":{\"wkid\":3857}}";
  polyline = PolylineBuilderEx.FromJson(json);

  EllipticArcSegment arc = polyline.Parts[0][0] as EllipticArcSegment;

  // No extension, distanceAlongCurve = 0.5

  // use the polyline
  Polyline poly_normal = GeometryEngine.Instance.QueryNormal(polyline, SegmentExtensionType.NoExtension, 0.5, AsRatioOrLength.AsRatio, 1000);
  // or a segment
  LineSegment seg_normal = GeometryEngine.Instance.QueryNormal(arc, SegmentExtensionType.NoExtension, 0.5, AsRatioOrLength.AsRatio, 1000);

  // TangentAtFrom, distanceAlongCurve = -1.2
  poly_normal = GeometryEngine.Instance.QueryNormal(polyline, SegmentExtensionType.ExtendTangentAtFrom, -1.2, AsRatioOrLength.AsRatio, 1000);
  seg_normal = GeometryEngine.Instance.QueryNormal(arc, SegmentExtensionType.ExtendTangentAtFrom, -1.2, AsRatioOrLength.AsRatio, 1000);

  // TangentAtTo (ignored because distanceAlongCurve < 0), distanceAlongCurve = -1.2
  poly_normal = GeometryEngine.Instance.QueryNormal(polyline, SegmentExtensionType.ExtendTangentAtTo, -1.2, AsRatioOrLength.AsRatio, 1000);
  seg_normal = GeometryEngine.Instance.QueryNormal(arc, SegmentExtensionType.ExtendTangentAtTo, -1.2, AsRatioOrLength.AsRatio, 1000);

  // TangentAtTo, distanceAlongCurve = 1.2
  poly_normal = GeometryEngine.Instance.QueryNormal(polyline, SegmentExtensionType.ExtendTangentAtTo, 1.2, AsRatioOrLength.AsRatio, 1000);
  seg_normal = GeometryEngine.Instance.QueryNormal(arc, SegmentExtensionType.ExtendTangentAtTo, 1.2, AsRatioOrLength.AsRatio, 1000);

  // TangentAtFrom (ignored because distanceAlongCurve > 0), distanceAlongCurve = 1.2
  poly_normal = GeometryEngine.Instance.QueryNormal(polyline, SegmentExtensionType.ExtendTangentAtFrom, 1.2, AsRatioOrLength.AsRatio, 1000);
  seg_normal = GeometryEngine.Instance.QueryNormal(arc, SegmentExtensionType.ExtendTangentAtFrom, 1.2, AsRatioOrLength.AsRatio, 1000);

  // EmbeddedAtTo, distanceAlongCurve = 1.2
  poly_normal = GeometryEngine.Instance.QueryNormal(polyline, SegmentExtensionType.ExtendEmbeddedAtTo, 1.2, AsRatioOrLength.AsRatio, 1000);
  seg_normal = GeometryEngine.Instance.QueryNormal(arc, SegmentExtensionType.ExtendEmbeddedAtTo, 1.2, AsRatioOrLength.AsRatio, 1000);

  // EmbeddedAtFrom, distanceAlongCurve = -0.2
  poly_normal = GeometryEngine.Instance.QueryNormal(polyline, SegmentExtensionType.ExtendEmbeddedAtFrom, -0.2, AsRatioOrLength.AsRatio, 1000);
  seg_normal = GeometryEngine.Instance.QueryNormal(arc, SegmentExtensionType.ExtendEmbeddedAtFrom, -0.2, AsRatioOrLength.AsRatio, 1000);

QueryPoint

SpatialReference sr = SpatialReferences.WGS84;

  // Horizontal line segment
  Coordinate2D start = new(1, 1);
  Coordinate2D end = new(11, 1);
  LineSegment line = LineBuilderEx.CreateLineSegment(start, end, sr);

  polyline = PolylineBuilderEx.CreatePolyline(line);

  // Don't extend the segment

  MapPoint outPoint = GeometryEngine.Instance.QueryPoint(polyline, SegmentExtensionType.NoExtension, 1.0, AsRatioOrLength.AsLength);
  // outPoint = (2, 1)

  // or the segment
  MapPoint outPoint_seg = GeometryEngine.Instance.QueryPoint(line, SegmentExtensionType.NoExtension, 1.0, AsRatioOrLength.AsLength);
  // outPoint_seg = (2, 1)

  // Extend infinitely in both directions
  outPoint = GeometryEngine.Instance.QueryPoint(polyline, SegmentExtensionType.ExtendTangents, 1.5, AsRatioOrLength.AsRatio);
  // outPoint = (16, 1)
  outPoint_seg = GeometryEngine.Instance.QueryPoint(line, SegmentExtensionType.ExtendTangents, 1.5, AsRatioOrLength.AsRatio);
  // outPoint_seg = (16, 1)

QueryPointAndDistance

// Horizontal line segment
  List<MapPoint> linePts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, SpatialReferences.WGS84),
MapPointBuilderEx.CreateMapPoint(11.0, 1.0, SpatialReferences.WGS84),
      ];
  polyline = PolylineBuilderEx.CreatePolyline(linePts);
  bool isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polyline);

  // Don't extend the segment
  SegmentExtensionType extension = SegmentExtensionType.NoExtension;

  // A point on the line segment
  MapPoint inPoint = MapPointBuilderEx.CreateMapPoint(2, 1, SpatialReferences.WGS84);

  AsRatioOrLength asRatioOrLength = AsRatioOrLength.AsLength;

  MapPoint outPoint = GeometryEngine.Instance.QueryPointAndDistance(polyline, extension, inPoint, asRatioOrLength, out double distanceAlongCurve, out double distanceFromCurve, out LeftOrRightSide whichSide);
  // outPoint = 2, 1
  // distanceAlongCurve = 1
  // distanceFromCurve = 0
  // whichSide = GeometryEngine.Instance.LeftOrRightSide.LeftSide

  // Extend infinitely in both directions
  extension = SegmentExtensionType.ExtendTangents;

  // A point on the left side
  inPoint = MapPointBuilderEx.CreateMapPoint(16, 6, SpatialReferences.WGS84);
  asRatioOrLength = AsRatioOrLength.AsRatio;

  outPoint = GeometryEngine.Instance.QueryPointAndDistance(polyline, extension, inPoint, asRatioOrLength, out distanceAlongCurve, out distanceFromCurve, out whichSide);
  // outPoint = 16, 1
  // distanceAlongCurve = 1.5
  // distanceFromCurve = 5
  // whichSide = GeometryEngine.Instance.LeftOrRightSide.LeftSide

QueryTangent

LineSegment line = LineBuilderEx.CreateLineSegment(new Coordinate2D(0, 0), new Coordinate2D(1, 0));

  // No extension, distanceAlongCurve = 0.5
  LineSegment tangent = GeometryEngine.Instance.QueryTangent(line, SegmentExtensionType.NoExtension, 0.5, AsRatioOrLength.AsRatio, 1);
  // tangent.StartCoordinate = (0.5, 0.0)
  // tangent.EndCoordinate = (1.5, 0.0)

  tangent = GeometryEngine.Instance.QueryTangent(line, SegmentExtensionType.NoExtension, 1.5, AsRatioOrLength.AsLength, 1);
  // tangent.StartCoordinate = (1.0, 0.0)
  // tangent.EndCoordinate = (2.0, 0.0)

  tangent = GeometryEngine.Instance.QueryTangent(line, SegmentExtensionType.ExtendTangentAtTo, 1.5, AsRatioOrLength.AsLength, 1);
  // tangent.StartCoordinate = (1.5, 0.0)
  // tangent.EndCoordinate = (2.5, 0.0)

  tangent = GeometryEngine.Instance.QueryTangent(line, SegmentExtensionType.ExtendTangentAtFrom, -1.5, AsRatioOrLength.AsLength, 1);
  // tangent.StartCoordinate = (-1.5, 0.0)
  // tangent.EndCoordinate = (-0.5, 0.0)

  tangent = GeometryEngine.Instance.QueryTangent(line, SegmentExtensionType.ExtendTangentAtFrom, -0.5, AsRatioOrLength.AsRatio, 1);
  // tangent.StartCoordinate = (-0.5, 0.0)
  // tangent.EndCoordinate = (0.5, 0.0)

Reflect a polygon about a line

SpatialReference sr = SpatialReferences.WGS84;

  Coordinate2D start = new(0, 0);
  Coordinate2D end = new(4, 4);
  LineSegment line = LineBuilderEx.CreateLineSegment(start, end, sr);

  Coordinate2D[] coords =
  [
    new Coordinate2D(-1, 2),
  new Coordinate2D(-1, 4),
  new Coordinate2D(1, 4),
  new Coordinate2D(-1, 2)
  ];

  polygon = PolygonBuilderEx.CreatePolygon(coords, sr);

  // reflect a polygon about the line
  Polygon reflectedPolygon = GeometryEngine.Instance.ReflectAboutLine(polygon, line) as Polygon;

  // reflectedPolygon points are 
  //    (2, -1), (4, -1), (4, 1), (2, -1)

Determine relationship between two geometries

// set up some geometries

  // points
  MapPoint point0 = MapPointBuilderEx.CreateMapPoint(0, 0, SpatialReferences.WGS84);
  MapPoint point1 = MapPointBuilderEx.CreateMapPoint(1, 1, SpatialReferences.WGS84);
  MapPoint point2 = MapPointBuilderEx.CreateMapPoint(-5, 5, SpatialReferences.WGS84);

  // multipoint
  List<MapPoint> points = [point0, point1, point2];
  Multipoint multipoint = MultipointBuilderEx.CreateMultipoint(points, SpatialReferences.WGS84);

  // polygon 
  List<Coordinate2D> polygonCoords =
  [
      new Coordinate2D(-10, 0),
  new Coordinate2D(0, 10),
  new Coordinate2D(10, 0),
  new Coordinate2D(-10, 0)
  ];
  polygon = PolygonBuilderEx.CreatePolygon(polygonCoords, SpatialReferences.WGS84);

  // polylines
  Polyline polyline1 = PolylineBuilderEx.CreatePolyline(LineBuilderEx.CreateLineSegment(new Coordinate2D(-9.1, 0.1), new Coordinate2D(0, 9)), SpatialReferences.WGS84);
  Polyline polyline2 = PolylineBuilderEx.CreatePolyline(LineBuilderEx.CreateLineSegment(new Coordinate2D(-5, 5), new Coordinate2D(0, 5)), SpatialReferences.WGS84);
  Polyline polyline3 = PolylineBuilderEx.CreatePolyline(LineBuilderEx.CreateLineSegment(new Coordinate2D(2.09, -2.04), new Coordinate2D(5, 10)), SpatialReferences.WGS84);
  Polyline polyline4 = PolylineBuilderEx.CreatePolyline(LineBuilderEx.CreateLineSegment(new Coordinate2D(10, -5), new Coordinate2D(10, 5)), SpatialReferences.WGS84);

  List<Segment> segments =
  [
      LineBuilderEx.CreateLineSegment(new Coordinate2D(5.05, -2.87), new Coordinate2D(6.35, 1.57)),
  LineBuilderEx.CreateLineSegment(new Coordinate2D(6.35, 1.57), new Coordinate2D(4.13, 2.59)),
  LineBuilderEx.CreateLineSegment(new Coordinate2D(4.13, 2.59), new Coordinate2D(5, 5))
  ];
  Polyline polyline5 = PolylineBuilderEx.CreatePolyline(segments, SpatialReferences.WGS84);

  segments.Add(LineBuilderEx.CreateLineSegment(new Coordinate2D(5, 5), new Coordinate2D(10, 10)));

  Polyline polyline6 = PolylineBuilderEx.CreatePolyline(segments, SpatialReferences.WGS84);
  Polyline polyline7 = PolylineBuilderEx.CreatePolyline(polyline5);
  Polyline polyline8 = PolylineBuilderEx.CreatePolyline(LineBuilderEx.CreateLineSegment(new Coordinate2D(5, 5), new Coordinate2D(10, 10)), SpatialReferences.WGS84);

  segments.Clear();
  segments.Add(LineBuilderEx.CreateLineSegment(new Coordinate2D(0.6, 3.5), new Coordinate2D(0.7, 7)));
  segments.Add(LineBuilderEx.CreateLineSegment(new Coordinate2D(0.7, 7), new Coordinate2D(3, 9)));

  Polyline polyline9 = PolylineBuilderEx.CreatePolyline(segments, SpatialReferences.WGS84);

  // now do the Related tests

  // Interior/Interior Intersects
  string scl = "T********";
  bool related = GeometryEngine.Instance.Relate(polygon, polyline1, scl);     // related = true
  related = GeometryEngine.Instance.Relate(point0, point1, scl);              // related = false
  related = GeometryEngine.Instance.Relate(point0, multipoint, scl);          // related = true
  related = GeometryEngine.Instance.Relate(multipoint, polygon, scl);         // related = true
  related = GeometryEngine.Instance.Relate(multipoint, polyline1, scl);       // related = false
  related = GeometryEngine.Instance.Relate(polyline2, point2, scl);           // related = false
  related = GeometryEngine.Instance.Relate(point1, polygon, scl);             // related = true

  // Interior/Boundary Intersects
  scl = "*T*******";
  related = GeometryEngine.Instance.Relate(polygon, polyline2, scl);          // related = true
  related = GeometryEngine.Instance.Relate(polygon, polyline3, scl);          // related = false
  related = GeometryEngine.Instance.Relate(point1, polygon, scl);             // related = false

  // Boundary/Boundary Interior intersects
  scl = "***T*****";
  related = GeometryEngine.Instance.Relate(polygon, polyline4, scl);          // related = true

  // Overlaps Dim1
  scl = "1*T***T**";
  related = GeometryEngine.Instance.Relate(polygon, polyline5, scl);          // related = true

  // Crosses Area/Line (LineB crosses PolygonA)
  scl = "1020F1102";
  related = GeometryEngine.Instance.Relate(polygon, polyline6, scl);          // related = false
  related = GeometryEngine.Instance.Relate(polygon, polyline9, scl);          // related = true

  // Boundary/Boundary Touches
  scl = "F***T****";
  related = GeometryEngine.Instance.Relate(polygon, polyline7, scl);          // related = false
  related = GeometryEngine.Instance.Relate(polygon, polyline8, scl);          // related = true

Replace NaN Zs in a polygon

List<Coordinate3D> coordsZ =
  [
    new Coordinate3D(1, 2, double.NaN),
  new Coordinate3D(4, 5, 3),
  new Coordinate3D(7, 8, double.NaN)
  ];

  polygon = PolygonBuilderEx.CreatePolygon(coordsZ);
  // polygon.HasZ = true

  Polygon polygonZReplaced = GeometryEngine.Instance.ReplaceNaNZs(polygon, -1) as Polygon;

  // polygonZReplaced.Points[0].Z = -1
  // polygonZReplaced.Points[1].Z = 3
  // polygonZReplaced.Points[2].Z = -1

Reshape a polygon

List<Coordinate2D> polygon1Coords =
  [
    new Coordinate2D(0, -11000),
  new Coordinate2D(1000, -11000),
  new Coordinate2D(1000, -12000),
  new Coordinate2D(0, -12000),
  new Coordinate2D(0, -11000)
  ];

  // reshaper coordinates intersect the polygon
  List<Coordinate2D> reshaperCoords =
  [
    new Coordinate2D(1500, -11800),
  new Coordinate2D(-2600, -11800)
  ];

  SpatialReference sr = SpatialReferenceBuilder.CreateSpatialReference(102010);
  Polygon polygon1 = PolygonBuilderEx.CreatePolygon(polygon1Coords, sr);
  Polyline reshaper = PolylineBuilderEx.CreatePolyline(reshaperCoords, sr);

  Polygon outPolygon = GeometryEngine.Instance.Reshape(polygon1, reshaper) as Polygon;
  // outPolygon.PartCount = 1

  ReadOnlySegmentCollection segments = outPolygon.Parts[0];
  // segments.Count = 4
  // outPolygon.PointCount = 5

  string json = GeometryEngine.Instance.ExportToJson(JsonExportFlags.JsonExportSkipCRS, outPolygon);
  // json = "{\"rings\":[[[0,-11800],[0,-11000],[1000,-11000],[1000,-11800],[0,-11800]]]}";

  // example where the Reshaper polyline doesn't intersect the input

  reshaperCoords.Clear();
  reshaperCoords.Add(new Coordinate2D(1000, 1000));
  reshaperCoords.Add(new Coordinate2D(2000, 1000));

  reshaper = PolylineBuilderEx.CreatePolyline(reshaperCoords, sr);

  outPolygon = GeometryEngine.Instance.Reshape(polygon1, reshaper) as Polygon;
  // outPolygon = null

Reverse the order of points in a Polygon

List<Coordinate2D> list2D =
  [
    new Coordinate2D(1.0, 1.0),
  new Coordinate2D(1.0, 2.0),
  new Coordinate2D(2.0, 2.0),
  new Coordinate2D(2.0, 1.0),
];

  polygon = PolygonBuilderEx.CreatePolygon(list2D);

  Geometry g = GeometryEngine.Instance.ReverseOrientation(polygon);
  Polygon gPolygon = g as Polygon;

  // gPolygon.Points[0] = 1.0, 1.0
  // gPolygon.Points[1] = 2.0, 1.0
  // gPolygon.Points[2] = 2.0, 2.0
  // gPolygon.Points[3] = 1.0, 2.0
  // gPolygon.Points[4] = 1.0, 1.0
  // gPolygon.Area = -1 * polygon.Area

Rotate a MapPoint

{
  MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 3.0);
  MapPoint rotatePt = MapPointBuilderEx.CreateMapPoint(3.0, 3.0);

  Geometry result = GeometryEngine.Instance.Rotate(pt, rotatePt, Math.PI / 2);
}
// result point is (3, 1)

Rotate a Polyline

// rotate a polyline

  MapPoint fixedPt = MapPointBuilderEx.CreateMapPoint(3.0, 3.0);

  List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
  MapPointBuilderEx.CreateMapPoint(1.0, 5.0),
  MapPointBuilderEx.CreateMapPoint(5, 5),
  MapPointBuilderEx.CreateMapPoint(5.0, 1.0),
];
  polyline = PolylineBuilderEx.CreatePolyline(pts);

  Polyline rotated = GeometryEngine.Instance.Rotate(polyline, fixedPt, Math.PI / 4) as Polyline;  // rotate 45 deg

Scale a geometry

List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, 3.0),
  MapPointBuilderEx.CreateMapPoint(1.0, 3.0, 3.0),
  MapPointBuilderEx.CreateMapPoint(3, 3, 3.0),
  MapPointBuilderEx.CreateMapPoint(3.0, 1.0, 3.0),
];

  MapPoint midPt = MapPointBuilderEx.CreateMapPoint(1.5, 1.5);

  // polyline
  polyline = PolylineBuilderEx.CreatePolyline(pts);
  // polyline.Length = 6
  // polyline.Length3D = 0
  Geometry g = GeometryEngine.Instance.Scale(polyline, midPt, 0.5, 0.5);
  Polyline resultPolyline = g as Polyline;
  // resultPolyline.length  = 3
  // resultPolyline.Points[0] = 1.25, 1.25, 3
  // resultPolyline.Points[1] = 1.25, 2.25, 3
  // resultPolyline.Points[2] = 2.25, 2.25, 3
  // resultPolyline.Points[3] = 2.25, 1.25, 3

  // 3D point - scale in 3d
  MapPoint midPtZ = MapPointBuilderEx.CreateMapPoint(1.5, 1.5, 1);
  g = GeometryEngine.Instance.Scale(polyline, midPtZ, 0.5, 0.5, 0.25);
  resultPolyline = g as Polyline;
  // resultPolyline.Points[0] = 1.25, 1.25, 1.5
  // resultPolyline.Points[1] = 1.25, 2.25, 1.5
  // resultPolyline.Points[2] = 2.25, 2.25, 1.5
  // resultPolyline.Points[3] = 2.25, 1.25, 1.5

Set all Zs in a polyline

List<Coordinate3D> coordsZ =
  [
    new Coordinate3D(1, 2, 3),
  new Coordinate3D(4, 5, 6),
  new Coordinate3D(7, 8, double.NaN)
  ];

  polyline = PolylineBuilderEx.CreatePolyline(coordsZ);
  // polyline.HasZ = true

  Polyline polylineSetZ = GeometryEngine.Instance.SetConstantZ(polyline, -1) as Polyline;
  // polylineSetZ.Points[0].Z = -1
  // polylineSetZ.Points[1].Z = -1
  // polylineSetZ.Points[2].Z = -1

  polylineSetZ = GeometryEngine.Instance.SetConstantZ(polyline, double.NaN) as Polyline;
  // polyline.HasZ = true
  // polylineSetZ.Points[0].HasZ = true
  // polylineSetZ.Points[0].Z = NaN
  // polylineSetZ.Points[1].HasZ = true
  // polylineSetZ.Points[1].Z = NaN
  // polylineSetZ.Points[2].HasZ = true
  // polylineSetZ.Points[2].Z = NaN

  polylineSetZ = GeometryEngine.Instance.SetConstantZ(polyline, double.PositiveInfinity) as Polyline;
  // polyline.HasZ = true
  // polylineSetZ.Points[0].HasZ = true
  // polylineSetZ.Points[0].Z = double.PositiveInfinity
  // polylineSetZ.Points[1].HasZ = true
  // polylineSetZ.Points[1].Z = double.PositiveInfinity
  // polylineSetZ.Points[2].HasZ = true
  // polylineSetZ.Points[2].Z = double.PositiveInfinity

Calculate area of geometry on surface of Earth's ellipsoid - ShapePreservingArea

// pt
  MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 3.0, SpatialReferences.WebMercator);
  double area = GeometryEngine.Instance.ShapePreservingArea(pt);         // area = 0

  List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, 3.0),
  MapPointBuilderEx.CreateMapPoint(1.0, 3.0, 3.0),
  MapPointBuilderEx.CreateMapPoint(3, 3, 3.0),
  MapPointBuilderEx.CreateMapPoint(3.0, 1.0, 3.0),
];

  // multipoint
  Multipoint mPt = MultipointBuilderEx.CreateMultipoint(pts);
  area = GeometryEngine.Instance.ShapePreservingArea(mPt);               // area = 0

  // polyline
  polyline = PolylineBuilderEx.CreatePolyline(pts);
  area = GeometryEngine.Instance.ShapePreservingArea(polyline);          // area = 0

  // polygon
  polygon = PolygonBuilderEx.CreatePolygon(pts, SpatialReferences.WGS84);
  area = GeometryEngine.Instance.ShapePreservingArea(polygon);

  polygon = PolygonBuilderEx.CreatePolygon(pts, SpatialReferences.WebMercator);
  area = GeometryEngine.Instance.ShapePreservingArea(polygon);

  polygon = PolygonBuilderEx.CreatePolygon(
  [
    MapPointBuilderEx.CreateMapPoint( -170, 45),
  MapPointBuilderEx.CreateMapPoint( 170, 45),
  MapPointBuilderEx.CreateMapPoint( 170, -45),
  MapPointBuilderEx.CreateMapPoint( -170, -54)
  ], SpatialReferences.WGS84);

  var area_meters = GeometryEngine.Instance.ShapePreservingArea(polygon);// , AreaUnits.SquareMeters);
  var area_miles = GeometryEngine.Instance.ShapePreservingArea(polygon, AreaUnit.SquareMiles);

  // area_meters - 352556425383104.37
  // area_miles - 136122796.848425

Calculate length of geometry on surface of Earth's ellipsoid - ShapePreservingLength

// pt
  MapPoint pt = MapPointBuilderEx.CreateMapPoint(1.0, 3.0, SpatialReferences.WebMercator);
  double len = GeometryEngine.Instance.ShapePreservingLength(pt);          // len = 0

  List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0, 3.0),
  MapPointBuilderEx.CreateMapPoint(1.0, 3.0, 3.0),
  MapPointBuilderEx.CreateMapPoint(3, 3, 3.0),
  MapPointBuilderEx.CreateMapPoint(3.0, 1.0, 3.0),
];

  // multipoint
  Multipoint mPt = MultipointBuilderEx.CreateMultipoint(pts);
  len = GeometryEngine.Instance.ShapePreservingLength(mPt);                // len = 0

  // polyline
  polyline = PolylineBuilderEx.CreatePolyline(pts, SpatialReferences.WGS84);
  len = GeometryEngine.Instance.ShapePreservingLength(polyline);

  // polygon
  polygon = PolygonBuilderEx.CreatePolygon(pts, SpatialReferences.WGS84);
  len = GeometryEngine.Instance.ShapePreservingLength(polygon);

  polyline = PolylineBuilderEx.CreatePolyline(
  [
    MapPointBuilderEx.CreateMapPoint( -170, 0),
  MapPointBuilderEx.CreateMapPoint( 170, 0)
  ], SpatialReferences.WGS84);


  var length_meters = GeometryEngine.Instance.ShapePreservingLength(polyline); // , LinearUnits.Meters);
  var length_miles = GeometryEngine.Instance.ShapePreservingLength(polyline, LinearUnit.Miles);

  // length_meters - 37848626.869713023
  // length_miles - 23518.046402579574

SideBuffer

// right side, round caps
  SpatialReference sr = SpatialReferenceBuilder.CreateSpatialReference(102010);
  List<Coordinate2D> coords =
  [
    new Coordinate2D(1200, 5800),
new Coordinate2D(1400, 5800),
new Coordinate2D(1400, 6000),
new Coordinate2D(1300, 6000),
new Coordinate2D(1300, 5700)
  ];

  polyline = PolylineBuilderEx.CreatePolyline(coords, sr);
  Polygon output = GeometryEngine.Instance.SideBuffer(polyline, 20, LeftOrRightSide.RightSide, LineCapType.Round) as Polygon;

SideBuffer Many

SpatialReference spatialReference = SpatialReferenceBuilder.CreateSpatialReference(102010);
  List<Coordinate2D> coordinates =
  [
    new Coordinate2D(1200, 5800),
new Coordinate2D(1400, 5800),
new Coordinate2D(1400, 6000),
new Coordinate2D(1300, 6000),
new Coordinate2D(1300, 5700)
  ];

  Polyline polyline1 = PolylineBuilderEx.CreatePolyline(coordinates, spatialReference);

  coordinates.Clear();
  coordinates.Add(new Coordinate2D(1400, 6050));
  coordinates.Add(new Coordinate2D(1600, 6150));
  coordinates.Add(new Coordinate2D(1800, 6050));

  Polyline polyline2 = PolylineBuilderEx.CreatePolyline(coordinates, spatialReference);
  List<Polyline> polylines = [polyline1, polyline2];
  IReadOnlyList<Geometry> outGeometries = GeometryEngine.Instance.SideBuffer(polylines, 10, LeftOrRightSide.RightSide, LineCapType.Round);

Simplify a polygon

var g1 = PolygonBuilderEx.FromJson("{\"rings\": [ [ [0, 0], [10, 0], [10, 10], [0, 10] ] ] }");
  var result = GeometryEngine.Instance.Area(g1);      // result = -100.0   - negative due to wrong ring orientation
                                                      // simplify it
  var result2 = GeometryEngine.Instance.Area(GeometryEngine.Instance.SimplifyAsFeature(g1, true));
  // result2 = 100.0  - positive due to correct ring orientation (clockwise)

Get Non Simple Reason

SpatialReference sr = SpatialReferences.WGS84;
  Coordinate2D[] coords = [new Coordinate2D(5, 10), new Coordinate2D(15, 20), new Coordinate2D(25, 10), new Coordinate2D(5, 20)];
  polyline = PolylineBuilderEx.CreatePolyline(coords, sr);

  bool isSimple = GeometryEngine.Instance.GetNonSimpleReason(polyline, out NonSimpleReason nonSimpleReason);
  // isSimple = true;
  // nonSimpleReason = NonSimpleReason.IsSimple

  double resolution = sr.XYResolution;
  coords = [new Coordinate2D(0, 0), new Coordinate2D(0, 1.8 * resolution), new Coordinate2D(10, 10), new Coordinate2D(0, 5)];
  polyline = PolylineBuilderEx.CreatePolyline(coords, sr);

  isSimple = GeometryEngine.Instance.GetNonSimpleReason(polyline, out nonSimpleReason);
  // isSimple = false
  // nonSimpleReason = NonSimpleReason.ShortSegments

  coords = [ new Coordinate2D(10, 10), new Coordinate2D(10, 20), new Coordinate2D(40, 20),
      new Coordinate2D(40, 10), new Coordinate2D(60, 10), new Coordinate2D(70, 10)];

  polygon = PolygonBuilderEx.CreatePolygon(coords, sr);

  isSimple = GeometryEngine.Instance.GetNonSimpleReason(polygon, out nonSimpleReason);
  //isSimple = false
  //nonSimpleReason = NonSimpleReason.SelfIntersections

Simplify a polyline with intersections, overlaps

List<Coordinate2D> coords =
  [
    new Coordinate2D(8, 0),
  new Coordinate2D(8, 4),
  new Coordinate2D(6, 4),
  new Coordinate2D(8, 4),
  new Coordinate2D(10, 4),
  new Coordinate2D(8, 4)
  ];

  SpatialReference sr = SpatialReferences.WGS84;

  // build a line that has segments that cross over each other
  polyline = PolylineBuilderEx.CreatePolyline(coords, sr);
  // polyline.PartCount = 1
  ReadOnlyPartCollection parts = polyline.Parts;
  ReadOnlySegmentCollection segments = parts[0];
  // segments.Count = 5

  //  note there is a difference between SimpleAsFeature (doesn't detect intersections and overlaps, determines if it's simple enough for gdb storage)
  //  and SimplifyPolyline  (does detect intersections etc)
  bool isSimple = GeometryEngine.Instance.IsSimpleAsFeature(polyline, false);
  // isSimple = true

  // simplify it (with force = false)
  // because it has already been deemed 'simple' (previous IsSimpleAsFeature call) no detection of intersections, overlaps occur
  Polyline simplePolyline = GeometryEngine.Instance.SimplifyPolyline(polyline, SimplifyType.Planar, false);
  // simplePolyline.PartCount = 1
  ReadOnlyPartCollection simpleParts = simplePolyline.Parts;
  ReadOnlySegmentCollection simpleSegments = simpleParts[0];
  // simpleSegments.Count = 5

  // simplify it (with force = true)
  // detection of intersections, overlaps occur 
  simplePolyline = GeometryEngine.Instance.SimplifyPolyline(polyline, SimplifyType.Planar, true);
  // simplePolyline.PartCount = 3
  simpleParts = simplePolyline.Parts;
  simpleSegments = simpleParts[0];
  // simpleSegments.Count = 1

SimplifyOGC

SpatialReference sr = SpatialReferences.WGS84;

  Coordinate2D[] coords = [new Coordinate2D(5, 10), new Coordinate2D(15, 20), new Coordinate2D(25, 10), new Coordinate2D(5, 20)];
  polyline = PolylineBuilderEx.CreatePolyline(coords, sr);
  // polyline.IsKnownSimpleOgc = false
  // polyline.IsKnownSimple = false

  bool isSimple = GeometryEngine.Instance.IsSimpleOgc(polyline, out NonSimpleReason nonSimpleReason, true);
  // isSimple = false
  // nonSimpleReason = NonSimpleReason.SelfIntersections

  Polyline simplePolyline = GeometryEngine.Instance.SimplifyOgc(polyline) as Polyline;
  // simplePolyline.IsKnownSimpleOgc = true
  // simplePolyline.IsKnownSimple = true

  double resolution = sr.XYResolution;
  Coordinate3D[] coords3D = [ new Coordinate3D(0, 0, 0), new Coordinate3D(0, 1.8 * resolution, 0.8 * sr.ZTolerance), new Coordinate3D(10, 10, 1),
new Coordinate3D(0, 5, 1) ];
  polyline = PolylineBuilderEx.CreatePolyline(coords3D, sr);

  isSimple = GeometryEngine.Instance.IsSimpleOgc(polyline, out nonSimpleReason);
  // isSimple = false
  // nonSimpleReason = NonSimpleReason.ShortSegments

  simplePolyline = GeometryEngine.Instance.SimplifyOgc(polyline, true) as Polyline;
  // simplePolyline.IsKnownSimpleOgc = true
  // simplePolyline.IsKnownSimple = true

  coords = [new Coordinate2D(0, 0), new Coordinate2D(0, 0)];
  Multipoint multipoint = MultipointBuilderEx.CreateMultipoint(coords, sr);

  isSimple = GeometryEngine.Instance.IsSimpleOgc(multipoint, out nonSimpleReason);
  // isSimple = false
  // nonSimpleReason = NonSimpleReason.DuplicateVertex

Slice a Polygon into equal parts

var slices = GeometryEngine.Instance.SlicePolygonIntoEqualParts(polygon, 3, 0, SliceType.Blocks);
  // slices.Count = 3

  // simple polygon
  List<Coordinate2D> list2D =
  [
    new Coordinate2D(1.0, 1.0),
  new Coordinate2D(1.0, 2.0),
  new Coordinate2D(2.0, 2.0),
  new Coordinate2D(2.0, 1.0),
];

  Polygon p = PolygonBuilderEx.CreatePolygon(list2D);
  slices = GeometryEngine.Instance.SlicePolygonIntoEqualParts(p, 2, 0, SliceType.Strips);

  // slice[0] coordinates - (1.0, 1.0), (1.0, 1.5), (2.0, 1.5), (2.0, 1.0), (1.0, 1.0) 
  // slice[1] coordinates - (1.0, 1.5), (1.0, 2.0), (2.0, 2.0), (2.0, 1.5), (1.0, 1.5)

  slices = GeometryEngine.Instance.SlicePolygonIntoEqualParts(p, 2, Math.PI / 4, SliceType.Strips);

  // slice[0] coordinates - (1.0, 1.0), (1.0, 2.0), (2.0, 1.0), (1.0, 1.0)
  // slice[1] coordinates - (1.0, 2.0), (2.0, 2.0), (2.0, 1.0), (1.0, 2.0)

Smooth a multipart

// smooth with a maxDeviation of 0
  Polyline smoothPolyline = GeometryEngine.Instance.Smooth(polyline, 0) as Polyline;

  // smooth with a maxDeviation of 0.5
  smoothPolyline = GeometryEngine.Instance.Smooth(polyline, 0.5) as Polyline;

  // smooth a polygon with a maxDeviation of 0
  Polygon smoothPolygon = GeometryEngine.Instance.Smooth(polygon, 0) as Polygon;

  // maxDeviation < 0 behaves as if maxDeviation = 0
  smoothPolygon = GeometryEngine.Instance.Smooth(polygon, -1) as Polygon;

  // NaN maxDeviation behaves as if maxDeviation = 0
  smoothPolygon = GeometryEngine.Instance.Smooth(polygon, double.NaN) as Polygon;

Split multipart at point

// define a polyline
  MapPoint startPointZ = MapPointBuilderEx.CreateMapPoint(1, 1, 5);
  MapPoint endPointZ = MapPointBuilderEx.CreateMapPoint(20, 1, 5);

  Polyline polylineZ = PolylineBuilderEx.CreatePolyline([startPointZ, endPointZ]);

  // define a split point
  MapPoint splitPointAboveLine = MapPointBuilderEx.CreateMapPoint(10, 10, 10);

  // split the polyline at the point. Don't project the split point onto the line, don't create a new part
  var splitPolyline = GeometryEngine.Instance.SplitAtPoint(polylineZ, splitPointAboveLine, false, false, out bool splitOccurred, out int partIndex, out int segmentIndex);

  // splitOccurred = true
  // partIndex = 0
  // segmentIndex = 1
  // splitPolyline.PointCount = 3
  // splitPolyline.PartCount = 1
  // splitPolyline coordinates are (1, 1, 5), (10, 10, 10), (20, 1, 5)

  // split the polyline at the point.  dont project the split point onto the line, do create a new part
  splitPolyline = GeometryEngine.Instance.SplitAtPoint(polylineZ, splitPointAboveLine, false, false, out splitOccurred, out partIndex, out segmentIndex);

  // splitOccurred = true
  // partIndex = 1
  // segmentIndex = 0
  // splitPolyline.PointCount = 4
  // splitPolyline.PartCount = 2
  // splitPolyline first part coordinates are (1, 1, 5), (10, 10, 10)
  // splitPolyline second part coordinates are (10, 10, 10), (20, 1, 5)

  // split the polyline at the point.  do project the split point onto the line, don't create a new part
  splitPolyline = GeometryEngine.Instance.SplitAtPoint(polylineZ, splitPointAboveLine, false, false, out splitOccurred, out partIndex, out segmentIndex);

  // splitOccurred = true
  // partIndex = 0
  // segmentIndex = 1
  // splitPolyline.PointCount = 3
  // splitPolyline.PartCount = 1
  // splitPolyline coordinates are (1, 1, 5), (10, 10, 5), (20, 1, 5)

  // split the polyline at the point.  do project the split point onto the line, do create a new part
  splitPolyline = GeometryEngine.Instance.SplitAtPoint(polylineZ, splitPointAboveLine, false, false, out splitOccurred, out partIndex, out segmentIndex);

  // splitOccurred = true
  // partIndex = 1
  // segmentIndex = 0
  // splitPolyline.PointCount = 4
  // splitPolyline.PartCount = 2
  // splitPolyline first part coordinates are (1, 1, 5), (10, 10, 5)
  // splitPolyline second part coordinates are (10, 10, 5), (20, 1, 5)

  //
  // try to split with a point that won't split the line  - pt extends beyond the line
  //

  var pointAfterLine = MapPointBuilderEx.CreateMapPoint(50, 1, 10);
  splitPolyline = GeometryEngine.Instance.SplitAtPoint(polylineZ, pointAfterLine, false, false, out splitOccurred, out partIndex, out segmentIndex);

  // splitOccurred = false
  // ignore partIndex, sgementIndex
  // splitPolyline is the same as polylineZ

  ///
  ///  multipart polygon
  ///
  List<Coordinate3D> coordsZ =
  [
    new Coordinate3D(10,10,5),
  new Coordinate3D(10,20,5),
  new Coordinate3D(20,20,5),
  new Coordinate3D(20,10,5)
  ];

  List<Coordinate3D> coordsZ_2ndPart =
  [
    new Coordinate3D(30,20,10),
  new Coordinate3D(30,30,10),
  new Coordinate3D(35,28,10),
  new Coordinate3D(40,30,10),
  new Coordinate3D(40,20,10)
  ];

  var builder = new PolygonBuilderEx
  {
    HasZ = true
  };
  builder.AddPart(coordsZ);
  builder.AddPart(coordsZ_2ndPart);

  Polygon multipart = builder.ToGeometry();

  // pointA is closer to the first part of the multipart - the split occurs in the first part
  var pointA = MapPointBuilderEx.CreateMapPoint(22, 18, 7);
  var splitPolygon = GeometryEngine.Instance.SplitAtPoint(multipart, pointA, false, false, out splitOccurred, out partIndex, out segmentIndex);

  // splitPolygon.PointCount = 12
  // splitPolygon.PartCount = 2
  // splitPolygon first part coordinates  (10, 10, 5), (10, 20, 5), (20, 20, 5), (22, 18, 7), (20, 10, 5), (10, 10, 5)

  // pointB is midPoint between the 2 parts - no split will occur
  var pointB = MapPointBuilderEx.CreateMapPoint(25, 20, 7);
  splitPolygon = GeometryEngine.Instance.SplitAtPoint(multipart, pointB, true, false, out splitOccurred, out partIndex, out segmentIndex);

  // splitOccurred = false
  // ignore partIndex, sgementIndex
  // splitPolyline is the same as polylineZ

Polygon touches another Polygon

// two disjoint polygons
  Envelope env = EnvelopeBuilderEx.CreateEnvelope(MapPointBuilderEx.CreateMapPoint(4.0, 4.0), MapPointBuilderEx.CreateMapPoint(8, 8));
  Polygon poly1 = PolygonBuilderEx.CreatePolygon(env);

  Envelope env2 = EnvelopeBuilderEx.CreateEnvelope(MapPointBuilderEx.CreateMapPoint(1.0, 1.0), MapPointBuilderEx.CreateMapPoint(5, 5));
  Polygon poly2 = PolygonBuilderEx.CreatePolygon(env2);

  bool touches = GeometryEngine.Instance.Touches(poly1, poly2);    // touches = false

  // another polygon that touches the first
  Envelope env3 = EnvelopeBuilderEx.CreateEnvelope(MapPointBuilderEx.CreateMapPoint(1.0, 1.0), MapPointBuilderEx.CreateMapPoint(4, 4));
  Polygon poly3 = PolygonBuilderEx.CreatePolygon(env3);

  touches = GeometryEngine.Instance.Touches(poly1, poly3);         // touches = true

Transform2D

// Not all of the input points are transformed as some of them are outside of the GCS horizon.
  Coordinate2D[] inCoords2D =
  [
    new Coordinate2D(-1, -1),
new Coordinate2D(-2, -5),
new Coordinate2D(-5, -11),
new Coordinate2D(-10, -19),
new Coordinate2D(-17, -29),
new Coordinate2D(-26, -41),
new Coordinate2D(-37, -5),
new Coordinate2D(-50, -21),
new Coordinate2D(-65, -39),
new Coordinate2D(-82, -9)
  ];

  int arraySize = inCoords2D.Length;

  ProjectionTransformation projTrans = ProjectionTransformation.Create(SpatialReferences.WGS84, SpatialReferenceBuilder.CreateSpatialReference(24891));

  Coordinate2D[] outCoords2D = new Coordinate2D[arraySize];

  // transform and choose to remove the clipped coordinates
  int numPointsTransformed = GeometryEngine.Instance.Transform2D(inCoords2D, projTrans, ref outCoords2D, true);

  // numPointsTransformed = 4
  // outCoords2D.Length = 4

  // outCoords2D[0] = {5580417.6876455201, 1328841.2376554986}
  // outCoords2D[1] = {3508774.290814558, -568027.23444226268}
  // outCoords2D[2] = {1568096.0886155984, -2343435.4394415971}
  // outCoords2D[3] = {57325.827391741652, 1095146.8917508761}

  // transform and don't remove the clipped coordinates
  numPointsTransformed = GeometryEngine.Instance.Transform2D(inCoords2D, projTrans, ref outCoords2D, false);

  // numPointsTransformed = 4
  // outCoords2D.Length = 10

  // outCoords2D[0] = {double.Nan, double.Nan}
  // outCoords2D[1] = {double.Nan, double.Nan}
  // outCoords2D[2] = {double.Nan, double.Nan}
  // outCoords2D[3] = {double.Nan, double.Nan}
  // outCoords2D[4] = {double.Nan, double.Nan}
  // outCoords2D[5] = {double.Nan, double.Nan}
  // outCoords2D[6] = {5580417.6876455201, 1328841.2376554986}
  // outCoords2D[7] = {3508774.290814558, -568027.23444226268}
  // outCoords2D[8] = {1568096.0886155984, -2343435.4394415971}
  // outCoords2D[9] = {57325.827391741652, 1095146.8917508761}

Transform3D

// Not all of the input points are transformed as some of them are outside of the GCS horizon.
  Coordinate3D[] inCoords3D =
  [
    new Coordinate3D(-1, -1, 0),
  new Coordinate3D(-2, -5, 1),
  new Coordinate3D(-5, -11, 2),
  new Coordinate3D(-10, -19, 3),
  new Coordinate3D(-17, -29, 4),
  new Coordinate3D(-26, -41, 5),
  new Coordinate3D(-37, -5, 6),
  new Coordinate3D(-50, -21, 7),
  new Coordinate3D(-65, -39, 8),
  new Coordinate3D(-82, -9, 9)
  ];

  int arraySize = inCoords3D.Length;

  ProjectionTransformation projTrans = ProjectionTransformation.Create(SpatialReferences.WGS84, SpatialReferenceBuilder.CreateSpatialReference(24891));

  Coordinate3D[] outCoords3D = new Coordinate3D[arraySize];

  // transform and choose to remove the clipped coordinates
  int numPointsTransformed = GeometryEngine.Instance.Transform3D(inCoords3D, projTrans, ref outCoords3D);

  // numPointsTransformed = 4
  // outCoords2D.Length = 4

  // outCoords2D[0] = {5580417.6876455201, 1328841.2376554986, 7}
  // outCoords2D[1] = {3508774.290814558, -568027.23444226268, 8}
  // outCoords2D[2] = {1568096.0886155984, -2343435.4394415971, 9}
  // outCoords2D[3] = {57325.827391741652, 1095146.8917508761, 10}

Union two MapPoints - creates a Multipoint

MapPoint pt1 = MapPointBuilderEx.CreateMapPoint(1.0, 1.0);
  MapPoint pt2 = MapPointBuilderEx.CreateMapPoint(2.0, 2.5);

  Geometry geometry = GeometryEngine.Instance.Union(pt1, pt2);
  Multipoint multipoint = geometry as Multipoint;   // multipoint has point count of 2

Union two Polygons

// union two polygons

  List<MapPoint> polyPts =
  [
    MapPointBuilderEx.CreateMapPoint(3.0, 2.0),
  MapPointBuilderEx.CreateMapPoint(3.0, 6.0),
  MapPointBuilderEx.CreateMapPoint(6.0, 6.0),
  MapPointBuilderEx.CreateMapPoint(6.0, 2.0),
];

  Polygon poly1 = PolygonBuilderEx.CreatePolygon(polyPts);
  bool isSimple = GeometryEngine.Instance.IsSimpleAsFeature(poly1);

  Envelope env = EnvelopeBuilderEx.CreateEnvelope(MapPointBuilderEx.CreateMapPoint(4.0, 4.0), MapPointBuilderEx.CreateMapPoint(8, 8));
  Polygon poly2 = PolygonBuilderEx.CreatePolygon(env);
  isSimple = GeometryEngine.Instance.IsSimpleAsFeature(poly2);

  Geometry g = GeometryEngine.Instance.Union(poly1, poly2);
  Polygon polyResult = g as Polygon;

Union many Polylines

// union many polylines

  List<Coordinate2D> coords =
  [
    new Coordinate2D(1, 2), new Coordinate2D(3, 4), new Coordinate2D(4, 2),
  new Coordinate2D(5, 6), new Coordinate2D(7, 8), new Coordinate2D(8, 4),
  new Coordinate2D(9, 10), new Coordinate2D(11, 12), new Coordinate2D(12, 8),
  new Coordinate2D(10, 8), new Coordinate2D(12, 12), new Coordinate2D(14, 10)
  ];

  // create Disjoint lines
  List<Polyline> manyLines =
  [
    PolylineBuilderEx.CreatePolyline([coords[0], coords[1], coords[2]], SpatialReferences.WGS84),
    PolylineBuilderEx.CreatePolyline([coords[3], coords[4], coords[5]]),
    PolylineBuilderEx.CreatePolyline([coords[6], coords[7], coords[8]])
  ];

  polyline = GeometryEngine.Instance.Union(manyLines) as Polyline;

Union many Polygons

// union many polygons

  List<Coordinate3D> coordsZ =
  [
    new Coordinate3D(1, 2, 0), new Coordinate3D(3, 4, 1), new Coordinate3D(4, 2, 2),
  new Coordinate3D(5, 6, 3), new Coordinate3D(7, 8, 4), new Coordinate3D(8, 4, 5),
  new Coordinate3D(9, 10, 6), new Coordinate3D(11, 12, 7), new Coordinate3D(12, 8, 8),
  new Coordinate3D(10, 8, 9), new Coordinate3D(12, 12, 10), new Coordinate3D(14, 10, 11)
  ];

  // create polygons
  List<Polygon> manyPolygonsZ =
  [
    PolygonBuilderEx.CreatePolygon([coordsZ[0], coordsZ[1], coordsZ[2]], SpatialReferences.WGS84),
    PolygonBuilderEx.CreatePolygon([coordsZ[3], coordsZ[4], coordsZ[5]]),
    PolygonBuilderEx.CreatePolygon([coordsZ[6], coordsZ[7], coordsZ[8]])
  ];

  polygon = GeometryEngine.Instance.Union(manyPolygonsZ) as Polygon;

Generalize a multipart - Weed

// generalize with a maxDeviation of 0
  Polyline weedPolyline = GeometryEngine.Instance.Weed(polyline, 0) as Polyline;

  // generalize with a maxDeviation < 0
  weedPolyline = GeometryEngine.Instance.Weed(polyline, -1000000) as Polyline;

  // generalize with a maxDeviation > 0
  weedPolyline = GeometryEngine.Instance.Weed(polyline, 1000000) as Polyline;

MapPoints, Polylines, Polygons within Polygon

// build a polygon      
  List<MapPoint> pts =
  [
    MapPointBuilderEx.CreateMapPoint(1.0, 1.0),
MapPointBuilderEx.CreateMapPoint(1.0, 2.0),
MapPointBuilderEx.CreateMapPoint(2.0, 2.0),
MapPointBuilderEx.CreateMapPoint(2.0, 1.0),
      ];

  Polygon poly = PolygonBuilderEx.CreatePolygon(pts);

  // an inner point
  MapPoint innerPt = MapPointBuilderEx.CreateMapPoint(1.5, 1.5);
  bool within = GeometryEngine.Instance.Within(innerPt, poly);   // within = true

  // point on a boundary
  within = GeometryEngine.Instance.Within(pts[0], poly);     // within = false

  // an interior line
  MapPoint innerPt2 = MapPointBuilderEx.CreateMapPoint(1.25, 1.75);
  List<MapPoint> innerLinePts = [innerPt, innerPt2];

  polyline = PolylineBuilderEx.CreatePolyline(innerLinePts);
  within = GeometryEngine.Instance.Within(polyline, poly);   // within = true

  // a line that crosses the boundary
  MapPoint outerPt = MapPointBuilderEx.CreateMapPoint(3, 1.5);
  List<MapPoint> crossingLinePts = [innerPt, outerPt];

  polyline = PolylineBuilderEx.CreatePolyline(crossingLinePts);
  within = GeometryEngine.Instance.Within(polyline, poly);     // within = false

  // polygon in polygon
  Envelope env = EnvelopeBuilderEx.CreateEnvelope(innerPt, innerPt2);
  within = GeometryEngine.Instance.Within(env, poly);      // within = true

Home

ProSnippets: GeometryEngine

Clone this wiki locally