By Augusto Goncalves (@augustomaia)
First, from the AutoCAD Civil 3D Knowledge Network, review the topic About Spiral Definitions. The following image summarize the article. We’re interested in start direction from Spiral In and end direction at Spiral Out.
At the API we have the AlignmentSCS object with only the direction, which is actually an angle, at the SpiralIn.StartDirection and SpiralOut.EndDirection properties.
Now let’s have some fun with the math piece: the direction vector is the Sin and Cos of this direction (which is actually the tangent). Here an image definition from Wikipedia:
From this definition we can create a Vector2d at both ends (SpiralIn.StartDirection and SpiralOut.EndDirection), then use Line2d to create lines and, finally, the intersection. Here is the code:
public static Point2d PI(this AlignmentSCS scs)
{
// vector at SpiralIn.StartDirection
Vector2d vectorIn = new Vector2d(
Math.Sin(scs.SpiralIn.StartDirection),
Math.Cos(scs.SpiralIn.StartDirection));
// vector at SpirtalOut.EndDirection
// negate to get the inner vector
// redundant as the line is infinite
Vector2d vectorOut = new Vector2d(
Math.Sin(scs.SpiralOut.EndDirection),
Math.Cos(scs.SpiralOut.EndDirection)).Negate();
// create line from start
using (Line2d lineIn = new Line2d(
scs.SpiralIn.StartPoint, vectorIn))
{
// and create line from end
using (Line2d lineOut = new Line2d(
scs.SpiralOut.EndPoint, vectorOut))
{
// now find the intersection
Point2d[] intersectPoints = lineIn.IntersectWith(lineOut);
// some minor error check
if (intersectPoints == null || intersectPoints.Length == 0)
throw new Autodesk.Civil.CivilException(
"Could not find PI for this SCS");
// should be just one point, return it
return intersectPoints[0];
}
}
}
We can use this method with Extension, as it was declared with this. Below is a command method that uses it:
[CommandMethod("getSCSPI")]
public static void CmdGetSCSPI()
{
// minimum error check...
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
ObjectId id = ed.GetEntity("Select alignment: ").ObjectId;
Database db = Application.DocumentManager.MdiActiveDocument.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Alignment align = tr.GetObject(id, OpenMode.ForRead) as Alignment;
if (align == null) return;
foreach (AlignmentEntity alignEnt in align.Entities)
{
// for this test, just SCS, skip others
if (alignEnt.EntityType !=
AlignmentEntityType.SpiralCurveSpiral) continue;
// finally get the PI (using the extension method)
AlignmentSCS scs = alignEnt as AlignmentSCS;
Point2d scsPI = scs.PI();
// let's add a point to Model Space
DBPoint newPointAtSCS = new DBPoint(
new Point3d(new Plane(), scsPI));
BlockTableRecord mSpace = tr.GetObject(
SymbolUtilityServices.GetBlockModelSpaceId(db),
OpenMode.ForWrite) as BlockTableRecord;
mSpace.AppendEntity(newPointAtSCS);
tr.AddNewlyCreatedDBObject(newPointAtSCS, true);
}
tr.Commit();
}
}