mirror of https://github.com/apache/lucene.git
LUCENE-9595: Make Component2D#withinPoint implementations consistent with ShapeQuery logic (#2059)
This commit is contained in:
parent
a5d0654a24
commit
44be9f903d
|
@ -253,6 +253,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
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -125,7 +125,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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue