View in MAUI WPF WinUI View on GitHub

Use the Geometry Editor to edit geometries using utility network connectivity rules.

Image of snapping

Use case

A field worker can create new features in a utility network by editing and snapping the vertices of a geometry to existing features on a map. In a gas utility network, gas pipeline features can be represented with the polyline geometry type. Utility networks use geometric coincident-based connectivity to provide pathways for resources. Rule-based snapping uses utility network connectivity rules when editing features based on their asset type and asset group to help maintain network connectivity.

How to use the sample

To edit a geometry, tap a point geometry to be edited in the map to select it. Then edit the geometry by clicking the button to start the geometry editor.

Snap sources can be enabled and disabled. Snapping will not occur when SnapRuleBehavior.RulesPreventSnapping even when the source is enabled.

To interactively snap a vertex to a feature or graphic, ensure that snapping is enabled for the relevant snap source, then move the mouse pointer or drag a vertex close to an existing feature or graphic. If the existing feature or graphic has valid utility network connectivity rules for the asset type that is being created or edited, the edit position will be adjusted to coincide with (or snap to) edges and vertices of its geometry. Click or release the touch pointer to place the vertex at the snapped location.

To discard changes and stop the geometry editor, press the discard button.

To save your edits, press the save button.

How it works

  1. Create a map with LoadSettings.FeatureTilingMode set to EnabledWithFullResolutionWhenSupported.

  2. Create a Geodatabase using the mobile geodatabase file location.

  3. Display Geodatabase.FeatureTables on the map using subtype feature layers.

  4. Create a GeometryEditor and connect it to the map view.

  5. When editing a feature:

    a. Call SnapRules.CreateAsync(UtilityNetwork, UtilityAssetType) to get the snap rules associated with a given UtilityAssetType.

    b. Use SyncSourceSettings(SnapRules, SnapSourceEnablingBehavior.SetFromRules) to populate the SnapSettings.SourceSettings with SnapSourceSettings enabling the sources with rules.

  6. Start the geometry editor with an existing geometry or GeometryType.Point.

Relevant API

  • FeatureLayer
  • Geometry
  • GeometryEditor
  • GeometryEditorStyle
  • GraphicsOverlay
  • MapView
  • SnapRuleBehavior
  • SnapRules
  • SnapSettings
  • SnapSource
  • SnapSourceEnablingBehavior
  • SnapSourceSettings
  • UtilityNetwork

About the data

The Naperville gas network mobile geodatabase contains a utility network with a set of connectivity rules that can be used to perform geometry edits with rules based snapping.

Tags

edit, feature, geometry editor, graphics, layers, map, snapping, utility network

Sample Code

SnapGeometryEditsWithUtilityNetworkRules.xaml SnapGeometryEditsWithUtilityNetworkRules.xaml SnapGeometryEditsWithUtilityNetworkRules.xaml.cs
<UserControl x:Class="ArcGIS.WPF.Samples.SnapGeometryEditsWithUtilityNetworkRules.SnapGeometryEditsWithUtilityNetworkRules"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="clr-namespace:ArcGIS.WPF.Viewer.Converters"
xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013">
<UserControl.Resources>
<DataTemplate x:Key="SnapSettingTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
Content="{Binding Path=Name}"
IsChecked="{Binding Path=SnapSourceSettings.IsEnabled}" />
<Image Grid.Column="1"
Width="15"
Height="15"
Margin="1"
Source="{Binding Path=Symbol}" />
</Grid>
</DataTemplate>
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
<Style x:Key="ButtonIconStyle" TargetType="Button">
<Style.Setters>
<Setter Property="FontFamily" Value="{StaticResource CalciteUIIconsMediumFontFamily}" />
<Setter Property="FontSize" Value="24" />
<Setter Property="Background" Value="White" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Padding" Value="3" />
<Setter Property="Margin" Value="3" />
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.8" />
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Grid>
<esri:MapView x:Name="MyMapView" GeoViewTapped="MyMapView_GeoViewTapped" />
<Border x:Name="SnappingControls"
Margin="10"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Background="White"
Visibility="Collapsed">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Margin="10"
Orientation="Vertical">
<TextBlock x:Name="InstructionsLabel"
Padding="0,5"
FontSize="14"
Text="Tap a point feature to edit."
TextWrapping="Wrap" />
<StackPanel x:Name="SelectedFeaturePanel" Visibility="Collapsed">
<TextBlock Padding="0,5,0,0"
FontSize="14"
FontWeight="Bold"
Text="Feature selected" />
<Grid Margin="0,3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Grid.Column="0"
Margin="0,0,5,0"
Text="AssetGroup:" />
<TextBlock x:Name="SelectedAssetGroupLabel"
Grid.Row="0"
Grid.Column="1" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Margin="0,0,5,0"
Text="AssetType:" />
<TextBlock x:Name="SelectedAssetTypeLabel"
Grid.Row="1"
Grid.Column="1" />
</Grid>
<Button x:Name="GeometryEditorButton"
Width="200"
Click="GeometryEditorButton_Click"
Content="Start editor"
IsEnabled="{Binding GeometryEditor.IsStarted, ElementName=MyMapView, Converter={StaticResource BoolNegationConverter}}" />
<Grid Width="205">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0"
Click="DiscardButton_Click"
IsEnabled="{Binding GeometryEditor.IsStarted, ElementName=MyMapView}"
Margin="3"
ToolTipService.ToolTip="Discard edits"
Style="{StaticResource ButtonIconStyle}"
Content="{StaticResource CalciteUIIcons_Glyph_CircleDisallowed}" />
<Button x:Name="SaveButton"
Grid.Column="1"
Click="SaveButton_Click"
IsEnabled="{Binding GeometryEditor.CanUndo, ElementName=MyMapView}"
Margin="3"
ToolTipService.ToolTip="Save edits"
Style="{StaticResource ButtonIconStyle}"
Content="{StaticResource CalciteUIIcons_Glyph_CheckCircle}" />
</Grid>
</StackPanel>
<StackPanel x:Name="SnapSourcesPanel" Visibility="Collapsed">
<TextBlock Padding="0,5"
FontSize="14"
FontWeight="Bold"
Text="Snap sources" />
<ListView x:Name="SnapSourcesList"
Grid.Column="1"
ItemTemplate="{StaticResource SnapSettingTemplate}" />
<TextBlock Padding="0,5"
FontSize="14"
FontWeight="Bold"
Text="SnapRuleBehavior" />
<StackPanel Margin="20,0,0,0" Orientation="Horizontal">
<Rectangle Grid.Column="0"
Width="10"
Height="10"
Margin="0,0,5,0"
Fill="Green" />
<TextBlock Text="None" />
</StackPanel>
<StackPanel Margin="20,0,0,0" Orientation="Horizontal">
<Rectangle Grid.Column="0"
Width="10"
Height="10"
Margin="0,0,5,0"
Fill="Orange" />
<TextBlock Text="RulesLimitSnapping" />
</StackPanel>
<StackPanel Margin="20,0,0,0" Orientation="Horizontal">
<Rectangle Grid.Column="0"
Width="10"
Height="10"
Margin="0,0,5,0"
Fill="Red" />
<TextBlock Text="RulesPreventSnapping" />
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
</Border>
</Grid>
</UserControl>