[vtkusers] Angle between two vectors
David Gobbi
david.gobbi at gmail.com
Mon Jan 6 12:25:47 EST 2014
On Mon, Jan 6, 2014 at 9:28 AM, David Cole <dlrdave at aol.com> wrote:
> Especially given that the most highly ranked Google results for "compute
> angle between two vectors" predominantly advise to use acos(dot)... There is
> mention of 3 techniques if you dig through enough links, but it certainly
> seems like this sort of advice would be ranked more highly.
I did some experiments, and the acos() method has an accuracy of around
1e-7 for double-precision inputs when the angle is small. The atan2() method
has an accuracy of around 1e-16. Is this difference going to be significant
for most people? No. Is the difference going to be significant for
some people?
Yes, definitely.
> I guess it comes down to how fast you need the method to be, and how much
> "error" you can tolerate. The acos(dot) technique requires fewer math ops,
Are you sure that is the case? For the acos method, if both of the vectors
are normalized, that means two sqrts and two divisions. Don't forget that
sqrt and division each require around 10x as many cycles as addition or
multiplication. The atan2 method requires just one sqrt, by comparison.
Overall, I wouldn't expect a significant difference. Of course, all of this
might be moot because the transcendental op (acos or atan2) is probably
the most expensive part of the whole computation.
Apart from accuracy, another strong argument for the atan2 method is that
it will never result in a division-by-zero. The atan2 function has a
well-defined finite output for any inputs except for NAN. If either input
vector has zero length, the atan2 method will return an angle of zero.
In contrast, the acos method fails if either input vector has zero length.
> So..... if I submit a gerrit patch to add this, using the atan2 technique,
> should it be named "double vtkMath::AngleBetweenTwoVectors(double *v1,
> double *v2)"? Or is there an better name for it (to follow other method
> names already existing in vtkMath)....?
The "Two" seems unnecessary, AngleBetweenVectors() sounds good to
me. Also, the parameters should be arrays to make it obvious that these
are 3D vectors and not 2D vectors.
double vtkMath::AngleBetweenVectors(const double v1[3], const double v2[3])
The use of array parameters also gives a size hint for the wrappers, which
allows the wrappers to wrap the method.
David
More information about the vtkusers
mailing list