You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by iv...@apache.org on 2021/01/04 08:43:07 UTC

[lucene-solr] branch master updated: LUCENE-9642: Rotate triangle points before checking triangle orientation (#2154)

This is an automated email from the ASF dual-hosted git repository.

ivera pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git


The following commit(s) were added to refs/heads/master by this push:
     new ce667fd  LUCENE-9642: Rotate triangle points before checking triangle orientation (#2154)
ce667fd is described below

commit ce667fdd2f9453f34c8dc393600565c425021fd1
Author: Ignacio Vera <iv...@apache.org>
AuthorDate: Mon Jan 4 09:42:44 2021 +0100

    LUCENE-9642: Rotate triangle points before checking triangle orientation (#2154)
    
    When encoding triangles in ShapeField, make sure generated triangles are CCW by rotating triangle points before checking triangle orientation.
---
 lucene/CHANGES.txt                                 |  3 +
 .../org/apache/lucene/document/ShapeField.java     | 93 +++++++++-------------
 .../lucene/document/BaseShapeEncodingTestCase.java |  2 +-
 .../lucene/document/TestXYShapeEncoding.java       | 10 +++
 4 files changed, 51 insertions(+), 57 deletions(-)

diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index a7a1103..742aed2 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -284,6 +284,9 @@ Bug Fixes
 * LUCENE-9617: Fix per-field memory leak in IndexWriter.deleteAll(). Reset next available internal
   field number to 0 on FieldInfos.clear(), to avoid wasting FieldInfo references. (Michael Froh)
 
+* LUCENE-9642: When encoding triangles in ShapeField, make sure generated triangles are CCW by rotating 
+  triangle points before checking triangle orientation. (Ignacio Vera)  
+
 Other
 ---------------------
 
diff --git a/lucene/core/src/java/org/apache/lucene/document/ShapeField.java b/lucene/core/src/java/org/apache/lucene/document/ShapeField.java
index c266aa7..8d74923 100644
--- a/lucene/core/src/java/org/apache/lucene/document/ShapeField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/ShapeField.java
@@ -144,51 +144,22 @@ public final class ShapeField {
    */
   public static void encodeTriangle(
       byte[] bytes,
-      int aLat,
-      int aLon,
-      boolean abFromShape,
-      int bLat,
-      int bLon,
-      boolean bcFromShape,
-      int cLat,
-      int cLon,
-      boolean caFromShape) {
+      int aY,
+      int aX,
+      boolean ab,
+      int bY,
+      int bX,
+      boolean bc,
+      int cY,
+      int cX,
+      boolean ca) {
     assert bytes.length == 7 * BYTES;
-    int aX;
-    int bX;
-    int cX;
-    int aY;
-    int bY;
-    int cY;
-    boolean ab, bc, ca;
-    // change orientation if CW
-    if (GeoUtils.orient(aLon, aLat, bLon, bLat, cLon, cLat) == -1) {
-      aX = cLon;
-      bX = bLon;
-      cX = aLon;
-      aY = cLat;
-      bY = bLat;
-      cY = aLat;
-      ab = bcFromShape;
-      bc = abFromShape;
-      ca = caFromShape;
-    } else {
-      aX = aLon;
-      bX = bLon;
-      cX = cLon;
-      aY = aLat;
-      bY = bLat;
-      cY = cLat;
-      ab = abFromShape;
-      bc = bcFromShape;
-      ca = caFromShape;
-    }
     // rotate edges and place minX at the beginning
     if (bX < aX || cX < aX) {
+      final int tempX = aX;
+      final int tempY = aY;
+      final boolean tempBool = ab;
       if (bX < cX) {
-        int tempX = aX;
-        int tempY = aY;
-        boolean tempBool = ab;
         aX = bX;
         aY = bY;
         ab = bc;
@@ -198,10 +169,7 @@ public final class ShapeField {
         cX = tempX;
         cY = tempY;
         ca = tempBool;
-      } else if (cX < aX) {
-        int tempX = aX;
-        int tempY = aY;
-        boolean tempBool = ab;
+      } else {
         aX = cX;
         aY = cY;
         ab = ca;
@@ -216,10 +184,10 @@ public final class ShapeField {
       // degenerated case, all points with same longitude
       // we need to prevent that aX is in the middle (not part of the MBS)
       if (bY < aY || cY < aY) {
+        final int tempX = aX;
+        final int tempY = aY;
+        final boolean tempBool = ab;
         if (bY < cY) {
-          int tempX = aX;
-          int tempY = aY;
-          boolean tempBool = ab;
           aX = bX;
           aY = bY;
           ab = bc;
@@ -229,10 +197,7 @@ public final class ShapeField {
           cX = tempX;
           cY = tempY;
           ca = tempBool;
-        } else if (cY < aY) {
-          int tempX = aX;
-          int tempY = aY;
-          boolean tempBool = ab;
+        } else {
           aX = cX;
           aY = cY;
           ab = ca;
@@ -246,10 +211,26 @@ public final class ShapeField {
       }
     }
 
-    int minX = aX;
-    int minY = StrictMath.min(aY, StrictMath.min(bY, cY));
-    int maxX = StrictMath.max(aX, StrictMath.max(bX, cX));
-    int maxY = StrictMath.max(aY, StrictMath.max(bY, cY));
+    // change orientation if CW
+    if (GeoUtils.orient(aX, aY, bX, bY, cX, cY) == -1) {
+      // swap b with c
+      final int tempX = bX;
+      final int tempY = bY;
+      final boolean tempBool = ab;
+      // aX and aY do not change, ab becomes bc
+      ab = bc;
+      bX = cX;
+      bY = cY;
+      // bc does not change, ca becomes ab
+      cX = tempX;
+      cY = tempY;
+      ca = tempBool;
+    }
+
+    final int minX = aX;
+    final int minY = StrictMath.min(aY, StrictMath.min(bY, cY));
+    final int maxX = StrictMath.max(aX, StrictMath.max(bX, cX));
+    final int maxY = StrictMath.max(aY, StrictMath.max(bY, cY));
 
     int bits, x, y;
     if (minY == aY) {
diff --git a/lucene/core/src/test/org/apache/lucene/document/BaseShapeEncodingTestCase.java b/lucene/core/src/test/org/apache/lucene/document/BaseShapeEncodingTestCase.java
index 28d22f6..668443c 100644
--- a/lucene/core/src/test/org/apache/lucene/document/BaseShapeEncodingTestCase.java
+++ b/lucene/core/src/test/org/apache/lucene/document/BaseShapeEncodingTestCase.java
@@ -496,7 +496,7 @@ public abstract class BaseShapeEncodingTestCase extends LuceneTestCase {
     verifyEncoding(ay, ax, by, bx, cy, cx);
   }
 
-  private void verifyEncoding(double ay, double ax, double by, double bx, double cy, double cx) {
+  protected void verifyEncoding(double ay, double ax, double by, double bx, double cy, double cx) {
     // encode triangle
     int[] original =
         new int[] {encodeX(ax), encodeY(ay), encodeX(bx), encodeY(by), encodeX(cx), encodeY(cy)};
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestXYShapeEncoding.java b/lucene/core/src/test/org/apache/lucene/document/TestXYShapeEncoding.java
index 50e9c55..ca4e4b6 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestXYShapeEncoding.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestXYShapeEncoding.java
@@ -63,4 +63,14 @@ public class TestXYShapeEncoding extends BaseShapeEncodingTestCase {
   protected Component2D createPolygon2D(Object polygon) {
     return XYGeometry.create((XYPolygon) polygon);
   }
+
+  public void testRotationChangesOrientation() {
+    double ay = -3.4028218437925203E38;
+    double ax = 3.4028220466166163E38;
+    double by = 3.4028218437925203E38;
+    double bx = -3.4028218437925203E38;
+    double cy = 3.4028230607370965E38;
+    double cx = -3.4028230607370965E38;
+    verifyEncoding(ay, ax, by, bx, cy, cx);
+  }
 }