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;}}}
Editing Associations
Create a utility network association
// 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.CreateEx(transformerBankLayer,transformerBankAttributes);// Create a poleRowTokenpoleToken=editOperation.CreateEx(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();
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) using the Export Subnetwork geoprocessing tool
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) using the Export Subnetwork geoprocessing tool
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;
Network Diagrams
Get a list of inconsistent Network Diagrams
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;}}
Retrieve Diagram Elements
publicvoidRetrieveDiagramElements(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);}
Change the Layout of a Network Diagram
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);}}
Open a diagram window 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);});