Fix flat polygons incorrectly containing intersecting geometries (#12022)

This commit is contained in:
Craig Taverner 2022-12-15 14:56:09 +01:00 committed by GitHub
parent 11f2bc2056
commit 3e8ef57e3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 0 deletions

View File

@ -195,6 +195,8 @@ Bug Fixes
* GITHUB#11986: Fix algorithm that chooses the bridge between a polygon and a hole when there is
common vertex. (Ignacio Vera)
* GITHUB#12020: Fixes bug whereby very flat polygons can incorrectly contain intersecting geometries. (Craig Taverner)
Optimizations
---------------------
* GITHUB#11738: Optimize MultiTermQueryConstantScoreWrapper when a term is present that matches all

View File

@ -376,6 +376,8 @@ public final class ShapeField {
if (triangle.aX == triangle.cX && triangle.aY == triangle.cY) {
triangle.type = DecodedTriangle.TYPE.POINT;
} else {
// a and b are identical, remove ab, and merge bc and ca
triangle.ab = triangle.bc | triangle.ca;
triangle.bX = triangle.cX;
triangle.bY = triangle.cY;
triangle.cX = triangle.aX;
@ -383,8 +385,12 @@ public final class ShapeField {
triangle.type = DecodedTriangle.TYPE.LINE;
}
} else if (triangle.aX == triangle.cX && triangle.aY == triangle.cY) {
// a and c are identical, remove ac, and merge ab and bc
triangle.ab = triangle.ab | triangle.bc;
triangle.type = DecodedTriangle.TYPE.LINE;
} else if (triangle.bX == triangle.cX && triangle.bY == triangle.cY) {
// b and c are identical, remove bc, and merge ab and ca
triangle.ab = triangle.ab | triangle.ca;
triangle.cX = triangle.aX;
triangle.cY = triangle.aY;
triangle.type = DecodedTriangle.TYPE.LINE;

View File

@ -949,6 +949,34 @@ public class TestLatLonShape extends LuceneTestCase {
LatLonShape.createIndexableFields(FIELDNAME, polygonInside));
}
public void testFlatPolygonDoesNotContainIntersectingLine() throws IOException {
// Create line intersecting very flat polygon (but not contained)
double[] lons = new double[] {-0.001, -0.001, 0.001, 0.001, -0.001};
double[] lats = new double[] {1e-10, 0, -1e-10, 0, 1e-10};
Polygon polygon = new Polygon(lats, lons);
Line line = new Line(new double[] {0.0, 0.001}, new double[] {0.0, 0.0});
// Index the polygon
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);
// search for line within the polygon
Query q = LatLonShape.newGeometryQuery(FIELDNAME, QueryRelation.CONTAINS, line);
TopDocs topDocs = s.search(q, 1);
assertEquals("Polygon should not contain the line,", 0, topDocs.scoreDocs.length);
// cleanup
IOUtils.close(r, dir);
}
private void doTestContainsGeometryCollectionIntersects(
Field[] containsFields, Field[] intersectsField) throws IOException {
Directory dir = newDirectory();