Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for .NET

Offset

Download Samples Repository

Description

Demonstrates how to create an offset geometry using the Offset method of the GeometryEngine class.

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

Sample Code

<UserControl x:Class="ArcGISRuntime.Samples.Desktop.Offset"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:sys="clr-namespace:System;assembly=mscorlib"
             xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013">
    <Grid x:Name="LayoutRoot">
        <Grid.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="FontSize" Value="14"/>
            </Style>
        </Grid.Resources>

        <esri:MapView x:Name="MyMapView" LayerLoaded="MyMapView_LayerLoaded">
			<esri:Map InitialViewpoint="-9275076, 5253226, -9274274, 5253886, 102100">
				<esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"
                    ServiceUri="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
			</esri:Map>
			<esri:MapView.GraphicsOverlays>
				<esri:GraphicsOverlay ID="ParcelsGraphicsOverlay" Opacity="0.3" >
					<esri:GraphicsOverlay.Renderer>
						<esri:SimpleRenderer>
							<esri:SimpleFillSymbol Color="#990000FF">
								<esri:SimpleFillSymbol.Outline>
									<esri:SimpleLineSymbol Color="Blue" Width="1"/>
								</esri:SimpleFillSymbol.Outline>
							</esri:SimpleFillSymbol>
						</esri:SimpleRenderer>
					</esri:GraphicsOverlay.Renderer>
				</esri:GraphicsOverlay>
				<esri:GraphicsOverlay  ID="OffsetGraphicsOverlay" Opacity="0.4"  >
					<esri:GraphicsOverlay.Renderer>
						<esri:SimpleRenderer>
							<esri:SimpleFillSymbol  Color="Bisque"    >
								<esri:SimpleFillSymbol.Outline>
									<esri:SimpleLineSymbol Color="Green" Width="2"/>
								</esri:SimpleFillSymbol.Outline>
							</esri:SimpleFillSymbol>
						</esri:SimpleRenderer>
					</esri:GraphicsOverlay.Renderer>
				</esri:GraphicsOverlay>
			</esri:MapView.GraphicsOverlays>
        </esri:MapView>

        <Border Background="White" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="30" Padding="20">
            <StackPanel Orientation="Vertical">
                <TextBlock x:Name="InstructionsTextBlock" FontSize="14" Width="275" TextWrapping="Wrap" Visibility="Visible" 
                           Text="First, click on a parcel to generate an offset using the selected parmeters. Update the parameters using the controls to see the changes immediately. Click Reset to clear the graphic." />

                <StackPanel Margin="0,20" x:Name="ControlsContainer">
                    <TextBlock Margin="6,0">
                        <Run Text="Offset Distance : "/>
                        <Run Text="{Binding Value, ElementName=OffsetDistanceSlider, Mode=TwoWay}" />
                    </TextBlock>
                    <Slider x:Name="OffsetDistanceSlider" Minimum="-50" Maximum="50" Value="-20"
                            IsSnapToTickEnabled="True" TickFrequency="5" TickPlacement="BottomRight" />

                    <TextBlock Text="Offset Type : " Margin="0,12,0,0"/>
                    <ComboBox x:Name="OffsetTypeComboBox" />

                    <TextBlock Margin="0,12,0,0">
                        <Run Text="Bevel Ratio : "/>
                        <Run Text="{Binding Value, ElementName=OffsetBevelRatioSlider, Mode=TwoWay}" />
                    </TextBlock>
                    <Slider x:Name="OffsetBevelRatioSlider" Minimum="0" Maximum="5" Value="1.1" 
                            IsSnapToTickEnabled="True" TickPlacement="BottomRight" TickFrequency="0.1" />

                    <TextBlock Margin="0,12,0,0">
                        <Run Text="Flatten Error : "/>
                        <Run Text="{Binding Value, ElementName=OffsetFlattenErrorSlider, Mode=TwoWay}" />
                    </TextBlock>
                    <Slider x:Name="OffsetFlattenErrorSlider" Minimum="0" Maximum="1000" Value="50" 
                            IsSnapToTickEnabled="True" TickPlacement="BottomRight" TickFrequency="25" />
                    
                    <Button x:Name="ResetButton" Content="Reset" Click="ResetButton_Click" Margin="20" IsEnabled="False"/>
                </StackPanel>

                <StackPanel x:Name="LoadingParcelsContainer" Visibility="Collapsed">
                    <TextBlock Text="Loading parcels..." HorizontalAlignment="Center" Margin="0,0,0,4"/>
                    <ProgressBar x:Name="LoadingParcelsIndicator" Height="6" IsIndeterminate="True"/>
                </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.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace ArcGISRuntime.Samples.Desktop
{
	/// <summary>
	/// Demonstrates how to create an offset geometry using the Offset method of the GeometryEngine class.
	/// </summary>
	/// <title>Offset</title>
	/// <category>Geometry</category>
	public partial class Offset : UserControl
	{
		private GraphicsOverlay _parcelOverlay;
		private GraphicsOverlay _offsetOverlay;
		private Graphic _selectedParcelGraphic;

		public Offset()
		{
			InitializeComponent();

			_parcelOverlay = MyMapView.GraphicsOverlays["ParcelsGraphicsOverlay"];
			_offsetOverlay = MyMapView.GraphicsOverlays["OffsetGraphicsOverlay"];

			InitializeOffsetTypes();
			OffsetDistanceSlider.ValueChanged += Slider_ValueChanged;
			OffsetTypeComboBox.SelectionChanged += ComboBox_SelectionChanged;
			OffsetFlattenErrorSlider.ValueChanged += Slider_ValueChanged;
			OffsetBevelRatioSlider.ValueChanged += Slider_ValueChanged;

			ControlsContainer.Visibility = Visibility.Collapsed;
		}

		void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
		{
			DoOffset();
		}

		void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			DoOffset();
		}

		private void InitializeOffsetTypes()
		{
			OffsetTypeComboBox.ItemsSource = new List<OffsetType> { OffsetType.Bevel, OffsetType.Miter, OffsetType.Round, OffsetType.Square };
			OffsetTypeComboBox.SelectedIndex = 0;
		}

		private async Task SelectParcelForOffsetAsync()
		{
			try
			{
				ResetButton.IsEnabled = false;
				_offsetOverlay.Graphics.Clear();

				var pointGeom = await MyMapView.Editor.RequestPointAsync();
				var screenPnt = MyMapView.LocationToScreen(pointGeom);

				_selectedParcelGraphic = await
					_parcelOverlay.HitTestAsync(MyMapView, screenPnt);

				DoOffset();
			}
			catch (TaskCanceledException) { }
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Sample Error");
			}
			finally
			{
				ResetButton.IsEnabled = true;
			}
		}

		private void DoOffset()
		{
			if (_selectedParcelGraphic != null)
			{
				_offsetOverlay.Graphics.Clear();

				try
				{
					var offsetGeom = GeometryEngine.Offset(_selectedParcelGraphic.Geometry,
						OffsetDistanceSlider.Value, (OffsetType)OffsetTypeComboBox.SelectedItem,
						OffsetBevelRatioSlider.Value, OffsetFlattenErrorSlider.Value);
					if (offsetGeom != null)
					{
						_offsetOverlay.Graphics.Add(new Graphic { Geometry = offsetGeom });
					}
				}
				catch (Exception ex)
				{
					MessageBox.Show(ex.Message, "Sample Error");
				}
			}
		}

		private async void ResetButton_Click(object sender, RoutedEventArgs e)
		{
			await SelectParcelForOffsetAsync();
		}

		private async void MyMapView_LayerLoaded(object sender, LayerLoadedEventArgs e)
		{

			if (_parcelOverlay != null && _parcelOverlay.Graphics.Count == 0)
			{
				try
				{
					ControlsContainer.Visibility = Visibility.Collapsed;
					LoadingParcelsContainer.Visibility = Visibility.Visible;

					QueryTask queryTask = new QueryTask(
						new Uri("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/TaxParcel/AssessorsParcelCharacteristics/MapServer/1"));

					// Get current viewpoints extent from the MapView
					var currentViewpoint = MyMapView.GetCurrentViewpoint(ViewpointType.BoundingGeometry);
					var viewpointExtent = currentViewpoint.TargetGeometry.Extent;

					//Create a geometry to use as the extent within which parcels will be returned
					var contractRatio = viewpointExtent.Width / 6;

					var extentGeometry = new Envelope(
						-83.3188395774275,
						42.61428312652851,
						-83.31295664068958,
						42.61670913269855,
						SpatialReferences.Wgs84);

					Query query = new Query(extentGeometry);
					query.ReturnGeometry = true;
					query.OutSpatialReference = SpatialReferences.WebMercator;

					var results = await queryTask.ExecuteAsync(query, CancellationToken.None);
					foreach (Graphic g in results.FeatureSet.Features)
					{
						_parcelOverlay.Graphics.Add(g);
					}

					ControlsContainer.Visibility = Visibility.Visible;
				}
				catch (Exception ex)
				{
					MessageBox.Show("Error loading parcel data: " + ex.Message, "Sample Error");
				}
				finally
				{
					LoadingParcelsContainer.Visibility = Visibility.Collapsed;
				}
			}
			await SelectParcelForOffsetAsync();
		}
	}
}
Feedback on this topic?