You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2018/09/17 13:41:54 UTC
[commons-geometry] 02/07: merging with master
This is an automated email from the ASF dual-hosted git repository.
erans pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-geometry.git
commit 85d2cddc9f2d8d3870b4622d1f96c54ff128cf66
Merge: fb028f0 2e6fc6a
Author: Matt Juntunen <ma...@hotmail.com>
AuthorDate: Sat Sep 15 15:52:08 2018 -0400
merging with master
.../org/apache/commons/geometry/core/Vector.java | 18 +-
.../GeometryException.java} | 23 +-
.../IllegalNormException.java} | 29 ++-
.../core/{util => exception}/package-info.java | 4 +-
.../core/internal/GeometryInternalError.java | 38 +++
.../geometry/core/internal/SimpleTupleFormat.java | 20 +-
.../commons/geometry/core/GeometryTestUtils.java | 32 +++
.../commons/geometry/enclosing/WelzlEncloser.java | 3 +-
.../geometry/enclosing/WelzlEncloser3DTest.java | 2 +-
.../geometry/euclidean/internal}/Vectors.java | 31 ++-
.../commons/geometry/euclidean/oned/Point1D.java | 14 +-
.../commons/geometry/euclidean/oned/Vector1D.java | 63 ++---
.../commons/geometry/euclidean/threed/Line.java | 2 +-
.../commons/geometry/euclidean/threed/Plane.java | 11 +-
.../commons/geometry/euclidean/threed/Point3D.java | 16 +-
.../geometry/euclidean/threed/Rotation.java | 213 +++++++++-------
.../commons/geometry/euclidean/threed/SubLine.java | 2 +-
.../geometry/euclidean/threed/Vector3D.java | 139 +++-------
.../geometry/euclidean/twod/NestedLoops.java | 4 +-
.../commons/geometry/euclidean/twod/Point2D.java | 16 +-
.../commons/geometry/euclidean/twod/Vector2D.java | 103 ++------
.../geometry/euclidean/internal}/VectorsTest.java | 39 ++-
.../geometry/euclidean/oned/Point1DTest.java | 26 --
.../geometry/euclidean/oned/Vector1DTest.java | 111 ++++----
.../geometry/euclidean/threed/Point3DTest.java | 26 --
.../geometry/euclidean/threed/RotationTest.java | 17 +-
.../geometry/euclidean/threed/Vector3DTest.java | 282 ++++++++-------------
.../geometry/euclidean/twod/Point2DTest.java | 26 --
.../geometry/euclidean/twod/Vector2DTest.java | 192 +++++---------
.../geometry/euclidean/twod/hull/ConvexHull2D.java | 2 +-
.../commons/geometry/spherical/oned/ArcsSet.java | 52 +---
.../commons/geometry/spherical/oned/S1Point.java | 2 +-
.../geometry/spherical/twod/EdgesBuilder.java | 6 +-
.../spherical/twod/PropertiesComputer.java | 7 +-
.../commons/geometry/spherical/twod/S2Point.java | 2 +-
.../spherical/twod/SphericalPolygonsSet.java | 8 +-
.../commons/geometry/spherical/twod/SubCircle.java | 3 +-
.../geometry/spherical/oned/ArcsSetTest.java | 2 +-
.../geometry/spherical/twod/CircleTest.java | 32 ++-
.../spherical/twod/SphericalPolygonsSetTest.java | 6 +-
40 files changed, 710 insertions(+), 914 deletions(-)
diff --cc commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
index 61c73d6,4b96f43..cb66b1c
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java
@@@ -16,11 -16,10 +16,12 @@@
*/
package org.apache.commons.geometry.euclidean.threed;
++
+ import org.apache.commons.geometry.core.exception.IllegalNormException;
+import org.apache.commons.geometry.core.internal.DoubleFunction3N;
import org.apache.commons.geometry.core.internal.SimpleTupleFormat;
- import org.apache.commons.geometry.core.util.Vectors;
import org.apache.commons.geometry.euclidean.EuclideanVector;
- import org.apache.commons.geometry.euclidean.internal.ZeroNormException;
+ import org.apache.commons.geometry.euclidean.internal.Vectors;
import org.apache.commons.numbers.arrays.LinearCombination;
/** This class represents a vector in three-dimensional Euclidean space.
@@@ -189,8 -188,8 +190,8 @@@ public class Vector3D extends Cartesian
/** {@inheritDoc} */
@Override
- public Vector3D normalize() throws IllegalStateException {
+ public Vector3D normalize() {
- return scalarMultiply(1.0 / getFiniteNonZeroNorm());
+ return normalize(getX(), getY(), getZ());
}
/** Get a vector orthogonal to the instance.
@@@ -226,19 -226,6 +228,19 @@@
return new Vector3D(inverse * y, -inverse * x, 0);
}
+ /** Returns a unit vector orthogonal to the current vector and pointing in the direction
+ * of {@code dir}. This method is equivalent to calling {@code dir.reject(vec).normalize()}
+ * except that no intermediate vector object is produced.
+ * @param dir the direction to use for generating the orthogonal vector
+ * @return unit vector orthogonal to the current vector and pointing in the direction of
+ * {@code dir} that does not lie along the current vector
- * @throws IllegalStateException if the norm of the current vector is zero or the given
- * vector is collinear with this vector.
++ * @throws IllegalNormException if either vector norm is zero, NaN or infinite,
++ * or the given vector is collinear with this vector.
+ */
- public Vector3D orthogonal(Vector3D dir) throws IllegalStateException {
++ public Vector3D orthogonal(Vector3D dir) {
+ return dir.getComponent(this, true, Vector3D::normalize);
+ }
+
/** {@inheritDoc}
* <p>This method computes the angular separation between two
* vectors using the dot product for well separated vectors and the
@@@ -336,14 -323,14 +338,14 @@@
/** {@inheritDoc} */
@Override
- public Vector3D project(Vector3D base) throws IllegalStateException {
+ public Vector3D project(Vector3D base) {
- return getComponent(base, false);
+ return getComponent(base, false, Vector3D::new);
}
/** {@inheritDoc} */
@Override
- public Vector3D reject(Vector3D base) throws IllegalStateException {
+ public Vector3D reject(Vector3D base) {
- return getComponent(base, true);
+ return getComponent(base, true, Vector3D::new);
}
/**
@@@ -416,87 -399,28 +414,35 @@@
* @param reject If true, the rejection of this instance from {@code base} is
* returned. If false, the projection of this instance onto {@code base}
* is returned.
+ * @param factory factory function used to build the final vector
* @return The projection or rejection of this instance relative to {@code base},
* depending on the value of {@code reject}.
- * @throws IllegalStateException if {@code base} has a zero norm
+ * @throws IllegalNormException if {@code base} has a zero, NaN, or infinite norm
*/
- private Vector3D getComponent(Vector3D base, boolean reject, DoubleFunction3N<Vector3D> factory) throws IllegalStateException {
- private Vector3D getComponent(Vector3D base, boolean reject) {
++ private Vector3D getComponent(Vector3D base, boolean reject, DoubleFunction3N<Vector3D> factory) {
final double aDotB = dotProduct(base);
- final double baseMagSq = base.getNormSq();
- if (baseMagSq == 0.0) {
- throw new ZeroNormException(ZeroNormException.INVALID_BASE);
- }
- final double baseMag = Vectors.ensureFiniteNonZeroNorm(base.getNorm());
++ // We need to check the norm value here to ensure that it's legal. However, we don't
++ // want to incur the cost or floating point error of getting the actual norm and then
++ // multiplying it again to get the square norm. So, we'll just check the squared norm
++ // directly. This will produce the same result as checking the actual norm since
++ // Math.sqrt(0.0) == 0.0, Math.sqrt(Double.NaN) == Double.NaN and
++ // Math.sqrt(Double.POSITIVE_INFINITY) == Double.POSITIVE_INFINITY.
++ final double baseMagSq = Vectors.ensureFiniteNonZeroNorm(base.getNormSq());
- final double scale = aDotB / (baseMag * baseMag);
+ final double scale = aDotB / baseMagSq;
final double projX = scale * base.getX();
final double projY = scale * base.getY();
final double projZ = scale * base.getZ();
if (reject) {
- return new Vector3D(getX() - projX, getY() - projY, getZ() - projZ);
+ return factory.apply(getX() - projX, getY() - projY, getZ() - projZ);
}
- return new Vector3D(projX, projY, projZ);
+ return factory.apply(projX, projY, projZ);
}
- /** Computes the dot product between to vectors. This method simply
- * calls {@code v1.dotProduct(v2)}.
- * @param v1 first vector
- * @param v2 second vector
- * @return the dot product
- * @see #dotProduct(Vector3D)
- */
- public static double dotProduct(Vector3D v1, Vector3D v2) {
- return v1.dotProduct(v2);
- }
-
- /** Computes the angle in radians between two vectors. This method
- * simply calls {@code v1.angle(v2)}.
- * @param v1 first vector
- * @param v2 second vector
- * @return the angle between the vectors in radians
- * @see #angle(Vector3D)
- */
- public static double angle(Vector3D v1, Vector3D v2) {
- return v1.angle(v2);
- }
-
- /** Projects the given vector onto {@code base}. This method simply
- * calls {@code v.project(base)}.
- * @param v vector to project
- * @param base the base vector to project onto
- * @return the projected vector
- * @see #project(Vector3D)
- */
- public static Vector3D project(Vector3D v, Vector3D base) {
- return v.project(base);
- }
-
- /** Returns the vector rejection of {@code v} from {@code base}. This
- * method simply calls {@code v.reject(base)}.
- * @param v vector to reject
- * @param base the base vector to reject from
- * @return the vector rejection
- * @see #reject(Vector3D)
- */
- public static Vector3D reject(Vector3D v, Vector3D base) {
- return v.reject(base);
- }
-
- /** Computes the cross product between two vectors. This method simply
- * calls {@code v1.crossProduct(v2)}.
- * @param v1 first vector
- * @param v2 second vector
- * @return the computed cross product vector
- * @see #crossProduct(Vector3D)
- */
- public static Vector3D crossProduct(Vector3D v1, Vector3D v2) {
- return v1.crossProduct(v2);
- }
-
/** Returns a vector with the given coordinate values.
* @param x abscissa (first coordinate value)
* @param y abscissa (second coordinate value)
@@@ -530,23 -454,6 +476,20 @@@
return SphericalCoordinates.toCartesian(radius, azimuth, polar, Vector3D::new);
}
+ /** Returns a normalized vector derived from the given values.
+ * @param x abscissa (first coordinate value)
+ * @param y abscissa (second coordinate value)
+ * @param z height (third coordinate value)
+ * @return normalized vector instance
- * @throws IllegalStateException if the norm of the given values is zero
++ * @throws IllegalNormException if the norm of the given values is zero
+ */
- public static Vector3D normalize(final double x, final double y, final double z) throws IllegalStateException {
- final double norm = Vectors.norm(x, y, z);
- if (norm == 0.0) {
- throw new ZeroNormException();
- }
++ public static Vector3D normalize(final double x, final double y, final double z) {
++ final double norm = Vectors.ensureFiniteNonZeroNorm(Vectors.norm(x, y, z));
+ final double invNorm = 1.0 / norm;
+
+ return new UnitVector(x * invNorm, y * invNorm, z * invNorm);
+ }
+
/** Parses the given string and returns a new vector instance. The expected string
* format is the same as that returned by {@link #toString()}.
* @param str the string to parse
diff --cc commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java
index e0de1c5,4d34a91..48c4524
--- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java
+++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java
@@@ -157,20 -144,19 +159,27 @@@ public class Vector3DTest
checkVector(Vector3D.of(x, y, z).withMagnitude(0.5), 0.5 * normX, 0.5 * normY, 0.5 * normZ);
checkVector(Vector3D.of(x, y, z).withMagnitude(3), 3 * normX, 3 * normY, 3 * normZ);
+
+ checkVector(Vector3D.of(x, y, z).withMagnitude(-0.5), -0.5 * normX, -0.5 * normY, -0.5 * normZ);
+ checkVector(Vector3D.of(x, y, z).withMagnitude(-3), -3 * normX, -3 * normY, -3 * normZ);
+
+ for (double mag = -10.0; mag <= 10.0; ++mag)
+ {
+ Assert.assertEquals(Math.abs(mag), Vector3D.of(x, y, z).withMagnitude(mag).getMagnitude(), EPS);
+ }
}
- @Test(expected = IllegalStateException.class)
- public void testWithMagnitude_zeroNorm() {
+ @Test
+ public void testWithMagnitude_illegalNorm() {
// act/assert
- Vector3D.ZERO.withMagnitude(1.0);
+ GeometryTestUtils.assertThrows(() -> Vector3D.ZERO.withMagnitude(2.0),
+ IllegalNormException.class);
+ GeometryTestUtils.assertThrows(() -> Vector3D.NaN.withMagnitude(2.0),
+ IllegalNormException.class);
+ GeometryTestUtils.assertThrows(() -> Vector3D.POSITIVE_INFINITY.withMagnitude(2.0),
+ IllegalNormException.class);
+ GeometryTestUtils.assertThrows(() -> Vector3D.NEGATIVE_INFINITY.withMagnitude(2.0),
+ IllegalNormException.class);
}
@Test
@@@ -286,13 -256,20 +295,20 @@@
checkVector(Vector3D.of(2, 2, 2).normalize(), invSqrt3, invSqrt3, invSqrt3);
checkVector(Vector3D.of(-2, -2, -2).normalize(), -invSqrt3, -invSqrt3, -invSqrt3);
- Assert.assertEquals(1.0, Vector3D.of(5, -4, 2).normalize().getNorm(), 1.0e-12);
+ Assert.assertEquals(1.0, Vector3D.of(5, -4, 2).normalize().getNorm(), EPS);
}
- @Test(expected = IllegalStateException.class)
- public void testNormalize_zeroNorm() {
+ @Test
+ public void testNormalize_illegalNorm() {
// act/assert
- Vector3D.ZERO.normalize();
+ GeometryTestUtils.assertThrows(() -> Vector3D.ZERO.normalize(),
+ IllegalNormException.class);
+ GeometryTestUtils.assertThrows(() -> Vector3D.NaN.normalize(),
+ IllegalNormException.class);
+ GeometryTestUtils.assertThrows(() -> Vector3D.POSITIVE_INFINITY.normalize(),
+ IllegalNormException.class);
+ GeometryTestUtils.assertThrows(() -> Vector3D.NEGATIVE_INFINITY.normalize(),
+ IllegalNormException.class);
}
@Test
@@@ -328,31 -301,6 +351,52 @@@
}
@Test
+ public void testOrthogonal_givenDirection() {
+ // arrange
+ double invSqrt2 = 1.0 / Math.sqrt(2.0);
+
+ // act/assert
+ checkVector(Vector3D.PLUS_X.orthogonal(Vector3D.of(-1.0, 0.1, 0.0)), 0.0, 1.0, 0.0);
+ checkVector(Vector3D.PLUS_Y.orthogonal(Vector3D.of(2.0, 2.0, 2.0)), invSqrt2, 0.0, invSqrt2);
+ checkVector(Vector3D.PLUS_Z.orthogonal(Vector3D.of(3.0, 3.0, -3.0)), invSqrt2, invSqrt2, 0.0);
+
+ checkVector(Vector3D.of(invSqrt2, invSqrt2, 0.0).orthogonal(Vector3D.of(1.0, 1.0, 0.2)), 0.0, 0.0, 1.0);
+ }
+
- @Test(expected = IllegalStateException.class)
- public void testOrthogonal_givenDirection_zeroNorm() {
++ @Test
++ public void testOrthogonal_givenDirection_illegalNorm() {
+ // act/assert
- Vector3D.ZERO.orthogonal(Vector3D.PLUS_X);
++ GeometryTestUtils.assertThrows(() -> Vector3D.ZERO.orthogonal(Vector3D.PLUS_X),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.NaN.orthogonal(Vector3D.PLUS_X),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.POSITIVE_INFINITY.orthogonal(Vector3D.PLUS_X),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.NEGATIVE_INFINITY.orthogonal(Vector3D.PLUS_X),
++ IllegalNormException.class);
++
++ GeometryTestUtils.assertThrows(() -> Vector3D.PLUS_X.orthogonal(Vector3D.ZERO),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.PLUS_X.orthogonal(Vector3D.NaN),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.PLUS_X.orthogonal(Vector3D.POSITIVE_INFINITY),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.PLUS_X.orthogonal(Vector3D.NEGATIVE_INFINITY),
++ IllegalNormException.class);
+ }
+
- @Test(expected = IllegalStateException.class)
++ @Test
+ public void testOrthogonal_givenDirection_directionIsCollinear() {
+ // act/assert
- Vector3D.PLUS_X.orthogonal(Vector3D.of(-2.0, 0.0, 0.0));
++ GeometryTestUtils.assertThrows(() -> Vector3D.PLUS_X.orthogonal(Vector3D.PLUS_X),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.PLUS_X.orthogonal(Vector3D.MINUS_X),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.of(1.0, 1.0, 1.0).orthogonal(Vector3D.of(-2.0, -2.0, -2.0)),
++ IllegalNormException.class);
+ }
+
+ @Test
public void testAngle() {
// arrange
double tolerance = 1e-10;
@@@ -1069,21 -904,6 +1000,28 @@@
}
@Test
+ public void testNormalize_static() {
+ // arrange
+ double invSqrt3 = 1.0 / Math.sqrt(3.0);
+
+ // act/assert
+ checkVector(Vector3D.normalize(2.0, -2.0, 2.0), invSqrt3, -invSqrt3, invSqrt3);
+ checkVector(Vector3D.normalize(-4.0, 4.0, -4.0), -invSqrt3, invSqrt3, -invSqrt3);
+ }
+
- @Test(expected = IllegalStateException.class)
- public void testNormalize_static_zeroNorm() {
- Vector3D.normalize(0.0, 0.0, 0.0);
++ @Test
++ public void testNormalize_static_illegalNorm() {
++ GeometryTestUtils.assertThrows(() -> Vector3D.normalize(0.0, 0.0, 0.0),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.normalize(Double.NaN, 1.0, 1.0),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.normalize(1.0, Double.NEGATIVE_INFINITY, 1.0),
++ IllegalNormException.class);
++ GeometryTestUtils.assertThrows(() -> Vector3D.normalize(1.0, 1.0, Double.POSITIVE_INFINITY),
++ IllegalNormException.class);
+ }
+
+ @Test
public void testLinearCombination1() {
// arrange
Vector3D p1 = Vector3D.of(1, 2, 3);