Finding an angle with 3 CGPoints

2020-02-29 11:42发布

问题:

In my application, a user taps 3 times and an angle will be created by the 3 points that were tapped. It draws the angle perfectly. I am trying to calculate the angle at the second tap, but I think I am doing it wrong (probably a math error). I haven't covered this in my calculus class yet, so I am going off of a formula on wikipedia.

http://en.wikipedia.org/wiki/Law_of_cosines

Here is what I am trying:

Note: First, Second, and Third are CGPoints created at the user's tap.

        CGFloat xDistA = (second.x - third.x);
        CGFloat yDistA = (second.y - third.y);
        CGFloat a = sqrt((xDistA * xDistA) + (yDistA * yDistA));

        CGFloat xDistB = (first.x - third.x);
        CGFloat yDistB = (first.y - third.y);
        CGFloat b = sqrt((xDistB * xDistB) + (yDistB * yDistB));

        CGFloat xDistC = (second.x - first.x);
        CGFloat yDistC = (second.y - first.y);
        CGFloat c = sqrt((xDistC * xDistC) + (yDistC * yDistC));

        CGFloat angle = acos(((a*a)+(b*b)-(c*c))/((2*(a)*(b))));

        NSLog(@"FULL ANGLE IS: %f, ANGLE IS: %.2f",angle, angle);

Sometimes, it gives the angle as 1 which doesn't make sense to me. Can anyone explain why this is, or how to fix it please?

回答1:

Not sure if this is the main problem but it is a problem

Your answer gives the angle at the wrong point:

To get the angle in green (which is probably angle you want based on your variable names "first", "second" and "third), use:

CGFloat angle = acos(((a*a)+(c*c)-(b*b))/((2*(a)*(c))));



回答2:

Here's a way that circumvents the law of cosines and instead calculates the angles of the two vectors. The difference between the angles is the searched value:

CGVector vec1 = { first.x - second.x, first.y - second.y };
CGVector vec2 = { third.x - second.x, third.y - second.y };

CGFloat theta1 = atan2f(vec1.dy, vec1.dx);
CGFloat theta2 = atan2f(vec2.dy, vec2.dx);

CGFloat angle = theta1 - theta2;
NSLog(@"angle: %.1f°, ", angle / M_PI * 180);

Note the atan2 function that takes the x and y components as separate arguments and thus avoids the 0/90/180/270° ambiguity.



回答3:

The cosine formula implementation looks right; did you take into account that acos() returns the angle in radians, not in degrees? In order to convert into degrees, multiply the angle by 180 and divide by Pi (3.14159...).



回答4:

The way I have done it is to calculate the two angles separately using atan2(y,x) then using this function.

static inline double
AngleDiff(const double Angle1, const double Angle2)
{
    double diff = 0;
    diff = fabs(Angle1 - Angle2);
    if (diff > <Pi>) {
        diff = (<2Pi>) - diff;
    }
    return diff;
}

The function deals in radians, but you can change <Pi> to 180 and <2Pi> to 360



回答5:

Using this answer to compute angle of the vector:

CGFloat angleForVector(CGFloat dx, CGFloat dy) {
    return atan2(dx, -dy) * 180.0/M_PI;
}

// Compute angle at point Corner, that is between AC and BC:

CGFloat angle = angleForVector(A.x - Corner.x, A.y - Corner.y)
              - angleForVector(B.x - Corner.x, B.y - Corner.y);

NSLog(@"FULL ANGLE IS: %f, ANGLE IS: %.2f",angle, angle);