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/11/23 08:37:49 UTC
[lucene-solr] branch branch_8x updated: LUCENE-9595: Make
Component2D#withinPoint implementations consistent with ShapeQuery logic
(#2059)
This is an automated email from the ASF dual-hosted git repository.
ivera pushed a commit to branch branch_8x
in repository https://gitbox.apache.org/repos/asf/lucene-solr.git
The following commit(s) were added to refs/heads/branch_8x by this push:
new 2d7d315 LUCENE-9595: Make Component2D#withinPoint implementations consistent with ShapeQuery logic (#2059)
2d7d315 is described below
commit 2d7d315f970ae413b27d5a11c10de1cb643b089d
Author: Ignacio Vera <iv...@apache.org>
AuthorDate: Mon Nov 23 09:36:35 2020 +0100
LUCENE-9595: Make Component2D#withinPoint implementations consistent with ShapeQuery logic (#2059)
---
lucene/CHANGES.txt | 3 ++
.../document/LatLonShapeBoundingBoxQuery.java | 3 +-
.../src/java/org/apache/lucene/geo/Circle2D.java | 2 +-
.../src/java/org/apache/lucene/geo/Line2D.java | 6 ++-
.../src/java/org/apache/lucene/geo/Polygon2D.java | 2 +-
.../java/org/apache/lucene/geo/Rectangle2D.java | 4 +-
.../apache/lucene/document/TestLatLonShape.java | 46 ++++++++++++++++++++++
.../org/apache/lucene/document/TestXYShape.java | 45 +++++++++++++++++++++
8 files changed, 104 insertions(+), 7 deletions(-)
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index fc32c40..5aeccb3 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -45,6 +45,9 @@ Bug Fixes
* LUCENE-9581: Japanese tokenizer should discard the compound token instead of disabling the decomposition
of long tokens when discardCompoundToken is activated. (Jim Ferenczi)
+* LUCENE-9595: Make Component2D#withinPoint implementations consistent with ShapeQuery logic.
+ (Ignacio Vera)
+
Other
---------------------
diff --git a/lucene/core/src/java/org/apache/lucene/document/LatLonShapeBoundingBoxQuery.java b/lucene/core/src/java/org/apache/lucene/document/LatLonShapeBoundingBoxQuery.java
index d7077e6..be3c7d3 100644
--- a/lucene/core/src/java/org/apache/lucene/document/LatLonShapeBoundingBoxQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/document/LatLonShapeBoundingBoxQuery.java
@@ -124,7 +124,8 @@ final class LatLonShapeBoundingBoxQuery extends ShapeQuery {
switch (scratchTriangle.type) {
case POINT: {
- return Component2D.WithinRelation.DISJOINT;
+ return encodedRectangle.contains(scratchTriangle.aX, scratchTriangle.aY)
+ ? Component2D.WithinRelation.NOTWITHIN : Component2D.WithinRelation.DISJOINT;
}
case LINE: {
return encodedRectangle.withinLine(scratchTriangle.aX, scratchTriangle.aY, scratchTriangle.ab,
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 1717846..4cc64ed 100644
--- a/lucene/core/src/java/org/apache/lucene/geo/Circle2D.java
+++ b/lucene/core/src/java/org/apache/lucene/geo/Circle2D.java
@@ -110,7 +110,7 @@ class Circle2D implements Component2D {
@Override
public WithinRelation withinPoint(double x, double y) {
- return WithinRelation.DISJOINT;
+ return contains(x, y) ? WithinRelation.NOTWITHIN : WithinRelation.DISJOINT;
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/geo/Line2D.java b/lucene/core/src/java/org/apache/lucene/geo/Line2D.java
index 313728e..97b2a49 100644
--- a/lucene/core/src/java/org/apache/lucene/geo/Line2D.java
+++ b/lucene/core/src/java/org/apache/lucene/geo/Line2D.java
@@ -129,13 +129,15 @@ final class Line2D implements Component2D {
@Override
public WithinRelation withinPoint(double x, double y) {
- return WithinRelation.DISJOINT;
+ return contains(x, y) ? WithinRelation.NOTWITHIN : WithinRelation.DISJOINT;
}
@Override
public WithinRelation withinLine(double minX, double maxX, double minY, double maxY,
double aX, double aY, boolean ab, double bX, double bY) {
- // can be improved?
+ if (ab && intersectsLine(minX, maxX, minY, maxY, aX, aY, bX, bY)) {
+ return WithinRelation.NOTWITHIN;
+ }
return WithinRelation.DISJOINT;
}
diff --git a/lucene/core/src/java/org/apache/lucene/geo/Polygon2D.java b/lucene/core/src/java/org/apache/lucene/geo/Polygon2D.java
index 438756d..a601f46 100644
--- a/lucene/core/src/java/org/apache/lucene/geo/Polygon2D.java
+++ b/lucene/core/src/java/org/apache/lucene/geo/Polygon2D.java
@@ -181,7 +181,7 @@ final class Polygon2D implements Component2D {
@Override
public WithinRelation withinPoint(double x, double y) {
- return WithinRelation.DISJOINT;
+ return contains(x, y) ? WithinRelation.NOTWITHIN : WithinRelation.DISJOINT;
}
@Override
diff --git a/lucene/core/src/java/org/apache/lucene/geo/Rectangle2D.java b/lucene/core/src/java/org/apache/lucene/geo/Rectangle2D.java
index 37b5f03..e0f1858 100644
--- a/lucene/core/src/java/org/apache/lucene/geo/Rectangle2D.java
+++ b/lucene/core/src/java/org/apache/lucene/geo/Rectangle2D.java
@@ -118,13 +118,13 @@ final class Rectangle2D implements Component2D {
@Override
public WithinRelation withinPoint(double x, double y) {
- return WithinRelation.DISJOINT;
+ return contains(x, y) ? WithinRelation.NOTWITHIN : WithinRelation.DISJOINT;
}
@Override
public WithinRelation withinLine(double minX, double maxX, double minY, double maxY,
double aX, double aY, boolean ab, double bX, double bY) {
- if (ab == true && Component2D.disjoint(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY) ==false &&
+ if (ab == true && Component2D.disjoint(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY) == false &&
edgesIntersect(aX, aY, bX, bY)) {
return WithinRelation.NOTWITHIN;
}
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 53b1ead..9773ffb 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestLatLonShape.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestLatLonShape.java
@@ -26,6 +26,7 @@ import org.apache.lucene.geo.GeoUtils;
import org.apache.lucene.geo.LatLonGeometry;
import org.apache.lucene.geo.Line;
import org.apache.lucene.geo.Polygon;
+import org.apache.lucene.geo.Rectangle;
import org.apache.lucene.geo.Tessellator;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
@@ -827,4 +828,49 @@ public class TestLatLonShape extends LuceneTestCase {
IOUtils.close(r, dir);
}
+
+ public void testContainsIndexedGeometryCollection() throws Exception {
+ Directory dir = newDirectory();
+ RandomIndexWriter w = new RandomIndexWriter(random(), dir);
+ Polygon polygon = new Polygon(new double[] {-64, -64, 64, 64, -64}, new double[] {-132, 132, 132, -132, -132});
+ Field[] polygonFields = LatLonShape.createIndexableFields(FIELDNAME, polygon);
+ // POINT(5, 5) inside the indexed polygon
+ Field[] pointFields = LatLonShape.createIndexableFields(FIELDNAME, 5, 5);
+ int numDocs = random().nextInt(1000);
+ // index the same multi geometry many times
+ for (int i = 0; i < numDocs; i++) {
+ Document doc = new Document();
+ for (Field f : polygonFields) {
+ doc.add(f);
+ }
+ for(int j = 0; j < 10; j++) {
+ for (Field f : pointFields) {
+ doc.add(f);
+ }
+ }
+ w.addDocument(doc);
+ }
+ w.forceMerge(1);
+
+ ///// search //////
+ IndexReader reader = w.getReader();
+ w.close();
+ IndexSearcher searcher = newSearcher(reader);
+ // Contains is only true if the query geometry is inside a geometry and does not intersect with any other geometry
+ // belonging to the same document. In this case the query geometry contains the indexed polygon but the point is
+ // inside the query as well, hence the result is 0.
+ Polygon polygonQuery = new Polygon(new double[] {4, 4, 6, 6, 4}, new double[] {4, 6, 6, 4, 4});
+ Query query = LatLonShape.newGeometryQuery(FIELDNAME, QueryRelation.CONTAINS, polygonQuery);
+ assertEquals(0, searcher.count(query));
+
+ Rectangle rectangle = new Rectangle(4.0, 6.0, 4.0, 6.0);
+ query = LatLonShape.newGeometryQuery(FIELDNAME, QueryRelation.CONTAINS, rectangle);
+ assertEquals(0, searcher.count(query));
+
+ Circle circle = new Circle(5, 5, 10000);
+ query = LatLonShape.newGeometryQuery(FIELDNAME, QueryRelation.CONTAINS, circle);
+ assertEquals(0, searcher.count(query));
+
+ IOUtils.close(w, reader, dir);
+ }
}
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestXYShape.java b/lucene/core/src/test/org/apache/lucene/document/TestXYShape.java
index 5cfdf07..3a90977 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestXYShape.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestXYShape.java
@@ -202,6 +202,51 @@ public class TestXYShape extends LuceneTestCase {
IOUtils.close(r, dir);
}
+ public void testContainsIndexedGeometryCollection() throws Exception {
+ Directory dir = newDirectory();
+ RandomIndexWriter w = new RandomIndexWriter(random(), dir);
+ XYPolygon polygon = new XYPolygon(new float[] {-132, 132, 132, -132, -132}, new float[] {-64, -64, 64, 64, -64});
+ Field[] polygonFields = XYShape.createIndexableFields(FIELDNAME, polygon);
+ // POINT(5, 5) inside the indexed polygon
+ Field[] pointFields = XYShape.createIndexableFields(FIELDNAME, 5, 5);
+ int numDocs = random().nextInt(1000);
+ // index the same multi geometry many times
+ for (int i = 0; i < numDocs; i++) {
+ Document doc = new Document();
+ for (Field f : polygonFields) {
+ doc.add(f);
+ }
+ for(int j = 0; j < 10; j++) {
+ for (Field f : pointFields) {
+ doc.add(f);
+ }
+ }
+ w.addDocument(doc);
+ }
+ w.forceMerge(1);
+
+ ///// search //////
+ IndexReader reader = w.getReader();
+ w.close();
+ IndexSearcher searcher = newSearcher(reader);
+ // Contains is only true if the query geometry is inside a geometry and does not intersect with any other geometry
+ // belonging to the same document. In this case the query geometry contains the indexed polygon but the point is
+ // inside the query as well, hence the result is 0.
+ XYPolygon polygonQuery = new XYPolygon(new float[] {4, 6, 6, 4, 4}, new float[] {4, 4, 6, 6, 4});
+ Query query = XYShape.newGeometryQuery(FIELDNAME, QueryRelation.CONTAINS, polygonQuery);
+ assertEquals(0, searcher.count(query));
+
+ XYRectangle rectangle = new XYRectangle(4, 6, 4, 6);
+ query = XYShape.newGeometryQuery(FIELDNAME, QueryRelation.CONTAINS, rectangle);
+ assertEquals(0, searcher.count(query));
+
+ XYCircle circle = new XYCircle(5, 5, 1);
+ query = XYShape.newGeometryQuery(FIELDNAME, QueryRelation.CONTAINS, circle);
+ assertEquals(0, searcher.count(query));
+
+ IOUtils.close(w, reader, dir);
+ }
+
private static boolean areBoxDisjoint(XYRectangle r1, XYRectangle r2) {
return ( r1.minX <= r2.minX && r1.minY <= r2.minY && r1.maxX >= r2.maxX && r1.maxY >= r2.maxY);
}