ArcFM Desktop Developer Guide
Export Cables to OHDA

Resource Center Home

Out of the box, Overhead Design Analysis (OHDA) provides a user interface to export ArcFM cables for use in OHDA models. The default behavior is for an administrator to add the NOMINALVOLTAGE, PHASEDESIGNATION, NEUTRALSIZE, and NEUTRALMATERIAL field model names to the OVERHEADCONDUCTOR Feature Class, and the CONDUCTORSIZE and CONDUCTORMATERIAL field model names to the CONDUCTORINFO Related Object class in the geodatabase for OHDA to consume.  You can programmatically create custom logic to change the field model name or control how assembly descriptions are processed, and the out-of-the-box user interface will utilize this custom logic. The code snippet below demonstrates how this works.

If your data model does not match this structure, you can modify the code sample and use it to extract this information from your database and send it to OHDA for analysis. These data extractors are used when you use the Export to Overhead Design and Analysis tool in ArcMap to extract these fields out of the poles and cables.

Cables poles with custom data miners for OHDA must be located in the bin directory where the OHDA files are installed. You can verify where this folder is by checking your registry key:

Export Cables
Copy Code
using System;
using Miner.Desktop.StructuralAnalysis;
using Miner.Geodatabase;
using Miner.Interop;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.esriSystem;
using System.Text.RegularExpressions;
using System.ComponentModel.Composition;
namespace OHDADataMinerSample
{
    [Export(typeof(IGISCableModel))]
    public class SampleGISCableModel : IGISCableModel
    {
        private static readonly log4net.ILog _log = log4net.LogManager.GetLogger("Miner.StructuralAnalysis");
        #region IMMGISCableModel Members
        private string _gisMatchingString;
        public string GISMatchingString
        {
            get { return _gisMatchingString; }
        }
        private string _GISNeutralMatchingString;
        public string GISNeutralMatchingString
        {
            get { return _GISNeutralMatchingString; }
        }
        private string _voltageName;
        public string VoltageName
        {
            get { return _voltageName; }
        }

        private double _voltageValue;
        public double VoltageValue
        {
            get
            {
                return _voltageValue;
            }
        }
        private bool _phaseA;
        public bool PhaseA { get { return _phaseA; } }
        private bool _phaseB;
        public bool PhaseB { get { return _phaseB; } }
        private bool _phaseC;
        public bool PhaseC { get { return _phaseC; } }
        private string _className;
        public string ClassName
        {
            get { return _className; }
        }
        public void Hydrate(IFeature cableFeature)
        {
            IFeatureClass featureClass = cableFeature.Class as IFeatureClass;
            IMMModelNameManager modelNameManager = ModelNameManager.Instance;
            bool hasConductorInfoModelName = false;
            _className = featureClass.AliasName;
            IField voltageField = modelNameManager.FieldFromModelName(cableFeature.Class, ModelNames.NominalVoltageField);
            if (voltageField == null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug("Unable to Hydrate Cable feature: <" + cableFeature.Class.AliasName + "> because the <" + ModelNames.NominalVoltageField + "> Field Model Name was not found on any available fields.");
                }
            }
            int voltageFieldIndex = cableFeature.Class.FindField(voltageField.Name);
            object voltageFieldValue = cableFeature.get_Value(voltageFieldIndex);
            if (voltageFieldValue != null && !DBNull.Value.Equals(voltageFieldValue))
            {
                ICodedValueDomain valueDomain = voltageField.Domain as ICodedValueDomain;
                if (valueDomain != null)
                {
                    for (int i = 0; i < valueDomain.CodeCount; i++)
                    {
                        if (valueDomain.get_Value(i).Equals(voltageFieldValue))
                        {
                            _voltageName = valueDomain.get_Name(i);
                            _voltageValue = GenerateVoltageDouble(valueDomain.get_Name(i));
                            if (_voltageValue == 0)
                            {
                                //No double were found in voltage field
                                _voltageValue = -1;
                            }
                            break;
                        }
                    }
                }
                else
                {
                    _voltageName = voltageFieldValue.ToString();
                }
            }
            IField phaseDesignationField = modelNameManager.FieldFromModelName(cableFeature.Class, ModelNames.PhaseDesignationField);
            if (phaseDesignationField == null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug("Unable to Hydrate Cable feature: <" + cableFeature.Class.AliasName + "> because the <" + ModelNames.PhaseDesignationField + "> Field Model Name was not found on any available fields.");
                }
            }
            int phaseDesignationFieldIndex = cableFeature.Class.FindField(phaseDesignationField.Name);
            object phaseDesignationFieldValue = cableFeature.get_Value(phaseDesignationFieldIndex);
            if (phaseDesignationFieldValue != null && !DBNull.Value.Equals(phaseDesignationFieldValue))
            {
                if (phaseDesignationFieldValue is int)
                {
                    // phase C is bit position 1, (phaseDesignationFieldValue & 1) != 0 means C is present
                    _phaseC = ((int)phaseDesignationFieldValue & 1) != 0;
                    // phase B is bit position 2, (phaseDesignationFieldValue & 2) != 0 means B is present
                    _phaseB = ((int)phaseDesignationFieldValue & 2) != 0;
                    // phase A is bit position 3, (phaseDesignationFieldValue & 4) != 0 means A is present
                    _phaseA = ((int)phaseDesignationFieldValue & 4) != 0;
                }
            }
            string neutralMaterial = GetStringfieldValue(cableFeature, ModelNames.NeutralMaterialField);
            string neutralSize = GetStringfieldValue(cableFeature, ModelNames.NeutralSizeField);
            _GISNeutralMatchingString = neutralMaterial + neutralSize;
            IEnumRelationshipClass cableRelationshipClasses = featureClass.get_RelationshipClasses(esriRelRole.esriRelRoleOrigin);
            cableRelationshipClasses.Reset();
            IRelationshipClass cableRelationshipClass = cableRelationshipClasses.Next();
            while (cableRelationshipClass != null)
            {
                if (modelNameManager.ContainsClassModelName(cableRelationshipClass.DestinationClass, ModelNames.ConductorInfo))
                {
                    hasConductorInfoModelName = true;
                    ISet relatedCableInfos = cableRelationshipClass.GetObjectsRelatedToObject(cableFeature);
                    relatedCableInfos.Reset();
                    IObject cableInfo = relatedCableInfos.Next() as IObject;
                    while (cableInfo != null)
                    {
                        string size = GetStringfieldValue(cableInfo, ModelNames.ConductorSizeField);
                        string material = GetStringfieldValue(cableInfo, ModelNames.ConductorMaterialField);
                        // find matching cable spec and add it to the list of matching cable specs
                        _gisMatchingString = material + size;
                        cableInfo = relatedCableInfos.Next() as IObject;
                    }
                    break;
                }
                cableRelationshipClass = cableRelationshipClasses.Next();
            }
            if (!hasConductorInfoModelName)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug("Unable to properly Hydrate Feature: <" + cableFeature.Class.AliasName + "> because no <" + ModelNames.ConductorInfo + "> Model Name was found.");
                }
            }
        }
        #endregion
        private string GetStringfieldValue(IObject cableObject, string modelName)
        {
            IMMModelNameManager modelNameManager = ModelNameManager.Instance;
            string value = "";
            IField field = modelNameManager.FieldFromModelName(cableObject.Class, modelName);
            if (field == null)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.Debug("Unable to GetStringFieldValue for cable: <" + cableObject.Class.AliasName + "> because no <" + modelName + "> Field Model Name was found on any available fields.");
                }
            }
            int fieldIndex = cableObject.Class.FindField(field.Name);
            object fieldValue = cableObject.get_Value(fieldIndex);
            if (fieldValue != null && !DBNull.Value.Equals(fieldValue))
            {
                value = fieldValue.ToString();
            }
            return value;
        }
        private double GenerateVoltageDouble(string voltageName)
        {
            double resultValue = FindMaxValueUsingRegex(voltageName);
            double multiplier = FindMulitilpierUsingRegex(voltageName);
            return resultValue * multiplier;
        }

        private double FindMulitilpierUsingRegex(string input)
        {
            string lowerInput = input.ToLower();
            if (lowerInput.Contains("kv"))
            {
                return 1000;
            }
            else
            {
                return 1;
            }
        }
        private double FindMaxValueUsingRegex(string input)
        {
            double max = 0;
            string pattern = @"\d*[\.\d*]*";
            Regex expressionEvaluator = new Regex(pattern);
            foreach (Match match in expressionEvaluator.Matches(input))
            {
                double foundDouble = -1;
                double.TryParse(match.Value, out foundDouble);
                if (foundDouble > max)
                {
                    max = foundDouble;
                }
            }
            return max;
        }
    }
}

 

 


Send Comment to ArcFMdocumentation@schneider-electric.com