Using this code I was able to get the index for the segment that was clicked on by the user. Which in turn means I was able to get the LineSegment3d object and print out the length, a good start!
[CommandMethod("SegmentTest")]
public void SegmentTest()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
var selection = ed.GetEntity(new PromptEntityOptions($"\nSelect CFA line:")
{
AllowNone = false,
AllowObjectOnLockedLayer = false,
});
if(selection.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
using(Polyline pline = tr.GetObject(selection.ObjectId, OpenMode.ForRead) as Polyline)
{
var nearest = pline.GetClosestPointTo(selection.PickedPoint, true);
var segmentIndex = pline.FindSegmentIndex(nearest);
if (segmentIndex < 0) return;
var segmentType = pline.GetSegmentType(segmentIndex);
switch (segmentType)
{
case SegmentType.Line:
var segment = pline.GetLineSegmentAt(segmentIndex);
Active.WriteMessage($"{segment.Length}");
break;
case SegmentType.Arc:
break;
case SegmentType.Coincident:
break;
case SegmentType.Point:
break;
case SegmentType.Empty:
break;
default:
break;
}
}
}
public static int FindSegmentIndex(this Polyline polyline, Point3d point)
{
for (int i = 0; i < polyline.NumberOfVertices - 1; i++)
{
// Get the start and end points of the current segment
Point3d startPoint = polyline.GetPoint3dAt(i);
Point3d endPoint = polyline.GetPoint3dAt(i + 1);
// Check if the closest point lies on this segment
if (point.IsPointBetween(startPoint, endPoint))
{
return i; // Return the index of the segment
}
}
// If no segment is found (which shouldn't happen), return -1
return -1;
}
public static bool IsPointBetween(this Point3d vertex, Point3d point1, Point3d point2)
{
// Check if the vertex is collinear with point1 and point2
Vector3d mainVector = point2 - point1;
Vector3d vertexVector = vertex - point1;
// Calculate the cross product to check collinearity
double crossProduct = mainVector.CrossProduct(vertexVector).Length;
if (crossProduct > 1e-6) // Allowing a small tolerance for floating-point precision
return false;
// Check if the vertex is within the bounds of the segment
double dotProduct = mainVector.DotProduct(vertexVector);
if (dotProduct < 0 || dotProduct > mainVector.LengthSqrd)
return false;
return true;
}