diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConcavePolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConcavePolygon.java index 0d8f6150b3c..a133b3e77db 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConcavePolygon.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConcavePolygon.java @@ -50,7 +50,11 @@ class GeoConcavePolygon extends GeoBasePolygon { protected boolean isDone = false; /** A bounds object for each sided plane */ protected Map eitherBounds = null; - + /** Edge plane for one side of intersection */ + protected Map edgePlanes = null; + /** Intersection bounds */ + protected Map intersectionBounds = null; + /** * Create a concave polygon from a list of points. The first point must be on the * external edge. @@ -210,6 +214,8 @@ class GeoConcavePolygon extends GeoBasePolygon { // For each edge, create a bounds object. eitherBounds = new HashMap<>(edges.length); + intersectionBounds = new HashMap<>(edges.length); + edgePlanes = new HashMap<>(edges.length); for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) { final SidedPlane edge = edges[edgeIndex]; final SidedPlane invertedEdge = invertedEdges[edgeIndex]; @@ -218,10 +224,29 @@ class GeoConcavePolygon extends GeoBasePolygon { bound1Index++; } int bound2Index = legalIndex(edgeIndex-1); + int otherIndex = bound2Index; + final SidedPlane otherEdge; + final SidedPlane otherInvertedEdge; + if (invertedEdges[legalIndex(otherIndex)].isNumericallyIdentical(invertedEdge)) { + otherInvertedEdge = null; + otherEdge = null; + } else { + otherInvertedEdge = invertedEdges[legalIndex(otherIndex)]; + otherEdge = edges[legalIndex(otherIndex)]; + } while (invertedEdges[legalIndex(bound2Index)].isNumericallyIdentical(invertedEdge)) { bound2Index--; } eitherBounds.put(edge, new EitherBound(invertedEdges[legalIndex(bound1Index)], invertedEdges[legalIndex(bound2Index)])); + // For intersections, we look at the point at the intersection between the previous edge and this one. We need to locate the + // Intersection bounds needs to look even further forwards/backwards + if (otherInvertedEdge != null) { + while (invertedEdges[legalIndex(otherIndex)].isNumericallyIdentical(otherInvertedEdge)) { + otherIndex--; + } + intersectionBounds.put(edge, new EitherBound(invertedEdges[legalIndex(otherIndex)], invertedEdges[legalIndex(bound2Index)])); + edgePlanes.put(edge, otherEdge); + } } // Pick an edge point arbitrarily from the outer polygon. Glom this together with all edge points from @@ -403,6 +428,10 @@ class GeoConcavePolygon extends GeoBasePolygon { // Add planes with membership. for (final SidedPlane edge : edges) { bounds.addPlane(planetModel, edge, eitherBounds.get(edge)); + final Membership m = intersectionBounds.get(edge); + if (m != null) { + bounds.addIntersection(planetModel, edgePlanes.get(edge), edge, m); + } } } diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConvexPolygon.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConvexPolygon.java index 2ed516ada2c..860eb2655ec 100755 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConvexPolygon.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/geom/GeoConvexPolygon.java @@ -48,6 +48,10 @@ class GeoConvexPolygon extends GeoBasePolygon { protected boolean isDone = false; /** A bounds object for each sided plane */ protected Map eitherBounds = null; + /** Edge plane for one side of intersection */ + protected Map edgePlanes = null; + /** Intersection bounds */ + protected Map intersectionBounds = null; /** * Create a convex polygon from a list of points. The first point must be on the @@ -206,6 +210,8 @@ class GeoConvexPolygon extends GeoBasePolygon { // For each edge, create a bounds object. eitherBounds = new HashMap<>(edges.length); + intersectionBounds = new HashMap<>(edges.length); + edgePlanes = new HashMap<>(edges.length); for (int edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) { final SidedPlane edge = edges[edgeIndex]; int bound1Index = legalIndex(edgeIndex+1); @@ -213,10 +219,27 @@ class GeoConvexPolygon extends GeoBasePolygon { bound1Index++; } int bound2Index = legalIndex(edgeIndex-1); + int otherIndex = bound2Index; + final SidedPlane otherEdge; + if (edges[legalIndex(otherIndex)].isNumericallyIdentical(edge)) { + otherEdge = null; + } else { + otherEdge = edges[legalIndex(otherIndex)]; + } + // Look for bound2 while (edges[legalIndex(bound2Index)].isNumericallyIdentical(edge)) { bound2Index--; } eitherBounds.put(edge, new EitherBound(edges[legalIndex(bound1Index)], edges[legalIndex(bound2Index)])); + // For intersections, we look at the point at the intersection between the previous edge and this one. We need to locate the + // Intersection bounds needs to look even further forwards/backwards + if (otherEdge != null) { + while (edges[legalIndex(otherIndex)].isNumericallyIdentical(otherEdge)) { + otherIndex--; + } + intersectionBounds.put(edge, new EitherBound(edges[legalIndex(otherIndex)], edges[legalIndex(bound2Index)])); + edgePlanes.put(edge, otherEdge); + } } // Pick an edge point arbitrarily from the outer polygon. Glom this together with all edge points from @@ -383,7 +406,7 @@ class GeoConvexPolygon extends GeoBasePolygon { bounds.addPoint(planetModel.MAX_Y_POLE); } - // Add all the points + // Add all the points and the intersections for (final GeoPoint point : points) { bounds.addPoint(point); } @@ -391,6 +414,10 @@ class GeoConvexPolygon extends GeoBasePolygon { // Add planes with membership. for (final SidedPlane edge : edges) { bounds.addPlane(planetModel, edge, eitherBounds.get(edge)); + final Membership m = intersectionBounds.get(edge); + if (m != null) { + bounds.addIntersection(planetModel, edgePlanes.get(edge), edge, m); + } } } diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java index d651491c9ff..69f5999cba7 100644 --- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java +++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java @@ -238,6 +238,29 @@ public class TestGeo3DPoint extends LuceneTestCase { log.println(" root cell: " + root); } + // make sure the root cell (XYZBounds) does in fact contain all points that the shape contains + { + boolean fail = false; + for(int docID=0;docID