OpenRoads Designer CONNECT Edition SDK Help

Vertical alignment reporter

Description

  • This is custom class for generating data related to vertical alignments(Profiles) from current dgn.

  • StationElevationsReport() method reads profiles and creates data of stations and elevations at an interval.

  • ProfileElementReport() method reads profiles and creates data of profiles and their elements.

  • ActiveStationElevationAtIntervalReport() method reads active profiles and creates data of stations and elevations at an interval also displays cardinal points.

Remarks

  • This sample code is a part of ManagedSDKExample which you get with SDK installation under "examples" section in SDK installation directory.

  • This code is simplified and does not include report generation code, but user can get it under ManagedSDKExample ->Examples ->VerticalAlignmentReporter

Source Code



//Required References
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bentley.DgnPlatformNET;
using Bentley.CifNET.GeometryModel.SDK;
using Bentley.CifNET.LinearGeometry;
using Bentley.CifNET.SDK;
using Bentley.CifNET.Formatting;

namespace ManagedSDKExample.Examples
{

    class VerticalAlignmentReporter
    {
        internal static DgnModel m_activeModel = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
        internal static double m_defaultUnitsToMeters = FormatSettingsConstants.GetMasterUnitsToMeters();

        /*------------------------------------------------------------------------------------**/
        /* Reads profiles and creates data of stations and elevations at an interval.
        /*--------------+---------------+---------------+---------------+---------------+------*/
        internal void StationElevationsReport()
        {
            ConsensusConnection sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
            if (sdkCon == null)
                return;

            GeometricModel geomModel = sdkCon.GetActiveGeometricModel();
            if (geomModel == null)
                return;

            StationFormatSettings settings = StationFormatSettings.GetStationFormatSettingsForModel(Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModelRef() as DgnModel);

            foreach (Alignment al in geomModel.Alignments)
            {
                if (!al.IsFinalElement)
                    continue;

                StationingFormatter formatter = new StationingFormatter(al);
                foreach (Profile profile in al.Profiles)
                {
                    if (!profile.IsFinalElement)
                        continue;

                    Dictionary<string, string> stations = new Dictionary<string, string>();
                    double interval = ConvertMasterToMeter(50.0);
                    int loopLength = (int)profile.ProfileGeometry.ProjectedLength; //convert to int to prevent crash
                    for (double station = 0.0; station < loopLength; station += interval)
                    {
                        string stnVal = "";
                        formatter.FormatStation(ref stnVal, station, settings);
                        string ElvVal = FormatDistance(profile.ProfileGeometry.GetYAtX(station));
                        stations.Add(stnVal, ElvVal);
                    }

                    string stnVal1 = "";
                    formatter.FormatStation(ref stnVal1, profile.ProfileGeometry.ProjectedLength, settings);
                    string ElvVal1 = FormatDistance(profile.ProfileGeometry.GetYAtX(profile.ProfileGeometry.ProjectedLength));
                    stations.Add(stnVal1, ElvVal1);
                }
            }
        }

        /*------------------------------------------------------------------------------------**/
        /* Reads active profiles and creates data of stations and elevations at an interval also displays cardinal points.
        /*--------------+---------------+---------------+---------------+---------------+------*/
        internal void ActiveStationElevationAtIntervalReport()
        {
            List<string> labels = new List<string>() { "Type", "Station", "Elevation" };
            SortedDictionary<double, string> data = new SortedDictionary<double, string>();
            double interval = ConvertMasterToMeter(50.0);
            StringBuilder sb = new StringBuilder();

            ConsensusConnection sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();

            if (sdkCon == null)
                return;

            GeometricModel geomModel = sdkCon.GetActiveGeometricModel();
            if (geomModel == null)
                return;

            Dictionary<string, string> header = new Dictionary<string, string>();
            header.Add("File Name", geomModel.DgnModel.GetDgnFile().GetFileName());
            header.Add("Model Name", geomModel.DgnModel.ModelName);

            StationFormatSettings settings = StationFormatSettings.GetStationFormatSettingsForModel(Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModelRef() as DgnModel);
            foreach (Alignment al in geomModel.Alignments)
            {
                if (!al.IsFinalElement)
                {
                    continue;
                }

                StationingFormatter formatter = new StationingFormatter(al);
                Profile activeProfile = al.ActiveProfile;

                data.Clear();
                sb.Clear();

                sb.Append("Horizontal Alignment: ");
                sb.Append(string.IsNullOrEmpty(al.Name) ? "Unnamed" : al.Name);
                sb.Append("Active Vertical Alignment Name: ");
                if (activeProfile != null)
                {
                    sb.Append(string.IsNullOrEmpty(activeProfile.Name) ? "Unnamed" : activeProfile.Name);
                }
                else
                {
                    sb.Append("No Active Vertical Alignment");
                }

                ProfileElement element = activeProfile?.ProfileGeometry;
                if (element != null)
                {
                    if (element is ProfileComplex)
                    {
                        ProfileComplex complex = element as ProfileComplex;
                        List<ProfileElement> subElements = complex.GetSubProfileElements().ToList();
                        for (int i = 0; i < subElements.Count; i++)
                        {
                            ProfileElement subElement = subElements[i];
                            if (subElement is ProfileCircularArc)
                            {
                                ProfileCircularArc arc = subElement as ProfileCircularArc;
                                if (i == 0)
                                {
                                    data.Add(arc.StartPoint.Coordinates.X, GetProfilePointData(element, "PVC", arc.StartPoint.Coordinates.X, settings, formatter));
                                }

                                data.Add(arc.VPIPoint.X, GetProfilePointData(element, "PVI", arc.VPIPoint.X, settings, formatter));

                                string pointType = GetVerticalPointType(subElements[i], ((i + 1 < subElements.Count) ? subElements[i + 1] : null));
                                data.Add(arc.EndPoint.Coordinates.X, GetProfilePointData(element, pointType, arc.EndPoint.Coordinates.X, settings, formatter));
                            }
                            else if (subElement is ProfileParabola)
                            {
                                ProfileParabola parabola = subElement as ProfileParabola;
                                if (i == 0)
                                {
                                    data.Add(parabola.StartPoint.Coordinates.X, GetProfilePointData(element, "PVC", parabola.StartPoint.Coordinates.X, settings, formatter));
                                }

                                data.Add(parabola.VPIPoint.X, GetProfilePointData(element, "PVI", parabola.VPIPoint.X, settings, formatter));

                                string pointType = GetVerticalPointType(subElements[i], ((i + 1 < subElements.Count) ? subElements[i + 1] : null));
                                data.Add(parabola.EndPoint.Coordinates.X, GetProfilePointData(element, pointType, parabola.EndPoint.Coordinates.X, settings, formatter));
                            }
                            else if (subElement is ProfileLine)
                            {
                                ProfileLine line = subElement as ProfileLine;
                                if (i == 0)
                                {
                                    data.Add(line.StartPoint.Coordinates.X, GetProfilePointData(element, "POB", line.StartPoint.Coordinates.X, settings, formatter));
                                }

                                string pointType = GetVerticalPointType(subElements[i], ((i + 1 < subElements.Count) ? subElements[i + 1] : null));
                                data.Add(line.EndPoint.Coordinates.X, GetProfilePointData(element, pointType, line.EndPoint.Coordinates.X, settings, formatter));
                            }
                        }
                    }
                    else
                    {
                        if (element is ProfileCircularArc)
                        {
                            ProfileCircularArc arc = element as ProfileCircularArc;
                            data.Add(arc.StartPoint.Coordinates.X, GetProfilePointData(element, "PVC", arc.StartPoint.Coordinates.X, settings, formatter));
                            data.Add(arc.VPIPoint.X, GetProfilePointData(element, "PVI", arc.VPIPoint.X, settings, formatter));
                            data.Add(arc.EndPoint.Coordinates.X, GetProfilePointData(element, "PVT", arc.EndPoint.Coordinates.X, settings, formatter));
                        }
                        else if (element is ProfileParabola)
                        {
                            ProfileParabola parabola = element as ProfileParabola;
                            data.Add(parabola.StartPoint.Coordinates.X, GetProfilePointData(element, "PVC", parabola.StartPoint.Coordinates.X, settings, formatter));
                            data.Add(parabola.VPIPoint.X, GetProfilePointData(element, "PVI", parabola.VPIPoint.X, settings, formatter));
                            data.Add(parabola.EndPoint.Coordinates.X, GetProfilePointData(element, "PVT", parabola.EndPoint.Coordinates.X, settings, formatter));
                        }
                        else if (element is ProfileLine)
                        {
                            ProfileLine line = element as ProfileLine;
                            data.Add(line.StartPoint.Coordinates.X, GetProfilePointData(element, "POB", line.StartPoint.Coordinates.X, settings, formatter));
                            data.Add(line.EndPoint.Coordinates.X, GetProfilePointData(element, "POE", line.EndPoint.Coordinates.X, settings, formatter));
                        }
                    }

                    for (double station = 0.0; station < element.ProjectedLength; station += interval)
                    {
                        if (!data.ContainsKey(station))
                        {
                            data.Add(station, GetProfilePointData(element, "Interval", station, settings, formatter));
                        }
                    }
                }
            }
        }

        /*------------------------------------------------------------------------------------**/
        /* Reads profiles and creates report of profiles and their elements.
        /*--------------+---------------+---------------+---------------+---------------+------*/
        internal void ProfileElementReport()
        {
            ConsensusConnection sdkCon = Bentley.CifNET.SDK.Edit.ConsensusConnectionEdit.GetActive();
            if (sdkCon == null)
                return;

            // Verify we can get the active profile model 
            GeometricModel gm = sdkCon.GetActiveGeometricModel();
            if (gm == null)
            {
                return;
            }

            StationFormatSettings settings = StationFormatSettings.GetStationFormatSettingsForModel(Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModelRef() as DgnModel);
            foreach (Alignment al in gm.Alignments)
            {
                if (!al.IsFinalElement)
                    continue;

                StationingFormatter formatter = new StationingFormatter(al);
                foreach (Profile profile in al.Profiles)
                {
                    if (!profile.IsFinalElement)
                        continue;

                    // Read Profile Geometry Information and Generate Report
                    Dictionary<string, string> profileProperties = new Dictionary<string, string>();
                    if (profile.ProfileGeometry is ProfileComplex)
                    {
                        ProfileComplex complex = profile.ProfileGeometry as ProfileComplex;
                        foreach (ProfileElement ele in complex.GetSubProfileElements())
                            ReportProfileElement(ele, settings, formatter);
                    }
                    else
                        ReportProfileElement(profile.ProfileGeometry, settings, formatter);
                }
            }
        }

        // Report Profile Element Based on Type
        private Dictionary<string, string> ReportProfileElement(ProfileElement ele, StationFormatSettings settings, StationingFormatter format)
        {

            Dictionary<string, string> properties = new Dictionary<string, string>();
            properties.Add("Type", ele.GetType().Name);
            if (ele is ProfileLine)
                ReportProfileLine(ele as ProfileLine, settings, format, properties);
            else if (ele is ProfileParabola)
                ReportProfileParabola(ele as ProfileParabola, settings, format, properties);

            return properties;
        }

        // Report Linear Profile Elements
        private void ReportProfileLine(ProfileLine ele, StationFormatSettings settings, StationingFormatter format, Dictionary<string, string> properties)
        {
            ReportProfilePoint("PVT", ele.StartPoint.Coordinates, settings, format, properties);
            ReportProfilePoint("PVC", ele.EndPoint.Coordinates, settings, format, properties);
            properties.Add("Tangent Grade", FormatGrade(ele.Slope));
            properties.Add("Tangent Length", FormatDistance(ele.ProjectedLength));
        }

        // Report Parabola Profile Elements 
        private void ReportProfileParabola(ProfileParabola ele, StationFormatSettings settings, StationingFormatter format, Dictionary<string, string> properties)
        {
            ReportProfilePoint("PVC", ele.StartPoint.Coordinates, settings, format, properties);
            ReportProfilePoint("PVI", ele.VPIPoint, settings, format, properties);
            ReportProfilePoint("PVT", ele.EndPoint.Coordinates, settings, format, properties);

            double projectedLeftLength = ele.VPIPoint.X - ele.StartPoint.Coordinates.X;
            double projectedRightLength = ele.EndPoint.Coordinates.X - ele.VPIPoint.X;
            LinearPoint summit = ele.SummitPoint;
            if (summit != null &&
                Math.Sign(ele.StartSlope) != Math.Sign(ele.EndSlope) &&
                projectedLeftLength != 0.0 &&
                projectedRightLength != 0.0 &&
                (ele.StartSlope - ele.EndSlope) != 0.0 &&
                (ele.EndSlope - ele.StartSlope) != 0.0)
            {
                if (ele.EndSlope - ele.StartSlope > 0.0)
                    ReportProfilePoint("VLOW", summit.Coordinates, settings, format, properties);
                else
                    ReportProfilePoint("VHIGH", summit.Coordinates, settings, format, properties);
            }

            properties.Add("Length", FormatDistance(ele.ProjectedLength));
            properties.Add("Entrance Grade", FormatGrade(ele.StartSlope));
            properties.Add("Exit Grade", FormatGrade(ele.EndSlope));
            double projectedLength = ConvertMeterToMaster(ele.ProjectedLength);
            properties.Add("r = (g2 - g1) / L", FormatNumber(projectedLength == 0.0 ? 0.0 : 100 * ((ele.EndSlope - ele.StartSlope) / (projectedLength / 100.0))));
            properties.Add("K = l / (g2 - g1)", FormatDistance(Math.Abs(ele.KValue)));
            if (ele.ProjectedLength != 0.0 && projectedLeftLength != 0.0 && projectedRightLength != 0.0)
            {
                double middleOrdinate = 0.0;
                if (Math.Abs(projectedLeftLength - projectedRightLength) < 0.0001)
                    middleOrdinate = ((ele.EndSlope - ele.StartSlope) / 8.0) * ele.ProjectedLength;
                else
                    middleOrdinate = ((ele.EndSlope - ele.StartSlope) / (2.0 * projectedLeftLength * projectedRightLength)) * projectedLeftLength * projectedRightLength;
                properties.Add("Middle Ordinate", FormatDistance(middleOrdinate));
            }
        }

        // Report Points
        private void ReportProfilePoint(string pointType, Bentley.GeometryNET.DPoint3d point, StationFormatSettings settings, StationingFormatter format, Dictionary<string, string> properties)
        {
            string station = string.Empty;
            format.FormatStation(ref station, point.X, settings);
            string elevation = FormatDistance(point.Y);
            properties.Add(pointType, "Station: " + station + " | Elevation: " + elevation);
        }

        // Get formatted point data
        private string GetProfilePointData(ProfileElement element, string pointType, double station, StationFormatSettings settings, StationingFormatter formatter)
        {
            string stationValue = "";
            formatter.FormatStation(ref stationValue, station, settings);
            string elevationValue = FormatDistance(ConvertMeterToMaster(element.GetYAtX(station)));

            return string.Format("{0}|{1}|{2}", pointType, stationValue, elevationValue);
        }

       
       

        /*------------------------------------------------------------------------------------**/
        /* Conversion
        /*--------------+---------------+---------------+---------------+---------------+------*/
        public static double ConvertMasterToMeter(double num)
        {
            return num * m_defaultUnitsToMeters;
        }
        public static double ConvertMeterToMaster(double num)
        {
            return num / m_defaultUnitsToMeters;
        }
        public static string FormatDistance(double value)
        {
            return FormatForDisplay.Distance(value, m_activeModel, 3);
        }
        /*------------------------------------------------------------------------------------**/
        /* Point type calculations
        /*--------------+---------------+---------------+---------------+---------------+------*/
        public static string GetVerticalPointType(ProfileElement element1, ProfileElement element2)
        {
            string pointType = string.Empty;

            if (element1 != null && element2 != null) //interior element
            {
                if (element1 is ProfileCircularArc)
                {
                    if (element2 is ProfileLine)
                    {
                        pointType = "PVT";
                    }
                    else
                    {
                        ProfileCircularArc arc = element1 as ProfileCircularArc;
                        double curvature1 = arc.Radius > 0.0 ? 1.0 : -1.0;
                        double curvature2 = 0.0;
                        if (element2 is ProfileCircularArc)
                        {
                            ProfileCircularArc next = element2 as ProfileCircularArc;
                            curvature2 = next.Radius > 0.0 ? 1.0 : -1.0;
                        }
                        else if (element2 is ProfileParabola)
                        {
                            ProfileParabola next = element2 as ProfileParabola;
                            double projectedLength = ConvertMeterToMaster(next.ProjectedLength);
                            double rateOfChange = (projectedLength == 0.0) ? 0.0 : (next.EndSlope - next.StartSlope) / (projectedLength / 100.0);
                            curvature2 = rateOfChange > 0.0 ? 1.0 : -1.0;
                        }
                        pointType = (curvature1 * curvature2 >= 0.0) ? "PVCC" : "PVRC";
                    }
                }
                else if (element1 is ProfileLine)
                {
                    if (element2 is ProfileCircularArc || element2 is ProfileParabola)
                    {
                        pointType = "PVC";
                    }
                    else if (element2 is ProfileLine)
                    {
                        pointType = "PVI";
                    }
                }
                else if (element1 is ProfileParabola)
                {
                    if (element2 is ProfileLine)
                    {
                        pointType = "PVT";
                    }
                    else
                    {
                        ProfileParabola parabola = element1 as ProfileParabola;
                        double projectedLength = ConvertMeterToMaster(parabola.ProjectedLength);
                        double rateOfChange = (projectedLength == 0.0) ? 0.0 : (parabola.EndSlope - parabola.StartSlope) / (projectedLength / 100.0);
                        double curvature1 = rateOfChange > 0.0 ? 1.0 : -1.0;
                        double curvature2 = 0.0;
                        if (element2 is ProfileCircularArc)
                        {
                            ProfileCircularArc next = element2 as ProfileCircularArc;
                            curvature2 = next.Radius > 0.0 ? 1.0 : -1.0;
                        }
                        else if (element2 is ProfileParabola)
                        {
                            ProfileParabola next = element2 as ProfileParabola;
                            projectedLength = ConvertMeterToMaster(next.ProjectedLength);
                            rateOfChange = (projectedLength == 0.0) ? 0.0 : (next.EndSlope - next.StartSlope) / (projectedLength / 100.0);
                            curvature2 = rateOfChange > 0.0 ? 1.0 : -1.0;
                        }
                        pointType = (curvature1 * curvature2 >= 0.0) ? "PVCC" : "PVRC";
                    }
                }
            }
            else if (element1 != null) //Last element
            {
                if (element1 is ProfileCircularArc || element2 is ProfileParabola)
                {
                    pointType = "PVT";
                }
                else if (element1 is ProfileLine)
                {
                    pointType = "POE";
                }
            }
            else if (element2 != null) //First element
            {
                if (element2 is ProfileCircularArc || element2 is ProfileParabola)
                {
                    pointType = "PVC";
                }
                else if (element2 is ProfileLine)
                {
                    pointType = "POB";
                }
            }

            return pointType;
        }
        public static string FormatGrade(double value)
        {
            string grade = FormatForDisplay.Double(100 * value); 
            return grade + "%";
        }
        public static string FormatNumber(double num)
        {
            return FormatForDisplay.Double(num);
        }
    }
}