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
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);
}
}
}