I have a nice isleft function for 3 2dpoints but I never really had one for 3d points,
so I thought I would make a plane and convert the points to 2d using that.
The problem with the plane is that if it has a negative normal it negates the 2d formula, then I realised that the normal gives all the info required. So far it tests fine. The plane formula does require a linear check (see below) as it gives weird results otherwise
public static Vector3d NormalFromPoints(Point3d P1,Point3d P2,Point3d P3)
{
//Check for linear as this function doesn't handle it
if(P1.GetVectorTo(P2).GetNormal()==P1.GetVectorTo(P3).GetNormal())
return new Vector3d (0,0,0);
//n = u×v = (V1-V0)×(V2-V0)
double Unit,x1,x2,x3,y1,y2,y3,n1,n2,n3;
//Get distance from zero
x1 = P2.X - P1.X; y1 = P3.X - P1.X;
x2 = P2.Y - P1.Y; y2 = P3.Y - P1.Y;
x3 = P2.Z - P1.Z; y3 = P3.Z - P1.Z;
//get CrossProduct
n1 = x2 * y3 - x3 * y2;
n2 = x3 * y1 - x1 * y3;
n3 = x1 * y2 - x2 * y1;
//Convert to unit normal
Unit =Math.Sqrt(n1 * n1 + n2 * n2 + n3 * n3);
return new Vector3d(n1 / Unit,n2 / Unit,n3 / Unit);
}
and the test
[CommandMethod("test")]
public void test()
{
Editor ed=acadApp.DocumentManager.MdiActiveDocument.Editor;
Matrix3d ucs = ed.CurrentUserCoordinateSystem;
PromptPointOptions ppo = new PromptPointOptions("\npt");
PromptPointResult ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK) return;
Point3d p1 = ppr.Value.TransformBy(ucs);
ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK) return;
Point3d p2 = ppr.Value.TransformBy(ucs);
ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK) return;
Point3d p3 = ppr.Value.TransformBy(ucs);
Vector3d normal=NormalFromPoints(p1, p2, p3);
ed.WriteMessage("\nnormal="+normal.ToString());
string clock="clockwise";
if (normal.Z == 0) clock = "linear";
else if (normal.Z > 0) clock = "counterclockwise";
ed.WriteMessage("\n" +clock);
}
Here's the nice and simple 2d version
public static int isLeftMath(Point2d Startpoint, Point2d Endpoint, Point2d P)
{
double Ans = ((Endpoint.X - Startpoint.X) * (P.Y - Startpoint.Y) -
(P.X - Startpoint.X) * (Endpoint.Y - Startpoint.Y));
if (Math.Abs(Ans) < 1.0e-8)
{ return 0; } //P is on the line
else
{
if (Ans > 0)
{ return 1; } //P is left of the line (CW)
else
{ return -1; } //P is right of the line (CCW)
}
}