1- // Copyright 2020 Esri.
1+ // Copyright 2021 Esri.
22//
33// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
44// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
1313using Esri . ArcGISRuntime . Security ;
1414using Esri . ArcGISRuntime . Symbology ;
1515using Esri . ArcGISRuntime . UI ;
16+ using Esri . ArcGISRuntime . UI . Controls ;
1617using Esri . ArcGISRuntime . UtilityNetworks ;
1718using System ;
1819using System . Collections . Generic ;
1920using System . Linq ;
21+ using System . Threading . Tasks ;
2022using Xamarin . Forms ;
2123
2224namespace ArcGISRuntimeXamarin . Samples . PerformValveIsolationTrace
@@ -25,8 +27,8 @@ namespace ArcGISRuntimeXamarin.Samples.PerformValveIsolationTrace
2527 name : "Perform valve isolation trace" ,
2628 category : "Utility network" ,
2729 description : "Run a filtered trace to locate operable features that will isolate an area from the flow of network resources." ,
28- instructions : "Create and set the configuration's filter barriers by selecting a category. Check or uncheck 'Include Isolated Features'. Tap 'Trace' to run a subnetwork-based isolation trace." ,
29- tags : new [ ] { "category comparison" , "condition barriers" , "isolated features" , "network analysis" , "subnetwork trace" , "trace configuration" , "trace filter" , "utility network" } ) ]
30+ instructions : "Tap on one or more features to use as filter barriers or create and set the configuration's filter barriers by selecting a category. Check or uncheck 'Include Isolated Features'. Tap 'Trace' to run a subnetwork-based isolation trace. Tap 'Reset' to clear filter barriers ." ,
31+ tags : new [ ] { "category comparison" , "condition barriers" , "filter barriers" , " isolated features", "network analysis" , "subnetwork trace" , "trace configuration" , "trace filter" , "utility network" } ) ]
3032 public partial class PerformValveIsolationTrace : ContentPage
3133 {
3234 // Feature service for an electric utility network in Naperville, Illinois.
@@ -47,6 +49,12 @@ public partial class PerformValveIsolationTrace : ContentPage
4749 private const string GlobalId = "{98A06E95-70BE-43E7-91B7-E34C9D3CB9FF}" ;
4850 private UtilityElement _startingLocation ;
4951
52+ private UtilityTraceParameters _parameters ;
53+ private GraphicsOverlay _barrierOverlay ;
54+
55+ // Task completion source for the user selected terminal.
56+ private TaskCompletionSource < string > _terminalCompletionSource = null ;
57+
5058 public PerformValveIsolationTrace ( )
5159 {
5260 InitializeComponent ( ) ;
@@ -112,6 +120,13 @@ private async void Initialize()
112120 Graphic graphic = new Graphic ( startingLocationGeometry , symbol ) ;
113121 overlay . Graphics . Add ( graphic ) ;
114122
123+ // Create a graphics overlay for barriers.
124+ _barrierOverlay = new GraphicsOverlay ( ) ;
125+ MyMapView . GraphicsOverlays . Add ( _barrierOverlay ) ;
126+
127+ // Create the utility trace parameters.
128+ _parameters = new UtilityTraceParameters ( UtilityTraceType . Isolation , new [ ] { _startingLocation } ) ;
129+
115130 // Set the starting viewpoint.
116131 await MyMapView . SetViewpointAsync ( new Viewpoint ( startingLocationGeometry , 3000 ) ) ;
117132
@@ -148,7 +163,7 @@ private async void OnTrace(object sender, EventArgs e)
148163 UtilityCategoryComparison categoryComparison = new UtilityCategoryComparison ( category , UtilityCategoryComparisonOperator . Exists ) ;
149164
150165 // Add the filter barrier.
151- _configuration . Filter . Barriers = categoryComparison ;
166+ _configuration . Filter = new UtilityTraceFilter ( ) { Barriers = categoryComparison } ;
152167 }
153168
154169 // Set the include isolated features property.
@@ -182,5 +197,103 @@ private async void OnTrace(object sender, EventArgs e)
182197 LoadingIndicator . IsVisible = false ;
183198 }
184199 }
200+
201+ private void OnReset ( object sender , EventArgs e )
202+ {
203+ _parameters . Barriers . Clear ( ) ;
204+ _barrierOverlay . Graphics . Clear ( ) ;
205+ foreach ( FeatureLayer layer in MyMapView . Map . OperationalLayers . OfType < FeatureLayer > ( ) )
206+ {
207+ layer . ClearSelection ( ) ;
208+ }
209+ }
210+
211+ private async Task < UtilityTerminal > GetTerminalAsync ( IEnumerable < UtilityTerminal > terminals )
212+ {
213+ try
214+ {
215+ // Switch the UI for the user choosing the junction.
216+ PickerUI . IsVisible = true ;
217+ MyMapView . GeoViewTapped -= OnGeoViewTapped ;
218+
219+ // Load the terminals into the UI.
220+ TerminalPicker . ItemsSource = terminals . Select ( x => x . Name ) . ToList ( ) ;
221+ TerminalPicker . SelectedItem = null ;
222+
223+ // Wait for the user to select a terminal.
224+ _terminalCompletionSource = new TaskCompletionSource < string > ( ) ;
225+ string selectedName = await _terminalCompletionSource . Task ;
226+ return terminals . Where ( x => x . Name . Equals ( selectedName ) ) . FirstOrDefault ( ) ;
227+ }
228+ finally
229+ {
230+ // Make the main UI visible again.
231+ PickerUI . IsVisible = false ;
232+ MyMapView . GeoViewTapped += OnGeoViewTapped ;
233+ }
234+ }
235+
236+ private void Terminal_Selected ( object sender , EventArgs e )
237+ {
238+ _terminalCompletionSource . TrySetResult ( TerminalPicker . SelectedItem as string ) ;
239+ }
240+
241+ private async void OnGeoViewTapped ( object sender , Esri . ArcGISRuntime . Xamarin . Forms . GeoViewInputEventArgs e )
242+ {
243+ try
244+ {
245+ LoadingIndicator . IsVisible = true ;
246+
247+ // Identify the feature to be used.
248+ IEnumerable < IdentifyLayerResult > identifyResult = await MyMapView . IdentifyLayersAsync ( e . Position , 10.0 , false ) ;
249+ ArcGISFeature feature = identifyResult ? . FirstOrDefault ( ) ? . GeoElements ? . FirstOrDefault ( ) as ArcGISFeature ;
250+ if ( feature == null ) { return ; }
251+
252+ // Create element from the identified feature.
253+ UtilityElement element = _utilityNetwork . CreateElement ( feature ) ;
254+
255+ if ( element . NetworkSource . SourceType == UtilityNetworkSourceType . Junction )
256+ {
257+ // Select terminal for junction feature.
258+ IEnumerable < UtilityTerminal > terminals = element . AssetType . TerminalConfiguration ? . Terminals ;
259+ if ( terminals ? . Count ( ) > 1 )
260+ {
261+ element . Terminal = await GetTerminalAsync ( terminals ) ;
262+ }
263+ }
264+ else if ( element . NetworkSource . SourceType == UtilityNetworkSourceType . Edge )
265+ {
266+ // Compute how far tapped location is along the edge feature.
267+ if ( feature . Geometry is Polyline line )
268+ {
269+ // Remove elevation data, FractionAlong only supports 2D lines.
270+ line = GeometryEngine . RemoveZ ( line ) as Polyline ;
271+ double fraction = GeometryEngine . FractionAlong ( line , e . Location , - 1 ) ;
272+
273+ // Check for rare edge case where the fraction is invalid.
274+ if ( double . IsNaN ( fraction ) ) { return ; }
275+
276+ // Set the fraction of the utility element.
277+ element . FractionAlongEdge = fraction ;
278+ }
279+ }
280+
281+ // Check whether starting location or barrier is added to update the right collection and symbology.
282+ _parameters . Barriers . Add ( element ) ;
283+ Symbol symbol = new SimpleMarkerSymbol ( SimpleMarkerSymbolStyle . X , System . Drawing . Color . OrangeRed , 25d ) ;
284+
285+ // Add a graphic for the new utility element.
286+ Graphic traceLocationGraphic = new Graphic ( feature . Geometry as MapPoint ?? e . Location , symbol ) ;
287+ _barrierOverlay . Graphics . Add ( traceLocationGraphic ) ;
288+ }
289+ catch ( Exception ex )
290+ {
291+ await Application . Current . MainPage . DisplayAlert ( ex . GetType ( ) . Name , ex . Message , "OK" ) ;
292+ }
293+ finally
294+ {
295+ LoadingIndicator . IsVisible = false ;
296+ }
297+ }
185298 }
186299}
0 commit comments