# Spatial operations

Find the union, intersection, or difference of two geometries.

## Use case

The different spatial operations (union, difference, symmetric difference, and intersection) can be used for a variety of spatial analyses. For example, government authorities may use the intersect operation to determine whether a proposed road cuts through a restricted piece of land such as a nature reserve or a private property. When these operations are chained together, they become even more powerful. An analysis of food deserts within an urban area might begin by union-ing service areas of grocery stores, farmer's markets, and food co-ops. Taking the difference between this single geometry of all services areas and that of a polygon delineating a neighborhood would reveal the areas within that neighborhood where access to healthy, whole foods may not exist.

## How to use the sample

The sample provides an option to select a spatial operation. When an operation is selected, the resulting geometry is shown in red.

## How it works

1. Create a `GraphicsOverlay` and add it to the `MapView`.
2. Use `PolygonBuilder` to create two polygons.
3. Add the overlapping polygons to the graphics overlay.
4. Perform spatial relationships between the polygons by using the appropriate operation:
• `GeometryEngine.unionOf(geometry1, geometry2)` - This method returns the two geometries united together as one geometry.
• `GeometryEngine.difference(geometry1, geometry2)` - This method returns any part of Geometry2 that does not intersect Geometry1.
• `GeometryEngine.symmetricDifference(geometry1, geometry2)` - This method returns any part of Geometry1 or Geometry2 which do not intersect.
• `GeometryEngine.intersection(geometry1, geometry2)` - This method returns the intersection of Geometry1 and Geometry2.
5. Use the geometry that is returned from the method call to create a new `Graphic` and add it to the graphics overlay for it to be displayed.

## Relevant API

• Geometry
• GeometryEngine
• GeometryEngine.difference
• GeometryEngine.intersection
• GeometryEngine.symmetricDifference
• GeometryEngine.unionOf
• Graphic
• GraphicsOverlay

## Tags

analysis, combine, difference, geometry, intersection, merge, polygon, union

## Sample Code

``````import QtQuick 2.6
import QtQuick.Controls 2.2
import Esri.ArcGISRuntime 100.9

Rectangle {
id: rootRectangle
clip: true
width: 800
height: 600

property var geometryOperations: ["None", "Union", "Difference", "Symmetric difference", "Intersection"]
property var geometry1
property var geometry2

MapView {
id: mapView
anchors.fill: parent

Map {
id: map
BasemapTopographic {}

ViewpointCenter {
Point {
x: -13453
y: 6710127
spatialReference: spatialRef
}
targetScale: 30000
}

}
}

GraphicsOverlay {
id: inputOverlay
}

GraphicsOverlay {
id: outputOverlay
}
}

// Display a ComboBox with options for each operation
ComboBox {
id: comboBox
anchors {
left: parent.left
top: parent.top
margins: 10
}
property int modelWidth: 0
model: geometryOperations

onCurrentIndexChanged: applyGeometryOperation(currentIndex);

Component.onCompleted : {
for (let i = 0; i < model.length; ++i) {
metrics.text = model[i];
modelWidth = Math.max(modelWidth, metrics.width);
}
}
TextMetrics {
id: metrics
font: comboBox.font
}
}

SpatialReference {
id: spatialRef
wkid: 3857
}

if (!inputOverlay)
return;

// create blue polygon
const polygonBuilder1 = ArcGISRuntimeEnvironment.createObject("PolygonBuilder", { spatialReference: spatialRef });

const fillSymbol1 = ArcGISRuntimeEnvironment.createObject("SimpleFillSymbol");
fillSymbol1.style = Enums.SimpleFillSymbolStyleSolid;
fillSymbol1.color = "blue";
geometry1 = polygonBuilder1.geometry;
const graphic1 = ArcGISRuntimeEnvironment.createObject("Graphic");
graphic1.geometry = geometry1;
graphic1.symbol = fillSymbol1;
inputOverlay.graphics.append(graphic1);

// create green polygon
// outer ring
const outerRing = ArcGISRuntimeEnvironment.createObject("Part", { spatialReference: spatialRef });

// inner ring
const innerRing = ArcGISRuntimeEnvironment.createObject("Part", { spatialReference: spatialRef });

const polygonBuilder2 = ArcGISRuntimeEnvironment.createObject("PolygonBuilder", { spatialReference: spatialRef });
geometry2 = polygonBuilder2.geometry;
const fillSymbol2 = ArcGISRuntimeEnvironment.createObject("SimpleFillSymbol");
fillSymbol2.style = Enums.SimpleFillSymbolStyleSolid;
fillSymbol2.color = "green";
const graphic2 = ArcGISRuntimeEnvironment.createObject("Graphic");
graphic2.geometry = geometry2;
graphic2.symbol = fillSymbol2;
inputOverlay.graphics.append(graphic2);
}

function applyGeometryOperation(index) {
return;

// Perform geometry calculations
let resultPolygon;
switch (index) {
case 1:
resultPolygon = GeometryEngine.unionOf(geometry1, geometry2);
break;
case 2:
resultPolygon = GeometryEngine.difference(geometry1, geometry2);
break;
case 3:
resultPolygon = GeometryEngine.symmetricDifference(geometry1, geometry2);
break;
case 4:
resultPolygon = GeometryEngine.intersection(geometry1, geometry2);
break;
case 0:
default:
break;
}

// Clear previous results
outputOverlay.graphics.clear();
if (!resultPolygon)
return;

// Add the resulting polygon as a Graphic
const fillSymbol = ArcGISRuntimeEnvironment.createObject("SimpleFillSymbol");
fillSymbol.style = Enums.SimpleFillSymbolStyleSolid;
fillSymbol.color = "red";
const graphic = ArcGISRuntimeEnvironment.createObject("Graphic");
graphic.geometry = resultPolygon;
graphic.symbol = fillSymbol;
outputOverlay.graphics.append(graphic);
}
}``````