Trace Geometric Network
The sample uses a Geoprocessing Package which contains a Model involving the Trace Geometric Network (Data Management) geoprocessing tool to perform an upstream trace from the "incident location" to determine the affected water distribution mains and system valves.
Download Sample Application<UserControl x:Class="ArcGISWPFSDK.TraceGeometricNetwork" 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"> <Grid x:Name="MainGrid"> <Grid.Resources> <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> <esri:PictureMarkerSymbol x:Key="IncidentMarkerSymbol" Source="/Assets/Images/Incident_48x48.png" Width="48" Height="48" OffsetX="18" OffsetY="40"/> <esri:PictureMarkerSymbol x:Key="ValveMarkerSymbol" Source="/Assets/Images/Valve_48x48.png" Width="48" Height="48" OffsetX="24" OffsetY="24"/> </Grid.Resources> <esri:Map x:Name="MyMap" UseAcceleratedDisplay="True" Extent="-9552200, 3812271, -9550728 , 3813197"> <esri:ArcGISTiledMapServiceLayer ID="World Topo Map" Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" InitializationFailed="ArcGISTiledMapServiceLayer_InitializationFailed"/> </esri:Map> <Border HorizontalAlignment="Right" Background="White" VerticalAlignment="Top" Margin="15" MinHeight="50" BorderBrush="Black" BorderThickness="1"> <Border.Effect> <DropShadowEffect/> </Border.Effect> <StackPanel Orientation="Vertical" HorizontalAlignment="Center" Margin="5" > <TextBlock FontSize="18" HorizontalAlignment="Center" > Click to perform an upstream trace <LineBreak/>on the geometric network. </TextBlock> <Button x:Name="TraceUpstreamButton" Content="Trace Network" IsEnabled="False" Width="160" Margin="5" FontSize="18" HorizontalAlignment="Center" Click="TraceUpstreamButton_Click" /> </StackPanel> </Border> <ProgressBar x:Name="MyProgressBar" IsIndeterminate="True" VerticalAlignment="Bottom" Width="200" Height="20" Margin="10" Visibility="{Binding Path=IsBusy, Converter={StaticResource BooleanToVisibilityConverter}}"></ProgressBar> </Grid> </UserControl>
using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using ESRI.ArcGIS.Client; using ESRI.ArcGIS.Client.Local; using ESRI.ArcGIS.Client.Tasks; using ESRI.ArcGIS.Client.Geometry; using System.Collections.Generic; using ESRI.ArcGIS.Client.Symbols; using System.ComponentModel; namespace ArcGISWPFSDK { public partial class TraceGeometricNetwork : UserControl, INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private bool _isBusy = true; public bool IsBusy { get { return _isBusy; } set { _isBusy = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("IsBusy")); } } } LocalGeoprocessingService traceNetworkLocalGpService; Geoprocessor geoprocessorTask; LocalGeometryService localGeometryService; GeometryService geometryTask; LocalMapService waterNetworkLocalMapService; GraphicsLayer inputGraphicsLayer; GraphicsLayer valvesGraphicsLayer; GraphicsLayer mainsGraphicsLayer; public TraceGeometricNetwork() { InitializeComponent(); DataContext = this; /* * Asynchronously start all the services... */ LocalGeoprocessingService.GetServiceAsync(@"..\data\gpks\TraceGeometricNetwork\TraceGeometricNetwork.gpk", GPServiceType.SubmitJob, localServiceCallback => { if (localServiceCallback.Error != null) { MessageBox.Show(localServiceCallback.Error.Message); return; } traceNetworkLocalGpService = localServiceCallback; geoprocessorTask = new Geoprocessor(traceNetworkLocalGpService.Tasks[0].Url); // Enable the UI when the Trace Geometric Network service is available TraceUpstreamButton.IsEnabled = true; IsBusy = false; }); LocalGeometryService.GetServiceAsync(callback => { localGeometryService = callback; geometryTask = new GeometryService(); geometryTask.Url = localGeometryService.UrlGeometryService; }); LocalMapService.GetServiceAsync(@"..\data\mpks\WaterDistributionNetwork.mpk", callback => { if (callback.Error != null) { MessageBox.Show("WaterDistributionNetwork map failed to load"); return; } waterNetworkLocalMapService = callback; ArcGISLocalDynamicMapServiceLayer WaterDistributionNetworkLayer = new ArcGISLocalDynamicMapServiceLayer(waterNetworkLocalMapService); MyMap.Layers.Insert(1, WaterDistributionNetworkLayer); }); /* * Create the Results GraphicsLayers and associated Renderers */ valvesGraphicsLayer = new GraphicsLayer() { Renderer = new SimpleRenderer() { Symbol = MainGrid.Resources["ValveMarkerSymbol"] as Symbol } }; mainsGraphicsLayer = new GraphicsLayer() { Renderer = new SimpleRenderer() { Symbol = new SimpleLineSymbol() { Color = new SolidColorBrush(Colors.Red), Width = 8, Style = SimpleLineSymbol.LineStyle.Dash } } }; // Add the GraphicsLayers to the Map MyMap.Layers.Add(mainsGraphicsLayer); MyMap.Layers.Add(valvesGraphicsLayer); } private void TraceUpstreamButton_Click(object sender, RoutedEventArgs e) { if (geoprocessorTask.IsBusy || geometryTask.IsBusy) return; ClearMap(); TraceUpstreamButton.IsEnabled = false; IsBusy = true; /* * Add a graphic at the input location */ MapPoint inputMapPoint = new MapPoint(-9551495, 3812812, MyMap.SpatialReference); if (inputGraphicsLayer == null) { inputGraphicsLayer = new GraphicsLayer(); MyMap.Layers.Add(inputGraphicsLayer); } Graphic graphic = new Graphic() { Symbol = MainGrid.Resources["IncidentMarkerSymbol"] as Symbol, Geometry = inputMapPoint, }; inputGraphicsLayer.Graphics.Add(graphic); /* * Reproject the input MapPoint into the GP coordinate system (for example if it came from a user map click) */ // Declare the ProjectCompleted Handler EventHandler<GraphicsEventArgs> ProjectCompletedHandler = null; // Handle the event ProjectCompletedHandler = (sender2, graphicsEventArgs) => { // Unregister the handler geometryTask.ProjectCompleted -= ProjectCompletedHandler; // Cancel any existing GP Jobs geoprocessorTask.CancelAsync(); // Declare the JobCompleted Handler EventHandler<JobInfoEventArgs> JobCompletedHandler = null; // Handle the JobCompleted event JobCompletedHandler = (sender3, jobInfoEventArgs) => { // Unregister the JobCompleted handler geoprocessorTask.JobCompleted -= JobCompletedHandler; // Check whether it succeeded if (jobInfoEventArgs.JobInfo.JobStatus != esriJobStatus.esriJobSucceeded) { MessageBox.Show("Geometric Network Trace Failed."); return; }; /* * Create two new Geoprocessor Tasks to fetch the result data (thereby allowing them to run concurrently) * Each will use the same event handler and we'll choose based on the Parameter Name. * Alternatively could use the overload which takes an object (userToken). */ Geoprocessor gpTaskSysvalves_Layer = new Geoprocessor(traceNetworkLocalGpService.Tasks[0].Url); gpTaskSysvalves_Layer.Failed += GetResultData_Failed; gpTaskSysvalves_Layer.GetResultDataCompleted += geoprocessorTask_GetResultDataCompleted; gpTaskSysvalves_Layer.GetResultDataAsync( jobInfoEventArgs.JobInfo.JobId, "Sysvalves_Layer"); Geoprocessor gpTaskDistribMains_Layer = new Geoprocessor(traceNetworkLocalGpService.Tasks[0].Url); gpTaskDistribMains_Layer.Failed += GetResultData_Failed; gpTaskDistribMains_Layer.GetResultDataCompleted += geoprocessorTask_GetResultDataCompleted; gpTaskDistribMains_Layer.GetResultDataAsync( jobInfoEventArgs.JobInfo.JobId, "DistribMains_Layer"); }; // Create the GP Parameter List List<GPParameter> parameters = new List<GPParameter>(); parameters.Add(new GPFeatureRecordSetLayer("Flags", graphicsEventArgs.Results[0].Geometry)); geoprocessorTask.JobCompleted += JobCompletedHandler; geoprocessorTask.SubmitJobAsync(parameters); }; // Register the handler for the ProjectCompleted event. geometryTask.ProjectCompleted += ProjectCompletedHandler; // Project the input point into the coordinate system of the data geometryTask.ProjectAsync(new List<Graphic>() { new Graphic() { Geometry = inputMapPoint, } }, waterNetworkLocalMapService.SpatialReference); } void GetResultData_Failed(object sender, TaskFailedEventArgs e) { MessageBox.Show("Analysis succeeded but failed to get result data."); IsBusy = false; TraceUpstreamButton.IsEnabled = true; } void geoprocessorTask_GetResultDataCompleted(object sender, GPParameterEventArgs gpParameterEventArgs) { // Get the result features from the parameter GPFeatureRecordSetLayer gpLayer; gpLayer = gpParameterEventArgs.Parameter as GPFeatureRecordSetLayer; // Check the parameter name, reproject and add to the appropriate graphics layer. // again - two separate tasks are created allowing them to run conncurrently. switch (gpParameterEventArgs.Parameter.Name) { case "Sysvalves_Layer": GeometryService valvesProjectTask = new GeometryService(localGeometryService.UrlGeometryService); valvesProjectTask.ProjectCompleted += (sender2, graphicsEventArgs) => { valvesGraphicsLayer.Graphics.AddRange(graphicsEventArgs.Results); }; valvesProjectTask.ProjectAsync(gpLayer.FeatureSet.Features, new SpatialReference(3857)); break; case "DistribMains_Layer": GeometryService mainsProjectTask = new GeometryService(localGeometryService.UrlGeometryService); mainsProjectTask.ProjectCompleted += (sender2, graphicsEventArgs) => { mainsGraphicsLayer.Graphics.AddRange(graphicsEventArgs.Results); }; mainsProjectTask.ProjectAsync(gpLayer.FeatureSet.Features, new SpatialReference(3857)); break; } IsBusy = false; TraceUpstreamButton.IsEnabled = true; } // Clear any existing graphics private void ClearMap() { if (inputGraphicsLayer != null) inputGraphicsLayer.Graphics.Clear(); mainsGraphicsLayer.Graphics.Clear(); valvesGraphicsLayer.Graphics.Clear(); } private void ArcGISTiledMapServiceLayer_InitializationFailed(object sender, System.EventArgs e) { ArcGISTiledMapServiceLayer onlineBasemap = sender as ArcGISTiledMapServiceLayer; MyMap.Layers.Remove(onlineBasemap); ArcGISLocalTiledLayer localBasemap = new ArcGISLocalTiledLayer(@"..\data\tpks\Topographic.tpk"); MyMap.Layers.Insert(0, localBasemap); } } }
Imports System.Windows Imports System.Windows.Controls Imports System.Windows.Media Imports ESRI.ArcGIS.Client Imports ESRI.ArcGIS.Client.Local Imports ESRI.ArcGIS.Client.Tasks Imports System.Collections.Generic Imports ESRI.ArcGIS.Client.Symbols Imports ESRI.ArcGIS.Client.Geometry Namespace ArcGISWPFSDK Partial Public Class TraceGeometricNetwork Inherits UserControl Private traceNetworkLocalGpService As LocalGeoprocessingService Private geoprocessorTask As Geoprocessor Private localGeometryService As LocalGeometryService Private geometryTask As GeometryService Private waterNetworkLocalMapService As LocalMapService Private inputGraphicsLayer As GraphicsLayer Private valvesGraphicsLayer As GraphicsLayer Private mainsGraphicsLayer As GraphicsLayer Public Sub New() InitializeComponent() ' ' * Asynchronously start all the services... ' LocalGeoprocessingService.GetServiceAsync( _ "..\data\gpks\TraceGeometricNetwork\TraceGeometricNetwork.gpk", _ GPServiceType.SubmitJob, _ Function(localServiceCallback) If localServiceCallback.[Error] IsNot Nothing Then MessageBox.Show(localServiceCallback.[Error].Message) Exit Function End If traceNetworkLocalGpService = localServiceCallback geoprocessorTask = New Geoprocessor(traceNetworkLocalGpService.Tasks(0).Url) ' Enable the UI when the Trace Geometric Network service is available TraceUpstreamButton.IsEnabled = True End Function) localGeometryService.GetServiceAsync( Function(callback) localGeometryService = callback geometryTask = New GeometryService() geometryTask.Url = localGeometryService.UrlGeometryService End Function) LocalMapService.GetServiceAsync( _ "..\data\mpks\WaterDistributionNetwork.mpk", _ Function(callback) If callback.[Error] IsNot Nothing Then MessageBox.Show("WaterDistributionNetwork map failed to load") Exit Function End If waterNetworkLocalMapService = callback Dim WaterDistributionNetworkLayer As New ArcGISLocalDynamicMapServiceLayer(waterNetworkLocalMapService) MyMap.Layers.Insert(1, WaterDistributionNetworkLayer) End Function) ' * Create the Results GraphicsLayers and associated Renderers valvesGraphicsLayer = New GraphicsLayer() With { _ .Renderer = New SimpleRenderer() With { _ .Symbol = TryCast(MainGrid.Resources("ValveMarkerSymbol"), Symbol) _ } _ } mainsGraphicsLayer = New GraphicsLayer() With { _ .Renderer = New SimpleRenderer() With { _ .Symbol = New SimpleLineSymbol() With { _ .Color = New SolidColorBrush(Colors.Red), _ .Width = 8, _ .Style = SimpleLineSymbol.LineStyle.Dash _ } _ } _ } ' Add the GraphicsLayers to the Map MyMap.Layers.Add(mainsGraphicsLayer) MyMap.Layers.Add(valvesGraphicsLayer) End Sub ' Clear any existing graphics and register the mouse click handler. Private Sub TraceUpstreamButton_Click(sender As Object, e As RoutedEventArgs) ClearMap() ' * Add a graphic at the input location If inputGraphicsLayer Is Nothing Then inputGraphicsLayer = New GraphicsLayer() MyMap.Layers.Add(inputGraphicsLayer) End If Dim inputMapPoint As New MapPoint(-9551495, 3812812, MyMap.SpatialReference) ' Add a Graphic at the input point Dim graphic As New Graphic() With { _ .Symbol = TryCast(MainGrid.Resources("IncidentMarkerSymbol"), Symbol), _ .Geometry = inputMapPoint _ } inputGraphicsLayer.Graphics.Add(graphic) ' * Reproject the input point into the GP coordinate system ' Handle the event AddHandler geometryTask.ProjectCompleted, Function(sender2, graphicsEventArgs) ' Cancel any existing Jobs geoprocessorTask.CancelAsync() ' Handle the JobCompleted AddHandler geoprocessorTask.JobCompleted, Function(sender3, jobInfoEventArgs) ' Check whether it succeeded 'Do Something If jobInfoEventArgs.JobInfo.JobStatus <> esriJobStatus.esriJobSucceeded Then End If ' * Create two new Geoprocessor Tasks to fetch the result data (thereby allowing them to run concurrently) ' * Each will use the same event handler and we'll choose based on the Parameter Name. ' * Alternatively could use the overload which takes an object (userToken). Dim gpTaskSysvalves_Layer As New Geoprocessor(traceNetworkLocalGpService.Tasks(0).Url) AddHandler gpTaskSysvalves_Layer.GetResultDataCompleted, AddressOf geoprocessorTask_GetResultDataCompleted gpTaskSysvalves_Layer.GetResultDataAsync(jobInfoEventArgs.JobInfo.JobId, "Sysvalves_Layer") Dim gpTaskDistribMains_Layer As New Geoprocessor(traceNetworkLocalGpService.Tasks(0).Url) AddHandler gpTaskDistribMains_Layer.GetResultDataCompleted, AddressOf geoprocessorTask_GetResultDataCompleted gpTaskDistribMains_Layer.GetResultDataAsync(jobInfoEventArgs.JobInfo.JobId, "DistribMains_Layer") End Function ' Create the GP Parameter List Dim parameters As New List(Of GPParameter)() parameters.Add(New GPFeatureRecordSetLayer("Flags", graphicsEventArgs.Results(0).Geometry)) geoprocessorTask.SubmitJobAsync(parameters) End Function ' Project the input point into the coordinate system of the data geometryTask.ProjectAsync(New List(Of Graphic)() From { _ New Graphic() With { _ .Geometry = inputMapPoint _ } _ }, waterNetworkLocalMapService.SpatialReference) End Sub Private Sub geoprocessorTask_GetResultDataCompleted(sender As Object, gpParameterEventArgs As GPParameterEventArgs) ' Get the result features from the parameter Dim gpLayer As GPFeatureRecordSetLayer gpLayer = TryCast(gpParameterEventArgs.Parameter, GPFeatureRecordSetLayer) ' Check the parameter name, reproject and add to the appropriate graphics layer. ' again - two separate tasks are created allowing them to run conncurrently. Select Case gpParameterEventArgs.Parameter.Name Case "Sysvalves_Layer" Dim valvesProjectTask As New GeometryService(localGeometryService.UrlGeometryService) AddHandler valvesProjectTask.ProjectCompleted, Function(sender2, graphicsEventArgs) valvesGraphicsLayer.Graphics.AddRange(graphicsEventArgs.Results) End Function valvesProjectTask.ProjectAsync(gpLayer.FeatureSet.Features, New SpatialReference(3857)) Exit Select Case "DistribMains_Layer" Dim mainsProjectTask As New GeometryService(localGeometryService.UrlGeometryService) AddHandler mainsProjectTask.ProjectCompleted, Function(sender2, graphicsEventArgs) mainsGraphicsLayer.Graphics.AddRange(graphicsEventArgs.Results) End Function mainsProjectTask.ProjectAsync(gpLayer.FeatureSet.Features, New SpatialReference(3857)) Exit Select End Select End Sub ' Clear any existing graphics Private Sub ClearMap() If inputGraphicsLayer IsNot Nothing Then inputGraphicsLayer.Graphics.Clear() End If mainsGraphicsLayer.Graphics.Clear() valvesGraphicsLayer.Graphics.Clear() End Sub Private Sub ArcGISTiledMapServiceLayer_InitializationFailed(sender As Object, e As System.EventArgs) Dim onlineBasemap As ArcGISTiledMapServiceLayer = TryCast(sender, ArcGISTiledMapServiceLayer) MyMap.Layers.Remove(onlineBasemap) Dim localBasemap As New ArcGISLocalTiledLayer("..\data\tpks\Topographic.tpk") MyMap.Layers.Insert(0, localBasemap) End Sub End Class End Namespace
Copyright © 1995-2014 Esri. All rights reserved.
5/16/2014