Given points ABC, how could I find angle ABC? I’m making a feehand tool for a vector drawing application and to minimize the number of points it generates, I wont add a points unless the angle of the mouse position and the last 2 points is greater than a certain threshold.
Thanks
what I had:
int CGlEngineFunctions::GetAngleABC( POINTFLOAT a, POINTFLOAT b, POINTFLOAT c )
{
POINTFLOAT ab;
POINTFLOAT ac;
ab.x = b.x - a.x;
ab.y = b.y - a.y;
ac.x = b.x - c.x;
ac.y = b.y - c.y;
float dotabac = (ab.x * ab.y + ac.x * ac.y);
float lenab = sqrt(ab.x * ab.x + ab.y * ab.y);
float lenac = sqrt(ac.x * ac.x + ac.y * ac.y);
float dacos = dotabac / lenab / lenac;
float rslt = acos(dacos);
float rs = (rslt * 180) / 3.141592;
RoundNumber(rs);
return (int)rs;
}
First suggestions regarding your method:
What you call
acis actuallycb. But it’s ok, this is what really needed.Next,
This is your first mistake. The real dot product of two vectors is:
Now,
Here you should note that due to some precision loss during the calculation it’s theoretically possible that
dacoswill become bigger than 1 (or lesser than -1). Hence – you should check this explicitly.Plus a performance note: you call a heavy
sqrtfunction twice for calculating the length of two vectors. Then you divide the dot product by those lengths.Instead you could call
sqrton the multiplication of squares of length of both vectors.And lastly, you should note that your result is accurate up to the
sign. That is, your method won’t distinguish 20° and -20°, since the cosine of both are the same.Your method will yield the same angle for ABC and CBA.
One correct method for calculating the angle is as “oslvbo” suggests:
(I’ve just replaced
atanbyatan2).It’s the simplest method, which always yields the correct result. The drawback of this method is that you actually call a heavy trigonometry function
atan2twice.I suggest the following method. It’s a bit more complex (requires some trigonometry skills to understand), however it’s superior from the performance point of view.
It just calls once a trigonometry function
atan2. And no square root calculations.EDIT:
Recently I’ve been working on a related subject. And then I’ve realized there’s a better way. It’s actually more-or-less the same (behind the scenes). However it’s more straightforward IMHO.
The idea is to rotate both vectors so that the first one is aligned to (positive) X-direction. Obviously rotating both vectors doesn’t affect the angle between them. OTOH after such a rotation one just has to find out the angle of the 2nd vector relative to X-axis. And this is exactly what
atan2is for.Rotation is achieved by multiplying a vector by the following matrix:
Once may see that vector
amultiplied by such a matrix indeed rotates toward positive X-axis.Note: Strictly speaking the above matrix isn’t just rotating, it’s also scaling. But this is ok in our case, since the only thing that matters is the vector direction, not its length.
Rotated vector
bbecomes:Finally, the answer can be expressed as: