Jump to content
Developer Wiki and Function Reference Links ×

Angle sense between 3 points


Recommended Posts

Banging my head against the wall on this one. I am testing a polygon.

If I have 3 vertices, "start point", "test point", "to point" - I can test the angle between the 3 points using the logic of the developer example

PROCEDURE Example;

VAR

pt1, pt2, pt3, pt4 :VECTOR;

ang :REAL;

BEGIN

GetPt(pt1.x, pt1.y); {start point}

GetPtL(pt1.x, pt1.y, pt2.x, pt2.y); {test point}

GetPtL(pt2.x, pt2.y, pt3.x, pt3.y); {to point}

MoveTo(pt1.x, pt1.y);

LineTo(pt2.x, pt2.y);

LineTo(pt3.x, pt3.y);

pt4 := (pt1 + pt3) / 2;

{Find the angle between the vectors.}

ang := Rad2Deg(ArcCos(DotProduct(UnitVec(pt1-pt2), UnitVec(pt3-pt2))));

TextOrigin(pt4.x, pt4.y);

CreateText(Concat(ang));

END;

RUN(Example);

This always returns a positive angle.

What I need to find out is if the "to point" is to the left (-ive) or right (+ive) of a vector "start point" to "test point"

I tried comp(p2-p1,p3-p1,v3,v4) with v4 orthogonal to p2-p1

I thought I could test v4.y for +ive or -ive sense but cant seem to get it to work.

TIA

Bill Wood

Link to comment

Bill,

   You can test CW / CCW 'ness with the CrossProduct() function. If the CrossProduct's Z component is positive, the angle turns one way. If it is negative it turns the other way. If it is 0, the lines are collinear. The sign of the Z component is determined by the Right-Hand-Rule, which is well documented online. The magnitude of the CrossProduct's Z component is not important in this test, just its sign.

   If your lines always have a left/right angle between them the following code will test for CW/CCW:

   This should be easy to follow:

function isCCW(P1, P2, P3 :Vector) :Boolean;
{ Return TRUE if the angle at P2 is CCW, FALSE if it is CW (or straight). }
Var
V1, V2, CP :Vector;
Begin
V1 := P2 - P1;	{ first line }
V2 := P3 - P2;	{ second line }
CP := CrossProduct(V1, V2);
isCCW := CP.z > 0;
End;	{ isCCW }

   If you are interested in more compact code (like me), then here's the same routine squished:

function isCCW(P1, P2, P3 :Vector) :Boolean;
{ Return TRUE if the angle at P2 is CCW, FALSE if it is CW (or straight). }
Var
CP :Vector;
Begin
CP := CrossProduct(P2-P1, P3-P2);
isCCW := CP.z > 0 ;
End;	{ isCCW }

HTH,

Raymond

  • Love 1
Link to comment

Raymond

Thanks for the code, much simpler. In the desperate need to finish the code, I didn't see/manage to pick up your code in time. I did it a slightly different way which seems to work fine - see below

Thanks anyway.

Bill Wood

procedure getpolydef(polyH : HANDLE; vertnum : INTEGER);

Var

j : INTEGER;

p1,p2,p3 : VECTOR;

v1,v2 : VECTOR;

ang,testang : REAL;

ang1,ang2 : REAL;

begin

for j := 1 to vertnum do begin

GetPolyPt(polyH ,j,p2.x,p2.y); {test vertex}

if (j = numvert) then GetPolyPt(polyH,1,p3.x,p3.y) {next vertex}

else GetPolyPt(objH,j+1,p3.x,p3.y);

if (j=1) then GetPolyPt(objH,numvert,p1.x,p1.y) {previous vertex}

else GetPolyPt(objH,j-1,p1.x,p1.y);

pathdef[j].x := p2.x; pathdef[j].y := p2.y;

ang := Rad2Deg(ArcCos(DotProduct(UnitVec(p1-p2), UnitVec(p3-p2)))); {angle between 3 points always positive}

v1.x := p2.x-p1.x; v1.y := p2.y-p1.y;

v2.x := p3.x-p1.x; v2.y := p3.y-p1.y;

ang1 := vec2ang(v1);

ang2 := vec2ang(v2);

testang := ang1-ang2;

{work out angle direction from test point to to point}

if testang >= 180 then pathdef[j].angle := -ang

else if testang >= 0 then pathdef[j].angle := ang

else if testang < -180 then pathdef[j].angle := ang

else pathdef[j].angle := -ang;

end;

end; {getpolydef}

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...