Vector.normalize() needs to avoid division by zero
See original GitHub issueCurrent normalization code is as follows:
public Vector3d normalize(Vector3d dest) {
double invLength = 1.0 / length();
dest.x = x * invLength;
dest.y = y * invLength;
dest.z = z * invLength;
return dest;
}
Instead division by zero should always be avoided, and the code should be something like the following to prevent division-by-zero (arguably dealing with a zero vector in the result is better from a robustness point of view than dealing with Inf
or NaN
, since these values propagate virally):
public Vector3d normalize(Vector3d dest) {
double lengthSq = lengthSquared();
if (lengthSq < 1.0e-30) {
dest.x = 0.0;
dest.y = 0.0;
dest.z = 0.0;
} else {
double invLength = 1.0 / Math.sqrt(lengthSq);
dest.x = x * invLength;
dest.y = y * invLength;
dest.z = z * invLength;
}
return dest;
}
Then there should be a Vector.isZero()
method for quickly testing if a vector is (exactly) equal to zero, so that return conditions from methods like the result of normalize()
can be quickly checked:
public boolean isZero() {
return x == 0.0 && y == 0.0 && z == 0.0;
}
There should probably also be a Vector.isCloseToZero()
method that would replace the if (lengthSq < 1.0e-30)
test above:
public boolean isCloseToZero() {
double lengthSq = lengthSquared();
return lengthSq < 1.0e-30;
}
The constant 1.0e-30
could be smaller for float
vectors (maybe 1.0e-12f
) – it should be something above the precision floor, but below the probable error/noise floor for the majority of applications.
Issue Analytics
- State:
- Created 4 years ago
- Comments:10 (5 by maintainers)
Top GitHub Comments
Just one thing missing… Any method that can result in NaN/infinity in any component needs to recommend in the Javadoc that the user call isFinite on the result, if there’s any chance of this happening (eg. when normalizing a zero vector).
Alright, just manually retriggered the build and this one went through, so 1.9.23-SNAPSHOT is available now.