Skip to content

Commit 97db85a

Browse files
authored
Merge pull request #130 from Esri/df/AddTraceUtilityNetwork
[New] Trace utility network
2 parents 74259cd + 203a807 commit 97db85a

File tree

8 files changed

+793
-0
lines changed

8 files changed

+793
-0
lines changed

Samples.xcodeproj/project.pbxproj

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@
8181
4D2ADC6929C50C4C003B367F /* AddDynamicEntityLayerView.SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D2ADC6829C50C4C003B367F /* AddDynamicEntityLayerView.SettingsView.swift */; };
8282
4D2ADC6A29C50D91003B367F /* AddDynamicEntityLayerView.Model.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 4D2ADC6629C50BD6003B367F /* AddDynamicEntityLayerView.Model.swift */; };
8383
4D2ADC6B29C50D91003B367F /* AddDynamicEntityLayerView.SettingsView.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 4D2ADC6829C50C4C003B367F /* AddDynamicEntityLayerView.SettingsView.swift */; };
84+
7573E81A29D6134C00BEED9C /* TraceUtilityNetworkView.Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7573E81329D6134C00BEED9C /* TraceUtilityNetworkView.Model.swift */; };
85+
7573E81C29D6134C00BEED9C /* TraceUtilityNetworkView.Enums.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7573E81529D6134C00BEED9C /* TraceUtilityNetworkView.Enums.swift */; };
86+
7573E81E29D6134C00BEED9C /* TraceUtilityNetworkView.Views.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7573E81729D6134C00BEED9C /* TraceUtilityNetworkView.Views.swift */; };
87+
7573E81F29D6134C00BEED9C /* TraceUtilityNetworkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7573E81829D6134C00BEED9C /* TraceUtilityNetworkView.swift */; };
88+
7573E82129D6136C00BEED9C /* TraceUtilityNetworkView.Model.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 7573E81329D6134C00BEED9C /* TraceUtilityNetworkView.Model.swift */; };
89+
7573E82229D6136C00BEED9C /* TraceUtilityNetworkView.Enums.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 7573E81529D6134C00BEED9C /* TraceUtilityNetworkView.Enums.swift */; };
90+
7573E82329D6136C00BEED9C /* TraceUtilityNetworkView.Views.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 7573E81729D6134C00BEED9C /* TraceUtilityNetworkView.Views.swift */; };
91+
7573E82429D6136C00BEED9C /* TraceUtilityNetworkView.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 7573E81829D6134C00BEED9C /* TraceUtilityNetworkView.swift */; };
8492
75DD736729D35FF40010229D /* ChangeMapViewBackgroundView.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 4D2ADC5529C4F612003B367F /* ChangeMapViewBackgroundView.swift */; };
8593
75DD736829D35FF40010229D /* ChangeMapViewBackgroundView.SettingsView.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 4D2ADC5829C4F612003B367F /* ChangeMapViewBackgroundView.SettingsView.swift */; };
8694
75DD736929D35FF40010229D /* ChangeMapViewBackgroundView.Model.swift in Copy Source Code Files */ = {isa = PBXBuildFile; fileRef = 4D2ADC6129C5071C003B367F /* ChangeMapViewBackgroundView.Model.swift */; };
@@ -230,6 +238,10 @@
230238
0039A4F92885C50300592C86 /* ShowResultOfSpatialOperationsView.swift in Copy Source Code Files */,
231239
0039A4FA2885C50300592C86 /* StyleGraphicsWithRendererView.swift in Copy Source Code Files */,
232240
0039A4FB2885C50300592C86 /* StyleGraphicsWithSymbolsView.swift in Copy Source Code Files */,
241+
7573E82129D6136C00BEED9C /* TraceUtilityNetworkView.Model.swift in Copy Source Code Files */,
242+
7573E82229D6136C00BEED9C /* TraceUtilityNetworkView.Enums.swift in Copy Source Code Files */,
243+
7573E82329D6136C00BEED9C /* TraceUtilityNetworkView.Views.swift in Copy Source Code Files */,
244+
7573E82429D6136C00BEED9C /* TraceUtilityNetworkView.swift in Copy Source Code Files */,
233245
);
234246
name = "Copy Source Code Files";
235247
runOnlyForDeploymentPostprocessing = 0;
@@ -281,6 +293,10 @@
281293
4D2ADC6129C5071C003B367F /* ChangeMapViewBackgroundView.Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChangeMapViewBackgroundView.Model.swift; sourceTree = "<group>"; };
282294
4D2ADC6629C50BD6003B367F /* AddDynamicEntityLayerView.Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddDynamicEntityLayerView.Model.swift; sourceTree = "<group>"; };
283295
4D2ADC6829C50C4C003B367F /* AddDynamicEntityLayerView.SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddDynamicEntityLayerView.SettingsView.swift; sourceTree = "<group>"; };
296+
7573E81329D6134C00BEED9C /* TraceUtilityNetworkView.Model.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TraceUtilityNetworkView.Model.swift; sourceTree = "<group>"; };
297+
7573E81529D6134C00BEED9C /* TraceUtilityNetworkView.Enums.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TraceUtilityNetworkView.Enums.swift; sourceTree = "<group>"; };
298+
7573E81729D6134C00BEED9C /* TraceUtilityNetworkView.Views.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TraceUtilityNetworkView.Views.swift; sourceTree = "<group>"; };
299+
7573E81829D6134C00BEED9C /* TraceUtilityNetworkView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TraceUtilityNetworkView.swift; sourceTree = "<group>"; };
284300
75DD739129D38B1B0010229D /* NavigateRouteView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigateRouteView.swift; sourceTree = "<group>"; };
285301
883C121429C9136600062FF9 /* DownloadPreplannedMapAreaView.MapPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadPreplannedMapAreaView.MapPicker.swift; sourceTree = "<group>"; };
286302
88F93CC029C3D59C0006B28E /* SketchOnMapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SketchOnMapView.swift; sourceTree = "<group>"; };
@@ -440,6 +456,7 @@
440456
88F93CBE29C3D4E30006B28E /* Sketch on map */,
441457
E066DD362860AB0B004D3D5B /* Style graphics with renderer */,
442458
E004A6E42846A609002A1FE6 /* Style graphics with symbols */,
459+
7573E81229D6134C00BEED9C /* Trace utility network */,
443460
);
444461
path = Samples;
445462
sourceTree = "<group>";
@@ -665,6 +682,17 @@
665682
path = "Change map view background";
666683
sourceTree = "<group>";
667684
};
685+
7573E81229D6134C00BEED9C /* Trace utility network */ = {
686+
isa = PBXGroup;
687+
children = (
688+
7573E81329D6134C00BEED9C /* TraceUtilityNetworkView.Model.swift */,
689+
7573E81529D6134C00BEED9C /* TraceUtilityNetworkView.Enums.swift */,
690+
7573E81729D6134C00BEED9C /* TraceUtilityNetworkView.Views.swift */,
691+
7573E81829D6134C00BEED9C /* TraceUtilityNetworkView.swift */,
692+
);
693+
path = "Trace utility network";
694+
sourceTree = "<group>";
695+
};
668696
75DD739029D38B1B0010229D /* Navigate route */ = {
669697
isa = PBXGroup;
670698
children = (
@@ -1061,6 +1089,8 @@
10611089
E004A6E928493BCE002A1FE6 /* ShowDeviceLocationView.swift in Sources */,
10621090
F111CCC1288B5D5600205358 /* DisplayMapFromMobileMapPackageView.swift in Sources */,
10631091
218F35B829C28F4A00502022 /* AuthenticateWithOAuthView.swift in Sources */,
1092+
7573E81C29D6134C00BEED9C /* TraceUtilityNetworkView.Enums.swift in Sources */,
1093+
7573E81A29D6134C00BEED9C /* TraceUtilityNetworkView.Model.swift in Sources */,
10641094
0005580C28185C0600224BC6 /* SampleList.swift in Sources */,
10651095
E004A6E028466279002A1FE6 /* ShowCalloutView.swift in Sources */,
10661096
E000E763286A0B18005D87C5 /* CutGeometryView.swift in Sources */,
@@ -1081,9 +1111,11 @@
10811111
E004A6F3284E4FEB002A1FE6 /* ShowResultOfSpatialOperationsView.swift in Sources */,
10821112
F1E71BF1289473760064C33F /* AddRasterFromFileView.swift in Sources */,
10831113
00B04273282EC59E0072E1B4 /* AboutView.swift in Sources */,
1114+
7573E81F29D6134C00BEED9C /* TraceUtilityNetworkView.swift in Sources */,
10841115
4D2ADC6929C50C4C003B367F /* AddDynamicEntityLayerView.SettingsView.swift in Sources */,
10851116
1C42E04729D2396B004FC4BE /* ShowPopupView.swift in Sources */,
10861117
E066DD3B2860CA08004D3D5B /* ShowResultOfSpatialRelationshipsView.swift in Sources */,
1118+
7573E81E29D6134C00BEED9C /* TraceUtilityNetworkView.Views.swift in Sources */,
10871119
4D2ADC5A29C4F612003B367F /* ChangeMapViewBackgroundView.swift in Sources */,
10881120
0044CDDF2995C39E004618CE /* ShowDeviceLocationHistoryView.swift in Sources */,
10891121
E041ABC0287CA9F00056009B /* WebView.swift in Sources */,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Trace utility network
2+
3+
Discover connected features in a utility network using connected, subnetwork, upstream, and downstream traces.
4+
5+
![Image of trace utility network](trace-utility-network.png)
6+
7+
## Use case
8+
9+
You can use a trace to visualize and validate the network topology of a utility network for quality assurance. Subnetwork traces are used for validating whether subnetworks, such as circuits or zones, are defined or edited appropriately.
10+
11+
## How to use the sample
12+
13+
Tap "Start a new trace" to select the type of trace using the confirmation dialogue. Tap on one or more features while "Start" or "Barrier" is selected. When a junction feature is identified, you may be prompted to select a terminal. When an edge feature is identified, the distance from the tapped location to the beginning of the edge feature will be computed. Tap "Trace" to initiate a trace on the network. Tap "Reset" to clear the trace parameters and start over.
14+
15+
## How it works
16+
17+
1. Create a `MapView` with a `Map` that contains one more utility networks.
18+
2. Add a `GraphicsOverlay` to hold symbology that distinguishes starting locations from barriers.
19+
3. Add relevant `FeatureLayer`(s) to the map as operation layers, optionally applying custom styling.
20+
4. Allow users to choose a trace type from the set of `UtilityTraceParameters.TraceType`(s).
21+
5. Create `UtilityTraceParameters` with the selected trace type.
22+
6. Set the `UtilityTraceConfiguration` with the utility tier's `defaultTraceConfiguration` property.
23+
7. Use the `onSingleTapGesture` modifier to listen for tap events on the map view.
24+
8. Identify tapped features on the map and add a `Graphic` that represents its purpose (starting point or barrier) at the tapped location.
25+
9. Create a `UtilityElement` for the identified feature.
26+
10. Determine the type of the identified feature using `UtilityNetworkSource.sourceType`.
27+
11. If the type is `junction`, display a terminal picker when more than one terminal is found.
28+
12. If the type is `edge`, compute how far along the edge the user tapped using `GeometryEngine.polyline(_:fractionalLengthClosestTo:tolerance:)`.
29+
13. Add any created `UtilityElement`(s) to the collection of starting locations or barriers in the `UtilityTraceParameters`.
30+
14. Run `UtilityNetwork.trace(using:)` using the `UtilityTraceParameters`.
31+
15. Group the `UtilityElementTraceResult.elements` by their `networkSource.name`.
32+
16. For every `FeatureLayer` in this map with trace result elements, select features by converting `UtilityElement`(s) to `ArcGISFeature`(s) using `UtilityNetwork.features(for:)`.
33+
34+
## Relevant API
35+
36+
* GeometryEngine.polyline(_:fractionalLengthClosestTo:tolerance:)
37+
* ServiceGeodatabase
38+
* UtilityAssetType
39+
* UtilityDomainNetwork
40+
* UtilityElement
41+
* UtilityElementTraceResult
42+
* UtilityNetwork
43+
* UtilityNetworkDefinition
44+
* UtilityNetworkSource
45+
* UtilityTerminal
46+
* UtilityTier
47+
* UtilityTraceConfiguration
48+
* UtilityTraceParameters
49+
* UtilityTraceResult
50+
* UtilityTraceType
51+
* UtilityTraversability
52+
53+
## Additional information
54+
55+
The [Naperville electrical](https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer) network feature service, hosted on ArcGIS Online, contains a utility network used to run the subnetwork-based trace shown in this sample.
56+
57+
A `UtilityNetworkTrace` toolkit component can be used for various utility network related use cases. For information about setting up the toolkit, as well as code for the underlying component, visit the [toolkit repository](https://github.com/Esri/arcgis-maps-sdk-swift-toolkit).
58+
59+
## Tags
60+
61+
condition barriers, downstream trace, network analysis, subnetwork trace, toolkit, trace configuration, traversability, upstream trace, utility network, validate consistency
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"category": "Utility network",
3+
"description": "Discover connected features in a utility network using connected, subnetwork, upstream, and downstream traces.",
4+
"ignore": false,
5+
"images": [
6+
"trace-utility-network.png"
7+
],
8+
"keywords": [
9+
"condition barriers",
10+
"downstream trace",
11+
"network analysis",
12+
"subnetwork trace",
13+
"toolkit",
14+
"trace configuration",
15+
"traversability",
16+
"upstream trace",
17+
"utility network",
18+
"validate consistency",
19+
"GeometryEngine.polyline(_:fractionalLengthClosestTo:tolerance:)",
20+
"ServiceGeodatabase",
21+
"UtilityAssetType",
22+
"UtilityDomainNetwork",
23+
"UtilityElement",
24+
"UtilityElementTraceResult",
25+
"UtilityNetwork",
26+
"UtilityNetworkDefinition",
27+
"UtilityNetworkSource",
28+
"UtilityTerminal",
29+
"UtilityTier",
30+
"UtilityTraceConfiguration",
31+
"UtilityTraceParameters",
32+
"UtilityTraceResult",
33+
"UtilityTraceType",
34+
"UtilityTraversability"
35+
],
36+
"redirect_from": [],
37+
"relevant_apis": [
38+
"GeometryEngine.polyline(_:fractionalLengthClosestTo:tolerance:)",
39+
"ServiceGeodatabase",
40+
"UtilityAssetType",
41+
"UtilityDomainNetwork",
42+
"UtilityElement",
43+
"UtilityElementTraceResult",
44+
"UtilityNetwork",
45+
"UtilityNetworkDefinition",
46+
"UtilityNetworkSource",
47+
"UtilityTerminal",
48+
"UtilityTier",
49+
"UtilityTraceConfiguration",
50+
"UtilityTraceParameters",
51+
"UtilityTraceResult",
52+
"UtilityTraceType",
53+
"UtilityTraversability"
54+
],
55+
"snippets": [
56+
"TraceUtilityNetworkView.swift",
57+
"TraceUtilityNetworkView.Enums.swift",
58+
"TraceUtilityNetworkView.Model.swift",
59+
"TraceUtilityNetworkView.Views.swift"
60+
],
61+
"title": "Trace utility network"
62+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2023 Esri
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
extension TraceUtilityNetworkView {
16+
/// The types of points used during a utility network trace.
17+
enum PointType: String {
18+
/// A point which marks a location for a trace to stop.
19+
case barrier
20+
/// A point which marks a location for a trace to begin.
21+
case start
22+
23+
/// A displayable name the point type.
24+
var label: String {
25+
switch self {
26+
case .barrier:
27+
return "Barrier"
28+
case .start:
29+
return "Start"
30+
}
31+
}
32+
}
33+
34+
/// The different states of a utility network trace.
35+
enum TracingActivity: Equatable {
36+
/// Starting points and barriers are being added.
37+
case settingPoints(pointType: PointType)
38+
/// The trace completed successfully.
39+
case traceCompleted
40+
/// The trace failed.
41+
case traceFailed(description: String)
42+
/// The trace is running.
43+
case traceRunning
44+
}
45+
}

0 commit comments

Comments
 (0)