Author Topic: Clockwise from 3 3dpoints  (Read 3360 times)

0 Members and 1 Guest are viewing this topic.

Bryco

  • Water Moccasin
  • Posts: 1883
Clockwise from 3 3dpoints
« on: September 25, 2009, 01:12:56 AM »
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
Code: [Select]
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
Code: [Select]
[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
Code: [Select]
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)
            }
        }

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Clockwise from 3 3dpoints
« Reply #1 on: September 26, 2009, 05:33:55 PM »
Hi,

The way your method works: (evaluating the Z coordinate of the normal vector) always refers to the WCS XY plane.

For example, if the 3points owns to a vertical plane as YZ plane (normal = 1,0,0) or ZX plane (normal = 0,1,0) or any perpendicular plane to XY plane (normal = x,y,0) the 3 points should be considered as aligned even they're not in the plane they own to.

IOW your method evaluates if the projected points on XY plane are clockwise, counterclockwise or aligned.
You shoud get the same result converting the 3d points to 2d points by removing their Z coordinate.

IMO, the only way to evaluate if 3 points are clockwise is according to a specified plane normal.

Code: [Select]
// Clockwise method, returns 1 if p1, p2, p3 are clockwise,
// 0 if they're aligned, -1 if they're counterclockwise

public static int Clockwise(Point3d p1, Point3d p2, Point3d p3, Vector3d normal)
{
    const double pi = 3.141592653589793;
    Vector3d v1 = p1.GetVectorTo(p2);
    Vector3d v2 = p1.GetVectorTo(p3);
    double angle = v1.GetAngleTo(v2, normal);
    if (angle == 0.0 || angle == pi)
        return 0;
    else
    {
        if (v1.GetAngleTo(v2, normal) < pi)
            return -1;
        else
            return 1;
    }
}
Speaking English as a French Frog

Bryco

  • Water Moccasin
  • Posts: 1883
Re: Clockwise from 3 3dpoints
« Reply #2 on: September 27, 2009, 02:08:48 PM »
Thanks for straightening that out gile, for some reason when I tested a couple of xy or yz I got correct results.
Although the z should be zero I always got enough to give a value and the neg or positive of that value seemed to relate to the winding.
normal=(-1.50775072885934E-32,1,1.17676764776341E-16)  Anyway today I got plenty of zeros so the normal thing fails. Perhaps using the viewdir would give a pretty accurate view but there is the chance that the user is in an iso view and really wants the points relative to the underside of plane he is picking. So it's a good point you make.