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 2020/03/03 05:44:45 UTC

[lucene-solr] branch master updated: LUCENE-9239: Circle2D#WithinTriangle detects properly if a triangle is Within distance. (#1280)

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 b732ce7  LUCENE-9239: Circle2D#WithinTriangle detects properly if a triangle is Within distance. (#1280)
b732ce7 is described below

commit b732ce700258ab05590f3904c8d2cd332aa4e0cb
Author: Ignacio Vera <iv...@apache.org>
AuthorDate: Tue Mar 3 06:44:35 2020 +0100

    LUCENE-9239: Circle2D#WithinTriangle detects properly if a triangle is Within distance. (#1280)
---
 lucene/CHANGES.txt                                 |  2 +
 .../src/java/org/apache/lucene/geo/Circle2D.java   | 46 ++++++----------------
 .../apache/lucene/document/TestLatLonShape.java    | 26 +++++++++++-
 3 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index eea937c..4bab649 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -222,6 +222,8 @@ Bug Fixes
 
 * LUCENE-9243: Add fudge factor when creating a bounding box of a XYCircle. (Ignacio Vera)
 
+* LUCENE-9239: Circle2D#WithinTriangle detects properly if a triangle is Within distance. (Ignacio Vera)
+
 Other
 ---------------------
 
diff --git a/lucene/core/src/java/org/apache/lucene/geo/Circle2D.java b/lucene/core/src/java/org/apache/lucene/geo/Circle2D.java
index a3227cb..47a15d8 100644
--- a/lucene/core/src/java/org/apache/lucene/geo/Circle2D.java
+++ b/lucene/core/src/java/org/apache/lucene/geo/Circle2D.java
@@ -102,50 +102,30 @@ class Circle2D implements Component2D {
       return WithinRelation.DISJOINT;
     }
 
-    // if any of the points is inside the polygon, the polygon cannot be within this indexed
-    // shape because points belong to the original indexed shape.
+    // if any of the points is inside the circle then we cannot be within this
+    // indexed shape
     if (contains(ax, ay) || contains(bx, by) || contains(cx, cy)) {
       return WithinRelation.NOTWITHIN;
     }
 
-    WithinRelation relation = WithinRelation.DISJOINT;
-    // if any of the edges intersects an the edge belongs to the shape then it cannot be within.
-    // if it only intersects edges that do not belong to the shape, then it is a candidate
-    // we skip edges at the dateline to support shapes crossing it
-    if (calculator.intersectsLine(ax, ay, bx, by)) {
-      if (ab == true) {
-        return WithinRelation.NOTWITHIN;
-      } else {
-        relation = WithinRelation.CANDIDATE;
-      }
-    }
-
-    if (calculator.intersectsLine(bx, by, cx, cy)) {
-      if (bc == true) {
-        return WithinRelation.NOTWITHIN;
-      } else {
-        relation = WithinRelation.CANDIDATE;
-      }
+    // we only check edges that belong to the original polygon. If we intersect any of them, then
+    // we are not within.
+    if (ab == true && calculator.intersectsLine(ax, ay, bx, by)) {
+      return WithinRelation.NOTWITHIN;
     }
-    if (calculator.intersectsLine(cx, cy, ax, ay)) {
-      if (ca == true) {
-        return WithinRelation.NOTWITHIN;
-      } else {
-        relation = WithinRelation.CANDIDATE;
-      }
+    if (bc == true && calculator.intersectsLine(bx, by, cx, cy)) {
+      return WithinRelation.NOTWITHIN;
     }
-
-    // if any of the edges crosses and edge that does not belong to the shape
-    // then it is a candidate for within
-    if (relation == WithinRelation.CANDIDATE) {
-      return WithinRelation.CANDIDATE;
+    if (ca == true && calculator.intersectsLine(cx, cy, ax, ay)) {
+      return WithinRelation.NOTWITHIN;
     }
 
-    // Check if shape is within the triangle
+    // check if center is within the triangle. This is the only check that returns this circle as a candidate but that is ol
+    // is fine as the center must be inside to be one of the triangles.
     if (Component2D.pointInTriangle(minX, maxX, minY, maxY, calculator.geX(), calculator.getY(), ax, ay, bx, by, cx, cy) == true) {
       return WithinRelation.CANDIDATE;
     }
-    return relation;
+    return WithinRelation.DISJOINT;
   }
 
   /** relates an indexed line segment (a "flat triangle") with the polygon */
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestLatLonShape.java b/lucene/core/src/test/org/apache/lucene/document/TestLatLonShape.java
index 7b0c0fc..de6b609 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestLatLonShape.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestLatLonShape.java
@@ -742,7 +742,6 @@ public class TestLatLonShape extends LuceneTestCase {
     IOUtils.close(w, reader, dir);
   }
 
-
   public void testPointIndexAndDistanceQuery() throws Exception {
     Directory dir = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
@@ -788,4 +787,29 @@ public class TestLatLonShape extends LuceneTestCase {
 
     IOUtils.close(r, dir);
   }
+
+  public void testLucene9239() throws Exception {
+
+    double[] lats = new double[] {-22.350172194105966, 90.0, 90.0, -22.350172194105966, -22.350172194105966};
+    double[] lons = new double[] {49.931598911327825, 49.931598911327825,51.40819689137876, 51.408196891378765, 49.931598911327825};
+    Polygon polygon = new Polygon(lats, lons);
+
+    Directory dir = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
+    Document document = new Document();
+    addPolygonsToDoc(FIELDNAME, document, polygon);
+    writer.addDocument(document);
+
+    //// search
+    IndexReader r = writer.getReader();
+    writer.close();
+    IndexSearcher s = newSearcher(r);
+
+    Circle circle = new Circle(78.01086555431775, 0.9513280497489234, 1097753.4254892308);
+    // Circle is not within the polygon
+    Query q = LatLonShape.newDistanceQuery(FIELDNAME, QueryRelation.CONTAINS, circle);
+    assertEquals(0, s.count(q));
+
+    IOUtils.close(r, dir);
+  }
 }