This sample demonstrates using the ArcGIS Runtime SDK for WPF to perform a geometry operation that takes two or more input polygons and returns a polygon that is the union of the inputs. The input polygons do not have to be contiguous (i.e. touching) to be unioned. Polygons that are spatially disparate, like islands, can be unioned into one polygon.
To use the sample, click on the parcel polygons to select or unselect graphic features. Click on the Union button to union selected parcels.
<UserControlx:Class="ArcGISWPFSDK.LocalUnion"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:esri="http://schemas.esri.com/arcgis/client/2009"><Gridx:Name="LayoutRoot"><Grid.Resources><esri:SimpleLineSymbolx:Key="RedLineSymbol"Color="Red"Width="4"Style="Solid"/><esri:FillSymbolx:Key="BlueFillSymbol"><esri:FillSymbol.ControlTemplate><ControlTemplatex:Name="CustomPolygonTemplate"><Grid><VisualStateManager.VisualStateGroups><VisualStateGroupx:Name="CommonStates"><VisualStatex:Name="Unselected"/><VisualStatex:Name="Selected"><Storyboard><ColorAnimationStoryboard.TargetName="Element"Storyboard.TargetProperty="(Fill).(Color)"To="#99FFFF00"Duration="0:0:0.1"/></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Pathx:Name="Element"Stroke="Red"Fill="#660000FF"StrokeStartLineCap="Round"StrokeThickness="2"StrokeLineJoin="Round"StrokeEndLineCap="Round"/></Grid></ControlTemplate></esri:FillSymbol.ControlTemplate></esri:FillSymbol><LinearGradientBrushx:Key="PanelGradient"EndPoint="0.5,1"StartPoint="0.5,0"><LinearGradientBrush.RelativeTransform><TransformGroup><ScaleTransformCenterY="0.5"CenterX="0.5"/><SkewTransformCenterY="0.5"CenterX="0.5"/><RotateTransformAngle="176"CenterY="0.5"CenterX="0.5"/><TranslateTransform/></TransformGroup></LinearGradientBrush.RelativeTransform><GradientStopColor="#FF145787"Offset="0.16"/><GradientStopColor="#FF3D7FAC"Offset="0.502"/><GradientStopColor="#FF88C5EF"Offset="0.984"/></LinearGradientBrush></Grid.Resources><esri:Mapx:Name="MyMap"Extent="-15000000,2000000,-7000000,8000000"Background="#FFE3E3E3"><esri:ArcGISLocalTiledLayerID="BaseMap"Path="..\\Data\\TPKs\\Topographic.tpk"/><esri:GraphicsLayerID="ParcelsGraphicsLayer"x:Name="_parcelGraphicsLayer"/></esri:Map><GridHorizontalAlignment="Right"VerticalAlignment="Top"Margin="0,10,10,0"><RectangleFill="{StaticResource PanelGradient}"Stroke="Gray"RadiusX="10"RadiusY="10"Margin="0,0,0,5"><Rectangle.Effect><DropShadowEffect/></Rectangle.Effect></Rectangle><RectangleFill="#FFFFFFFF"Stroke="DarkGray"RadiusX="5"RadiusY="5"Margin="10,10,10,15"/><StackPanelOrientation="Vertical"HorizontalAlignment="Center"Margin="30,20,20,30"><TextBlockx:Name="ResponseTextBlock"Width="200"Text="Click on the parcel polygons to select or unselect graphic features. Click on the Union button to union selected parcels."TextAlignment="Left"TextWrapping="Wrap"Foreground="Black"/><ButtonContent="Union"Margin="0,5,5,0"x:Name="UnionButton"Width="100"Click="UnionButton_Click"IsEnabled="False"/></StackPanel></Grid></Grid></UserControl>
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Tasks;
using ESRI.ArcGIS.Client.Local;
namespace ArcGISWPFSDK
{
publicpartialclass LocalUnion : UserControl
{
private Draw _drawObject;
List<Graphic> _selectedGraphics = new List<Graphic>();
GeometryService _geometryTask;
public LocalUnion()
{
InitializeComponent();
MyMap.Layers.LayersInitialized += (s, e) =>
{
LocalMapService.GetServiceAsync("..\\Data\\MPKS\\USCitiesStates.mpk", (localMapService) =>
{
QueryTask _queryTask = new QueryTask();
_queryTask.Url = localMapService.UrlMapService + "/2";
Query query = new Query();
query.Geometry = MyMap.Extent;
query.ReturnGeometry = true;
_queryTask.ExecuteCompleted += queryTask_ExecuteCompleted;
_queryTask.Failed += queryTask_Failed;
_queryTask.ExecuteAsync(query);
});
_drawObject = new Draw(MyMap)
{
DrawMode = DrawMode.Point,
IsEnabled = false,
};
_drawObject.DrawComplete += DrawObject_DrawComplete;
};
LocalGeometryService.GetServiceAsync(lgs =>
{
_geometryTask = new GeometryService();
_geometryTask.Url = lgs.UrlGeometryService;
_geometryTask.UnionCompleted += GeometryService_UnionCompleted;
_geometryTask.Failed += GeometryService_Failed;
});
MyMap.MinimumResolution = double.Epsilon;
}
void queryTask_Failed(object sender, TaskFailedEventArgs e)
{
MessageBox.Show("Query error: " + e.Error);
}
void queryTask_ExecuteCompleted(object sender, QueryEventArgs e)
{
foreach (Graphic g in e.FeatureSet.Features)
{
g.Symbol = LayoutRoot.Resources["BlueFillSymbol"] as ESRI.ArcGIS.Client.Symbols.Symbol;
g.Geometry.SpatialReference = MyMap.SpatialReference;
_parcelGraphicsLayer.Graphics.Add(g);
}
_drawObject.IsEnabled = true;
}
privatevoid DrawObject_DrawComplete(object sender, DrawEventArgs args)
{
ESRI.ArcGIS.Client.Geometry.MapPoint point = args.Geometry as ESRI.ArcGIS.Client.Geometry.MapPoint;
point.SpatialReference = MyMap.SpatialReference;
System.Windows.Point screenPnt = MyMap.MapToScreen(point);
// Account for difference between Map and application origin
GeneralTransform generalTransform = MyMap.TransformToVisual(Application.Current.MainWindow);
System.Windows.Point transformScreenPnt = generalTransform.Transform(screenPnt);
IEnumerable<Graphic> selected =
_parcelGraphicsLayer.FindGraphicsInHostCoordinates(transformScreenPnt);
foreach (Graphic g in selected)
if (g.Selected) { g.UnSelect(); _selectedGraphics.Remove(g); }
else { g.Select(); _selectedGraphics.Add(g); }
if (_selectedGraphics.Count > 1)
UnionButton.IsEnabled = true;
else
UnionButton.IsEnabled = false;
}
privatevoid UnionButton_Click(object sender, RoutedEventArgs e)
{
UnionButton.IsEnabled = false;
_drawObject.IsEnabled = false;
_geometryTask.UnionAsync(_selectedGraphics);
}
void GeometryService_UnionCompleted(object sender, GeometryEventArgs e)
{
foreach (Graphic g in _selectedGraphics)
_parcelGraphicsLayer.Graphics.Remove(g);
_selectedGraphics.Clear();
_parcelGraphicsLayer.Graphics.Add(new Graphic() { Geometry = e.Result, Symbol = LayoutRoot.Resources["BlueFillSymbol"] as ESRI.ArcGIS.Client.Symbols.Symbol });
_drawObject.IsEnabled = true;
}
privatevoid GeometryService_Failed(object sender, TaskFailedEventArgs e)
{
MessageBox.Show("Geometry Service error: " + e.Error);
}
}
}
Imports System.Collections.Generic
Imports System.Linq
Imports System.Net
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Shapes
Imports ESRI.ArcGIS.Client
Imports ESRI.ArcGIS.Client.Tasks
Imports ESRI.ArcGIS.Client.Local
Namespace ArcGISWPFSDK
PartialPublicClass LocalUnion
Inherits UserControl
Private MyDrawObject As Draw
Private parcelGraphicsLayer As GraphicsLayer
Private selectedGraphics AsNew List(Of Graphic)()
Private _geometryService As GeometryService
Private _queryTask As QueryTask
Private _mapService As LocalMapService
PublicSubNew()
InitializeComponent()
LocalMapService.GetServiceAsync("..\Data\MPKS\USCitiesStates.mpk", Function(localMapService__1)
_mapService = localMapService__1
_queryTask = New QueryTask()
_queryTask.Url = _mapService.UrlMapService & "/2"Dim query AsNew Query()
query.Geometry = MyMap.Extent
query.ReturnGeometry = TrueAddHandler _queryTask.ExecuteCompleted, AddressOf queryTask_ExecuteCompleted
AddHandler _queryTask.Failed, AddressOf queryTask_Failed
_queryTask.ExecuteAsync(query)
EndFunction)
Dim localGeometryService AsNew LocalGeometryService()
AddHandler localGeometryService.StartCompleted, Function(sender, eventargs)
Dim lgs As LocalGeometryService = TryCast(sender, LocalGeometryService)
_geometryService = New GeometryService()
_geometryService.Url = lgs.UrlGeometryService
AddHandler _geometryService.UnionCompleted, AddressOf GeometryService_UnionCompleted
AddHandler _geometryService.Failed, AddressOf GeometryService_Failed
EndFunction
localGeometryService.StartAsync()
MyMap.MinimumResolution = Double.Epsilon
MyDrawObject = New Draw(MyMap) With { _
.DrawMode = DrawMode.Point, _
.IsEnabled = False _
}
AddHandler MyDrawObject.DrawComplete, AddressOf MyDrawObject_DrawComplete
parcelGraphicsLayer = TryCast(MyMap.Layers("ParcelsGraphicsLayer"), GraphicsLayer)
EndSubPrivateSub queryTask_Failed(sender AsObject, e As TaskFailedEventArgs)
MessageBox.Show("Query error: " & Convert.ToString(e.[Error]))
EndSubPrivateSub queryTask_ExecuteCompleted(sender AsObject, e As QueryEventArgs)
ForEach g As Graphic In e.FeatureSet.Features
g.Symbol = TryCast(LayoutRoot.Resources("BlueFillSymbol"), ESRI.ArcGIS.Client.Symbols.Symbol)
g.Geometry.SpatialReference = MyMap.SpatialReference
parcelGraphicsLayer.Graphics.Add(g)
Next
MyDrawObject.IsEnabled = TrueEndSubPrivateSub MyDrawObject_DrawComplete(sender AsObject, args As DrawEventArgs)
Dim point As ESRI.ArcGIS.Client.Geometry.MapPoint = TryCast(args.Geometry, ESRI.ArcGIS.Client.Geometry.MapPoint)
point.SpatialReference = MyMap.SpatialReference
Dim screenPnt As System.Windows.Point = MyMap.MapToScreen(point)
' Account for difference between Map and application originDim generalTransform As GeneralTransform = MyMap.TransformToVisual(Application.Current.MainWindow)
Dim transformScreenPnt As System.Windows.Point = generalTransform.Transform(screenPnt)
Dim selected As IEnumerable(Of Graphic) = parcelGraphicsLayer.FindGraphicsInHostCoordinates(transformScreenPnt)
ForEach g As Graphic In selected
If g.Selected Then
g.UnSelect()
selectedGraphics.Remove(g)
Else
g.[Select]()
selectedGraphics.Add(g)
EndIfNextIf selectedGraphics.Count > 1 Then
UnionButton.IsEnabled = TrueElse
UnionButton.IsEnabled = FalseEndIfEndSubPrivateSub UnionButton_Click(sender AsObject, e As RoutedEventArgs)
UnionButton.IsEnabled = False
MyDrawObject.IsEnabled = False
_geometryService.UnionAsync(selectedGraphics)
EndSubPrivateSub GeometryService_UnionCompleted(sender AsObject, e As GeometryEventArgs)
ForEach g As Graphic In selectedGraphics
parcelGraphicsLayer.Graphics.Remove(g)
Next
selectedGraphics.Clear()
parcelGraphicsLayer.Graphics.Add(New Graphic() With { _
.Geometry = e.Result, _
.Symbol = TryCast(LayoutRoot.Resources("BlueFillSymbol"), ESRI.ArcGIS.Client.Symbols.Symbol) _
})
MyDrawObject.IsEnabled = TrueEndSubPrivateSub GeometryService_Failed(sender AsObject, e As TaskFailedEventArgs)
MessageBox.Show("Geometry Service error: " & Convert.ToString(e.[Error]))
EndSubEndClassEndNamespace