//Tool to place Cogo Points along an Alignment at a Profile's even number elevations (120, 121, 122, 123, etc)
// by Jeff Mishler @ Quux Software
// Feb. 18, 2017 Provided as an example of how to get specific elevations of a profile.
// May be freely used and/or modified, providing this header stays intact
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil.ApplicationServices;
using Autodesk.Civil.DatabaseServices;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Civil3D_Misc_Commands.Profiles
{
public static class ProfileTools
{
[CommandMethod("ProfileLevels")]
public static void profilelvelscommand()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
CivilDocument civdoc = CivilApplication.ActiveDocument;
PromptEntityOptions entOpts
= new PromptEntityOptions
("Select Profile:"); entOpts.SetRejectMessage("...not a Profile, try again.");
entOpts
.AddAllowedClass(typeof(Profile
),
true); PromptEntityResult entRes = ed.GetEntity(entOpts);
if (entRes.Status != PromptStatus.OK)
return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
var prof = (Profile)tr.GetObject(entRes.ObjectId, OpenMode.ForRead);
var minElev = Math.Floor(prof.ElevationMin) + 1;
var maxElev = Math.Floor(prof.ElevationMax);
var profEnts = prof.Entities;
var output
= new List
<ProfileStationElevation
>(); for (double elev = minElev; elev <= maxElev; elev++)
{
foreach (ProfileEntity ent in profEnts)
{
var e1 = ent.StartElevation;
var e2 = ent.EndElevation;
var lowpt = Math.Min(e1, e2);
var highPt = Math.Max(e1, e2);
var highlow = double.NaN;
var pse
= new ProfileStationElevation
(); var x1 = double.NaN;
var x2 = double.NaN;
var g1 = double.NaN;
var g2 = double.NaN;
var L = double.NaN;
switch (ent.EntityType)
{
case ProfileEntityType.Tangent:
if (!(elev > lowpt && elev < highPt))
continue;
var l = (elev - e1) / prof.GradeAt(ent.StartStation + 0.01);
pse
= new ProfileStationElevation
(); pse.Elevation = elev;
pse.Station = ent.StartStation + l;
output.Add(pse);
break;
case ProfileEntityType.Circular:
var crvEnt = (ProfileCircular)ent;
highlow = crvEnt.HighLowPointElevation;
lowpt = Math.Min(highlow, lowpt);
highPt = Math.Max(highlow, highPt);
if (!(elev > lowpt && elev < highPt))
continue;
//NEED FORMULA TO CALC LOCATION OF SPECIFIC ELEVATION ON CIRCULAR CURVE, using parabolic calc for now
g1 = crvEnt.GradeIn;
g2 = crvEnt.GradeOut;
L = crvEnt.Length;
x1 = ((g1 * L) + Math.Sqrt((L * ((-2 * elev * g1) + (2 * elev * g2) + ((g1 * g1) * L) + (2 * g1 * e1) - (2 * g2 * e1))))) / (g1 - g2);
x2 = ((g1 * L) - Math.Sqrt((L * ((-2 * elev * g1) + (2 * elev * g2) + ((g1 * g1) * L) + (2 * g1 * e1) - (2 * g2 * e1))))) / (g1 - g2);
if (x1 > 0)
{
pse
= new ProfileStationElevation
(); pse.Station = crvEnt.StartStation + x1;
pse.Elevation = elev;
output.Add(pse);
}
if (x2 > 0)
{
pse
= new ProfileStationElevation
(); pse.Station = crvEnt.StartStation + x2;
pse.Elevation = elev;
output.Add(pse);
}
break;
case ProfileEntityType.ParabolaAsymmetric:
var crvAsymEnt = (ProfileParabolaAsymmetric)ent;
highlow = crvAsymEnt.HighLowPointElevation;
lowpt = Math.Min(highlow, lowpt);
highPt = Math.Max(highlow, highPt);
if (!(elev > lowpt && elev < highPt))
continue;
//NEED FORMULA TO CALC LOCATION OF SPECIFIC ELEVATION ON ASYMMETRICAL PARABOLIC CURVE
break;
case ProfileEntityType.ParabolaSymmetric:
var crvSymEnt = (ProfileParabolaSymmetric)ent;
highlow = crvSymEnt.HighLowPointElevation;
lowpt = Math.Min(highlow, lowpt);
highPt = Math.Max(highlow, highPt);
if (!(elev > lowpt && elev < highPt))
continue;
g1 = crvSymEnt.GradeIn;
g2 = crvSymEnt.GradeOut;
L = crvSymEnt.Length;
x1 = ((g1 * L) + Math.Sqrt((L * ((-2 * elev * g1) + (2 * elev * g2) + ((g1 * g1) * L) + (2 * g1 * e1) - (2 * g2 * e1))))) / (g1 - g2);
x2 = ((g1 * L) - Math.Sqrt((L * ((-2 * elev * g1) + (2 * elev * g2) + ((g1 * g1) * L) + (2 * g1 * e1) - (2 * g2 * e1))))) / (g1 - g2);
if (x1 > 0)
{
pse
= new ProfileStationElevation
(); pse.Station = crvSymEnt.StartStation + x1;
pse.Elevation = elev;
output.Add(pse);
}
if (x2 > 0)
{
pse
= new ProfileStationElevation
(); pse.Station = crvSymEnt.StartStation + x2;
pse.Elevation = elev;
output.Add(pse);
}
break;
default:
//SHOULDN'T GET TO HERE
break;
}
}
}
output = output.OrderBy(s => s.Station).ToList();
var align = (Alignment)tr.GetObject(prof.AlignmentId, OpenMode.ForRead);
double east = 0, north = 0;
var points = CivilApplication.ActiveDocument.CogoPoints;
foreach (var pair in output)
{
align.PointLocation(pair.Station, 0, ref east, ref north);
var pt
= points
.Add(new Point3d
(east, north, pair
.Elevation),
true); ed.WriteMessage("\nStation: {0}, Elev: {1}", pair.Station.ToStationString(), pair.Elevation.ToString("F2"));
}
tr.Commit();
}
}
public static string ToStationString(this double Value)
{
var civdoc = Autodesk.Civil.ApplicationServices.CivilApplication.ActiveDocument;
var stasettings = civdoc.Settings.DrawingSettings.AmbientSettings.Station;
var stationstring = Value.ToString("F" + stasettings.Precision.Value);
var symbolposition = stasettings.StationDelimiterPosition.Value;
switch (stasettings.StationDelimiterPosition.Value)
{
case Autodesk.Civil.StationDelimiterPositionType.Delimiter10:
stationstring = stationstring.Insert(stationstring.IndexOf('.') - 1, "+");
break;
case Autodesk.Civil.StationDelimiterPositionType.Delimiter100:
stationstring = stationstring.Insert(stationstring.IndexOf('.') - 2, "+");
break;
case Autodesk.Civil.StationDelimiterPositionType.Delimiter1000:
stationstring = stationstring.Insert(stationstring.IndexOf('.') - 3, "+");
break;
case Autodesk.Civil.StationDelimiterPositionType.Delimiter10000:
stationstring = stationstring.Insert(stationstring.IndexOf('.') - 4, "+");
break;
case Autodesk.Civil.StationDelimiterPositionType.Delimiter100000:
stationstring = stationstring.Insert(stationstring.IndexOf('.') - 5, "+");
break;
}
return stationstring;
}
}
public class ProfileStationElevation
{
public double Station = double.NaN;
public double Elevation = double.NaN;
public ProfileStationElevation()
{
}
}
}