This sample demonstrates using the ArcGIS Runtime SDK for WPF to perform a geometry operation that takes an input polyline graphic that cuts across a polygon graphic to generate a new polygon graphics that is reshaped to be smaller by the cutting polyline. To make this sample work requires a two step interaction of first selection and existing polygon via a mouse click and then drawing a polyline across the selected polygon. The Draw_Complete event in the code-behind uses If/Else logic to determine if the user is in the first step or the second step via the an ESRI.ArcGIS.Client Draw object to determine what drawing mode (Point, Polyline, Polygon, etc.) is being used.
To use the sample, (step 1) click to select a parcel polygon and (step 2) digitize a line that intersects the selected polygon. The start and/or end point of the line can be inside the polygon.
<UserControlx:Class="ArcGISWPFSDK.LocalReshape"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"xmlns:sys="clr-namespace:System;assembly=mscorlib"><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="Normal"/><VisualStatex:Name="Selected"><Storyboard><ColorAnimationUsingKeyFramesBeginTime="0"Duration="0"Storyboard.TargetName="Element"Storyboard.TargetProperty="(Fill).(Color)"><SplineColorKeyFrameKeyTime="0"Value="#6600FFFF"/></ColorAnimationUsingKeyFrames></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><sys:Stringx:Key="StartText">Click to select a parcel polygon.</sys:String><sys:Stringx:Key="EndText">Digitize a line that intersects the selected polygon. The start and/or end point of the line can be inside the polygon.</sys:String><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"/><TextBlockx:Name="InfoTextBlock"Text="{StaticResource StartText}"Width="200"TextAlignment="Left"Margin="30,20,20,30"TextWrapping="Wrap"Foreground="Black"/></Grid></Grid></UserControl>
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Tasks;
using System.Collections.Generic;
using System.Windows.Media;
using ESRI.ArcGIS.Client.Local;
namespace ArcGISWPFSDK
{
publicpartialclass LocalReshape : UserControl
{
private Draw _drawObject;
private Graphic _selectedGraphic;
GeometryService _geometryTask;
public LocalReshape()
{
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;
query.OutSpatialReference = MyMap.SpatialReference;
_queryTask.ExecuteCompleted += queryTask_ExecuteCompleted;
_queryTask.Failed += queryTask_Failed;
_queryTask.ExecuteAsync(query);
});
_drawObject = new Draw(MyMap)
{
DrawMode = DrawMode.Point,
LineSymbol = LayoutRoot.Resources["RedLineSymbol"] as ESRI.ArcGIS.Client.Symbols.LineSymbol,
IsEnabled = false
};
_drawObject.DrawComplete += DrawObject_DrawComplete;
};
LocalGeometryService.GetServiceAsync(lgs =>
{
_geometryTask = new GeometryService();
_geometryTask.Url = lgs.UrlGeometryService;
_geometryTask.ReshapeCompleted += GeometryService_ReshapeCompleted;
_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)
{
_drawObject.IsEnabled = false;
if (_drawObject.DrawMode == DrawMode.Point)
{
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);
if (selected.ToArray().Length <= 0)
{
_drawObject.IsEnabled = true;
return;
}
_selectedGraphic = selected.ToList()[0] as Graphic;
_selectedGraphic.Select();
_drawObject.DrawMode = DrawMode.Polyline;
_drawObject.IsEnabled = true;
InfoTextBlock.Text = LayoutRoot.Resources["EndText"] asstring;
}
else
{
ESRI.ArcGIS.Client.Geometry.Polyline polyline = args.Geometry as ESRI.ArcGIS.Client.Geometry.Polyline;
polyline.SpatialReference = MyMap.SpatialReference;
// Should use one of the other geometry operations, such as RelationAsync, prior to calling ReshapeAsync to ensure that the user defined polyline actually // does intersect the selected polygon. For simplicity here we assume that it always does.
_geometryTask.ReshapeAsync(_selectedGraphic.Geometry, polyline);
}
}
void GeometryService_ReshapeCompleted(object sender, GeometryEventArgs e)
{
_parcelGraphicsLayer.Graphics.Remove(_selectedGraphic);
Graphic graphic = new Graphic()
{
Symbol = LayoutRoot.Resources["BlueFillSymbol"] as ESRI.ArcGIS.Client.Symbols.Symbol,
Geometry = e.Result
};
_parcelGraphicsLayer.Graphics.Add(graphic);
_drawObject.DrawMode = DrawMode.Point;
_drawObject.IsEnabled = true;
InfoTextBlock.Text = LayoutRoot.Resources["StartText"] asstring;
}
privatevoid GeometryService_Failed(object sender, TaskFailedEventArgs e)
{
MessageBox.Show("Geometry Service error: " + e.Error);
}
}
}
Imports System.Linq
Imports System.Windows
Imports System.Windows.Controls
Imports ESRI.ArcGIS.Client
Imports ESRI.ArcGIS.Client.Tasks
Imports System.Collections.Generic
Imports System.Windows.Media
Imports ESRI.ArcGIS.Client.Local
Namespace ArcGISWPFSDK
PartialPublicClass LocalReshape
Inherits UserControl
Private MyDrawObject As Draw
Private parcelGraphicsLayer As GraphicsLayer
Private selectedGraphic As 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 = True
query.OutSpatialReference = MyMap.SpatialReference
AddHandler _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.ReshapeCompleted, AddressOf GeometryService_ReshapeCompleted
AddHandler _geometryService.Failed, AddressOf GeometryService_Failed
MyDrawObject = New Draw(MyMap) With { _
.DrawMode = DrawMode.Point, _
.LineSymbol = TryCast(LayoutRoot.Resources("RedLineSymbol"), ESRI.ArcGIS.Client.Symbols.LineSymbol), _
.IsEnabled = False _
}
AddHandler MyDrawObject.DrawComplete, AddressOf MyDrawObject_DrawComplete
EndFunction
localGeometryService.StartAsync()
MyMap.MinimumResolution = Double.Epsilon
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)
MyDrawObject.IsEnabled = FalseIf MyDrawObject.DrawMode = DrawMode.Point ThenDim 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)
If selected.ToArray().Length <= 0 Then
MyDrawObject.IsEnabled = TrueReturnEndIf
selectedGraphic = TryCast(selected.ToList()(0), Graphic)
selectedGraphic.[Select]()
MyDrawObject.DrawMode = DrawMode.Polyline
MyDrawObject.IsEnabled = True
InfoTextBlock.Text = TryCast(LayoutRoot.Resources("EndText"), String)
ElseDim polyline As ESRI.ArcGIS.Client.Geometry.Polyline = TryCast(args.Geometry, ESRI.ArcGIS.Client.Geometry.Polyline)
polyline.SpatialReference = MyMap.SpatialReference
' Should use one of the other geometry operations, such as RelationAsync, prior to calling ReshapeAsync to ensure that the user defined polyline actually ' does intersect the selected polygon. For simplicity here we assume that it always does.
_geometryService.ReshapeAsync(selectedGraphic.Geometry, polyline)
EndIfEndSubPrivateSub GeometryService_ReshapeCompleted(sender AsObject, e As GeometryEventArgs)
parcelGraphicsLayer.Graphics.Remove(selectedGraphic)
Dim graphic AsNew Graphic() With { _
.Symbol = TryCast(LayoutRoot.Resources("BlueFillSymbol"), ESRI.ArcGIS.Client.Symbols.Symbol), _
.Geometry = e.Result _
}
parcelGraphicsLayer.Graphics.Add(graphic)
MyDrawObject.DrawMode = DrawMode.Point
MyDrawObject.IsEnabled = True
InfoTextBlock.Text = TryCast(LayoutRoot.Resources("StartText"), String)
EndSubPrivateSub GeometryService_Failed(sender AsObject, e As TaskFailedEventArgs)
MessageBox.Show("Geometry Service error: " & Convert.ToString(e.[Error]))
EndSubEndClassEndNamespace