three.js: vector3.angleTo with vec on (0,0,0) returns NaN
I noticed that vector3.angleTo() returns NaN when either the vector on which it’s called or the target vector is at the origin (0,0,0).
let vec1 = new THREE.Vector3( -2, 2, 0 );
let vec2 = new THREE.Vector3( 0, 0, 0 );
console.log( vec2.angleTo(vec1) ); // NaN
console.log( vec1.angleTo(vec2) ); // NaN
Three.js version : r108 Browser : Chrome OS : Windows
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 30 (8 by maintainers)
As the user has to deal with valid inputs anways (test for non-zero vectors), wouldn’t it be better to just return π/2 radians (90°) instead of a console.error? Returning π/2 seems for me to be mathematical correct … Wikipedia: “In Euclidean space, two vectors are orthogonal if and only if their dot product is zero, i.e. they make an angle of 90° (π/2 radians), or one of the vectors is zero.” (https://en.wikipedia.org/wiki/Orthogonality). Wikibooks: “the angle between the zero vector and any other vector is defined to be a right angle” (https://en.wikibooks.org/wiki/Linear_Algebra/Length_and_Angle_Measures). Returning (mathematically wrong) NaN (and conole.error) because the user should not try to calculate the angle to/from a zero-vector doesn’t look like a good solution for me.
Users would then only have to check for zero-vectors if the returned angle is exactly π/2 and only if this is relevant later on.
By the way: I use “angleTo” while calculating weighted (angle and surface) vertex normals. That worked perfectly fine because I had to test the angle to be in a certain range anyways. After updating three.js I got thousands of console.errors, so I now have to test every (calculated) vector to be non-zero before using “angleTo”.
@felixmariotto You are right, this behavior is unfortunate. I suggest the same what Unity does in Vector3.Angle.
Vector3.angleTo()
would look like so then:I definitely continue thinking that we should not validate inputs. But, in a case by case basis, we can try to make dealing with javascript easier.
In this case, I think it’s okay to add a
console.error()
whendenominator
is0
.Oh I see.
Hmm… Don’t you see this request similar to the
Error
we throw when a matrix is degenerate?https://github.com/mrdoob/three.js/blob/dev/src/math/Matrix4.js#L543-L559
@felixmariotto Would you prefer such a behavior compared to the current one?
angleTo
doesn’t seem to be a hot method (we don’t use it in the render loop) so I think it would be okay to throw an error ifdenominator
is0
. In this case it wouldn’t be so much about validating inputs, but about avoiding dividing by 0. How does that sound?You can’t calculate an angle to a vector that that defines no direction.
This is a user error and an invalid input.
Valid inputs will not divide by zero. If we check for zero here, we are validating input and we will need to do it everywhere.
The true issue is not to find the correct answer to this incorrect question, but rather to do something user-friendly. You could stick to mathematical correctness, but still help the users by throwing a console error in this situation, so the debugging would be straightforward.
I agree with @WestLangley 0 doesn’t seem like a reasonable value to return in this case.
AngleTo
implies that the vector can be rotated by the returned value to point in the same direction and that’s not possible for a zero vector.I think silently / untraceably returning that two vectors are pointing in the same direction when they are not could make life harder for other devs, no? Appropriately handling the corner case of trying to get the angle to a zero vector seems like an application-specific concern. Assuming that 0 is a reasonable or appropriate value in all cases doesn’t seem right.
Perhaps the docs could just be updated to inform users that the function will return
NaN
if one of the vectors is zero?I am not a fan of returning an incorrect answer. Ever.
three.js does not validate inputs, so there are many methods for which users can pass in problematic values. We can’t go down this path, unless we change our policy.
Since the angle to the zero vector does not make sense anyway, I would do nothing.
Unity does not check for zero equality, so that is not exactly what Unity does.