From 08ca33f57e5f0ae4aa6008ea898ff4c7a25bcec0 Mon Sep 17 00:00:00 2001 From: Karl Wright Date: Sun, 2 Oct 2016 15:17:58 -0400 Subject: [PATCH] LUCENE-7430: Add some explicit delta for bounds objects that corresponds to point resolution in doc values. --- .../lucene/spatial3d/Geo3DDocValuesField.java | 54 +++++++++++++++++++ .../PointInShapeIntersectVisitor.java | 30 +++++++---- .../lucene/spatial3d/TestGeo3DPoint.java | 4 +- 3 files changed, 78 insertions(+), 10 deletions(-) diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java index dd171ec1ae0..ef33fd572bd 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DDocValuesField.java @@ -67,6 +67,12 @@ public class Geo3DDocValuesField extends Field { private final static double yFactor = 1.0 / inverseYFactor; private final static double zFactor = 1.0 / inverseZFactor; + // These values are the delta between a value and the next value in each specific dimension + + private final static double xStep = inverseXFactor; + private final static double yStep = inverseYFactor; + private final static double zStep = inverseZFactor; + /** * Type for a Geo3DDocValuesField *

@@ -182,6 +188,54 @@ public class Geo3DDocValuesField extends Field { return decodeZ(((int)(docValue)) & 0x1FFFFF); } + /** Round the provided X value down, by encoding it, decrementing it, and unencoding it. + * @param startValue is the starting value. + * @return the rounded value. + */ + public static double roundDownX(final double startValue) { + return startValue - xStep; + } + + /** Round the provided X value up, by encoding it, incrementing it, and unencoding it. + * @param startValue is the starting value. + * @return the rounded value. + */ + public static double roundUpX(final double startValue) { + return startValue + xStep; + } + + /** Round the provided Y value down, by encoding it, decrementing it, and unencoding it. + * @param startValue is the starting value. + * @return the rounded value. + */ + public static double roundDownY(final double startValue) { + return startValue - yStep; + } + + /** Round the provided Y value up, by encoding it, incrementing it, and unencoding it. + * @param startValue is the starting value. + * @return the rounded value. + */ + public static double roundUpY(final double startValue) { + return startValue + yStep; + } + + /** Round the provided Z value down, by encoding it, decrementing it, and unencoding it. + * @param startValue is the starting value. + * @return the rounded value. + */ + public static double roundDownZ(final double startValue) { + return startValue - zStep; + } + + /** Round the provided Z value up, by encoding it, incrementing it, and unencoding it. + * @param startValue is the starting value. + * @return the rounded value. + */ + public static double roundUpZ(final double startValue) { + return startValue + zStep; + } + // For encoding/decoding, we generally want the following behavior: // (1) If you encode the maximum value or the minimum value, the resulting int fits in 21 bits. // (2) If you decode an encoded value, you get back the original value for both the minimum and maximum planet model values. 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 77551090e51..422c40f68fe 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInShapeIntersectVisitor.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/PointInShapeIntersectVisitor.java @@ -30,13 +30,25 @@ import org.apache.lucene.util.NumericUtils; class PointInShapeIntersectVisitor implements IntersectVisitor { private final DocIdSetBuilder hits; private final GeoShape shape; - private final XYZBounds shapeBounds; + private final double minimumX; + private final double maximumX; + private final double minimumY; + private final double maximumY; + private final double minimumZ; + private final double maximumZ; private DocIdSetBuilder.BulkAdder adder; - public PointInShapeIntersectVisitor(DocIdSetBuilder hits, GeoShape shape, XYZBounds shapeBounds) { + public PointInShapeIntersectVisitor(DocIdSetBuilder hits, + GeoShape shape, + XYZBounds bounds) { this.hits = hits; this.shape = shape; - this.shapeBounds = shapeBounds; + this.minimumX = Geo3DDocValuesField.roundDownX(bounds.getMinimumX()); + this.maximumX = Geo3DDocValuesField.roundUpX(bounds.getMaximumX()); + this.minimumY = Geo3DDocValuesField.roundDownY(bounds.getMinimumY()); + this.maximumY = Geo3DDocValuesField.roundUpY(bounds.getMaximumY()); + this.minimumZ = Geo3DDocValuesField.roundDownZ(bounds.getMinimumZ()); + this.maximumZ = Geo3DDocValuesField.roundUpZ(bounds.getMaximumZ()); } @Override @@ -55,9 +67,9 @@ 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 (x >= shapeBounds.getMinimumX() && x <= shapeBounds.getMaximumX() && - y >= shapeBounds.getMinimumY() && y <= shapeBounds.getMaximumY() && - z >= shapeBounds.getMinimumZ() && z <= shapeBounds.getMaximumZ()) { + if (x >= minimumX && x <= maximumX && + y >= minimumY && y <= maximumY && + z >= minimumZ && z <= maximumZ) { if (shape.isWithin(x, y, z)) { adder.add(docID); } @@ -83,9 +95,9 @@ class PointInShapeIntersectVisitor implements IntersectVisitor { 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) { + if (minimumX >= xMin && maximumX <= xMax && + minimumY >= yMin && maximumY <= yMax && + minimumZ >= zMin && maximumZ <= zMax) { return Relation.CELL_CROSSES_QUERY; } 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 d9baf612e2b..f5b744182fd 100644 --- a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java +++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/TestGeo3DPoint.java @@ -1480,7 +1480,9 @@ public class TestGeo3DPoint extends LuceneTestCase { b.append("target is in leaf " + leafReader + " of full reader " + reader + "\n"); DocIdSetBuilder hits = new DocIdSetBuilder(leafReader.maxDoc()); - ExplainingVisitor visitor = new ExplainingVisitor(shape, targetDocPoint, scaledDocPoint, new PointInShapeIntersectVisitor(hits, shape, bounds), docID - reader.leaves().get(subIndex).docBase, 3, Integer.BYTES, b); + ExplainingVisitor visitor = new ExplainingVisitor(shape, targetDocPoint, scaledDocPoint, + new PointInShapeIntersectVisitor(hits, shape, bounds), + docID - reader.leaves().get(subIndex).docBase, 3, Integer.BYTES, b); // Do first phase, where we just figure out the "path" that leads to the target docID: leafReader.getPointValues().intersect(fieldName, visitor);