Skip to content Skip to sidebar Skip to footer

Arc Via 3 Points In Specific Direction

I need to draw the arc from 3 points in specific direction. Lets say i have 3 vec2 points P1, P2, P3; I've been manage to find arc center: circleCenter: function (b, c, d) { va

Solution 1:

heh was there too while convert some specific vector data elliptic arcs to SVG ...

few if should do it. I see your case like this:

arc

try this angle correction:

if (a2-a1>+180.0) a2-=360.0;
if (a2-a1<-180.0) a2+=360.0;
if (a3-a2>+180.0) a3-=360.0;
if (a3-a2<-180.0) a3+=360.0;

and after this is direction easy:

if (a2-a1< 0) dir = CW;
if (a2-a1> 0) dir = CCW;
if (a2-a1==0) dir = none;

The only problem is when your arc cover whole 360 degree circle or more ...

  • then this is not enough

draw can be done like this:

for (i=0,a=a1;i<100;i++,a+=(a3-a1)/99.0) // 100 lines per arc or use GDI arc ...
 {
 x=C.x + R*cos(a*PI/180.0);
 y=C.y + R*sin(a*PI/180.0); // or - R*...  if your render device has opposite Y directionif (!i) ...->Canvas->MoveTo(x,y);
 else    ...->Canvas->LineTo(x,y);
 }
  • R = |P1-C|

Solution 2:

I'm working on a similar problem, and it looks like you can calculate both direction and sweep angle by comparing the angles you've calculated. If you have to go further back from the end angle to get to the start angle than to get to the middle angle, you're going clockwise. You can regularize the angles for comparison by using the modulo operator (%), which solves the problem of crossing 360. Something like this:

functiondetermineDirection(start, middle, end) {
    endToStart = (end - start + 360) % 360;
    endToMiddle = (end - middle + 360) % 360;
    if (endToMiddle < endToStart) {
        return {direction: 'cw', sweepAngle: endToStart};
    } else {
        return {direction: 'ccw', sweepAngle: (360 - endToStart)};
    }
}

angleStart = angleFromOrigin(centerOfCircle, P1);
angleMiddle = angleFromOrigin(centerOfCircle, P2);
angleEnd = angleFromOrigin(centerOfCircle, P3);

direction = determineDirection(angleStart, angleMiddle, angleEnd);

Note that this function assumes that angles increase in the clockwise direction. If you're using it for the typical case where angles increase in the counterclockwise direction, exchange the positions of 'cw' and 'ccw'.

Trying it out:

determineDirection(0, 1, 2)
> {direction: "cw", sweepAngle: 2}

determineDirection(2, 1, 0)
> {direction: "ccw", sweepAngle: 2}

determineDirection(0, 2, 1)
> {direction: "ccw", sweepAngle: 359}

determineDirection(1, 2, 0)
> {direction: "cw", sweepAngle: 359}

determineDirection(359, 0, 1)
> {direction: "cw", sweepAngle: 2}

determineDirection(359, 1, 0)
> {direction: "ccw", sweepAngle: 359}

determineDirection(0, 1, 359)
> {direction: "cw", sweepAngle: 359}

determineDirection(1, 0, 359)
> {direction: "ccw", sweepAngle: 2}

determineDirection(0, 359, 1)
> {direction: "ccw", sweepAngle: 359}

determineDirection(1, 359, 0)
> {direction: "cw", sweepAngle: 359}

determineDirection(0, 90, 180)
> {direction: "cw", sweepAngle: 180}

determineDirection(180, 90, 0)
> {direction: "ccw", sweepAngle: 180}

determineDirection(180, 0, 90)
> {direction: "cw", sweepAngle: 270}

I noticed that you're using "centerPoint" for both the center of the circle and the middle point in your arc, so I changed the variable names to avoid confusion.

Post a Comment for "Arc Via 3 Points In Specific Direction"