diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInGeo3DShapeQuery.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInGeo3DShapeQuery.java index ef0fe47f1e1..24a4224ac03 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInGeo3DShapeQuery.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInGeo3DShapeQuery.java @@ -21,6 +21,7 @@ import java.io.IOException; import org.apache.lucene.spatial3d.geom.BasePlanetObject; import org.apache.lucene.spatial3d.geom.GeoShape; import org.apache.lucene.spatial3d.geom.PlanetModel; +import org.apache.lucene.spatial3d.geom.XYZBounds; import org.apache.lucene.index.PointValues; import org.apache.lucene.index.LeafReader; import org.apache.lucene.index.LeafReaderContext; @@ -41,12 +42,15 @@ import org.apache.lucene.util.DocIdSetBuilder; final class PointInGeo3DShapeQuery extends Query { final String field; final GeoShape shape; - + final XYZBounds shapeBounds; + /** The lats/lons must be clockwise or counter-clockwise. */ public PointInGeo3DShapeQuery(String field, GeoShape shape) { this.field = field; this.shape = shape; - + this.shapeBounds = new XYZBounds(); + shape.getBounds(shapeBounds); + if (shape instanceof BasePlanetObject) { BasePlanetObject planetObject = (BasePlanetObject) shape; if (planetObject.getPlanetModel().equals(PlanetModel.WGS84) == false) { @@ -95,7 +99,7 @@ final class PointInGeo3DShapeQuery extends Query { DocIdSetBuilder result = new DocIdSetBuilder(reader.maxDoc()); - values.intersect(field, new PointInShapeIntersectVisitor(result, shape)); + values.intersect(field, new PointInShapeIntersectVisitor(result, shape, shapeBounds)); return new ConstantScoreScorer(this, score(), result.build().iterator()); } diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInShapeIntersectVisitor.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInShapeIntersectVisitor.java index b9d4e70a6c8..348396bc97b 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInShapeIntersectVisitor.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInShapeIntersectVisitor.java @@ -23,16 +23,19 @@ import org.apache.lucene.spatial3d.geom.GeoArea; import org.apache.lucene.spatial3d.geom.GeoAreaFactory; import org.apache.lucene.spatial3d.geom.GeoShape; import org.apache.lucene.spatial3d.geom.PlanetModel; +import org.apache.lucene.spatial3d.geom.XYZBounds; import org.apache.lucene.util.DocIdSetBuilder; import org.apache.lucene.util.NumericUtils; class PointInShapeIntersectVisitor implements IntersectVisitor { private final DocIdSetBuilder hits; private final GeoShape shape; - - public PointInShapeIntersectVisitor(DocIdSetBuilder hits, GeoShape shape) { + private final XYZBounds shapeBounds; + + public PointInShapeIntersectVisitor(DocIdSetBuilder hits, GeoShape shape, XYZBounds shapeBounds) { this.hits = hits; this.shape = shape; + this.shapeBounds = shapeBounds; } @Override @@ -46,8 +49,12 @@ class PointInShapeIntersectVisitor implements IntersectVisitor { double x = Geo3DPoint.decodeDimension(packedValue, 0); double y = Geo3DPoint.decodeDimension(packedValue, Integer.BYTES); double z = Geo3DPoint.decodeDimension(packedValue, 2 * Integer.BYTES); - if (shape.isWithin(x, y, z)) { - hits.add(docID); + if (x >= shapeBounds.getMinimumX() && x <= shapeBounds.getMaximumX() && + y >= shapeBounds.getMinimumY() && y <= shapeBounds.getMaximumY() && + z >= shapeBounds.getMinimumZ() && z <= shapeBounds.getMaximumZ()) { + if (shape.isWithin(x, y, z)) { + hits.add(docID); + } } } @@ -69,6 +76,14 @@ class PointInShapeIntersectVisitor implements IntersectVisitor { assert yMin <= yMax; assert zMin <= zMax; + // First, check bounds. If the shape is entirely contained, return CELL_CROSSES_QUERY. + if (shapeBounds.getMinimumX() >= xMin && shapeBounds.getMaximumX() <= xMax && + shapeBounds.getMinimumY() >= yMin && shapeBounds.getMaximumY() <= yMax && + shapeBounds.getMinimumZ() >= zMin && shapeBounds.getMaximumZ() <= zMax) { + return Relation.CELL_CROSSES_QUERY; + } + + // Quick test failed so do slower one... GeoArea xyzSolid = GeoAreaFactory.makeGeoArea(PlanetModel.WGS84, xMin, xMax, yMin, yMax, zMin, zMax); switch(xyzSolid.getRelationship(shape)) {