publicstaticUtilityNetworkGetUtilityNetworkFromTable(Tabletable){UtilityNetworkutilityNetwork=null;if(table.IsControllerDatasetSupported()){// Tables can belong to multiple controller datasets, but at most one of them will be a UtilityNetworkIReadOnlyList<Dataset>controllerDatasets=table.GetControllerDatasets();foreach(DatasetcontrollerDatasetincontrollerDatasets){if(controllerDatasetisUtilityNetwork){utilityNetwork=controllerDatasetasUtilityNetwork;}else{controllerDataset.Dispose();}}}returnutilityNetwork;}
Get a Utility Network from a Layer
// This routine obtains a utility network from a FeatureLayer, SubtypeGroupLayer, or UtilityNetworkLayerpublicstaticUtilityNetworkGetUtilityNetworkFromLayer(Layerlayer){UtilityNetworkutilityNetwork=null;if(layerisUtilityNetworkLayer){UtilityNetworkLayerutilityNetworkLayer=layerasUtilityNetworkLayer;utilityNetwork=utilityNetworkLayer.GetUtilityNetwork();}elseif(layerisSubtypeGroupLayer){CompositeLayercompositeLayer=layerasCompositeLayer;utilityNetwork=GetUtilityNetworkFromLayer(compositeLayer.Layers.First());}elseif(layerisFeatureLayer){FeatureLayerfeatureLayer=layerasFeatureLayer;using(FeatureClassfeatureClass=featureLayer.GetFeatureClass()){if(featureClass.IsControllerDatasetSupported()){IReadOnlyList<Dataset>controllerDatasets=newList<Dataset>();controllerDatasets=featureClass.GetControllerDatasets();foreach(DatasetcontrollerDatasetincontrollerDatasets){if(controllerDatasetisUtilityNetwork){utilityNetwork=controllerDatasetasUtilityNetwork;}else{controllerDataset.Dispose();}}}}}returnutilityNetwork;}
Elements
Fetching a Row from an Element
// usage : using (var row = FetchRowFromElement(...))publicstaticRowFetchRowFromElement(UtilityNetworkutilityNetwork,Elementelement){// Get the table from the elementusing(Tabletable=utilityNetwork.GetTable(element.NetworkSource)){// Create a query filter to fetch the appropriate rowQueryFilterqueryFilter=newQueryFilter(){ObjectIDs=newList<long>(){element.ObjectID}};// Fetch and return the rowusing(RowCursorrowCursor=table.Search(queryFilter)){if(rowCursor.MoveNext()){returnrowCursor.Current;}returnnull;}}}
// Create edit operationEditOperationeditOperation=newEditOperation();editOperation.Name="Create structural attachment association";// Create a RowHandle for the poleElementpoleElement=utilityNetwork.CreateElement(poleAssetType,poleGlobalID);RowHandlepoleRowHandle=newRowHandle(poleElement,utilityNetwork);// Create a RowHandle for the transformer bankElementtransformerBankElement=utilityNetwork.CreateElement(transformerBankAssetType,transformerBankGlobalID);RowHandletransformerBankRowHandle=newRowHandle(transformerBankElement,utilityNetwork);// Attach the transformer bank to the poleAssociationDescriptionstructuralAttachmentAssociationDescription=newAssociationDescription(AssociationType.Attachment,poleRowHandle,transformerBankRowHandle);editOperation.Create(structuralAttachmentAssociationDescription);editOperation.Execute();
Create utility network features and associations in a single edit operation
// Create an EditOperationEditOperationeditOperation=newEditOperation();editOperation.Name="Create pole; create transformer bank; attach transformer bank to pole";// Create the transformer bankRowTokentransformerBankToken=editOperation.Create(transformerBankLayer,transformerBankAttributes);// Create a poleRowTokenpoleToken=editOperation.Create(poleLayer,poleAttributes);// Create a structural attachment association between the pole and the transformer bankRowHandlepoleHandle=newRowHandle(poleToken);RowHandletransformerBankHandle=newRowHandle(transformerBankToken);AssociationDescriptionpoleAttachment=newAssociationDescription(AssociationType.Attachment,poleHandle,transformerBankHandle);editOperation.Create(poleAttachment);// Execute the EditOperationeditOperation.Execute();
Traverse Associations
Get traverse associations result from downward traversal
publicstaticvoidGetTraverseAssociationsResultFromDownwardTraversal(UtilityNetworkutilityNetwork,IReadOnlyList<Element>startingElements){// Set downward traversal with maximum depthTraverseAssociationsDescriptiontraverseAssociationsDescription=newTraverseAssociationsDescription(TraversalDirection.Descending);// Get traverse associations result from the staring element up to maximum depthTraverseAssociationsResulttraverseAssociationsResult=utilityNetwork.TraverseAssociations(startingElements,traverseAssociationsDescription);// Get associations participated in traversalIReadOnlyList<Association>associations=traverseAssociationsResult.Associations;}
Get traverse associations result from upward traversal with depth limit
publicstaticvoidGetTraverseAssociationsResultFromUpwardTraversalWithDepthLimit(UtilityNetworkutilityNetwork,IReadOnlyList<Element>startingElements){// List of fields whose values will be fetched as name-values pairs during association traversal operationList<string>additionalFieldsToFetch=newList<string>{"ObjectId","AssetName","AssetGroup","AssetType"};// Set downward traversal with maximum depth level of 3 TraverseAssociationsDescriptiontraverseAssociationsDescription=newTraverseAssociationsDescription(TraversalDirection.Ascending,3){AdditionalFields=additionalFieldsToFetch};// Get traverse associations result from the staring element up to depth level 3TraverseAssociationsResulttraverseAssociationsResult=utilityNetwork.TraverseAssociations(startingElements,traverseAssociationsDescription);// List of associations participated in traversalIReadOnlyList<Association>associations=traverseAssociationsResult.Associations;// KeyValue mapping between involved elements and their field name-values //At 2.x - IReadOnlyDictionary<Element, IReadOnlyList<AssociationElementFieldValue>> associationElementValuePairs = traverseAssociationsResult.AdditionalFieldValues;IReadOnlyDictionary<Element,IReadOnlyList<FieldValue>>associationElementValuePairs=traverseAssociationsResult.AdditionalFieldValues;foreach(KeyValuePair<Element,IReadOnlyList<FieldValue>>keyValuePairinassociationElementValuePairs){// Element Elementelement=keyValuePair.Key;// List of field names and their values //At 2.x - IReadOnlyList<AssociationElementFieldValue> elementFieldValues = keyValuePair.Value;IReadOnlyList<FieldValue>elementFieldValues=keyValuePair.Value;}}
Subnetworks and Tiers
Find a Tier given a Domain Network name and Tier name
Life cycle for a simple radial subnetwork with one controller
// Create a subnetwork named "Radial1" with a single controller// elementR1 represents the device that serves as the subnetwork controller (e.g., circuit breaker)SubnetworksubnetworkRadial1=subnetworkManager.EnableControllerInEditOperation(mediumVoltageTier,elementR1,"Radial1","R1","my description","my notes");// ...// Update the subnetwork and refresh the mapsubnetworkRadial1.Update();MapView.Active.Redraw(true);// ...// At some point, a subnetwork will need to be deleted.// First step is to disable the controllersubnetworkManager.DisableControllerInEditOperation(elementR1);// At this point, the subnetwork is deleted, but all of the rows that have been labeled with the subnetwork ID need to be updatedsubnetworkRadial1.Update();MapView.Active.Redraw(true);// The final step is to notify external systems (if any) by exporting the subnetworkSubnetworkExportOptionssubnetworkExportOptions=newSubnetworkExportOptions(){SetAcknowledged=true,IncludeDomainDescriptions=true,IncludeGeometry=true,ServiceSynchronizationType=ServiceSynchronizationType.Asynchronous,SubnetworkExportResultTypes=newList<SubnetworkExportResultType>(){SubnetworkExportResultType.Features}// Set networks attributes and attribute fields to export//ResultNetworkAttributes = new List<NetworkAttribute>(networkAttributes),//ResultFieldsByNetworkSourceID = new Dictionary<int, List<string>>()// { { electricDevice.ID, new List<string>() { "AssetID" } } }};subnetworkRadial1.Export(newUri($"{Path.GetTempPath()}SubnetworkExportResult.json"),subnetworkExportOptions);
Life cycle for a mesh subnetwork with multiple controllers
// Create a subnetwork named "Mesh1" from three controllers// elementM1, elementM2, and elementM3 represent the devices that serve as subnetwork controllers (e.g., network protectors)subnetworkManager.EnableController(lowVoltageMeshTier,elementM1,"Mesh1","M1","my description","my notes");subnetworkManager.EnableController(lowVoltageMeshTier,elementM2,"Mesh1","M2","my description","my notes");SubnetworksubnetworkMesh1=subnetworkManager.EnableController(lowVoltageMeshTier,elementM3,"Mesh1","M3","my description","my notes");subnetworkMesh1.Update();MapView.Active.Redraw(true);// ...// When deleting the subnetwork, each controller must be disabled before the subnetwork itself is deletedsubnetworkManager.DisableControllerInEditOperation(elementM1);subnetworkManager.DisableControllerInEditOperation(elementM2);subnetworkManager.DisableControllerInEditOperation(elementM3);// After the subnetwork is deleted, all of the rows that have been labeled with the subnetwork ID need to be updatedsubnetworkMesh1.Update();MapView.Active.Redraw(true);// The final step is to notify external systems (if any) by exporting the subnetworkSubnetworkExportOptionssubnetworkExportOptions=newSubnetworkExportOptions(){SetAcknowledged=true,IncludeDomainDescriptions=true,IncludeGeometry=true,ServiceSynchronizationType=ServiceSynchronizationType.Asynchronous,SubnetworkExportResultTypes=newList<SubnetworkExportResultType>(){SubnetworkExportResultType.Features}// Set networks attributes and attribute fields to export//ResultNetworkAttributes = new List<NetworkAttribute>(networkAttributes),//ResultFieldsByNetworkSourceID = new Dictionary<int, List<string>>()// { { electricDevice.ID, new List<string>() { "AssetID" } } }};subnetworkMesh1.Export(newUri($"{Path.GetTempPath()}SubnetworkExportResult.json"),subnetworkExportOptions);
Life cycle for a multifeed radial subnetwork with two controllers
// Create a subnetwork named "R2, R3" from two controllers// elementR2 and elementR3 represent the devices that serve as subnetwork controllers (e.g., circuit breakers)subnetworkManager.EnableControllerInEditOperation(mediumVoltageTier,elementR2,"R2, R3","R2","my description","my notes");subnetworkManager.EnableControllerInEditOperation(mediumVoltageTier,elementR3,"R2, R3","R3","my description","my notes");// If the tie switch between them is opened, the original subnetwork controllers must be disabled and re-enabled with different names// This will create two new subnetworks, named "R2" and "R3"subnetworkManager.DisableControllerInEditOperation(elementR2);subnetworkManager.DisableControllerInEditOperation(elementR3);SubnetworksubnetworkR2=subnetworkManager.EnableControllerInEditOperation(mediumVoltageTier,elementR2,"R2","R2","my description","my notes");SubnetworksubnetworkR3=subnetworkManager.EnableControllerInEditOperation(mediumVoltageTier,elementR3,"R3","R3","my description","my notes");subnetworkR2.Update();subnetworkR3.Update();MapView.Active.Redraw(true);
IReadOnlyList<Element>startingPointList=newList<Element>();// Code to fill in list of starting points goes here...TraceArgumenttraceArgument=newTraceArgument(startingPointList);TraceConfigurationtraceConfiguration=newTraceConfiguration();// Code to fill in trace configuration goes here...traceArgument.Configuration=traceConfiguration;
Create a Condition to compare a Network Attribute against a set of values
// Create a NetworkAttribute object for the Lifecycle network attribute from the UtilityNetworkDefinitionusing(NetworkAttributelifecycleNetworkAttribute=utilityNetworkDefinition.GetNetworkAttribute("Lifecycle")){// Create a NetworkAttributeComparison that stops traversal if Lifecycle <> "In Design" (represented by the constant InDesign)NetworkAttributeComparisoninDesignNetworkAttributeComparison=newNetworkAttributeComparison(lifecycleNetworkAttribute,Operator.NotEqual,InDesign);// Create a NetworkAttributeComparison to stop traversal if Lifecycle <> "In Service" (represented by the constant InService)NetworkAttributeComparisoninServiceNetworkAttributeComparison=newNetworkAttributeComparison(lifecycleNetworkAttribute,Operator.NotEqual,InService);// Combine these two comparisons together with "And"AndlifecycleFilter=newAnd(inDesignNetworkAttributeComparison,inServiceNetworkAttributeComparison);// Final condition stops traversal if Lifecycle <> "In Design" and Lifecycle <> "In Service"traceConfiguration.Traversability.Barriers=lifecycleFilter;}
Create a Function
// Get a NetworkAttribute object for the Load network attribute from the UtilityNetworkDefinitionusing(NetworkAttributeloadNetworkAttribute=utilityNetworkDefinition.GetNetworkAttribute("Load")){// Create a function to sum the LoadAddsumLoadFunction=newAdd(loadNetworkAttribute);// Add this function to our trace configurationtraceConfiguration.Functions=newList<Function>(){sumLoadFunction};}
Create a FunctionBarrier
// Create a NetworkAttribute object for the Shape length network attribute from the UtilityNetworkDefinitionusing(NetworkAttributeshapeLengthNetworkAttribute=utilityNetworkDefinition.GetNetworkAttribute("Shape length")){// Create a function that adds up shape lengthAddlengthFunction=newAdd(shapeLengthNetworkAttribute);// Create a function barrier that stops traversal after 1000 feetFunctionBarrierdistanceBarrier=newFunctionBarrier(lengthFunction,Operator.GreaterThan,1000.0);// Set this function barriertraceConfiguration.Traversability.FunctionBarriers=newList<FunctionBarrier>(){distanceBarrier};}
Create an output condition
// Create an output category to filter the trace results to only include// features with the "Service Point" category assignedtraceConfiguration.OutputCondition=newCategoryComparison(CategoryOperator.IsEqual,"Service Point");
Create a Propagator
// Get a NetworkAttribute object for the Phases Normal attribute from the UtilityNetworkDefinitionusing(NetworkAttributenormalPhaseAttribute=utilityNetworkDefinition.GetNetworkAttribute("Phases Normal")){// Create a propagator to propagate the Phases Normal attribute downstream from the source, using a Bitwise And function// Allow traversal to continue as long as the Phases Normal value includes any of the ABC phases// (represented by the constant ABCPhase)PropagatorphasePropagator=newPropagator(normalPhaseAttribute,PropagatorFunction.BitwiseAnd,Operator.IncludesAny,ABCPhase);// Assign this propagator to our trace configurationtraceConfiguration.Propagators=newList<Propagator>(){phasePropagator};}
Using Function Results
// Get the FunctionOutputResult from the trace resultsFunctionOutputResultfunctionOutputResult=traceResults.OfType<FunctionOutputResult>().First();// First() can be used here if only one Function was included in the TraceConfiguration.Functions collection.// Otherwise you will have to search the list for the correct FunctionOutput object.FunctionOutputfunctionOutput=functionOutputResult.FunctionOutputs.First();// Extract the total load from the GlobalValue propertydoubletotalLoad=(double)functionOutput.Value;
Fetch a named trace configuration by name
privateNamedTraceConfigurationGetNamedTraceConfigurationsByName(UtilityNetworkutilityNetwork,stringconfigurationName="WaterNetwork"){// Query to find named trace configurationsNamedTraceConfigurationQuerynamedTraceConfigurationQuery=newNamedTraceConfigurationQuery{Names=newList<string>{configurationName}};// Get the trace manager from the utility networkusing(TraceManagertraceManager=utilityNetwork.GetTraceManager()){// A set of named trace configurations specified by the named traced configuration query IReadOnlyList<NamedTraceConfiguration>namedTraceConfigurations=traceManager.GetNamedTraceConfigurations(namedTraceConfigurationQuery);NamedTraceConfigurationwaterConfiguration=namedTraceConfigurations.First(f =>f.Description.Equals(configurationName));returnwaterConfiguration;}}
Fetch named trace configurations from a utility network layer
privateNamedTraceConfigurationGetNamedTraceConfigurationsFromUtilityNetworkLayer(UtilityNetworkLayerutilityNetworkLayer,stringconfigurationName="WaterNetwork"){// Get all named trace configurations in the utility networkIReadOnlyList<NamedTraceConfiguration>namedTraceConfigurations=utilityNetworkLayer.GetNamedTraceConfigurations();foreach(NamedTraceConfigurationnamedTraceConfigurationinnamedTraceConfigurations){if(namedTraceConfiguration.Name==configurationName){returnnamedTraceConfiguration;}}returnnull;}
Trace a utility network using a named trace configuration
privatevoidTraceUtilityNetworkUsingNamedTraceConfiguration(UtilityNetworkutilityNetwork,NamedTraceConfigurationnamedTraceConfiguration,ElementstartElement){// Get the trace manager from the utility networkusing(TraceManagertraceManager=utilityNetwork.GetTraceManager()){// Get a tracer from the trace manager using the named trace configurationTracerupstreamTracer=traceManager.GetTracer(namedTraceConfiguration);// Trace argument holding the trace input parametersTraceArgumentupstreamTraceArgument=newTraceArgument(namedTraceConfiguration,newList<Element>{startElement});// Trace results IReadOnlyList<Result>upstreamTraceResults=upstreamTracer.Trace(upstreamTraceArgument);}}
Trace a utility network with the digitized direction
privatevoidTraceWithDigitizedDirection(UtilityNetworkutilityNetwork,ElementstartElement){usingTraceManagertraceManager=utilityNetwork.GetTraceManager();// Trace configuration with digitized direction TraceConfigurationtraceConfiguration=newTraceConfiguration(){IncludeIsolatedFeatures=true,IncludeBarriersWithResults=true,UseDigitizedDirection=true};// Trace argumentList<Element>startElements=newList<Element>{startElement};TraceArgumenttraceArgument=newTraceArgument(startElements);traceArgument.Configuration=traceConfiguration;// ResultsDownstreamTracerdownstreamTracer=traceManager.GetTracer<DownstreamTracer>();IReadOnlyList<Result>traceResults=downstreamTracer.Trace(traceArgument);foreach(ResulttraceResultintraceResults){// Iterate trace results}}
Export a utility network trace as a JSON file
privatevoidExportUtilityNetworkTraceAsJSON(UtilityNetworkutilityNetwork){using(TraceManagertraceManager=utilityNetwork.GetTraceManager())using(UtilityNetworkDefinitionutilityNetworkDefinition=utilityNetwork.GetDefinition())using(NetworkSourcedeviceNetworkSource=GetNetworkSource(utilityNetworkDefinition,"GasDevice")asNetworkSource)using(FeatureClassdistributionDeviceFeatureClass=utilityNetwork.GetTable(deviceNetworkSource)asFeatureClass)using(FeatureClassDefinitiondistributionDeviceDefinition=distributionDeviceFeatureClass.GetDefinition())using(AssetGroupdeviceAssetGroup=deviceNetworkSource.GetAssetGroup("Regulator"))using(AssetTypedeviceAssetType=deviceAssetGroup.GetAssetType("Pressure Reducing"))using(NetworkAttributedeviceStatusNetworkAttribute=utilityNetworkDefinition.GetNetworkAttribute("DeviceStatus"))using(NetworkAttributeaccessibleNetworkAttribute=utilityNetworkDefinition.GetNetworkAttribute("Accessible")){// Domain and tier informationDomainNetworkdomainNetwork=utilityNetworkDefinition.GetDomainNetwork("Gas");TierpipeDistributionSystemTier=domainNetwork.GetTier("Pipe Distribution");// Start elementsElementstartingPoint1=utilityNetwork.CreateElement(deviceAssetType,Guid.Parse("{28CF437E-950C-41B7-B839-8BC45570DE40}"));ElementstartingPoint2=utilityNetwork.CreateElement(deviceAssetType,Guid.Parse("{63C22828-7BC9-49ED-A14A-A596559B6CB3}"));startingPoint1.Terminal=startingPoint1.AssetType.GetTerminalConfiguration().Terminals.First(x =>x.IsUpstreamTerminal);startingPoint2.Terminal=startingPoint2.AssetType.GetTerminalConfiguration().Terminals.First(x =>x.IsUpstreamTerminal);List<Element>startingPoints=newList<Element>(){startingPoint1,startingPoint2};List<Element>barriers=newList<Element>();// Set up trace filter: DeviceStatus = Open (1) AND Accessible = 1NetworkAttributeComparisonstatusNetworkAttributeComparison=newNetworkAttributeComparison(deviceStatusNetworkAttribute,Operator.Equal,1);NetworkAttributeComparisonnetworkAttributeComparison=newNetworkAttributeComparison(accessibleNetworkAttribute,Operator.Equal,1);// Set trace configuration TraceConfigurationtraceConfiguration=newTraceConfiguration{AllowIndeterminateFlow=true,IgnoreBarriersAtStartingPoints=false,IncludeBarriersWithResults=true,IncludeContainers=true,IncludeContent=true,IncludeIsolatedFeatures=false,IncludeUpToFirstSpatialContainer=false};traceConfiguration.Filter.Barriers=newAnd(statusNetworkAttributeComparison,networkAttributeComparison);traceConfiguration.DomainNetwork=domainNetwork;traceConfiguration.SourceTier=pipeDistributionSystemTier;// Attribute fields of a network sourceList<string>deviceFields=distributionDeviceDefinition.GetFields().Select(f =>f.Name).ToList();// Network attributes List<string>networkattributeNames=newList<string>();IReadOnlyList<NetworkAttribute>networkAttributes=utilityNetworkDefinition.GetNetworkAttributes();foreach(NetworkAttributenetworkAttributeinnetworkAttributes){networkattributeNames.Add(networkAttribute.Name);}// Result TypesList<ResultType>resultTypeList=newList<ResultType>(){ResultType.Feature};// Resutl OptionsResultOptionsresultOptions=newResultOptions(){IncludeGeometry=true,NetworkAttributes=networkattributeNames,ResultFields=newDictionary<NetworkSource,List<string>>(){{deviceNetworkSource,deviceFields}}};// Trace ArgumentsTraceArgumenttraceArgument=newTraceArgument(startingPoints){Barriers=barriers,Configuration=traceConfiguration,ResultTypes=resultTypeList,ResultOptions=resultOptions};ConnectedTracerconnectedTracer=traceManager.GetTracer<ConnectedTracer>();// Set export options TraceExportOptionsexportOptions=newTraceExportOptions(){ServiceSynchronizationType=ServiceSynchronizationType.Asynchronous,IncludeDomainDescriptions=true,};// Path to export JSONstringjsonPath=$"{Path.GetTempPath()}TraceResults.json";UrijsonUri=newUri(jsonPath);// Export connectedTracer.Export(jsonUri,traceArgument,exportOptions);stringjsonAbsolutePath=HttpUtility.UrlDecode(jsonUri.AbsolutePath);if(jsonUri.IsFile&&File.Exists(jsonAbsolutePath)){// Work with the JSON results}}NetworkSourceGetNetworkSource(UtilityNetworkDefinitionunDefinition,stringname){IReadOnlyList<NetworkSource>allSources=unDefinition.GetNetworkSources();foreach(NetworkSourcesourceinallSources){if(name.Contains("Partitioned Sink")){if(source.Name.Replace(" ","").ToUpper().Contains(name.Replace(" ","").ToUpper())||source.Name.Replace(" ","").ToUpper().Contains(name.Replace("Partitioned Sink","Part_Sink").Replace(" ","").ToUpper())){returnsource;}}if(name.Contains("Hierarchical Sink")){if(source.Name.Replace(" ","").ToUpper().Contains(name.Replace(" ","").ToUpper())||source.Name.Replace(" ","").ToUpper().Contains(name.Replace("Hierarchical Sink","Hier_Sink").Replace(" ","").ToUpper())){returnsource;}}if(source.Name.Replace(" ","").ToUpper().Contains(name.Replace(" ","").ToUpper())){returnsource;}}returnnull;}}
Fetch features and network attributes from a utility network during trace
privatevoidFetchFeaturesAndAttributes(UtilityNetworkutilityNetwork){using(TraceManagertraceManager=utilityNetwork.GetTraceManager())using(UtilityNetworkDefinitionutilityNetworkDefinition=utilityNetwork.GetDefinition())using(NetworkSourcedeviceNetworkSource=GetNetworkSource(utilityNetworkDefinition,"GasDevice")asNetworkSource)using(FeatureClassdistributionDeviceFeatureClass=utilityNetwork.GetTable(deviceNetworkSource)asFeatureClass)using(FeatureClassDefinitiondistributionDeviceDefinition=distributionDeviceFeatureClass.GetDefinition())using(AssetGroupdeviceAssetGroup=deviceNetworkSource.GetAssetGroup("Regulator"))using(AssetTypedeviceAssetType=deviceAssetGroup.GetAssetType("Pressure Reducing"))using(NetworkAttributedeviceStatusNetworkAttribute=utilityNetworkDefinition.GetNetworkAttribute("DeviceStatus"))using(NetworkAttributeaccessibleNetworkAttribute=utilityNetworkDefinition.GetNetworkAttribute("Accessible")){// Domain and tier informationDomainNetworkdomainNetwork=utilityNetworkDefinition.GetDomainNetwork("Gas");TierpipeDistributionSystemTier=domainNetwork.GetTier("Pipe Distribution");// Start elementsElementstartingPoint1=utilityNetwork.CreateElement(deviceAssetType,Guid.Parse("{28CF437E-950C-41B7-B839-8BC45570DE40}"));ElementstartingPoint2=utilityNetwork.CreateElement(deviceAssetType,Guid.Parse("{63C22828-7BC9-49ED-A14A-A596559B6CB3}"));startingPoint1.Terminal=startingPoint1.AssetType.GetTerminalConfiguration().Terminals.First(x =>x.IsUpstreamTerminal);startingPoint2.Terminal=startingPoint2.AssetType.GetTerminalConfiguration().Terminals.First(x =>x.IsUpstreamTerminal);List<Element>startingPoints=newList<Element>(){startingPoint1,startingPoint2};List<Element>barriers=newList<Element>();// Set up trace filter: DeviceStatus = Open (1) AND Accessible = 1NetworkAttributeComparisonstatusNetworkAttributeComparison=newNetworkAttributeComparison(deviceStatusNetworkAttribute,Operator.Equal,1);NetworkAttributeComparisonnetworkAttributeComparison=newNetworkAttributeComparison(accessibleNetworkAttribute,Operator.Equal,1);// Set trace configuration TraceConfigurationtraceConfiguration=newTraceConfiguration{AllowIndeterminateFlow=true,IgnoreBarriersAtStartingPoints=false,IncludeBarriersWithResults=true,IncludeContainers=true,IncludeContent=true,IncludeIsolatedFeatures=false,IncludeUpToFirstSpatialContainer=false};traceConfiguration.Filter.Barriers=newAnd(statusNetworkAttributeComparison,networkAttributeComparison);traceConfiguration.DomainNetwork=domainNetwork;traceConfiguration.SourceTier=pipeDistributionSystemTier;// Attribute fields of a network sourceList<string>deviceFields=distributionDeviceDefinition.GetFields().Select(f =>f.Name).ToList();// Network attributes List<string>networkattributeNames=newList<string>();IReadOnlyList<NetworkAttribute>networkAttributes=utilityNetworkDefinition.GetNetworkAttributes();foreach(NetworkAttributenetworkAttributeinnetworkAttributes){networkattributeNames.Add(networkAttribute.Name);}// Result TypesList<ResultType>resultTypeList=newList<ResultType>(){ResultType.Feature};// Resutl OptionsResultOptionsresultOptions=newResultOptions(){IncludeGeometry=true,NetworkAttributes=networkattributeNames,ResultFields=newDictionary<NetworkSource,List<string>>(){{deviceNetworkSource,deviceFields}}};// Trace ArgumentsTraceArgumenttraceArgument=newTraceArgument(startingPoints){Barriers=barriers,Configuration=traceConfiguration,ResultTypes=resultTypeList,ResultOptions=resultOptions};// Tracer ConnectedTracerconnectedTracer=traceManager.GetTracer<ConnectedTracer>();// Async trace resultIReadOnlyList<Result>traceResults=connectedTracer.Trace(traceArgument,ServiceSynchronizationType.Asynchronous);// Iterate trace resultsforeach(ResulttraceResultintraceResults){if(traceResultisFeatureElementResultfeatureElementResult){IReadOnlyList<FeatureElement>featureElements=featureElementResult.FeatureElements;}}}// Helper inline functionNetworkSourceGetNetworkSource(UtilityNetworkDefinitionunDefinition,stringname){IReadOnlyList<NetworkSource>allSources=unDefinition.GetNetworkSources();foreach(NetworkSourcesourceinallSources){if(name.Contains("Partitioned Sink")){if(source.Name.Replace(" ","").ToUpper().Contains(name.Replace(" ","").ToUpper())||source.Name.Replace(" ","").ToUpper().Contains(name.Replace("Partitioned Sink","Part_Sink").Replace(" ","").ToUpper())){returnsource;}}if(name.Contains("Hierarchical Sink")){if(source.Name.Replace(" ","").ToUpper().Contains(name.Replace(" ","").ToUpper())||source.Name.Replace(" ","").ToUpper().Contains(name.Replace("Hierarchical Sink","Hier_Sink").Replace(" ","").ToUpper())){returnsource;}}if(source.Name.Replace(" ","").ToUpper().Contains(name.Replace(" ","").ToUpper())){returnsource;}}returnnull;}}
Get selected features from a list of elements
privatevoidFeatureSelectionsFromTrace(UtilityNetworkutilityNetwork,TraceArgumenttraceArgument){// Get the trace manager from the utility networkusing(TraceManagertraceManager=utilityNetwork.GetTraceManager()){UpstreamTracertracer=traceManager.GetTracer<UpstreamTracer>();IReadOnlyList<Result>tracerResults=tracer.Trace(traceArgument);foreach(ResulttraceResultintracerResults){if(traceResultisElementResultelementResult){IReadOnlyList<Element>elements=elementResult.Elements;// Feature selection from a list of elementsIReadOnlyList<Selection>selections=utilityNetwork.GetFeaturesForElements(elements);}}}}
Network Diagrams
Get the Diagram Manager
using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// Todo - do something}
Get Network Diagrams
using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// get all the diagramsIReadOnlyList<NetworkDiagram>diagrams=diagramManager.GetNetworkDiagrams();// get a diagram by nameNetworkDiagramdiagram=diagramManager.GetNetworkDiagram(diagrameName);// get diagrams by extentdiagrams=diagramManager.GetNetworkDiagrams(extentOfInterest);// get diagrams from a set of utility network feature GlobalIDsdiagrams=diagramManager.GetNetworkDiagrams(globalIDs);// get diagrams from a set of utility network feature GlobalIDs within an extentdiagrams=diagramManager.GetNetworkDiagrams(extentOfInterest,globalIDs);}
Get a list of Network Diagrams with inconsistent ConsistencyState
publicList<NetworkDiagram>GetInconsistentDiagrams(UtilityNetworkutilityNetwork){// Get the DiagramManager from the utility networkusing(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){List<NetworkDiagram>myList=newList<NetworkDiagram>();// Loop through the network diagrams in the diagram managerforeach(NetworkDiagramdiagramindiagramManager.GetNetworkDiagrams()){NetworkDiagramInfodiagramInfo=diagram.GetDiagramInfo();// If the diagram is not a system diagram and is in an inconsistent state, add it to our listif(!diagramInfo.IsSystem&&diagram.GetConsistencyState()!=NetworkDiagramConsistencyState.DiagramIsConsistent){myList.Add(diagram);}else{diagram.Dispose();// If we are not returning it we need to Dispose it}}returnmyList;}}
Open a diagram pane from a Network Diagram
// Create a diagram layer from a NetworkDiagram (myDiagram)DiagramLayerdiagramLayer=awaitQueuedTask.Run<DiagramLayer>(()=>{// Create the diagram mapvarnewMap=MapFactory.Instance.CreateMap(myDiagram.Name,ArcGIS.Core.CIM.MapType.NetworkDiagram,MapViewingMode.Map);if(newMap==null)returnnull;// Open the diagram mapvarmapPane=ArcGIS.Desktop.Core.ProApp.Panes.CreateMapPaneAsync(newMap,MapViewingMode.Map);if(mapPane==null)returnnull;//Add the diagram to the mapreturnnewMap.AddDiagramLayer(myDiagram);});
Get Diagram from DiagramLayer
publicvoidGetDiagram(DiagramLayerdiagramLayer){// note - methods need to run on MCTNetworkDiagramdiagram=diagramLayer.GetNetworkDiagram();// get the consistency state from the layerDiagramLayerConsistencyStatedlState=diagramLayer.ConsistencyState;// or from the diagramNetworkDiagramConsistencyStatendState=diagram.GetConsistencyState();}
Get Diagram Templates
publicvoidRetrieveDiagramTemplates(UtilityNetworkutilityNetwork){using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// get all templatesIReadOnlyList<DiagramTemplate>templates=diagramManager.GetDiagramTemplates();// get a template by nameDiagramTemplatetemplate=diagramManager.GetDiagramTemplate(templateName);}}
Get Network Diagrams from a Diagram Template
publicvoidGetNetworkDiagramFromDiagramTemplates(UtilityNetworkutilityNetwork){using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// get the first templatesDiagramTemplatetemplate=diagramManager.GetDiagramTemplates().FirstOrDefault();// get the network diagrams fromt he templateIEnumerable<NetworkDiagram>diagrams=template.GetNetworkDiagrams();// or get a network diagram by nameNetworkDiagramdiagram=template.GetNetworkDiagram(diagrameName);}}
Create a Network Diagram
publicvoidCreateNetworkDiagram(UtilityNetworkutilityNetwork,IEnumerable<Guid>globalIDs){using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// get the templateDiagramTemplatetemplate=diagramManager.GetDiagramTemplate(templateName);// create the diagramNetworkDiagramdiagram=diagramManager.CreateNetworkDiagram(template,globalIDs);}}
Get Network Diagram Information as JSON string
publicvoidGetDiagramContent(UtilityNetworkutilityNetwork){using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// get a diagram by nameNetworkDiagramdiagram=diagramManager.GetNetworkDiagram(templateName);stringjson_content=diagram.GetContent(true,true,true,true);}}
Get Diagram Elements
publicvoidGetDiagramElements(MapViewmapView,NetworkDiagramnetworkDiagram){// Create a DiagramElementQueryByExtent to retrieve diagram element junctions whose extent// intersects the active map extentDiagramElementQueryByExtentelementQuery=newDiagramElementQueryByExtent();elementQuery.ExtentOfInterest=MapView.Active.Extent;elementQuery.AddContents=false;elementQuery.QueryDiagramJunctionElement=true;elementQuery.QueryDiagramEdgeElement=false;elementQuery.QueryDiagramContainerElement=false;// Use this DiagramElementQueryByExtent as an argument to the QueryDiagramElements methodDiagramElementQueryResultresult=networkDiagram.QueryDiagramElements(elementQuery);// get the container, junction, edge elements// in this case result.DiagramJunctionElements and result.DiagramEdgeElements will be empty // since elementQuery.QueryDiagramEdgeElement and elementQuery.QueryDiagramContainerElement are set to falseIReadOnlyList<DiagramContainerElement>containerElements=result.DiagramContainerElements;IReadOnlyList<DiagramJunctionElement>junctionElements=result.DiagramJunctionElements;IReadOnlyList<DiagramEdgeElement>edgeElements=result.DiagramEdgeElements;}
publicvoidDiagramElementQueryResultAndNetworkDiagramSubsetClasses(Geodatabasegeodatabase,DiagramManagerdiagramManager,stringdiagramName){// Retrieve a diagramusing(NetworkDiagramdiagramTest=diagramManager.GetNetworkDiagram(diagramName)){// Create a DiagramElementQueryByElementTypes query object to get the diagram elements we want to work withDiagramElementQueryByElementTypesquery=newDiagramElementQueryByElementTypes();query.QueryDiagramJunctionElement=true;query.QueryDiagramEdgeElement=true;query.QueryDiagramContainerElement=true;// Retrieve those diagram elementsDiagramElementQueryResultelements=diagramTest.QueryDiagramElements(query);// Create a NetworkDiagramSubset object to edit this set of diagram elementsNetworkDiagramSubsetsubset=newNetworkDiagramSubset();subset.DiagramJunctionElements=elements.DiagramJunctionElements;subset.DiagramEdgeElements=elements.DiagramEdgeElements;subset.DiagramContainerElements=elements.DiagramContainerElements;// Edit the shapes of the diagram elements - left as an exercise for the studentTranslateDiagramElements(subset);// Save the new layout of the diagram elementsdiagramTest.SaveLayout(subset,true);}}
Editing Network Diagram
publicvoidEditDiagram(NetworkDiagramdiagram,List<Guid>globalIDs){// These routines generate their own editing transaction, and therefore cannot be wrapped// in a separate transaction. Because the editing performed by these routines cannot// be undone, thise routines can also not be called within an editing session. All// edits in the current edit session must be saved or discarded before calling these// routines.// refresh the diagram - synchronizes it based on the latest network topologydiagram.Update();// append features to the diagramdiagram.Append(globalIDs);// overite the diagram with a set of features diagram.Overwrite(globalIDs);NetworkDiagramInfoinfo=diagram.GetDiagramInfo();if(info.CanExtend){diagram.Extend(NetworkDiagramExtendType.ExtendByContainment);// or extend for only a set of utility network globalIDsdiagram.Extend(NetworkDiagramExtendType.ExtendByContainment,globalIDs);}// delete a diagrandiagram.Delete();}