mirror of https://github.com/apache/lucene.git
LUCENE-10514: Component2D#Within methods should return NOTWITHIN for triangles within the query geometry (#809)
This commit brings makes sure we always return NOTWITHIN for fully contained triangles in Component2D#within* methods
This commit is contained in:
parent
15ecf3c27f
commit
4c133f435d
|
@ -485,8 +485,11 @@ final class LatLonShapeBoundingBoxQuery extends SpatialQuery {
|
|||
}
|
||||
|
||||
/** Returns the Within relation to the provided triangle */
|
||||
Component2D.WithinRelation withinLine(int ax, int ay, boolean ab, int bx, int by) {
|
||||
if (ab == true && edgeIntersectsBox(ax, ay, bx, by, minX, maxX, minY, maxY) == true) {
|
||||
Component2D.WithinRelation withinLine(int aX, int aY, boolean ab, int bX, int bY) {
|
||||
if (contains(aX, aY) || contains(bX, bY)) {
|
||||
return Component2D.WithinRelation.NOTWITHIN;
|
||||
}
|
||||
if (ab == true && edgeIntersectsBox(aX, aY, bX, bY, minX, maxX, minY, maxY) == true) {
|
||||
return Component2D.WithinRelation.NOTWITHIN;
|
||||
}
|
||||
return Component2D.WithinRelation.DISJOINT;
|
||||
|
|
|
@ -159,6 +159,9 @@ class Circle2D implements Component2D {
|
|||
if (calculator.disjoint(minX, maxX, minY, maxY)) {
|
||||
return WithinRelation.DISJOINT;
|
||||
}
|
||||
if (contains(aX, aY) || contains(bX, bY)) {
|
||||
return WithinRelation.NOTWITHIN;
|
||||
}
|
||||
if (ab == true && calculator.intersectsLine(aX, aY, bX, bY)) {
|
||||
return WithinRelation.NOTWITHIN;
|
||||
}
|
||||
|
|
|
@ -257,10 +257,13 @@ final class Polygon2D implements Component2D {
|
|||
boolean ab,
|
||||
double bX,
|
||||
double bY) {
|
||||
if (ab == true
|
||||
&& Component2D.disjoint(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY)
|
||||
== false
|
||||
&& tree.crossesLine(minX, maxX, minY, maxY, aX, aY, bX, bY, true)) {
|
||||
if (Component2D.disjoint(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY)) {
|
||||
return WithinRelation.DISJOINT;
|
||||
}
|
||||
if (contains(aX, aY) || contains(bX, bY)) {
|
||||
return WithinRelation.NOTWITHIN;
|
||||
}
|
||||
if (ab == true && tree.crossesLine(minX, maxX, minY, maxY, aX, aY, bX, bY, true)) {
|
||||
return WithinRelation.NOTWITHIN;
|
||||
}
|
||||
return WithinRelation.DISJOINT;
|
||||
|
|
|
@ -164,10 +164,13 @@ final class Rectangle2D implements Component2D {
|
|||
boolean ab,
|
||||
double bX,
|
||||
double bY) {
|
||||
if (ab == true
|
||||
&& Component2D.disjoint(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY)
|
||||
== false
|
||||
&& edgesIntersect(aX, aY, bX, bY)) {
|
||||
if (Component2D.disjoint(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY)) {
|
||||
return WithinRelation.DISJOINT;
|
||||
}
|
||||
if (contains(aX, aY) || contains(bX, bY)) {
|
||||
return WithinRelation.NOTWITHIN;
|
||||
}
|
||||
if (ab == true && edgesIntersect(aX, aY, bX, bY)) {
|
||||
return WithinRelation.NOTWITHIN;
|
||||
}
|
||||
return WithinRelation.DISJOINT;
|
||||
|
|
|
@ -22,6 +22,7 @@ import static org.apache.lucene.geo.GeoEncodingUtils.encodeLatitude;
|
|||
import static org.apache.lucene.geo.GeoEncodingUtils.encodeLongitude;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomNumbers;
|
||||
import java.io.IOException;
|
||||
import org.apache.lucene.document.ShapeField.QueryRelation;
|
||||
import org.apache.lucene.geo.Circle;
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
|
@ -915,24 +916,52 @@ public class TestLatLonShape extends LuceneTestCase {
|
|||
IOUtils.close(r, dir);
|
||||
}
|
||||
|
||||
public void testContainsIndexedGeometryCollection() throws Exception {
|
||||
Directory dir = newDirectory();
|
||||
RandomIndexWriter w = new RandomIndexWriter(random(), dir);
|
||||
public void testContainsGeometryCollectionIntersectsPoint() throws Exception {
|
||||
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);
|
||||
doTestContainsGeometryCollectionIntersects(
|
||||
LatLonShape.createIndexableFields(FIELDNAME, polygon),
|
||||
// point inside the indexed polygon
|
||||
LatLonShape.createIndexableFields(FIELDNAME, 5, 5));
|
||||
}
|
||||
|
||||
public void testContainsGeometryCollectionIntersectsLine() throws Exception {
|
||||
Polygon polygon =
|
||||
new Polygon(
|
||||
new double[] {-64, -64, 64, 64, -64}, new double[] {-132, 132, 132, -132, -132});
|
||||
Line line = new Line(new double[] {5, 5.1}, new double[] {5, 5.1});
|
||||
doTestContainsGeometryCollectionIntersects(
|
||||
LatLonShape.createIndexableFields(FIELDNAME, polygon),
|
||||
// Line inside the polygon
|
||||
LatLonShape.createIndexableFields(FIELDNAME, line));
|
||||
}
|
||||
|
||||
public void testContainsGeometryCollectionIntersectsPolygon() throws Exception {
|
||||
Polygon polygon =
|
||||
new Polygon(
|
||||
new double[] {-64, -64, 64, 64, -64}, new double[] {-132, 132, 132, -132, -132});
|
||||
Polygon polygonInside =
|
||||
new Polygon(new double[] {5, 5, 5.1, 5.1, 5}, new double[] {5, 5.1, 5.1, 5, 5});
|
||||
doTestContainsGeometryCollectionIntersects(
|
||||
LatLonShape.createIndexableFields(FIELDNAME, polygon),
|
||||
// this polygon is inside the other polygon
|
||||
LatLonShape.createIndexableFields(FIELDNAME, polygonInside));
|
||||
}
|
||||
|
||||
private void doTestContainsGeometryCollectionIntersects(
|
||||
Field[] containsFields, Field[] intersectsField) throws IOException {
|
||||
Directory dir = newDirectory();
|
||||
RandomIndexWriter w = new RandomIndexWriter(random(), dir);
|
||||
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) {
|
||||
for (Field f : containsFields) {
|
||||
doc.add(f);
|
||||
}
|
||||
for (int j = 0; j < 10; j++) {
|
||||
for (Field f : pointFields) {
|
||||
for (Field f : intersectsField) {
|
||||
doc.add(f);
|
||||
}
|
||||
}
|
||||
|
@ -946,8 +975,8 @@ public class TestLatLonShape extends LuceneTestCase {
|
|||
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
|
||||
// belonging to the same document. In this case the query geometry contains the indexed fields
|
||||
// but the intersectsFields are
|
||||
// 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);
|
||||
|
|
Loading…
Reference in New Issue