Skip to content

ProGuide Custom Relational Operations

UmaHarano edited this page May 6, 2024 · 19 revisions
Language:      C#
Subject:       Geometry
Contributor:   ArcGIS Pro SDK Team <arcgisprosdk@esri.com>
Organization:  Esri, http://www.esri.com
Date:          04/04/2024
ArcGIS Pro:    3.3
Visual Studio: 2022

This ProGuide shows how the Relate method of the GeometryEngine class can express custom relational operations. In this example, you're expressing a relationship in which a polyline geometry needs to completely cross a polygon in order to test true. You'll create a pattern matrix string as described in the ProConcepts to express this relationship. Imagine polygon geometries in the following configuration:

ProGuide: Geometry - Custom Spatial Relationship

In the previous image, consider geometries in the context of splitting land parcels. The parcels are represented by the adjacent polygon geometries and the split line going across the polygons. However, you only want to consider splitting the polygon that is completely crossed by the line.

Create geometries

// create a list of coordinates for the parcels
List<Coordinate2D> parcelCoordinates = new List<Coordinate2D>();

// top row of coordinates (left to right)
parcelCoordinates.Add(new Coordinate2D(-13046462, 4036415)); // top-left coordinate
parcelCoordinates.Add(new Coordinate2D(-13046446, 4036415));
parcelCoordinates.Add(new Coordinate2D(-13046430, 4036415));
parcelCoordinates.Add(new Coordinate2D(-13046417, 4036415));
// bottom row of coordinates (right to left)
parcelCoordinates.Add(new Coordinate2D(-13046417, 4036388)); // bottom-right coordinate
parcelCoordinates.Add(new Coordinate2D(-13046430, 4036388)); 
parcelCoordinates.Add(new Coordinate2D(-13046446, 4036388)); 
parcelCoordinates.Add(new Coordinate2D(-13046462, 4036388));

List<Coordinate2D> coordinatesPolygonA = new List<Coordinate2D>();
coordinatesPolygonA.Add(parcelCoordinates[0]); // top-left coordinate
coordinatesPolygonA.Add(parcelCoordinates[1]); // top-right coordinate
coordinatesPolygonA.Add(parcelCoordinates[6]); // bottom-right coordinate
coordinatesPolygonA.Add(parcelCoordinates[7]); // bottom-left coordinate
Polygon polygonA = PolygonBuilderEx.CreatePolygon(coordinatesPolygonA, SpatialReferences.WebMercator);

// create polygon B by creating a list of the corner coordinates
List<Coordinate2D> coordinatesPolygonB = new List<Coordinate2D>();
coordinatesPolygonB.Add(parcelCoordinates[1]); // top-left coordinate
coordinatesPolygonB.Add(parcelCoordinates[2]); // top-right coordinate
coordinatesPolygonB.Add(parcelCoordinates[5]); // bottom-right coordinate
coordinatesPolygonB.Add(parcelCoordinates[6]); // bottom-left coordinate
Polygon polygonB = PolygonBuilderEx.CreatePolygon(coordinatesPolygonB, SpatialReferences.WebMercator);

// create polygon C by creating a list of the corner coordinates
List<Coordinate2D> coordinatesPolygonC = new List<Coordinate2D>();
coordinatesPolygonC.Add(new Coordinate2D(-13046432, 4036372)); // top-left coordinate
coordinatesPolygonC.Add(new Coordinate2D(-13046420, 4036372)); // top-right coordinate
coordinatesPolygonC.Add(new Coordinate2D(-13046420, 4036360)); // bottom-right coordinate
coordinatesPolygonC.Add(new Coordinate2D(-13046432, 4036360)); // bottom-left coordinate
Polygon polygonC = PolygonBuilderEx.CreatePolygon(coordinatesPolygonC, SpatialReferences.WebMercator);

// create the cut line 
Polyline cutLine = PolylineBuilderEx.CreatePolyline(new[] { new Coordinate2D(-13046450, 4036395), new Coordinate2D(-13046425, 4036395) });

Test the spatial relationship

In the previous image, consider the relationship of the interiors, the boundaries, and the exteriors for the combination of the polygon and the polyline. The union of the interior of the line and the interior of the polygon must evaluate to true as does the boundary of the polygon. The specific requirements are that the line needs to completely cross the polygon and the polyline boundary (the endpoints) cannot be inside a polygon. The spatial relationship results in the following matrix shown in code:

// test the spatial relationship by considering the following DE-9IM matrix
// L represents the line and P represents the polygon
//
//       | I(P) | B(P) | E(P)
// ------|------|------|------
//  I(L) |  T   |  T   |  *
// ------|------|------|------
//  B(L) |  F   |  *   |  *
// ------|------|------|------
//  E(L) |  *   |  *   |  *

// returns false, as testing polygon A and the cutLine
bool doCrossCompletely = GeometryEngine.Instance.Relate(cutLine, polygonA, "TT*F*****");

// returns true, as testing polygon B and the cutLine
doCrossCompletely = GeometryEngine.Instance.Relate(cutLine, polygonB, "TT*F*****");

// returns false, as testing polygon C and the cutLine
doCrossCompletely = GeometryEngine.Instance.Relate(cutLine, polygonC, "TT*F*****");

When you write code, for an editing tool for example, you might use the test for spatial relationships in conjunction with a LINQ statement. In the following example, you have a list of polygons called parcels resulting from an interactive selection. The result of the LINQ statement is a collection of geometries that are completely crossed by the polyline.

// combine the relate method with a LINQ query to find matching geometries
List<Geometry> parcels = new List<Geometry>(new [] { polygonA, polygonB, polygonC });
IEnumerable<Geometry> polygonToCut = parcels.Where(poly => GeometryEngine.Instance.Relate(cutLine, poly, "TT*F*****"));

// there is only one geometry that fits the spatial relationship
int numberOfGeometries = polygonToCut.Count();

Developing with ArcGIS Pro

    Migration


Framework

    Add-ins

    Configurations

    Customization

    Styling


Arcade


Content


CoreHost


DataReviewer


Editing


Geodatabase

    3D Analyst Data

    Plugin Datasources

    Topology

    Object Model Diagram


Geometry

    Relational Operations


Geoprocessing


Knowledge Graph


Layouts

    Reports


Map Authoring

    3D Analyst

    CIM

    Graphics

    Scene

    Stream

    Voxel


Map Exploration

    Map Tools


Networks

    Network Diagrams


Parcel Fabric


Raster


Sharing


Tasks


Workflow Manager Classic


Workflow Manager


Reference

Clone this wiki locally