Пример #1
0
        // ValidateDataModel - This sample is hard-wired to a particular version of the Naperville data model.
        // This routine checks to make sure we are using the correct one
        private bool ValidateDataModel(UtilityNetwork utilityNetwork)
        {
            bool dataModelIsValid = false;

            try
            {
                using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())

                    using (NetworkSource transformerBankNetworkSource = GetNetworkSource(utilityNetworkDefinition, AssemblyNetworkSourceName))
                        using (AssetGroup transformerBankAssetGroup = transformerBankNetworkSource.GetAssetGroup(TransformerBankAssetGroupName))
                            using (AssetType transformerBankAssetType = transformerBankAssetGroup.GetAssetType(TransformerBankAssetTypeName))

                                // Transformer
                                using (NetworkSource deviceNetworkSource = GetNetworkSource(utilityNetworkDefinition, DeviceNetworkSourceName))
                                    using (AssetGroup transformerAssetGroup = deviceNetworkSource.GetAssetGroup(TransformerAssetGroupName))
                                        using (AssetType transformerAssetType = transformerAssetGroup.GetAssetType(TransformerAssetTypeName))

                                            // Arrester
                                            using (AssetGroup arresterAssetGroup = deviceNetworkSource.GetAssetGroup(ArresterAssetGroupName))
                                                using (AssetType arresterAssetType = arresterAssetGroup.GetAssetType(ArresterAssetTypeName))

                                                    // Fuse
                                                    using (AssetGroup fuseAssetGroup = deviceNetworkSource.GetAssetGroup(FuseAssetGroupName))
                                                        using (AssetType fuseAssetType = fuseAssetGroup.GetAssetType(FuseAssetTypeName))
                                                        {
                                                            // Find the upstream terminal on the transformer
                                                            TerminalConfiguration terminalConfiguration = transformerAssetType.GetTerminalConfiguration();
                                                            Terminal upstreamTerminal = null;
                                                            foreach (Terminal terminal in terminalConfiguration.Terminals)
                                                            {
                                                                if (terminal.IsUpstreamTerminal)
                                                                {
                                                                    upstreamTerminal = terminal;
                                                                    break;
                                                                }
                                                            }

                                                            // Find the terminal on the fuse
                                                            Terminal fuseTerminal = fuseAssetType.GetTerminalConfiguration().Terminals[0];

                                                            // Find the terminal on the arrester
                                                            Terminal arresterTerminal = arresterAssetType.GetTerminalConfiguration().Terminals[0];

                                                            // All of our asset groups and asset types exist.  Now we have to check for rules.

                                                            IReadOnlyList <Rule> rules = utilityNetworkDefinition.GetRules();
                                                            if (ContainmentRuleExists(rules, transformerBankAssetType, transformerAssetType) &&
                                                                ContainmentRuleExists(rules, transformerBankAssetType, fuseAssetType) &&
                                                                ContainmentRuleExists(rules, transformerBankAssetType, arresterAssetType) &&
                                                                ConnectivityRuleExists(rules, transformerAssetType, upstreamTerminal, fuseAssetType, fuseTerminal) &&
                                                                ConnectivityRuleExists(rules, fuseAssetType, fuseTerminal, arresterAssetType, arresterTerminal))
                                                            {
                                                                dataModelIsValid = true;
                                                            }
                                                        }
            }
            catch { }

            return(dataModelIsValid);
        }
Пример #2
0
        /// <summary>
        /// Get the Un Schema version
        /// </summary>
        /// <param name="diagram">NetworkDiagram</param>
        /// <returns>string</returns>
        /// <remarks>UN Version 3 and earlier use only Subnetwork name
        /// UN Version 4 and later use Supported subnetwork name for container
        /// UN Version 5 and later use Supporting subnetwork name for structure</remarks>
        internal static int GetSchemaVersion(NetworkDiagram diagram)
        {
            DiagramManager diagramManager = diagram.DiagramManager;
            UtilityNetwork utilityNetwork = diagramManager.GetNetwork <UtilityNetwork>();

            UtilityNetworkDefinition unDefinition = utilityNetwork.GetDefinition();

            return(Convert.ToInt32(unDefinition.GetSchemaVersion()));
        }
        protected override async void OnClick()
        {
            try
            {
                string unLayerName = "Electric Utility Network";
                Layer  unLayer     = await GetLayerByName(MapView.Active.Map, unLayerName);

                UtilityNetwork utilityNetwork = await GetUNByLayer(unLayer);

                QueuedTask.Run(() =>
                {
                    UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition();

                    /* Uncomment to print out the network attributes in the utlity network
                     * IReadOnlyList<NetworkAttribute> networkAttributes = utilityNetworkDefinition.GetNetworkAttributes();
                     * string attributesMessage = "Network attributes: " + Environment.NewLine;
                     * foreach (var networkAttribute in networkAttributes)
                     * {
                     *  attributesMessage += networkAttribute.Name + Environment.NewLine;
                     * }
                     * MessageBox.Show(attributesMessage);
                     */

                    /* Uncomment to print out the categories in the utlity network
                     * IReadOnlyList<string> categories = utilityNetworkDefinition.GetAvailableCategories();
                     * string categoriesMsg = "Categories: " + Environment.NewLine;
                     * foreach (var category in categories)
                     * {
                     *  categoriesMsg += category + Environment.NewLine;
                     * }
                     * MessageBox.Show(categoriesMsg);
                     */

                    string result = $"Domain Networks: {Environment.NewLine}";
                    IReadOnlyList <DomainNetwork> domainNetworks = utilityNetworkDefinition.GetDomainNetworks();
                    if (domainNetworks != null)
                    {
                        foreach (DomainNetwork domainNetwork in domainNetworks)
                        {
                            result += $"{domainNetwork.Name}{Environment.NewLine}";
                        }
                    }
                    else
                    {
                        result += "No domain networks found";
                    }
                    MessageBox.Show(result);
                }).Wait();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"An exception occurred: {ex.Message}");
            }
        }
        /// <summary>
        /// This method makes sure
        /// 1. The Mapview is Active
        /// 2. There is at least one layer selected
        /// 3. That layer is either
        ///   a. A utility network layer
        ///   b. A feature layer whose feature class belongs to a utility network
        ///   c. A subtype group layer whose feature class belongs to a utility network
        ///
        /// If all of these hold true, we populate the combo box with the list of categories that are registered with this utility network
        /// </summary>
        private async void UpdateCategoryList(MapViewEventArgs mapViewEventArgs)
        {
            // Verify that the map view is active and at least one layer is selected
            if (MapView.Active == null ||
                mapViewEventArgs.MapView.GetSelectedLayers().Count < 1)
            {
                Enabled = false;
                return;
            }

            // Verify that we have the correct kind of layer
            Layer selectedLayer = mapViewEventArgs.MapView.GetSelectedLayers()[0];

            if (!(selectedLayer is UtilityNetworkLayer) && !(selectedLayer is FeatureLayer) && !(selectedLayer is SubtypeGroupLayer))
            {
                Enabled = false;
                return;
            }

            // Switch to the MCT to access the geodatabase
            await QueuedTask.Run(() =>
            {
                // Get the utility network from the layer.
                // It's possible that the layer is a FeatureLayer or SubtypeGroupLayer that doesn't refer to a utility network at all.
                using (UtilityNetwork utilityNetwork = UtilityNetworkUtils.GetUtilityNetworkFromLayer(selectedLayer))
                {
                    if (utilityNetwork == null)
                    {
                        Enabled = false;
                        return;
                    }

                    // Enable the combo box and clear out its contents
                    Enabled = true;
                    Clear();

                    // Fill the combo box with all of the categories in the utility network
                    using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())
                    {
                        IReadOnlyList <string> categories = utilityNetworkDefinition.GetAvailableCategories();
                        foreach (string category in categories)
                        {
                            Add(new ComboBoxItem(category));
                        }
                    }
                }
            });

            // Store the layer
            if (Enabled)
            {
                myLayer = selectedLayer;
            }
        }
Пример #5
0
        void FindATierFromDomainNetworkNameAndTierName(UtilityNetwork utilityNetwork, string domainNetworkName, string tierName)
        {
            #region Find a Tier given a Domain Network name and Tier name

            using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())
            {
                DomainNetwork domainNetwork = utilityNetworkDefinition.GetDomainNetwork(domainNetworkName);
                Tier          tier          = domainNetwork.GetTier(tierName);
            }


            #endregion
        }
Пример #6
0
        protected override async void OnClick()
        {
            try
            {
                string unLayerName       = "Electric Utility Network";
                string domainNetworkName = "ElectricTransmission";
                string tierName          = "AC High Voltage";
                Layer  unLayer           = await GetLayerByName(MapView.Active.Map, unLayerName);

                UtilityNetwork utilityNetwork = await GetUNByLayer(unLayer);

                await QueuedTask.Run(() =>
                {
                    using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())
                    {
                        DomainNetwork domainNetwork = utilityNetworkDefinition.GetDomainNetwork(domainNetworkName);
                        Tier tier = domainNetwork.GetTier(tierName);

                        using (SubnetworkManager subnetworkManager = utilityNetwork.GetSubnetworkManager())
                        {
                            Subnetwork dirtySubnetwork = subnetworkManager.GetSubnetworks(tier, SubnetworkStates.Dirty).FirstOrDefault();
                            try
                            {
                                if (dirtySubnetwork != null)
                                {
                                    SubnetworkController subnetworkController = dirtySubnetwork.GetControllers().First();
                                    subnetworkManager.DisableControllerInEditOperation(subnetworkController.Element);
                                    utilityNetwork.ValidateNetworkTopologyInEditOperation();
                                    dirtySubnetwork.Update();

                                    // Redraw map and clear cache
                                    MapView.Active.Redraw(true);
                                }
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }
                        }
                    }
                    // utilityNetwork.ValidateNetworkTopology();
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show($"An exception occurred: {ex.Message}");
            }
        }
        /// <summary>
        /// This routine validates the utility network schema matches what we are expecting
        /// </summary>
        /// <param name="utilityNetwork"></param>
        /// <returns>true if the data model has all of the correct schema</returns>
        private bool ValidateDataModel(UtilityNetwork utilityNetwork)
        {
            bool dataModelIsValid = false;

            using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())
            {
                try
                {
                    DomainNetwork    electricDomainNetwork = utilityNetworkDefinition.GetDomainNetwork(ElectricDomainNetwork);
                    Tier             mediumVoltageTier     = electricDomainNetwork.GetTier(MediumVoltageTier);
                    NetworkAttribute phaseNetworkAttribute = utilityNetworkDefinition.GetNetworkAttribute(PhaseAttributeName);
                    NetworkAttribute loadNetworkAttribute  = utilityNetworkDefinition.GetNetworkAttribute(LoadAttributeName);
                    if (utilityNetworkDefinition.GetAvailableCategories().Contains(ServicePointCategory))
                    {
                        dataModelIsValid = true;
                    }
                }
                catch (Exception) { };
            }
            return(dataModelIsValid);
        }
        private static void ExecuteTrace(Guid traceStartGuid, string geodatabasePath)
        {
            using (Geodatabase geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(geodatabasePath))))
            {
                IReadOnlyList <UtilityNetworkDefinition> utilityNetworkDefinitions = geodatabase.GetDefinitions <UtilityNetworkDefinition>();

                string utilityNetworkName = string.Empty;

                if (utilityNetworkDefinitions.Count < 0 || utilityNetworkDefinitions.Count > 1)
                {
                    return;
                }

                // Get utility network name from the dataset
                foreach (UtilityNetworkDefinition definition in utilityNetworkDefinitions)
                {
                    utilityNetworkName = definition.GetName();

                    Console.WriteLine($"Utility network name: {utilityNetworkName}");
                    definition.Dispose();
                }

                // Open utility network
                using (UtilityNetwork utilityNetwork = geodatabase.OpenDataset <UtilityNetwork>(utilityNetworkName))
                    using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())
                    {
                        using (NetworkSource networkSource = utilityNetworkDefinition.GetNetworkSource("ElectricDevice"))
                            using (AssetGroup assetGroup = networkSource.GetAssetGroup("Medium Voltage Transformer"))
                                using (AssetType assetType = assetGroup.GetAssetType("Overhead Single Phase"))
                                {
                                    DomainNetwork      domainNetwork      = utilityNetworkDefinition.GetDomainNetwork("Electric");
                                    Tier               sourceTier         = domainNetwork.GetTier("Electric Distribution");
                                    TraceConfiguration traceConfiguration = sourceTier.GetTraceConfiguration();

                                    // Get downstream side of the terminal
                                    Terminal terminal = null;
                                    if (assetType.IsTerminalConfigurationSupported())
                                    {
                                        TerminalConfiguration    terminalConfiguration = assetType.GetTerminalConfiguration();
                                        IReadOnlyList <Terminal> terminals             = terminalConfiguration.Terminals;
                                        terminal = terminals.First(t => !t.IsUpstreamTerminal);
                                    }

                                    // Create an element to begin a trace
                                    Element startingPointElement = utilityNetwork.CreateElement(assetType, traceStartGuid, terminal);

                                    List <Element> startingPoints = new List <Element>();
                                    startingPoints.Add(startingPointElement);


                                    // Get trace manager
                                    using (TraceManager traceManager = utilityNetwork.GetTraceManager())
                                    {
                                        // Set trace configurations
                                        TraceArgument traceArgument = new TraceArgument(startingPoints);
                                        traceArgument.Configuration = traceConfiguration;

                                        // Get downstream tracer
                                        Tracer tracer = traceManager.GetTracer <DownstreamTracer>();

                                        // Execuate downstream trace
                                        IReadOnlyList <Result> traceResults = tracer.Trace(traceArgument);

                                        // Display trace results in console
                                        foreach (Result result in traceResults)
                                        {
                                            if (result is ElementResult)
                                            {
                                                ElementResult           elementResult = result as ElementResult;
                                                IReadOnlyList <Element> elements      = elementResult.Elements;

                                                Console.WriteLine("Trace result elements:");
                                                foreach (Element element in elements)
                                                {
                                                    Console.WriteLine($"\t OID: {element.ObjectID}, Name:{element.AssetType.Name}");
                                                }
                                            }
                                            else if (result is FunctionOutputResult)
                                            {
                                                FunctionOutputResult           functionResult  = result as FunctionOutputResult;
                                                IReadOnlyList <FunctionOutput> functionOutputs = functionResult.FunctionOutputs;

                                                Console.WriteLine("Trace result function outputs:");
                                                foreach (FunctionOutput functionOut in functionOutputs)
                                                {
                                                    Console.WriteLine($"\t Function result:{functionOut.Value}, name: {functionOut.Function}");
                                                }
                                            }
                                            else if (result is AggregatedGeometryResult)
                                            {
                                                AggregatedGeometryResult aggResults = result as AggregatedGeometryResult;
                                                Polyline   aggregatedLine           = aggResults.Line as Polyline;
                                                Multipoint aggregatedPoint          = aggResults.Point as Multipoint;
                                                Polygon    aggregatedPolygon        = aggResults.Polygon as Polygon;
                                            }
                                        }
                                    }
                                }
                    }
            }
        }
Пример #9
0
        /// <summary>
        /// GenerateReport
        ///
        /// This routine takes a feature layer that references a feature class that participates in a utility network.
        /// It returns a set of data to display on the UI thread.
        ///
        ///
        /// </summary>

        public LoadTraceResults GenerateReport(Layer selectedLayer)
        {
            // Create a new results object.  We use this class to pass back a set of data from the worker thread to the UI thread

            LoadTraceResults results = new LoadTraceResults();

            // Initialize a number of geodatabase objects

            using (UtilityNetwork utilityNetwork = UtilityNetworkUtils.GetUtilityNetworkFromLayer(selectedLayer))
            {
                if (utilityNetwork == null)
                {
                    results.Message = "Please select a utility network layer.";
                    results.Success = false;
                }
                else
                {
                    using (Geodatabase utilityNetworkGeodatabase = utilityNetwork.GetDatastore() as Geodatabase)
                        using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())
                            using (Geodatabase defaultGeodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath))))
                                using (TraceManager traceManager = utilityNetwork.GetTraceManager())
                                {
                                    // First check to make sure we have a feature service workspace.  Utility Network functionality requires this.
                                    if (utilityNetworkGeodatabase.GetGeodatabaseType() != GeodatabaseType.Service)
                                    {
                                        results.Message = "A feature service workspace connection is required.";
                                        results.Success = false;
                                        return(results);
                                    }

                                    // Get a row from the starting points table in the default project workspace.  This table is created the first time the user creates a starting point
                                    // If the table is missing or empty, a null row is returned

                                    using (Row startingPointRow = GetStartingPointRow(defaultGeodatabase, ref results))
                                    {
                                        if (startingPointRow != null)
                                        {
                                            // Convert starting point row into network element

                                            Element startingPointElement = GetElementFromPointRow(startingPointRow, utilityNetwork, utilityNetworkDefinition);

                                            // Obtain a tracer object

                                            DownstreamTracer downstreamTracer = traceManager.GetTracer <DownstreamTracer>();

                                            // Get the network attributes that we will use in our trace

                                            using (NetworkAttribute phasesNetworkAttribute = GetAttribute(utilityNetworkDefinition, PhaseAttributeNames))
                                                using (NetworkAttribute loadNetworkAttribute = GetAttribute(utilityNetworkDefinition, LoadAttributeNames))
                                                    using (NetworkAttribute deviceStatusNetworkAttribute = GetAttribute(utilityNetworkDefinition, DeviceStatusAttributeNames))
                                                    {
                                                        if (phasesNetworkAttribute == null || loadNetworkAttribute == null || deviceStatusNetworkAttribute == null)
                                                        {
                                                            results.Success = false;
                                                            results.Message = "This add-in requires network attributes for phase, service load, and device status.\n";
                                                            return(results);
                                                        }


                                                        // Get the Tier for Medium Voltage Radial

                                                        DomainNetwork electricDomainNetwork = utilityNetworkDefinition.GetDomainNetwork(ElectricDomainNetwork);
                                                        Tier          mediumVoltageTier     = electricDomainNetwork.GetTier(MediumVoltageTier);


                                                        // Set up the trace configuration

                                                        TraceConfiguration traceConfiguration = new TraceConfiguration();

                                                        // Configure the trace to use the electric domain network

                                                        traceConfiguration.DomainNetwork = electricDomainNetwork;

                                                        // Take the default TraceConfiguration from the Tier for Traversability

                                                        Traversability tierTraceTraversability = mediumVoltageTier.TraceConfiguration.Traversability;
                                                        traceConfiguration.Traversability.FunctionBarriers = tierTraceTraversability.FunctionBarriers;
                                                        traceConfiguration.IncludeBarriersWithResults      = mediumVoltageTier.TraceConfiguration.IncludeBarriersWithResults;
                                                        traceConfiguration.Traversability.Scope            = tierTraceTraversability.Scope;
                                                        ConditionalExpression baseCondition = tierTraceTraversability.Barriers as ConditionalExpression;

                                                        // Create a condition to only return features that have the service point category

                                                        ConditionalExpression servicePointCategoryCondition = new CategoryComparison(CategoryOperator.IsEqual, ServicePointCategory);

                                                        // Create function to sum loads on service points where phase = A

                                                        ConditionalExpression aPhaseCondition = new NetworkAttributeComparison(phasesNetworkAttribute, Operator.DoesNotIncludeTheValues, APhase);
                                                        Add aPhaseLoad = new Add(loadNetworkAttribute, servicePointCategoryCondition);


                                                        // Create function to sum loads on service points where phase = B

                                                        ConditionalExpression bPhaseCondition = new NetworkAttributeComparison(phasesNetworkAttribute, Operator.DoesNotIncludeTheValues, BPhase);
                                                        Add bPhaseLoad = new Add(loadNetworkAttribute, servicePointCategoryCondition);

                                                        // Create function to sum loads on service points where phase = C

                                                        ConditionalExpression cPhaseCondition = new NetworkAttributeComparison(phasesNetworkAttribute, Operator.DoesNotIncludeTheValues, CPhase);
                                                        Add cPhaseLoad = new Add(loadNetworkAttribute, servicePointCategoryCondition);

                                                        // Set the output condition to only return features that have the service point category

                                                        traceConfiguration.OutputCondition = servicePointCategoryCondition;

                                                        // Create starting point list and trace argument object

                                                        List <Element> startingPointList = new List <Element>()
                                                        {
                                                            startingPointElement
                                                        };
                                                        TraceArgument traceArgument = new TraceArgument(startingPointList);
                                                        traceArgument.Configuration = traceConfiguration;

                                                        // Trace on the A phase

                                                        traceConfiguration.Traversability.Barriers = new Or(baseCondition, aPhaseCondition);
                                                        traceConfiguration.Functions = new List <Function>()
                                                        {
                                                            aPhaseLoad
                                                        };
                                                        traceArgument.Configuration = traceConfiguration;

                                                        try
                                                        {
                                                            IReadOnlyList <Result> resultsA = downstreamTracer.Trace(traceArgument);

                                                            ElementResult elementResult = resultsA.OfType <ElementResult>().First();
                                                            results.NumberServicePointsA = elementResult.Elements.Count;

                                                            FunctionOutputResult functionOutputResult = resultsA.OfType <FunctionOutputResult>().First();
                                                            results.TotalLoadA = (double)functionOutputResult.FunctionOutputs.First().Value;
                                                        }
                                                        catch (ArcGIS.Core.Data.GeodatabaseUtilityNetworkException e)
                                                        {
                                                            //No A phase connectivity to source
                                                            if (!e.Message.Equals("No subnetwork source was discovered."))
                                                            {
                                                                results.Success  = false;
                                                                results.Message += e.Message;
                                                            }
                                                        }

                                                        // Trace on the B phase

                                                        traceConfiguration.Traversability.Barriers = new Or(baseCondition, bPhaseCondition);
                                                        traceConfiguration.Functions = new List <Function>()
                                                        {
                                                            bPhaseLoad
                                                        };
                                                        traceArgument.Configuration = traceConfiguration;

                                                        try
                                                        {
                                                            IReadOnlyList <Result> resultsB = downstreamTracer.Trace(traceArgument);

                                                            ElementResult elementResult = resultsB.OfType <ElementResult>().First();
                                                            results.NumberServicePointsB = elementResult.Elements.Count;

                                                            FunctionOutputResult functionOutputResult = resultsB.OfType <FunctionOutputResult>().First();
                                                            results.TotalLoadB = (double)functionOutputResult.FunctionOutputs.First().Value;
                                                        }
                                                        catch (ArcGIS.Core.Data.GeodatabaseUtilityNetworkException e)
                                                        {
                                                            // No B phase connectivity to source
                                                            if (!e.Message.Equals("No subnetwork source was discovered."))
                                                            {
                                                                results.Success  = false;
                                                                results.Message += e.Message;
                                                            }
                                                        }

                                                        // Trace on the C phase
                                                        traceConfiguration.Traversability.Barriers = new Or(baseCondition, cPhaseCondition);
                                                        traceConfiguration.Functions = new List <Function>()
                                                        {
                                                            cPhaseLoad
                                                        };
                                                        traceArgument.Configuration = traceConfiguration;

                                                        try
                                                        {
                                                            IReadOnlyList <Result> resultsC = downstreamTracer.Trace(traceArgument);

                                                            ElementResult elementResult = resultsC.OfType <ElementResult>().First();
                                                            results.NumberServicePointsC = elementResult.Elements.Count;

                                                            FunctionOutputResult functionOutputResult = resultsC.OfType <FunctionOutputResult>().First();
                                                            results.TotalLoadC = (double)functionOutputResult.FunctionOutputs.First().Value;
                                                        }
                                                        catch (ArcGIS.Core.Data.GeodatabaseUtilityNetworkException e)
                                                        {
                                                            // No C phase connectivity to source
                                                            if (!e.Message.Equals("No subnetwork source was discovered."))
                                                            {
                                                                results.Success  = false;
                                                                results.Message += e.Message;
                                                            }
                                                        }
                                                    }

                                            // append success message to the output string

                                            results.Message += "Trace successful.";
                                            results.Success  = true;
                                        }
                                    }
                                }
                }
            }
            return(results);
        }
        /// <summary>
        /// The on comboBox selection change event. This creates a new table that lists the assignments for the specified category.  This table is added to the map, selected in the TOC, and opened.
        /// </summary>
        /// <param name="item">The newly selected combo box item</param>
        protected override async void OnSelectionChange(ComboBoxItem item)
        {
            if (item == null)
            {
                return;
            }

            if (string.IsNullOrEmpty(item.Text))
            {
                return;
            }

            if (myLayer == null)
            {
                return;
            }

            //Construct the name of our table for the category assignment report
            string baseCategoryReportTableName = "CategoryAssignments_" + item.Text;
            string categoryReportTableName     = baseCategoryReportTableName.Replace(" ", "_");

            bool needToCreateTable        = true;
            bool needToAddStandaloneTable = true;

            // Switch to the MCT to access the geodatabase
            await QueuedTask.Run(() =>
            {
                // Check if the table exists

                using (Geodatabase projectWorkspace = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath))))
                {
                    try
                    {
                        using (Table categoryReportTable = projectWorkspace.OpenDataset <Table>(categoryReportTableName))
                        {
                            // Table exists, we do not need to create it...
                            needToCreateTable = false;

                            // .. but we should delete the existing contents
                            categoryReportTable.DeleteRows(new QueryFilter());

                            // Check to see if a Standalone table exists in the map
                            bool standaloneTableFound = false;
                            ReadOnlyObservableCollection <StandaloneTable> initialStandaloneTables = MapView.Active.Map.StandaloneTables;
                            foreach (StandaloneTable standaloneTable in initialStandaloneTables)
                            {
                                if (standaloneTable.Name == categoryReportTableName)
                                {
                                    standaloneTableFound = true;
                                }
                            }

                            // Since there is already a StandaloneTable that references our category table in the map, we don't need to add it
                            needToAddStandaloneTable = !standaloneTableFound;
                        }
                    }
                    catch
                    {
                        //Table doesn't exist.  Not an error, but we will have to create it
                    }
                }
            });

            // Create the category report table

            if (needToCreateTable)
            {
                // Create table
                IReadOnlyList <string> createParams = Geoprocessing.MakeValueArray(new object[] { Project.Current.DefaultGeodatabasePath, categoryReportTableName, null, null });
                IGPResult result = await Geoprocessing.ExecuteToolAsync("management.CreateTable", createParams);

                if (result.IsFailed)
                {
                    MessageBox.Show("Unable to create category assignment table in project workspace", "Category Assignments");
                    return;
                }

                // Add field for feature class alias
                IReadOnlyList <string> addFieldParams = Geoprocessing.MakeValueArray(new object[] { categoryReportTableName, "FeatureClassAlias", "TEXT", null, null, 32, "Feature Class", "NULLABLE", "NON_REQUIRED", null });
                result = await Geoprocessing.ExecuteToolAsync("management.AddField", addFieldParams);

                if (result.IsFailed)
                {
                    MessageBox.Show("Unable to modify schema of category assignment table in project workspace", "Category Assignments");
                    return;
                }

                // Add field for Asset Group name
                addFieldParams = Geoprocessing.MakeValueArray(new object[] { categoryReportTableName, "AssetGroupName", "TEXT", null, null, 256, "Asset Group Name", "NULLABLE", "NON_REQUIRED", null });
                result         = await Geoprocessing.ExecuteToolAsync("management.AddField", addFieldParams);

                if (result.IsFailed)
                {
                    MessageBox.Show("Unable to modify schema of category assignment table in project workspace", "Category Assignments");
                    return;
                }

                // Add field for Asset Type name
                addFieldParams = Geoprocessing.MakeValueArray(new object[] { categoryReportTableName, "AssetTypeName", "TEXT", null, null, 256, "Asset Type Name", "NULLABLE", "NON_REQUIRED", null });
                result         = await Geoprocessing.ExecuteToolAsync("management.AddField", addFieldParams);

                if (result.IsFailed)
                {
                    MessageBox.Show("Unable to modify schema of category assignment table in project workspace", "Category Assignments");
                    return;
                }

                needToAddStandaloneTable = false; //creating a table automatically adds it to the map
            }


            // Populate table
            // Again, we need to switch to the MCT to execute geodatabase and utility network code
            await QueuedTask.Run(() =>
            {
                using (Geodatabase projectWorkspace = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(Project.Current.DefaultGeodatabasePath))))
                    using (Table categoryReportTable = projectWorkspace.OpenDataset <Table>(categoryReportTableName))
                        using (UtilityNetwork utilityNetwork = UtilityNetworkSamples.UtilityNetworkUtils.GetUtilityNetworkFromLayer(myLayer))
                            using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())
                            {
                                IReadOnlyList <NetworkSource> networkSources = utilityNetworkDefinition.GetNetworkSources();

                                // Step through each NetworkSource
                                foreach (NetworkSource networkSource in networkSources)
                                {
                                    IReadOnlyList <AssetGroup> assetGroups = networkSource.GetAssetGroups();

                                    // Step through each AssetGroup
                                    foreach (AssetGroup assetGroup in assetGroups)
                                    {
                                        IReadOnlyList <AssetType> assetTypes = assetGroup.GetAssetTypes();

                                        // Step through each AssetType
                                        foreach (AssetType assetType in assetTypes)
                                        {
                                            // Check to see if this AssetType is assigned the Category we are looking for
                                            IReadOnlyList <string> assignedCategoryList = assetType.CategoryList;
                                            foreach (string assignedCategory in assignedCategoryList)
                                            {
                                                if (assignedCategory == item.Text)
                                                {
                                                    // Our Category is assigned to this AssetType.  Create a row to store in the category report table
                                                    using (FeatureClass networkSourceFeatureClass = utilityNetwork.GetTable(networkSource) as FeatureClass)
                                                        using (FeatureClassDefinition networkSourceFeatureClassDefinition = networkSourceFeatureClass.GetDefinition())
                                                            using (RowBuffer rowBuffer = categoryReportTable.CreateRowBuffer())
                                                            {
                                                                rowBuffer["FeatureClassAlias"] = networkSourceFeatureClassDefinition.GetAliasName();
                                                                rowBuffer["AssetGroupName"]    = assetGroup.Name;
                                                                rowBuffer["AssetTypeName"]     = assetType.Name;
                                                                categoryReportTable.CreateRow(rowBuffer).Dispose();
                                                            }
                                                }
                                            }
                                        }
                                    }
                                }

                                // If necessary, add our category report table to the map as a standalone table
                                if (needToAddStandaloneTable)
                                {
                                    IStandaloneTableFactory tableFactory = StandaloneTableFactory.Instance;
                                    tableFactory.CreateStandaloneTable(categoryReportTable, MapView.Active.Map);
                                }
                            }
            });

            // Open category report stand alone table into a window
            ReadOnlyObservableCollection <StandaloneTable> standaloneTables = MapView.Active.Map.StandaloneTables;

            foreach (StandaloneTable standaloneTable in standaloneTables)
            {
                if (standaloneTable.Name == categoryReportTableName)
                {
                    FrameworkApplication.Panes.OpenTablePane(standaloneTable, TableViewMode.eAllRecords);
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Called when the sketch finishes. This is where we will create the sketch operation and then execute it.
        /// </summary>
        /// <param name="geometry">The geometry created by the sketch.</param>
        /// <returns>A Task returning a Boolean indicating if the sketch complete event was successfully handled.</returns>
        protected override async Task <bool> OnSketchCompleteAsync(Geometry geometry)
        {
            if (geometry == null)
            {
                return(false);
            }

            // Create an edit operation
            var createOperation = new EditOperation();

            createOperation.Name = "Create Transformer Bank";
            createOperation.SelectNewFeatures = true;

            bool   success      = false;
            string errorMessage = "";

            await QueuedTask.Run(() =>
            {
                Map map = GetMap();

                using (UtilityNetwork utilityNetwork = GetUtilityNetwork())
                {
                    if (utilityNetwork == null)
                    {
                        errorMessage = "Please select a layer that participates in a utility network.";
                    }
                    else
                    {
                        using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())

                            // Get the NetworkSource, AssetGroup, and AssetTypes for all of the features we want to create
                            // If this was production code, you would want to check the return values to make sure that these asset groups and asset types existed.

                            // TransformerBank
                            using (NetworkSource transformerBankNetworkSource = utilityNetworkDefinition.GetNetworkSource(AssemblyNetworkSourceName))
                                using (AssetGroup transformerBankAssetGroup = transformerBankNetworkSource.GetAssetGroup(TransformerBankAssetGroupName))
                                    using (AssetType transformerBankAssetType = transformerBankAssetGroup.GetAssetType(TransformerBankAssetTypeName))

                                        // Transformer
                                        using (NetworkSource deviceNetworkSource = utilityNetworkDefinition.GetNetworkSource(DeviceNetworkSourceName))
                                            using (AssetGroup transformerAssetGroup = deviceNetworkSource.GetAssetGroup(TransformerAssetGroupName))
                                                using (AssetType transformerAssetType = transformerAssetGroup.GetAssetType(TransformerAssetTypeName))

                                                    // Arrester
                                                    using (AssetGroup arresterAssetGroup = deviceNetworkSource.GetAssetGroup(ArresterAssetGroupName))
                                                        using (AssetType arresterAssetType = arresterAssetGroup.GetAssetType(ArresterAssetTypeName))

                                                            // Fuse
                                                            using (AssetGroup fuseAssetGroup = deviceNetworkSource.GetAssetGroup(FuseAssetGroupName))
                                                                using (AssetType fuseAssetType = fuseAssetGroup.GetAssetType(FuseAssetTypeName))
                                                                {
                                                                    MapPoint clickPoint = geometry as MapPoint;

                                                                    // Create a transformer bank
                                                                    Layer transformerBankLayer      = GetLayerForEdit(map, AssemblyNetworkSourceName, TransformerBankAssetGroupName);
                                                                    RowToken token                  = createOperation.CreateEx(transformerBankLayer, CreateAttributes(transformerBankAssetGroup, transformerBankAssetType, clickPoint));
                                                                    RowHandle transformerBankHandle = new RowHandle(token);

                                                                    // Create three transformers, one for each phase
                                                                    Layer transformerLayer = GetLayerForEdit(map, DeviceNetworkSourceName, TransformerAssetGroupName);

                                                                    MapPoint transformerPointA = CreateOffsetMapPoint(clickPoint, -1 * XOffset, YOffset);
                                                                    token = createOperation.CreateEx(transformerLayer, CreateDeviceAttributes(transformerAssetGroup, transformerAssetType, transformerPointA, APhase));
                                                                    RowHandle transformerHandleA = new RowHandle(token);

                                                                    MapPoint transformerPointB = CreateOffsetMapPoint(clickPoint, 0, YOffset);
                                                                    token = createOperation.CreateEx(transformerLayer, CreateDeviceAttributes(transformerAssetGroup, transformerAssetType, transformerPointB, BPhase));
                                                                    RowHandle transformerHandleB = new RowHandle(token);

                                                                    MapPoint transformerPointC = CreateOffsetMapPoint(clickPoint, XOffset, YOffset);
                                                                    token = createOperation.CreateEx(transformerLayer, CreateDeviceAttributes(transformerAssetGroup, transformerAssetType, transformerPointC, CPhase));
                                                                    RowHandle transformerHandleC = new RowHandle(token);

                                                                    // Create containment associations between the bank and the transformers
                                                                    ContainmentAssociationDescription containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, transformerHandleA, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, transformerHandleB, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, transformerHandleC, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    // Create three arresters, one for each phase
                                                                    Layer arresterLayer = GetLayerForEdit(map, DeviceNetworkSourceName, ArresterAssetGroupName);

                                                                    MapPoint arresterPointA = CreateOffsetMapPoint(clickPoint, -1 * XOffset, 2 * YOffset);
                                                                    token = createOperation.CreateEx(arresterLayer, CreateDeviceAttributes(arresterAssetGroup, arresterAssetType, arresterPointA, APhase));
                                                                    RowHandle arresterHandlA = new RowHandle(token);

                                                                    MapPoint arresterPointB = CreateOffsetMapPoint(clickPoint, 0, 2 * YOffset);
                                                                    token = createOperation.CreateEx(arresterLayer, CreateDeviceAttributes(arresterAssetGroup, arresterAssetType, arresterPointB, BPhase));
                                                                    RowHandle arresterHandleB = new RowHandle(token);

                                                                    MapPoint arresterPointC = CreateOffsetMapPoint(clickPoint, XOffset, 2 * YOffset);
                                                                    token = createOperation.CreateEx(arresterLayer, CreateDeviceAttributes(arresterAssetGroup, arresterAssetType, arresterPointC, CPhase));
                                                                    RowHandle arresterHandleC = new RowHandle(token);

                                                                    // Create containment associations between the bank and the arresters
                                                                    containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, arresterHandlA, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, arresterHandleB, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, arresterHandleC, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    // Find the high-side terminal for transformers
                                                                    TerminalConfiguration transformerTerminalConfiguration = transformerAssetType.GetTerminalConfiguration();
                                                                    IReadOnlyList <Terminal> terminals = transformerTerminalConfiguration.Terminals;
                                                                    Terminal highSideTerminal          = terminals.First(x => x.IsUpstreamTerminal == true);
                                                                    long highSideTerminalID            = highSideTerminal.ID;

                                                                    // Connect the high-side transformer terminals to the arresters (connect the A-phase transformer to the A-phase arrester, and so on)
                                                                    ConnectivityAssociationDescription connectivityAssociationDescription = new ConnectivityAssociationDescription(transformerHandleA, highSideTerminalID, arresterHandlA);
                                                                    createOperation.Create(connectivityAssociationDescription);

                                                                    connectivityAssociationDescription = new ConnectivityAssociationDescription(transformerHandleB, highSideTerminalID, arresterHandleB);
                                                                    createOperation.Create(connectivityAssociationDescription);

                                                                    connectivityAssociationDescription = new ConnectivityAssociationDescription(transformerHandleC, highSideTerminalID, arresterHandleC);
                                                                    createOperation.Create(connectivityAssociationDescription);

                                                                    // Create three fuses, one for each phase
                                                                    Layer fuseLayer = GetLayerForEdit(map, DeviceNetworkSourceName, FuseAssetGroupName);

                                                                    MapPoint fusePointA = CreateOffsetMapPoint(clickPoint, -1 * XOffset, 3 * YOffset);
                                                                    token = createOperation.CreateEx(fuseLayer, CreateDeviceAttributes(fuseAssetGroup, fuseAssetType, fusePointA, APhase));
                                                                    RowHandle fuseHandleA = new RowHandle(token);

                                                                    MapPoint fusePointB = CreateOffsetMapPoint(clickPoint, 0, 3 * YOffset);
                                                                    token = createOperation.CreateEx(fuseLayer, CreateDeviceAttributes(fuseAssetGroup, fuseAssetType, fusePointB, BPhase));
                                                                    RowHandle fuseHandleB = new RowHandle(token);

                                                                    MapPoint fusePointC = CreateOffsetMapPoint(clickPoint, XOffset, 3 * YOffset);
                                                                    token = createOperation.CreateEx(fuseLayer, CreateDeviceAttributes(fuseAssetGroup, fuseAssetType, fusePointC, CPhase));
                                                                    RowHandle fuseHandleC = new RowHandle(token);

                                                                    // Create containment associations between the bank and the fuses
                                                                    containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, fuseHandleA, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, fuseHandleB, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    containmentAssociationDescription = new ContainmentAssociationDescription(transformerBankHandle, fuseHandleC, false);
                                                                    createOperation.Create(containmentAssociationDescription);

                                                                    // Create connectivity associations between the fuses and the arresters (connect the A-phase fuse the A-phase arrester, and so on)
                                                                    connectivityAssociationDescription = new ConnectivityAssociationDescription(fuseHandleA, arresterHandlA);
                                                                    createOperation.Create(connectivityAssociationDescription);

                                                                    connectivityAssociationDescription = new ConnectivityAssociationDescription(fuseHandleB, arresterHandleB);
                                                                    createOperation.Create(connectivityAssociationDescription);

                                                                    connectivityAssociationDescription = new ConnectivityAssociationDescription(fuseHandleC, arresterHandleC);
                                                                    createOperation.Create(connectivityAssociationDescription);

                                                                    // Execute the edit operation, which creates all of the rows and associations
                                                                    success = createOperation.Execute();

                                                                    if (!success)
                                                                    {
                                                                        errorMessage = createOperation.ErrorMessage;
                                                                    }
                                                                }
                    }
                }
            });

            if (!success)
            {
                MessageBox.Show(errorMessage, "Create Transformer Bank Tool");
            }
            return(success);
        }
Пример #12
0
        /// <summary>
        /// Called when the sketch finishes. This is where we will create the sketch operation and then execute it.
        /// </summary>
        /// <param name="geometry">The geometry created by the sketch.</param>
        /// <returns>A Task returning a Boolean indicating if the sketch complete event was successfully handled.</returns>
        protected override async Task <bool> OnSketchCompleteAsync(Geometry geometry)
        {
            if (geometry == null)
            {
                return(false);
            }

            // Create an edit operation
            var createOperation = new EditOperation()
            {
                Name = "Create Transformer Bank",
                SelectNewFeatures = true
            };

            bool   success      = false;
            string errorMessage = "";

            await QueuedTask.Run(() =>
            {
                Map map = GetMap();

                using (UtilityNetwork utilityNetwork = GetUtilityNetwork())
                {
                    if (utilityNetwork == null)
                    {
                        errorMessage = "Please select a layer that participates in a utility network.";
                    }
                    else
                    {
                        if (!ValidateDataModel(utilityNetwork))
                        {
                            errorMessage = "This sample is designed for a different utility network data model";
                        }
                        else
                        {
                            using (UtilityNetworkDefinition utilityNetworkDefinition = utilityNetwork.GetDefinition())
                                // Get the NetworkSource, FeatureClass, AssetGroup, and AssetTypes for all of the features we want to create
                                // The existence of these values has already been confirmed in the ValidateDataModel() routine

                                // TransformerBank
                                using (NetworkSource transformerBankNetworkSource = GetNetworkSource(utilityNetworkDefinition, AssemblyNetworkSourceName))
                                    using (FeatureClass transformerBankFeatureClass = utilityNetwork.GetTable(transformerBankNetworkSource) as FeatureClass)
                                        using (AssetGroup transformerBankAssetGroup = transformerBankNetworkSource.GetAssetGroup(TransformerBankAssetGroupName))
                                            using (AssetType transformerBankAssetType = transformerBankAssetGroup.GetAssetType(TransformerBankAssetTypeName))

                                                // Transformer
                                                using (NetworkSource deviceNetworkSource = GetNetworkSource(utilityNetworkDefinition, DeviceNetworkSourceName))
                                                    using (FeatureClass deviceFeatureClass = utilityNetwork.GetTable(deviceNetworkSource) as FeatureClass)
                                                        using (AssetGroup transformerAssetGroup = deviceNetworkSource.GetAssetGroup(TransformerAssetGroupName))
                                                            using (AssetType transformerAssetType = transformerAssetGroup.GetAssetType(TransformerAssetTypeName))

                                                                // Arrester
                                                                using (AssetGroup arresterAssetGroup = deviceNetworkSource.GetAssetGroup(ArresterAssetGroupName))
                                                                    using (AssetType arresterAssetType = arresterAssetGroup.GetAssetType(ArresterAssetTypeName))

                                                                        // Fuse
                                                                        using (AssetGroup fuseAssetGroup = deviceNetworkSource.GetAssetGroup(FuseAssetGroupName))
                                                                            using (AssetType fuseAssetType = fuseAssetGroup.GetAssetType(FuseAssetTypeName))
                                                                            {
                                                                                MapPoint clickPoint = geometry as MapPoint;

                                                                                // Create a transformer bank

                                                                                RowToken token = createOperation.CreateEx(transformerBankFeatureClass, CreateAttributes(transformerBankAssetGroup, transformerBankAssetType, clickPoint));
                                                                                RowHandle transformerBankHandle = new RowHandle(token);

                                                                                // Create three transformers, one for each phase

                                                                                MapPoint transformerPointA = CreateOffsetMapPoint(clickPoint, -1 * XOffset, YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(transformerAssetGroup, transformerAssetType, transformerPointA, APhase));
                                                                                RowHandle transformerHandleA = new RowHandle(token);

                                                                                MapPoint transformerPointB = CreateOffsetMapPoint(clickPoint, 0, YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(transformerAssetGroup, transformerAssetType, transformerPointB, BPhase));
                                                                                RowHandle transformerHandleB = new RowHandle(token);

                                                                                MapPoint transformerPointC = CreateOffsetMapPoint(clickPoint, XOffset, YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(transformerAssetGroup, transformerAssetType, transformerPointC, CPhase));
                                                                                RowHandle transformerHandleC = new RowHandle(token);

                                                                                // Create containment associations between the bank and the transformers
                                                                                AssociationDescription containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, transformerHandleA, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, transformerHandleB, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, transformerHandleC, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                // Find the high-side terminal for transformers
                                                                                TerminalConfiguration transformerTerminalConfiguration = transformerAssetType.GetTerminalConfiguration();
                                                                                IReadOnlyList <Terminal> terminals = transformerTerminalConfiguration.Terminals;
                                                                                Terminal highSideTerminal          = terminals.First(x => x.IsUpstreamTerminal == true);
                                                                                long highSideTerminalID            = highSideTerminal.ID;

                                                                                // Create three fuses, one for each phase

                                                                                MapPoint fusePointA = CreateOffsetMapPoint(clickPoint, -1 * XOffset, 2 * YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(fuseAssetGroup, fuseAssetType, fusePointA, APhase));
                                                                                RowHandle fuseHandleA = new RowHandle(token);

                                                                                MapPoint fusePointB = CreateOffsetMapPoint(clickPoint, 0, 2 * YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(fuseAssetGroup, fuseAssetType, fusePointB, BPhase));
                                                                                RowHandle fuseHandleB = new RowHandle(token);

                                                                                MapPoint fusePointC = CreateOffsetMapPoint(clickPoint, XOffset, 2 * YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(fuseAssetGroup, fuseAssetType, fusePointC, CPhase));
                                                                                RowHandle fuseHandleC = new RowHandle(token);

                                                                                // Create containment associations between the bank and the fuses
                                                                                containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, fuseHandleA, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, fuseHandleB, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, fuseHandleC, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                // Connect the high-side transformer terminals to the fuses (connect the A-phase transformer to the A-phase fuse, and so on)
                                                                                AssociationDescription connectivityAssociationDescription = new AssociationDescription(AssociationType.JunctionJunctionConnectivity, transformerHandleA, highSideTerminalID, fuseHandleA);
                                                                                createOperation.Create(connectivityAssociationDescription);

                                                                                connectivityAssociationDescription = new AssociationDescription(AssociationType.JunctionJunctionConnectivity, transformerHandleB, highSideTerminalID, fuseHandleB);
                                                                                createOperation.Create(connectivityAssociationDescription);

                                                                                connectivityAssociationDescription = new AssociationDescription(AssociationType.JunctionJunctionConnectivity, transformerHandleC, highSideTerminalID, fuseHandleC);
                                                                                createOperation.Create(connectivityAssociationDescription);

                                                                                // Create three arresters, one for each phase

                                                                                MapPoint arresterPointA = CreateOffsetMapPoint(clickPoint, -1 * XOffset, 3 * YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(arresterAssetGroup, arresterAssetType, arresterPointA, APhase));
                                                                                RowHandle arresterHandleA = new RowHandle(token);

                                                                                MapPoint arresterPointB = CreateOffsetMapPoint(clickPoint, 0, 3 * YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(arresterAssetGroup, arresterAssetType, arresterPointB, BPhase));
                                                                                RowHandle arresterHandleB = new RowHandle(token);

                                                                                MapPoint arresterPointC = CreateOffsetMapPoint(clickPoint, XOffset, 3 * YOffset);
                                                                                token = createOperation.CreateEx(deviceFeatureClass, CreateDeviceAttributes(arresterAssetGroup, arresterAssetType, arresterPointC, CPhase));
                                                                                RowHandle arresterHandleC = new RowHandle(token);

                                                                                // Create containment associations between the bank and the arresters
                                                                                containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, arresterHandleA, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, arresterHandleB, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                containmentAssociationDescription = new AssociationDescription(AssociationType.Containment, transformerBankHandle, arresterHandleC, false);
                                                                                createOperation.Create(containmentAssociationDescription);

                                                                                // Create connectivity associations between the fuses and the arresters (connect the A-phase fuse the A-phase arrester, and so on)
                                                                                connectivityAssociationDescription = new AssociationDescription(AssociationType.JunctionJunctionConnectivity, fuseHandleA, arresterHandleA);
                                                                                createOperation.Create(connectivityAssociationDescription);

                                                                                connectivityAssociationDescription = new AssociationDescription(AssociationType.JunctionJunctionConnectivity, fuseHandleB, arresterHandleB);
                                                                                createOperation.Create(connectivityAssociationDescription);

                                                                                connectivityAssociationDescription = new AssociationDescription(AssociationType.JunctionJunctionConnectivity, fuseHandleC, arresterHandleC);
                                                                                createOperation.Create(connectivityAssociationDescription);

                                                                                // Execute the edit operation, which creates all of the rows and associations
                                                                                success = createOperation.Execute();

                                                                                if (!success)
                                                                                {
                                                                                    errorMessage = createOperation.ErrorMessage;
                                                                                }
                                                                            }
                        }
                    }
                }
            });

            if (!success)
            {
                MessageBox.Show(errorMessage, "Create Transformer Bank Tool");
            }
            return(success);
        }
        /// <summary>
        /// Execute the layout on the Diagram
        /// </summary>
        /// <param name="diagram"></param>
        internal void Execute(NetworkDiagram diagram)
        {
            _graphModel.Initialize(diagram);

            var junctions = _graphModel.Junctions;

            if (!junctions.Any())
            {
                return;
            }

            int maxColorCount = 12;

            var containerIDs = new HashSet <int>();

            UtilityNetwork un = diagram.DiagramManager?.GetNetwork <UtilityNetwork>();

            IReadOnlyList <NetworkSource> theSources = un.GetDefinition().GetNetworkSources();

            if (!_graphModel.Containers.Any() || !_graphModel.Edges.Any())
            {
                return;
            }

            Dictionary <int, Dictionary <int, Dictionary <string, string> > > attributesBySourceID = new Dictionary <int, Dictionary <int, Dictionary <string, string> > >();

            foreach (var jsonContainer in _graphModel.Containers)
            {
                int sourceID = jsonContainer.Element.AssociatedSourceID;
                if (sourceID != 9) // Communications Device source ID
                {
                    continue;
                }

                if (!attributesBySourceID.TryGetValue(sourceID, out Dictionary <int, Dictionary <string, string> > AttributesByEID))
                {
                    AttributesByEID = FillSources(Diagram: diagram, theSources: theSources, SourceID: sourceID);
                    attributesBySourceID.Add(sourceID, AttributesByEID);
                }

                if (AttributesByEID.TryGetValue(jsonContainer.ID, out Dictionary <string, string> IdProperties))
                {
                    jsonContainer.AssetGroup = IdProperties["Asset group"];
                    jsonContainer.AssetType  = IdProperties["Asset type"];
                }
            }

            foreach (var jsonEdge in _graphModel.Edges)
            {
                int sourceID = jsonEdge.Element.AssociatedSourceID;
                if (sourceID != 15) // Communications Edge Object source ID
                {
                    continue;
                }

                if (!attributesBySourceID.TryGetValue(sourceID, out Dictionary <int, Dictionary <string, string> > AttributesByEID))
                {
                    AttributesByEID = FillSources(Diagram: diagram, theSources: theSources, SourceID: sourceID, IsEdge: true);
                    attributesBySourceID.Add(sourceID, AttributesByEID);
                }

                if (AttributesByEID.TryGetValue(jsonEdge.ID, out Dictionary <string, string> IdProperties))
                {
                    string assetGroup = IdProperties["Asset group"];
                    string assetType  = IdProperties["Asset type"];

                    if (assetGroup != "Strand" || assetType != "Fiber")
                    {
                        continue;
                    }

                    string groupColor = IdProperties["Strand Group Color"].ToString();
                    string color      = IdProperties["Strand Color"].ToString();

                    int groupColorRank = GetColorRank(groupColor);
                    int colorRank      = GetColorRank(color);

                    if (groupColorRank < 0 || colorRank < 0)
                    {
                        continue;
                    }

                    int rank = maxColorCount * groupColorRank + colorRank;

                    int fromID = jsonEdge.Element.FromID;
                    int toID   = jsonEdge.Element.ToID;

                    int fromContainerID = 0;
                    int toContainerID   = 0;

                    var fromJunction = _graphModel.GetJunction(fromID);
                    fromJunction.Rank = rank;
                    fromContainerID   = fromJunction.Element.ContainerID;
                    if (fromContainerID > 0)
                    {
                        containerIDs.Add(fromContainerID);
                    }

                    var toJunction = _graphModel.GetJunction(toID);
                    toJunction.Rank = rank;
                    toContainerID   = toJunction.Element.ContainerID;
                    if (toContainerID > 0)
                    {
                        containerIDs.Add(toContainerID);
                    }

                    if (fromContainerID > 0 && toContainerID > 0)
                    {
                        var fromContainer = _graphModel.GetContainer(fromContainerID);
                        fromContainer.ToContainers.Add(toContainerID);
                        fromContainer.HasOutputFibers = true;

                        var toContainer = _graphModel.GetContainer(toContainerID);
                        toContainer.FromContainers.Add(fromContainerID);
                        toContainer.HasInputFibers = true;
                        if (fromJunction.Rank < toContainer.FromJunctionRankMin)
                        {
                            toContainer.FromJunctionRankMin = fromJunction.Rank;
                        }
                    }
                }
            }

            attributesBySourceID = null;

            foreach (var junction in junctions)
            {
                if (junction.Element.ContainerID < 1)
                {
                    continue;
                }

                if (junction.Rank >= 0)
                {
                    continue;
                }

                _graphModel.GetConnectedJunctions(junction.Element.ID, out IList <int> connectedJunctions);

                int             fromRank      = -1;
                int             toRank        = -1;
                CustomContainer fromContainer = null;
                CustomContainer toContainer   = null;

                int count = Math.Min(connectedJunctions.Count, 2);
                for (int i = 0; i < count; i++)
                {
                    var connectedJunction = _graphModel.GetJunction(connectedJunctions[i]);
                    var container         = _graphModel.GetContainer(connectedJunction.Element.ContainerID);
                    if (container.HasInputFibers)
                    {
                        fromRank      = connectedJunction.Rank;
                        fromContainer = container;
                    }
                    else if (container.HasOutputFibers)
                    {
                        toRank      = connectedJunction.Rank;
                        toContainer = container;
                    }
                }

                if (fromRank >= 0 || toRank >= 0)
                {
                    junction.Rank = fromRank >= 0 ? fromRank : toRank;

                    var container = _graphModel.GetContainer(junction.Element.ContainerID);
                    containerIDs.Add(container.Element.ID);

                    if (fromContainer != null)
                    {
                        container.FromContainers.Add(fromContainer.Element.ID);
                        fromContainer.ToContainers.Add(container.Element.ID);
                    }

                    if (toContainer != null)
                    {
                        container.ToContainers.Add(toContainer.Element.ID);
                        toContainer.FromContainers.Add(container.Element.ID);
                        if (junction.Rank < toContainer.FromJunctionRankMin)
                        {
                            toContainer.FromJunctionRankMin = junction.Rank;
                        }
                    }
                }
            }

            var    diagramInfo   = diagram.GetDiagramInfo();
            var    diagramExtent = diagramInfo.DiagramExtent;
            double ySpacing      = diagramInfo.ContainerMargin;
            double xSpacingMin   = diagramInfo.ContainerMargin * 15;

            var startContainers = new List <CustomContainer>();

            foreach (var containerID in containerIDs)
            {
                var container = _graphModel.GetContainer(containerID);
                if (!(container is null) && (container.FromContainers.Count > 0 || container.ToContainers.Count < 1))
                {
                    continue;
                }

                if (container.Element is null)
                {
                    continue;
                }

                var parent = _graphModel.GetContainer(container.Element.ContainerID);
                if (parent == null)
                {
                    continue;
                }

                if (parent.AssetType != "Hub Terminator" && parent.AssetType != "Mid Cable Splice Enclosure")
                {
                    continue;
                }

                startContainers.Add(container);
            }

            double startY = diagramExtent.YMax;

            foreach (var startContainer in startContainers)
            {
                if (startContainer.FromContainerOrder != Int32.MaxValue)
                {
                    continue;
                }

                var toContainerIDs = new HashSet <int>();
                foreach (var toContainerID in startContainer.ToContainers)
                {
                    toContainerIDs.Add(toContainerID);
                }

                double startX = diagramExtent.XMin;

                startContainer.X = startX;
                startContainer.Y = startY;

                while (toContainerIDs.Count > 0)
                {
                    double y     = startY;
                    bool   first = true;

                    var toContainers = new List <CustomContainer>();
                    foreach (var containerID in toContainerIDs)
                    {
                        var toContainer = _graphModel.GetContainer(containerID);
                        if (startContainer.FromContainerOrder == Int32.MaxValue)
                        {
                            toContainers.Add(toContainer);
                        }
                    }

                    var sortedContainers = toContainers.OrderBy(cntr => cntr.FromContainerOrder + 0.001 * cntr.FromJunctionRankMin);

                    int vertivalOrder = 0;
                    foreach (var container in sortedContainers)
                    {
                        int containerID = container.Element.ID;

                        container.Y = y;

                        y -= (_graphModel.GetContainedElements(containerID).Count() * ySpacing + 7 * diagramInfo.ContainerMargin);

                        if (first)
                        {
                            first       = false;
                            container.X = startX + xSpacingMin;
                            startX      = container.X;
                        }
                        else
                        {
                            container.X = startX;
                        }

                        foreach (var toContainerID in container.ToContainers)
                        {
                            var toContainer = _graphModel.GetContainer(toContainerID);
                            if (toContainer.FromContainerOrder == Int32.MaxValue)
                            {
                                toContainer.FromContainerOrder = vertivalOrder;
                                toContainerIDs.Add(toContainerID);
                            }
                        }

                        vertivalOrder++;

                        toContainerIDs.Remove(containerID);
                    }
                }

                startY -= (_graphModel.GetContainedElements(startContainer.Element.ID).Count() * ySpacing + 4 * diagramInfo.ContainerMargin);
            }

            IList <DiagramJunctionElement> junctionsToSave = new List <DiagramJunctionElement>();

            SpatialReference spatialRef      = diagramInfo.DiagramExtent.SpatialReference;
            MapPointBuilder  mapPointBuilder = new MapPointBuilder(spatialRef)
            {
                Z = 0
            };

            foreach (var containerID in containerIDs)
            {
                var container = _graphModel.GetContainer(containerID);
                if (container == null)
                {
                    continue;
                }

                int rankCount = maxColorCount * maxColorCount;

                BitArray isEmpty = new BitArray(rankCount, true);

                double yTop = container.Y;

                var containedJunctions   = _graphModel.GetContainedElements(containerID);
                var unconnectedJunctions = new Stack <int>();

                foreach (var junctionID in containedJunctions)
                {
                    var junction = _graphModel.GetJunction(junctionID);
                    if (junction == null)
                    {
                        continue;
                    }

                    if (junction.Rank < 0)
                    {
                        unconnectedJunctions.Push(junction.Element.ID);
                        continue;
                    }

                    isEmpty[junction.Rank] = false;

                    mapPointBuilder.X      = container.X;
                    mapPointBuilder.Y      = yTop - junction.Rank * ySpacing;
                    junction.Element.Shape = mapPointBuilder.ToGeometry();

                    junctionsToSave.Add(junction.Element);
                }

                int rank = 0;
                while (unconnectedJunctions.Count > 0 && rank < rankCount)
                {
                    if (isEmpty[rank])
                    {
                        var junction = _graphModel.GetJunction(unconnectedJunctions.Pop());
                        if (junction != null)
                        {
                            mapPointBuilder.X      = container.X;
                            mapPointBuilder.Y      = yTop - rank * ySpacing;
                            junction.Element.Shape = mapPointBuilder.ToGeometry();
                            junctionsToSave.Add(junction.Element);
                        }
                    }
                    rank++;
                }
            }

            if (junctionsToSave.Count > 0)
            {
                NetworkDiagramSubset nds = new NetworkDiagramSubset
                {
                    DiagramJunctionElements = junctionsToSave
                };

                diagram.SaveLayout(nds, true);
            }
        }