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


The following commit(s) were added to refs/heads/master by this push:
     new eba3a8e  GEOMETRY-42: Adding Vector2D.signedArea(Vector2D) method; 
removing Vector2D.cross() method since the cross product is not defined in two 
dimensions
     new 1f334d1  Merge branch 'GEOMETRY-42__matt'
eba3a8e is described below

commit eba3a8e286cf960d93b6b896592eb95120b3d6a2
Author: Matt Juntunen <matt.juntu...@hotmail.com>
AuthorDate: Wed Feb 6 00:25:35 2019 -0500

    GEOMETRY-42: Adding Vector2D.signedArea(Vector2D) method; removing 
Vector2D.cross() method since the cross product is not defined in two dimensions
---
 .../commons/geometry/euclidean/twod/Vector2D.java  | 40 ++++++++-----------
 .../geometry/euclidean/twod/Vector2DTest.java      | 45 +++++++++++++++++-----
 .../euclidean/twod/hull/AklToussaintHeuristic.java | 15 +++++++-
 3 files changed, 65 insertions(+), 35 deletions(-)

diff --git 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
index 08b4f1f..b5c1356 100644
--- 
a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
+++ 
b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java
@@ -281,32 +281,24 @@ public class Vector2D extends 
MultiDimensionalEuclideanVector<Vector2D> {
         return dir.getComponent(this, true, Vector2D::normalize);
     }
 
-    /**
-     * Compute the cross-product of the instance and the given vector.
-     * <p>
-     * The cross product can be used to determine the location of a point
-     * with regard to the line formed by (p1, p2) and is calculated as:
-     * \[
-     *    P = (x_2 - x_1)(y_3 - y_1) - (y_2 - y_1)(x_3 - x_1)
-     * \]
-     * with \(p3 = (x_3, y_3)\) being this instance.
-     * <p>
-     * If the result is 0, the points are collinear, i.e. lie on a single 
straight line L;
-     * if it is positive, this point lies to the left, otherwise to the right 
of the line
-     * formed by (p1, p2).
-     *
-     * @param p1 first point of the line
-     * @param p2 second point of the line
-     * @return the cross-product
+    /** Compute the signed area of the parallelogram with sides formed by this 
instance
+     * and the given vector.
      *
-     * @see <a href="http://mathworld.wolfram.com/CrossProduct.html";>Cross 
product (Mathworld)</a>
+     * <p>The parallelogram in question can be visualized by taking the 
current instance as the
+     * first side and placing {@code v} at the end of it to create the second. 
The other sides
+     * are formed by lines parallel to these two vectors. If {@code v} points 
to the <em>left</em> of
+     * the current instance (ie, the parallelogram is wound 
counter-clockwise), then the
+     * returned area is positive. If {@code v} points to the <em>right</em> of 
the current instance,
+     * (ie, the parallelogram is wound clockwise), then the returned area is 
negative. If
+     * the vectors are collinear (ie, they lie on the same line), then 0 is 
returned. The area of
+     * the triangle formed by the two vectors is exactly half of the returned 
value.
+     * @param v vector representing the second side of the constructed 
parallelogram
+     * @return the signed area of the parallelogram formed by this instance 
and the given vector
      */
-    public double cross(final Vector2D p1, final Vector2D p2) {
-        final double x1 = p2.x - p1.x;
-        final double y1 = y - p1.y;
-        final double x2 = x - p1.x;
-        final double y2 = p2.y - p1.y;
-        return LinearCombination.value(x1, y1, -x2, y2);
+    public double signedArea(final Vector2D v) {
+        return LinearCombination.value(
+                x, v.y,
+                -y, v.x);
     }
 
     /** Apply the given transform to this vector, returning the result as a
diff --git 
a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java
 
b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java
index 5a4c268..aac0f5d 100644
--- 
a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java
+++ 
b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java
@@ -513,19 +513,46 @@ public class Vector2DTest {
     }
 
     @Test
-    public void testCrossProduct() {
+    public void testSignedArea() {
         // arrange
-        Vector2D p1 = Vector2D.of(1, 1);
-        Vector2D p2 = Vector2D.of(2, 2);
+        double eps = 1e-10;
 
-        Vector2D p3 = Vector2D.of(3, 3);
-        Vector2D p4 = Vector2D.of(1, 2);
-        Vector2D p5 = Vector2D.of(2, 1);
+        Vector2D a = Vector2D.PLUS_X;
+        Vector2D b = Vector2D.PLUS_Y;
+        Vector2D c = Vector2D.of(1, 1).withNorm(2.0);
+        Vector2D d = Vector2D.of(-1, 1).withNorm(3.0);
 
         // act/assert
-        Assert.assertEquals(0.0, p3.cross(p1, p2), EPS);
-        Assert.assertEquals(1.0, p4.cross(p1, p2), EPS);
-        Assert.assertEquals(-1.0, p5.cross(p1, p2), EPS);
+        Assert.assertEquals(1.0, a.signedArea(b), eps);
+        Assert.assertEquals(-1.0, b.signedArea(a), eps);
+
+        double xAxisAndCArea = 2 * Math.cos(0.25 * Geometry.PI);
+        Assert.assertEquals(xAxisAndCArea, a.signedArea(c), eps);
+        Assert.assertEquals(-xAxisAndCArea, c.signedArea(a), eps);
+
+        double xAxisAndDArea = 3 * Math.cos(0.25 * Geometry.PI);
+        Assert.assertEquals(xAxisAndDArea, a.signedArea(d), eps);
+        Assert.assertEquals(-xAxisAndDArea, d.signedArea(a), eps);
+
+        Assert.assertEquals(6.0, c.signedArea(d), eps);
+        Assert.assertEquals(-6.0, d.signedArea(c), eps);
+    }
+
+    @Test
+    public void testSignedArea_collinear() {
+        // arrange
+        Vector2D a = Vector2D.PLUS_X;
+        Vector2D b = Vector2D.PLUS_Y;
+        Vector2D c = Vector2D.of(-3, 8);
+
+        // act/assert
+        Assert.assertEquals(0.0, a.signedArea(a), EPS);
+        Assert.assertEquals(0.0, b.signedArea(b), EPS);
+        Assert.assertEquals(0.0, c.signedArea(c), EPS);
+
+        Assert.assertEquals(0.0, a.signedArea(a.multiply(100.0)), EPS);
+        Assert.assertEquals(0.0, b.signedArea(b.negate()), EPS);
+        Assert.assertEquals(0.0, c.signedArea(c.multiply(-0.03)), EPS);
     }
 
     @Test
diff --git 
a/commons-geometry-hull/src/main/java/org/apache/commons/geometry/euclidean/twod/hull/AklToussaintHeuristic.java
 
b/commons-geometry-hull/src/main/java/org/apache/commons/geometry/euclidean/twod/hull/AklToussaintHeuristic.java
index af3c034..27e42b6 100644
--- 
a/commons-geometry-hull/src/main/java/org/apache/commons/geometry/euclidean/twod/hull/AklToussaintHeuristic.java
+++ 
b/commons-geometry-hull/src/main/java/org/apache/commons/geometry/euclidean/twod/hull/AklToussaintHeuristic.java
@@ -129,7 +129,7 @@ public final class AklToussaintHeuristic {
         }
 
         // get the location of the point relative to the first two vertices
-        final double last = v0.cross(v1, v2);
+        final double last = signedAreaPoints(v1, v2, v0);
         final int size = quadrilateralPoints.size();
         // loop through the rest of the vertices
         for (int i = 1; i < size; i++) {
@@ -143,11 +143,22 @@ public final class AklToussaintHeuristic {
             // do side of line test: multiply the last location with this 
location
             // if they are the same sign then the operation will yield a 
positive result
             // -x * -y = +xy, x * y = +xy, -x * y = -xy, x * -y = -xy
-            if (last * v0.cross(v1, v2) < 0) {
+            if (last * signedAreaPoints(v1, v2, v0) < 0) {
                 return false;
             }
         }
         return true;
     }
 
+    /** Compute the signed area of the parallelogram formed by vectors between 
the given points. The first
+     * vector points from {@code p0} to {@code p1} and the second from {@code 
p0} to {@code p3}.
+     * @param p0 first point
+     * @param p1 second point
+     * @param p2 third point
+     * @return signed area of parallelogram formed by vectors between the 
given points
+     */
+    private static double signedAreaPoints(final Vector2D p0, final Vector2D 
p1, final Vector2D p2) {
+        return p0.vectorTo(p1).signedArea(p0.vectorTo(p2));
+    }
+
 }

Reply via email to