staticUtilityNetworkGetUtilityNetworkFromTable(){UtilityNetworkutilityNetwork=null;Tabletable=MapView.Active.Map.GetStandaloneTablesAsFlattenedList().First().GetTable();// This routine obtains a utility network from a tableif(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
staticUtilityNetworkGetUtilityNetworkFromLayer(LayerunLayer){UtilityNetworkutilityNetwork=null;Layerlayer=MapView.Active.Map.GetLayersAsFlattenedList().First();// This routine obtains a utility network from a FeatureLayer, SubtypeGroupLayer, or UtilityNetworkLayerif(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
staticRowFetchRowFromElement(UtilityNetworkutilityNetwork,Elementelement){// Get the table from the elementusing(TableunTable=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=unTable.Search(queryFilter)){if(rowCursor.MoveNext()){returnrowCursor.Current;}returnnull;}}}
// This routine creates a structural attachment association between a pole and a transformer bankstaticvoidCreateUNAssociation(UtilityNetworkutilityNetwork,AssetTypepoleAssetType,GuidpoleGlobalID,AssetTypetransformerBankAssetType,GuidtransformerBankGlobalID){// 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
// This routine creates a pole and a transformer bank, and then creates a structural attachment association between them, all in a single edit operationstaticvoidCreateUNFeaturesAndAssociations(FeatureLayertransformerBankLayer,Dictionary<string,object>transformerBankAttributes,FeatureLayerpoleLayer,Dictionary<string,object>poleAttributes){// 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
// This routine demonstrates how to get the associations involved in a downward traversal from a set of starting elementsstaticvoidGetTraverseAssociationsResultFromDownwardTraversal(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
// This routine demonstrates how to get the associations involved in an upward traversal from a set of starting elements, up to a specified depth limitstaticvoidGetTraverseAssociationsResultFromUpwardTraversalWithDepthLimit(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 3TraverseAssociationsDescriptiontraverseAssociationsDescription=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-valuesIReadOnlyDictionary<Element,IReadOnlyList<FieldValue>>associationElementValuePairs=traverseAssociationsResult.AdditionalFieldValues;foreach(KeyValuePair<Element,IReadOnlyList<FieldValue>>keyValuePairinassociationElementValuePairs){// ElementElementelement=keyValuePair.Key;// List of field names and their valuesIReadOnlyList<FieldValue>elementFieldValues=keyValuePair.Value;}}
Subnetworks and Tiers
Find a Tier given a Domain Network name and Tier name
// This routine updates all dirty subnetworks in a given tier and refreshes the map viewstaticvoidUpdateAllDirtySubnetworks(UtilityNetworkutilityNetwork,Tiertier,MapViewmapView){usingSubnetworkManagersubnetworkManager=utilityNetwork.GetSubnetworkManager();subnetworkManager.UpdateAllSubnetworks(tier,true);mapView.Redraw(true);}
Life cycle for a simple radial subnetwork with one controller
// This routine demonstrates the life cycle of a simple radial subnetwork with one controllerstaticvoidRadialNetworkLifecycle(SubnetworkManagersubnetworkManager,TiermediumVoltageTier,ElementelementR1){// 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
// This routine demonstrates the life cycle of a mesh subnetwork with multiple controllersstaticvoidMeshNetworkLifeCycle(SubnetworkManagersubnetworkManager,TierlowVoltageMeshTier,ElementelementM1,ElementelementM2,ElementelementM3){// 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
// This routine demonstrates the life cycle of a multifeed radial subnetwork with two controllersstaticvoidMultifeedRadialLifeCycle(SubnetworkManagersubnetworkManager,TiermediumVoltageTier,ElementelementR2,ElementelementR3){// 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);}
Export Subnetwork
// This routine exports a subnetwork to a JSON filestaticvoidExportSubnetwork(UtilityNetworkutilityNetwork,stringsubnetworkName,UriexportResultJsonPath){usingUtilityNetworkDefinitionutilityNetworkDefinition=utilityNetwork.GetDefinition();usingSubnetworkManagersubnetworkManager=utilityNetwork.GetSubnetworkManager();Subnetworksubnetwork=subnetworkManager.GetSubnetwork(subnetworkName);IReadOnlyList<NetworkAttribute>networkAttributes=utilityNetworkDefinition.GetNetworkAttributes();IReadOnlyList<NetworkSource>networkSources=utilityNetworkDefinition.GetNetworkSources();NetworkSourceelectricDevice=networkSources.First(f =>f.Name.Contains("ElectricDevice"));// Export optionsSubnetworkExportOptionssubnetworkExportOptions=new(){SetAcknowledged=false,IncludeDomainDescriptions=true,IncludeGeometry=true,ServiceSynchronizationType=ServiceSynchronizationType.Asynchronous,SubnetworkExportResultTypes=newList<SubnetworkExportResultType>(){SubnetworkExportResultType.Connectivity,SubnetworkExportResultType.Features},ResultNetworkAttributes=newList<NetworkAttribute>(networkAttributes),ResultFieldsByNetworkSourceID=newDictionary<int,List<string>>(){{electricDevice.ID,newList<string>(){"AssetID"}}}};subnetwork.Export(exportResultJsonPath,subnetworkExportOptions);}
Tracing
Create a DownstreamTracer
// This routine creates a DownstreamTracer object from a UtilityNetworkstaticvoidCreateADownstreamTracerObject(UtilityNetworkutilityNetwork){usingTraceManagertraceManager=utilityNetwork.GetTraceManager();DownstreamTracerdownstreamTracer=traceManager.GetTracer<DownstreamTracer>();}
Create a Trace Argument
// This routine creates a TraceArgument object and assigns a TraceConfiguration to itstaticvoidCreateTraceArgument(){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
staticvoidCreateNetworkAttributeComparison(UtilityNetworkDefinitionutilityNetworkDefinition,TraceConfigurationtraceConfiguration){// This routine creates a NetworkAttributeComparison to compare the Lifecycle network attribute against two values: "In Design" and "In Service"constintInDesign=4;constintInService=8;// Create a NetworkAttribute object for the Lifecycle network attribute from the UtilityNetworkDefinitionusingNetworkAttributelifecycleNetworkAttribute=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
// This routine creates an Add function to sum the Load network attribute during a tracestaticvoidApplyFunction(UtilityNetworkDefinitionutilityNetworkDefinition,TraceConfigurationtraceConfiguration){// Get a NetworkAttribute object for the Load network attribute from the UtilityNetworkDefinitionusingNetworkAttributeloadNetworkAttribute=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
// This routine creates a FunctionBarrier that stops traversal when the total shape length exceeds 1000 feetstaticvoidCreateFunctionBarrier(UtilityNetworkDefinitionutilityNetworkDefinition,TraceConfigurationtraceConfiguration){// Create a NetworkAttribute object for the Shape length network attribute from the UtilityNetworkDefinitionusingNetworkAttributeshapeLengthNetworkAttribute=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
// This routine creates an output condition to filter trace results to only include features with the "Service Point" category assignedstaticvoidCreateOutputFilter(TraceConfigurationtraceConfiguration){// 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
// This routine creates a Propagator to propagate the Phases Normal network attribute downstream during a tracestaticvoidCreatePropagator(UtilityNetworkDefinitionutilityNetworkDefinition,TraceConfigurationtraceConfiguration){constintABCPhase=7;// Get a NetworkAttribute object for the Phases Normal attribute from the UtilityNetworkDefinitionusingNetworkAttributenormalPhaseAttribute=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
// This routine demonstrates how to extract function results from trace resultsstaticvoidUseFunctionResults(IReadOnlyList<Result>traceResults){// 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
// This routine fetches a named trace configuration by name from a utility networkstaticNamedTraceConfigurationGetNamedTraceConfigurationsByName(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 queryIReadOnlyList<NamedTraceConfiguration>namedTraceConfigurations=traceManager.GetNamedTraceConfigurations(namedTraceConfigurationQuery);NamedTraceConfigurationwaterConfiguration=namedTraceConfigurations.First(f =>f.Description.Equals(configurationName));returnwaterConfiguration;}}
Fetch named trace configurations from a utility network layer
// This routine fetches a named trace configuration by name from a utility network layerstaticNamedTraceConfigurationGetNamedTraceConfigurationsFromUtilityNetworkLayer(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
// This routine demonstrates how to perform a trace using a named trace configuration from a utility networkstaticvoidTraceUtilityNetworkUsingNamedTraceConfiguration(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 resultsIReadOnlyList<Result>upstreamTraceResults=upstreamTracer.Trace(upstreamTraceArgument);}}
Trace a utility network with the digitized direction
// This routine demonstrates how to perform a trace using the digitized direction of featuresstaticvoidTraceWithDigitizedDirection(UtilityNetworkutilityNetwork,ElementstartElement){usingTraceManagertraceManager=utilityNetwork.GetTraceManager();// Trace configuration with digitized directionTraceConfigurationtraceConfiguration=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
// This routine demonstrates how to perform a trace and export the results as a JSON filestaticvoidExportUtilityNetworkTraceAsJSON(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=[startingPoint1,startingPoint2];List<Element>barriers=[];// Set up trace filter: DeviceStatus = Open (1) AND Accessible = 1NetworkAttributeComparisonstatusNetworkAttributeComparison=newNetworkAttributeComparison(deviceStatusNetworkAttribute,Operator.Equal,1);NetworkAttributeComparisonnetworkAttributeComparison=newNetworkAttributeComparison(accessibleNetworkAttribute,Operator.Equal,1);// Set trace configurationTraceConfigurationtraceConfiguration=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 attributesList<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 optionsTraceExportOptionsexportOptions=newTraceExportOptions(){ServiceSynchronizationType=ServiceSynchronizationType.Asynchronous,IncludeDomainDescriptions=true,};// Path to export JSONstringjsonPath=$"{Path.GetTempPath()}TraceResults.json";UrijsonUri=newUri(jsonPath);// ExportconnectedTracer.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
// This routine demonstrates how to fetch features and network attributes from a utility network during a tracestaticvoidFetchFeaturesAndAttributes(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 configurationTraceConfigurationtraceConfiguration=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 attributesList<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};// TracerConnectedTracerconnectedTracer=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
// This routine demonstrates how to get a list of feature selections from a list of elementsstaticvoidFeatureSelectionsFromTrace(UtilityNetworkutilityNetwork,TraceArgumenttraceArgument){// Get the trace manager from the utility networkusingTraceManagertraceManager=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
staticvoidGetDiagramManager(UtilityNetworkutilityNetwork){// Get the DiagramManager from the utility networkusing(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// Use the diagram manager...}}
Get Network Diagrams
staticvoidGetDiagram(UtilityNetworkutilityNetwork,IEnumerable<Guid>globalIDs){EnvelopeextentOfInterest=MapView.Active.Map.GetDefaultExtent();using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// Get all the diagramsIReadOnlyList<NetworkDiagram>diagrams=diagramManager.GetNetworkDiagrams();// Get a diagram by nameNetworkDiagramdiagram=diagramManager.GetNetworkDiagram(_diagramName);// 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
staticList<NetworkDiagram>GetInconsistentDiagrams(UtilityNetworkutilityNetwork){// Get the DiagramManager from the utility networkusing(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){List<NetworkDiagram>networkDiagrams=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){networkDiagrams.Add(diagram);}else{diagram.Dispose();// If we are not returning it we need to Dispose it}}returnnetworkDiagrams;}}
Open a diagram pane from a Network Diagram
// Create a diagram layer from a NetworkDiagramstaticvoidCreateDiagramLayerFromNetworkDiagram(NetworkDiagramnetworkDiagram){// Create the diagram mapMapnewMap=MapFactory.Instance.CreateMap(networkDiagram.Name,MapType.NetworkDiagram,MapViewingMode.Map);// Open the diagram mapTask<IMapPane>mapPane=ProApp.Panes.CreateMapPaneAsync(newMap,MapViewingMode.Map);//Add the diagram to the mapDiagramLayerdiagramLayer=newMap.AddDiagramLayer(networkDiagram);}
Get Diagram from DiagramLayer
// Get the NetworkDiagram from a DiagramLayer and check its ConsistencyStatestaticvoidGetDiagram(DiagramLayerdiagramLayer){NetworkDiagramdiagram=diagramLayer.GetNetworkDiagram();// Get the consistency state from the layerDiagramLayerConsistencyStatediagramLayerConsistencyState=diagramLayer.ConsistencyState;// Or from the diagramNetworkDiagramConsistencyStatediagramConsistencyState=diagram.GetConsistencyState();}
Get Diagram Templates
// Get all the diagram templates or a template by namestaticvoidRetrieveDiagramTemplates(UtilityNetworkutilityNetwork){stringtemplateName="ElectricNetworkTemplate";usingDiagramManagerdiagramManager=utilityNetwork.GetDiagramManager();// Get all templatesIReadOnlyList<DiagramTemplate>templates=diagramManager.GetDiagramTemplates();// Get a template by nameDiagramTemplatetemplate=diagramManager.GetDiagramTemplate(templateName);}
Get Network Diagrams from a Diagram Template
// Get all the network diagrams from a template or a diagram by namestaticvoidGetNetworkDiagramFromDiagramTemplates(UtilityNetworkutilityNetwork){using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// Get the first templatesDiagramTemplatetemplate=diagramManager.GetDiagramTemplates().FirstOrDefault();// Get the network diagrams fromt he templateIEnumerable<NetworkDiagram>diagrams=template.GetNetworkDiagrams();// Get a network diagram by nameNetworkDiagramdiagram=template.GetNetworkDiagram(_diagramName);}}
Create a Network Diagram
// Create a network diagram from a template and a set of utility network feature GlobalIDsstaticvoidCreateNetworkDiagram(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
staticvoidGetDiagramContent(UtilityNetworkutilityNetwork){using(DiagramManagerdiagramManager=utilityNetwork.GetDiagramManager()){// Get a diagram by nameNetworkDiagramdiagram=diagramManager.GetNetworkDiagram(TemplateName);stringjsonContent=diagram.GetContent(true,true,true,true);}}
Get Diagram Elements
// Get the diagram elements whose extent intersects the active map extentstaticvoidGetDiagramElements(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. IReadOnlyList<DiagramContainerElement>containerElements=result.DiagramContainerElements;// In this case result.DiagramJunctionElements and result.DiagramEdgeElements will be empty// because elementQuery.QueryDiagramEdgeElement and elementQuery.QueryDiagramContainerElement are set to 'false'IReadOnlyList<DiagramJunctionElement>junctionElements=result.DiagramJunctionElements;IReadOnlyList<DiagramEdgeElement>edgeElements=result.DiagramEdgeElements;}
Get Diagram Aggregations
// Get the diagram aggregationsstaticvoidGetDiagramAggregation(NetworkDiagramnetworkDiagram){IReadOnlyList<DiagramAggregation>aggregations=networkDiagram.GetAggregations();foreach(DiagramAggregationaggregationinaggregations){NetworkDiagramAggregationTypetype=aggregation.AggregationType;}}
Find Diagram Features for a set of utility network rows
// Given a list of utility network feature GlobalIDs, find the corresponding diagram features in a network diagramstaticvoidFindDiagramFeatures(NetworkDiagramdiagram,List<Guid>globalIDs){FindDiagramFeatureQueryfeatureQuery=newFindDiagramFeatureQuery();featureQuery.NetworkRowGlobalIDs=globalIDs;featureQuery.AddAggregations=true;featureQuery.AddConnectivityAssociations=true;featureQuery.AddStructuralAttachments=true;IReadOnlyList<FindResultItem>features=diagram.FindDiagramFeatures(featureQuery);foreach(FindResultItemfindFeatureinfeatures){longobjectID=findFeature.ObjectID;Guidguid=findFeature.GlobalID;GeometryTypegeometryType=findFeature.GeometryType;intsourceID=findFeature.SourceID;}}
Find Utility Network Rows for a set of diagram features
// Given a list of diagram feature GlobalIDs, find the corresponding utility network rows in a network diagramstaticvoidFindDiagramRows(NetworkDiagramdiagram,List<Guid>globalIDs){FindNetworkRowQueryrowQuery=newFindNetworkRowQuery();rowQuery.DiagramFeatureGlobalIDs=globalIDs;rowQuery.AddAggregations=true;IReadOnlyList<FindResultItem>rows=diagram.FindNetworkRows(rowQuery);foreach(FindResultItemfindRowinrows){longobjectID=findRow.ObjectID;Guidguid=findRow.GlobalID;GeometryTypegeometryType=findRow.GeometryType;intsourceID=findRow.SourceID;}}
Find Initial Network Rows Used to create a Network Diagram
// Find the utility network rows used to create a network diagramstaticvoidFindInitialNetworkRows(NetworkDiagramdiagram){IReadOnlyList<FindResultItem>rows=diagram.FindInitialNetworkRows();foreach(FindResultItemfindRowinrows){longobjectID=findRow.ObjectID;Guidguid=findRow.GlobalID;GeometryTypegeometryType=findRow.GeometryType;intsourceID=findRow.SourceID;}}
Change the Layout of a Network Diagram
// Change the layout of a network diagram by querying for all the diagram elements, editing their shapes,staticvoidChangeDiagramLayout(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;// Save the new layout of the diagram elementsdiagramTest.SaveLayout(subset,true);}}
Editing Network Diagram
// Various editing operations on a network diagramstaticvoidEditDiagram(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);// Overwrite the diagram with a set of featuresdiagram.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 diagramdiagram.Delete();}