Here's an example that was quickly adapted from a jig I've used to obtain a point that lies on any type of Curve. You can use a LineSegment3d as the curve argument to get a point on that line that's perpendicular to the current cursor location.
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
namespace AcMgdLib.Geometry
{
/// <summary>
/// Acquires a point that is constrained to be
/// on a curve, perpendicular/nearest to the
/// selected point.
/// </summary>
public class PointOnCurveJig : DrawJig
{
Curve3d curve;
bool flag = false;
Point3d last = Point3d.Origin;
Point3d basePoint;
string message;
public PointOnCurveJig(Curve3d curve, string message = null)
{
this.curve = curve;
this.basePoint = curve.StartPoint;
this.message = message ?? "\nPoint on curve: ";
}
/// <summary>
/// The resulting point on the Curve3d that
/// was passed to the constructor.
/// </summary>
public Point3d PointOnCurve => basePoint;
/// <summary>
/// The other endpoint of the perpendicular
/// line, that was picked by the user.
/// </summary>
public Point3d PickedPoint => last;
protected override SamplerStatus Sampler(JigPrompts prompts)
{
var options = new JigPromptPointOptions();
options.Message = this.message;
options.UserInputControls = UserInputControls.UseBasePointElevation;
options.Cursor = CursorType.RubberBand;
options.UseBasePoint = true;
options.BasePoint = basePoint;
PromptPointResult ppr;
using(new SystemVariable("ORTHOMODE", 0))
{
ppr = prompts.AcquirePoint(options);
}
if(ppr.Status == PromptStatus.OK)
{
last = ppr.Value;
basePoint = curve.GetClosestPointTo(last).Point;
return SamplerStatus.OK;
}
return SamplerStatus.Cancel;
}
protected override bool WorldDraw(WorldDraw draw)
{
return true;
}
[CommandMethod("POINTONCURVEJIG")]
public static void PointOnCurveJigExample()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var ed = doc.Editor;
var peo = new PromptEntityOptions("\nSelect a curve: ");
peo.SetRejectMessage("\nInvalid, requires a Curve");
peo.AddAllowedClass(typeof(Curve), false);
var per = ed.GetEntity(peo);
if(per.Status != PromptStatus.OK)
return;
Curve3d curve3d;
using(var tr = new OpenCloseTransaction())
{
var curve = (Curve)tr.GetObject(per.ObjectId, OpenMode.ForRead);
curve3d = curve.GetGeCurve();
tr.Commit();
}
var jig = new PointOnCurveJig(curve3d);
var res = doc.Editor.Drag(jig);
if(res.Status == PromptStatus.OK)
{
using(new SystemVariable("OSMODE", 0))
{
ed.Command("._LINE", jig.PointOnCurve, jig.PickedPoint, "");
}
}
}
}
public class SystemVariable : IDisposable
{
string name;
object value;
public SystemVariable(string name, object value)
{
this.value = Application.GetSystemVariable(name);
this.name = name;
Application.SetSystemVariable(name, value);
}
public void Dispose()
{
if(value != null)
{
Application.SetSystemVariable(name, value);
value = null;
}
}
}
}