Here's a way.
static Point3d GetCentralPoint(Point3d ptA, Point3d ptB, Vector3d direction)
{
var normal = direction.CrossProduct(ptA.GetVectorTo(ptB));
if (normal.Length == 0.0)
return ptA + ptA.GetVectorTo(ptB) / 2.0;
var plane = new Plane(ptA, normal);
var ptA2d = ptA.Convert2d(plane);
var ptB2d = ptB.Convert2d(plane);
var segmentAB = new LineSegment2d(ptA2d, ptB2d);
var axis = new Line2d(segmentAB.MidPoint, segmentAB.Direction.GetPerpendicularVector());
var dirA = direction.Convert2d(plane);
var dirB = dirA.TransformBy(Matrix2d.Mirroring(axis));
var ptCen2d = new Line2d(ptA2d, dirA).IntersectWith(new Line2d(ptB2d, dirB))[0];
return new Point3d(ptCen2d.X, ptCen2d.Y, 0.0).TransformBy(Matrix3d.PlaneToWorld(plane));
}
A testing command
[CommandMethod("TEST")]
public void Test()
{
var doc = AcAp.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var ppo = new PromptPointOptions("\nSpecify first point: ");
var ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK)
return;
var ptA = ppr.Value;
ppo.Message = "\nSpecify second point: ";
ppo.UseBasePoint = true;
ppo.BasePoint = ptA;
ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK)
return;
var ptB = ppr.Value;
ppo.Message = "\nSpecify direction: ";
ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK)
return;
var dir = ptA.GetVectorTo(ppr.Value);
var ptCen = GetCentralPoint(ptA, ptB, dir);
ed.Command("_point", ptCen);
}