Learn how to determine the spatial relationship between geometries.
A spatial relationship, also known as a spatial relation, is how one geometry is topologically associated with another geometry. The association is made based on their interiors, boundaries, and exteriors.
In this tutorial, you will use the geometry
to determine spatial relationships between two geometries.
To determine if a spatial relationship exists, operations such as intersects
, disjoint
, and within
are used. If the operation is successful, then true
is returned.
Prerequisites
Steps
Create a new pen
- To get started, either complete the Display a map tutorial or .
Get an access token
You need an access token with the correct privileges to access the location services used in this tutorial.
- Go to the Create an API key tutorial and create an API key with the following privilege(s):
- Privileges
- Location services > Basemaps
- Privileges
- In CodePen, set
esri
to your access token.Config.api Key Use dark colors for code blocks var esriConfig = { apiKey: "YOUR_ACCESS_TOKEN" };
To learn about other ways to get an access token, go to Types of authentication.
Add HTML elements
Add an arcgis-sketch
component to interactively draw geometries and graphics. We will also add a calcite list to display the spatial relationships between the drawn graphics.
-
In the
body
, create a newarcgis-sketch
component. Hide some of the tools that are not needed for this tutorial using attributes.Use dark colors for code blocks <body> <arcgis-map basemap="arcgis/topographic" center="-118.805, 34.027" zoom="13"> <arcgis-zoom position="top-left"></arcgis-zoom> <arcgis-sketch creation-mode="continuous" hide-create-tools-point hide-duplicate-button hide-selection-tools-lasso-selection hide-selection-tools-rectangle-selection hide-settings-menu layout="horizontal" position="top-left" > </arcgis-sketch> </arcgis-map> </body>
-
Add a
calcite-list
that will display the spatial relationships between graphics in anarcgis-placement
component that will place the list in the bottom right corner of the map.Use dark colors for code blocks <body> <arcgis-map basemap="arcgis/topographic" center="-118.805, 34.027" zoom="13"> <arcgis-zoom position="top-left"></arcgis-zoom> <arcgis-sketch creation-mode="continuous" hide-create-tools-point hide-duplicate-button hide-selection-tools-lasso-selection hide-selection-tools-rectangle-selection hide-settings-menu layout="horizontal" position="top-left" > </arcgis-sketch> <arcgis-placement position="bottom-right"> <calcite-list id="list" selection-mode="none"> <calcite-list-item-group heading="Spatial relationships"> <calcite-list-item id="contains" label="Contains"> </calcite-list-item> <calcite-list-item id="crosses" label="Crosses"> </calcite-list-item> <calcite-list-item id="disjoint" label="Disjoint"> </calcite-list-item> <calcite-list-item id="equals" label="Equals"> </calcite-list-item> <calcite-list-item id="intersects" label="Intersects"> </calcite-list-item> <calcite-list-item id="overlaps" label="Overlaps"> </calcite-list-item> <calcite-list-item id="touches" label="Touches"> </calcite-list-item> <calcite-list-item id="within" label="Within"> </calcite-list-item> </calcite-list-item-group> </calcite-list> </arcgis-placement> </arcgis-map> </body>
-
Add some CSS to format the results list. This class will set the list item's background color to the calcite color for success. See the Calcite colors and theming documentation for more information.
Use dark colors for code blocks <style> html, body { padding: 0; margin: 0; height: 100%; width: 100%; } .true { --calcite-color-foreground-1: var(--calcite-color-status-success); } </style>
Add modules
- In a new
<script
at the bottom of the> <body
, use a> require
statement to add theGraphic
,Graphics
, andLayer geometry
modules.Engine The ArcGIS Maps SDK for JavaScript is available as AMD modules and ES modules, but this tutorial is based on AMD. The AMD
require
function uses references to determine which modules will be loaded – for example, you can specify"esri/layers/
for loading the FeatureLayer module. After the modules are loaded, they are passed as parameters (e.g.Feature Layer" Feature
) to the callback function where they can be used in your application. It is important to keep the module references and callback parameters in the same order. To learn more about the API's different modules visit the Overview Guide page.Layer Use dark colors for code blocks <script> require(["esri/Graphic", "esri/layers/GraphicsLayer", "esri/geometry/geometryEngine"], ( Graphic, GraphicsLayer, geometryEngine ) => { }); </script>
Create graphics
You need two geometries to execute a spatial relationship operation. Create a polyline and a polygon graphic that displays when the application runs.
-
Get references to the HTML elements in our app.
Use dark colors for code blocks <script> require(["esri/Graphic", "esri/layers/GraphicsLayer", "esri/geometry/geometryEngine"], ( Graphic, GraphicsLayer, geometryEngine ) => { const arcgisMap = document.querySelector("arcgis-map"); const arcgisSketch = document.querySelector("arcgis-sketch"); const list = document.querySelector("#list"); }); </script>
-
Create a new
Graphics
and add it to theLayer arcgis-map
.Use dark colors for code blocks <script> require(["esri/Graphic", "esri/layers/GraphicsLayer", "esri/geometry/geometryEngine"], ( Graphic, GraphicsLayer, geometryEngine ) => { const arcgisMap = document.querySelector("arcgis-map"); const arcgisSketch = document.querySelector("arcgis-sketch"); const list = document.querySelector("#list"); const graphicsLayer = new GraphicsLayer(); arcgisMap.addLayer(graphicsLayer); }); </script>
-
Create a polyline graphic and add it to the
graphics
.Layer Use dark colors for code blocks const polyline = { type: "polyline", paths: [ [-13227000.704542402, 4032506.197638312], [-13223540.698857695, 4034443.92109266], [-13222135.94452635, 4032506.197638312], [-13221470.479577951, 4033494.9524006792], [-13221470.404932415, 4033494.9524006792] ], spatialReference: { wkid: 102100 } }; const simpleLineSymbol = { type: "simple-line", width: 2 }; const polylineGraphic = new Graphic({ geometry: polyline, symbol: simpleLineSymbol }); graphicsLayer.add(polylineGraphic);
-
Create a polygon graphic and add it to the
graphics
.Layer Use dark colors for code blocks // Create a polygon geometry const polygon = { type: "polygon", rings: [ [-13228098.704542402, 4035365.9427463487], [-13226362.225451587, 4035365.9427463487], [-13226362.225451587, 4032059.2948176656], [-13228098.704542402, 4032059.2948176656], [-13228098.704542402, 4035365.9427463487] ], spatialReference: { wkid: 102100 } }; const simpleFillSymbol = { type: "simple-fill" }; const polygonGraphic = new Graphic({ geometry: polygon, symbol: simpleFillSymbol }); graphicsLayer.add(polygonGraphic);
-
Run the code to verify that the graphics appear in the view.
Set sketch component properties
Use the arcgis-sketch
component and GraphicsLayer classes to interactively create a graphic and add it to the arcgis-map
. An event handler will listen for a change from the sketch component and update the spatial relationship accordingly.
-
Set the
snapping
andOptions layer
properties on the sketch component. This will allow you to move and update the line and polyline graphics created in the last step.Use dark colors for code blocks arcgisSketch.snappingOptions = { enabled: true, featureSources: [ { layer: graphicsLayer } ] }; arcgisSketch.layer = graphicsLayer;
-
Run the code to verify that you can use the sketch component to move/update the line and polygon geometries created in the last step.
Determine spatial relationships
Spatial relationships are determined based on the interiors, boundaries, and exteriors of two geometries. Use methods such as contains()
and intersects()
to find the spatial relationship between the sketched geometries.
-
To format the results, create a
show
function. This function takes two parameters: a string representing the spatial relationship type and a value representing whether that relationship is true or false. Find the list item for the spatial relationship by querying the list for the proper id. If the value of the spatial relationship isSpatial Relationship true
, then apply thetrue
CSS class to the appropriate list item. If it'sfalse
, remove the CSS class.Use dark colors for code blocks function showSpatialRelationship(string, value) { const listItem = list.querySelector(`#${string}`); if (value) { listItem.classList.add("true"); } else { listItem.classList.remove("true"); } }
-
Create a function called
on
. If there are less than two graphics in theGraphic Update graphics
remove theLayer true
css class from all the calcite list items and return out of the function.Use dark colors for code blocks function onGraphicUpdate() { if (graphicsLayer.graphics.length < 2) { list.querySelectorAll("calcite-list-item").forEach((listItem) => { listItem.classList.remove("true"); }); return; } }
-
If there are two graphics in the graphics layer, get the geometries to find the spatial relationships.
Use dark colors for code blocks function onGraphicUpdate() { if (graphicsLayer.graphics.length < 2) { list.querySelectorAll("calcite-list-item").forEach((listItem) => { listItem.classList.remove("true"); }); return; } const geometry1 = graphicsLayer.graphics.getItemAt(0).geometry; const geometry2 = graphicsLayer.graphics.getItemAt(1).geometry; }
-
Test each spatial relationship on the two geometries and display the results in the list. Call the
show
function to display the results.Spatial Relationship Use dark colors for code blocks function onGraphicUpdate() { if (graphicsLayer.graphics.length < 2) { list.querySelectorAll("calcite-list-item").forEach((listItem) => { listItem.classList.remove("true"); }); return; } const geometry1 = graphicsLayer.graphics.getItemAt(0).geometry; const geometry2 = graphicsLayer.graphics.getItemAt(1).geometry; const contains = geometryEngine.contains(geometry1, geometry2); showSpatialRelationship("contains", contains); const crosses = geometryEngine.crosses(geometry1, geometry2); showSpatialRelationship("crosses", crosses); const disjoint = geometryEngine.disjoint(geometry1, geometry2); showSpatialRelationship("disjoint", disjoint); const equals = geometryEngine.equals(geometry1, geometry2); showSpatialRelationship("equals", equals); const intersects = geometryEngine.intersects(geometry1, geometry2); showSpatialRelationship("intersects", intersects); const overlaps = geometryEngine.overlaps(geometry1, geometry2); showSpatialRelationship("overlaps", overlaps); const touches = geometryEngine.touches(geometry1, geometry2); showSpatialRelationship("touches", touches); const within = geometryEngine.within(geometry1, geometry2); showSpatialRelationship("within", within); }
Add event listeners
Create an event listener to register a change when a new graphic is drawn or updated. If you draw a new graphic, the last graphic from the graphics layer is removed. The on
function is called to determine the spatial relationships between the remaining geometries.
-
Listen for events on the Sketch widget. Watch for the
arcgis
,Update arcgis
, orUndo arcgis
events, and call theRedo on
method to determine the spatial relationships when these events occur.Graphic Update Use dark colors for code blocks ["arcgisUpdate", "arcgisUndo", "arcgisRedo"].forEach((eventName) => { arcgisSketch.addEventListener(eventName, () => { onGraphicUpdate(); }); });
-
Listen for the
arcgis
event on theCreate arcgis-sketch
component. When theevent.detail.state
is equal to"start"
, remove all but the first graphic in thegraphics
. This will ensure there can only be two graphics in theLayer graphics
at one time. Call theLayer on
function after the new graphic has been created to determine the spatial relationship between the geometries.Graphic Update Use dark colors for code blocks ["arcgisUpdate", "arcgisUndo", "arcgisRedo"].forEach((eventName) => { arcgisSketch.addEventListener(eventName, () => { onGraphicUpdate(); }); }); arcgisSketch.addEventListener("arcgisCreate", async (event) => { if (event.detail.state === "start") { graphicsLayer.graphics = [graphicsLayer.graphics.shift()]; } if (event.detail.state === "complete") { onGraphicUpdate(); } });
-
Call the
on
to calculate the spatial relationships when theGraphic Update arcgis-sketch
component is ready. Use the sketch components'supdate
method to select the polyline graphic so that the user knows they can move that graphic around.Use dark colors for code blocks ["arcgisUpdate", "arcgisUndo", "arcgisRedo"].forEach((eventName) => { arcgisSketch.addEventListener(eventName, () => { onGraphicUpdate(); }); }); arcgisSketch.addEventListener("arcgisCreate", async (event) => { if (event.detail.state === "start") { graphicsLayer.graphics = [graphicsLayer.graphics.shift()]; } if (event.detail.state === "complete") { onGraphicUpdate(); } }); arcgisSketch.addEventListener("arcgisReady", () => { arcgisSketch.update(polylineGraphic).then(onGraphicUpdate); });
Run the app
In CodePen, run your code to display the map.
The map loads and displays a line and polygon graphic. In the bottom right, the spatial relationships between the graphics are displayed. Move the graphics to see how the spatial relationships change. Create new graphics using the Sketch widget to explore the spatial relationships between different geometry types.
What's next?
Learn how to use additional API features and ArcGIS services in these tutorials: