Simplify

Download Samples Repository

Description

This sample demonstrates use of the GeometryEngine.Simplify method to simplify a polygon, and demonstrates the importance of simplification. To use the sample, click the Query with Original Polygon button. Observe the results include parcels that are not wholly within the red polygon. Then click the Simplify Polygon, then Query button. Observe the resulting parcels are now wholly within the red polygon.

"Desktop" "Store" "Phone" Available for Desktop, Store, Phone

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.Simplify"
             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/runtime/2013">
    <Grid x:Name="layoutGrid">
        <Grid.Resources>
            <esri:SimpleFillSymbol x:Key="ParcelSymbol" Color="#660000FF" Style="Solid">
                <esri:SimpleFillSymbol.Outline>
                    <esri:SimpleLineSymbol Color="Blue" Width="2" />
                </esri:SimpleFillSymbol.Outline>
            </esri:SimpleFillSymbol>

            <esri:SimpleFillSymbol x:Key="PolygonSymbol" Color="#66FF0000" Style="Solid">
                <esri:SimpleFillSymbol.Outline>
                    <esri:SimpleLineSymbol Color="Red" Width="2" />
                </esri:SimpleFillSymbol.Outline>
            </esri:SimpleFillSymbol>
        </Grid.Resources>

        <esri:MapView x:Name="MyMapView" WrapAround="True">
			<esri:Map InitialViewpoint="-9270434.248,5246977.326,-9269261.417,5247569.712">
				<esri:ArcGISTiledMapServiceLayer
                    ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
            </esri:Map>
			
			<esri:MapView.GraphicsOverlays>
				<esri:GraphicsOverlay ID="parcelOverlay">
					<esri:GraphicsOverlay.Renderer>
						<esri:SimpleRenderer Symbol="{StaticResource ParcelSymbol}" />
					</esri:GraphicsOverlay.Renderer>
				</esri:GraphicsOverlay>
				<esri:GraphicsOverlay ID="polygonOverlay">
					<esri:GraphicsOverlay.Renderer>
						<esri:SimpleRenderer Symbol="{StaticResource PolygonSymbol}" />
					</esri:GraphicsOverlay.Renderer>
				</esri:GraphicsOverlay>
			</esri:MapView.GraphicsOverlays>
        </esri:MapView>

		<Border Background="White" BorderBrush="Black" BorderThickness="1"
				 HorizontalAlignment="Right" VerticalAlignment="Top"
				 Margin="30" Padding="20">
			<Border.Effect>
				<DropShadowEffect/>
			</Border.Effect>
			<StackPanel>
                <TextBlock Text="Many spatial operations require topologically correct geometry.  If you try to use the self-intersecting geometry below without simplifying it you will get incorrect results.  The query's spatial relationship is Contains, which should only return the parcels that the polygon contains." 
                           Width="550" TextWrapping="Wrap" />
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="12,16,12,0">
                    <Button Content="Query with Original Polygon" Margin="8,8,24,0" Click="QueryOnlyButton_Click" />
                    <Button Content="Simplify Polygon, then Query" Margin="8,8,8,0" Click="SimplifyAndQueryButton_Click" />
                </StackPanel>
            </StackPanel>
        </Border>
    </Grid>
</UserControl>
using Esri.ArcGISRuntime.Controls;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Layers;
using Esri.ArcGISRuntime.Tasks.Query;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace ArcGISRuntime.Samples.Desktop
{
	/// <summary>
	/// This sample demonstrates use of the GeometryEngine.Simplify method to simplify a polygon, and demonstrates the importance of simplification. To use the sample, click the Query with Original Polygon button. Observe the results include parcels that are not wholly within the red polygon. Then click the Simplify Polygon, then Query button. Observe the resulting parcels are now wholly within the red polygon.
	/// </summary>
	/// <title>Simplify</title>
	/// <category>Geometry</category>
	public partial class Simplify : UserControl
	{
		private Polygon _unsimplifiedPolygon;
		private GraphicsOverlay _parcelOverlay;
		private GraphicsOverlay _polygonOverlay;

		/// <summary>Construct Geodesic Move sample control</summary>
		public Simplify()
		{
			InitializeComponent();

			_parcelOverlay = MyMapView.GraphicsOverlays["parcelOverlay"];
			_polygonOverlay = MyMapView.GraphicsOverlays["polygonOverlay"];

			MyMapView.NavigationCompleted += MyMapView_NavigationCompleted;
		}

		// Start map interaction once the mapview finishes navigation to initial viewpoint
		private void MyMapView_NavigationCompleted(object sender, EventArgs e)
		{
			MyMapView.NavigationCompleted -= MyMapView_NavigationCompleted;
			DrawPolygon();
		}

		// Query without simplifying original geometry
		private async void QueryOnlyButton_Click(object sender, RoutedEventArgs e)
		{
			await ParcelQuery(_unsimplifiedPolygon);
		}

		// Simplify and then query
		private async void SimplifyAndQueryButton_Click(object sender, RoutedEventArgs e)
		{
			var simplifiedPolygon = GeometryEngine.Simplify(_unsimplifiedPolygon);
			await ParcelQuery(simplifiedPolygon);
		}

		// Draw the unsimplified polygon
		private void DrawPolygon()
		{
			// Get current viewpoints extent from the MapView
			var currentViewpoint = MyMapView.GetCurrentViewpoint(ViewpointType.BoundingGeometry);
			var viewpointExtent = currentViewpoint.TargetGeometry.Extent; 

			MapPoint center = viewpointExtent.GetCenter();
			double lat = center.Y;
			double lon = center.X + 300;
			double latOffset = 300;
			double lonOffset = 300;

			var points = new PointCollection()
			{
				new MapPoint(lon - lonOffset, lat),
				new MapPoint(lon, lat + latOffset),
				new MapPoint(lon + lonOffset, lat),
				new MapPoint(lon, lat - latOffset),
				new MapPoint(lon - lonOffset, lat),
				new MapPoint(lon - 2 * lonOffset, lat + latOffset),
				new MapPoint(lon - 3 * lonOffset, lat),
				new MapPoint(lon - 2 * lonOffset, lat - latOffset),
				new MapPoint(lon - 1.5 * lonOffset, lat + latOffset),
				new MapPoint(lon - lonOffset, lat)
			};
			_unsimplifiedPolygon = new Polygon(points, MyMapView.SpatialReference);

			_polygonOverlay.Graphics.Clear();
			_polygonOverlay.Graphics.Add(new Graphic(_unsimplifiedPolygon));
		}

		// Query the parcel service with the given geometry (Contains)
		private async Task ParcelQuery(Geometry geometry)
		{
			try
			{
				QueryTask queryTask = new QueryTask(
					new Uri("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer/2"));
				var query = new Query(geometry)
				{
					ReturnGeometry = true,
					OutSpatialReference = MyMapView.SpatialReference,
					SpatialRelationship = SpatialRelationship.Contains,
					OutFields = OutFields.All
				};
				var result = await queryTask.ExecuteAsync(query);

				_parcelOverlay.Graphics.Clear();
				_parcelOverlay.Graphics.AddRange(result.FeatureSet.Features.OfType<Graphic>());
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Simplify Geometry Sample");
			}
		}
	}
}
Feedback on this topic?