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);