diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 8a60f771abc1..0a986abade2f 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -32,6 +32,9 @@ Other --------------------- (No changes) +* LUCENE-8746: Refactor EdgeTree - Introduce a Component tree that represents the tree of components (e.g polygons). + Edge tree is now just a tree of edges. (Ignacio Vera) + Build * Upgrade forbiddenapis to version 2.7; upgrade Groovy to 2.4.17. (Uwe Schindler) diff --git a/lucene/core/src/java/org/apache/lucene/document/LatLonDocValuesPointInPolygonQuery.java b/lucene/core/src/java/org/apache/lucene/document/LatLonDocValuesPointInPolygonQuery.java index 7b09f84bcdb6..525b77ece46f 100644 --- a/lucene/core/src/java/org/apache/lucene/document/LatLonDocValuesPointInPolygonQuery.java +++ b/lucene/core/src/java/org/apache/lucene/document/LatLonDocValuesPointInPolygonQuery.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.Arrays; +import org.apache.lucene.geo.Component2D; import org.apache.lucene.geo.GeoEncodingUtils; import org.apache.lucene.geo.Polygon; import org.apache.lucene.geo.Polygon2D; @@ -103,8 +104,8 @@ public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float bo return new ConstantScoreWeight(this, boost) { - final Polygon2D tree = Polygon2D.create(polygons); - final GeoEncodingUtils.PolygonPredicate polygonPredicate = GeoEncodingUtils.createPolygonPredicate(polygons, tree); + final Component2D tree = Polygon2D.create(polygons); + final GeoEncodingUtils.PolygonPredicate polygonPredicate = GeoEncodingUtils.createComponentPredicate(tree); @Override public Scorer scorer(LeafReaderContext context) throws IOException { diff --git a/lucene/core/src/java/org/apache/lucene/document/LatLonPointInPolygonQuery.java b/lucene/core/src/java/org/apache/lucene/document/LatLonPointInPolygonQuery.java index 9006f160f17c..82212aed3ad7 100644 --- a/lucene/core/src/java/org/apache/lucene/document/LatLonPointInPolygonQuery.java +++ b/lucene/core/src/java/org/apache/lucene/document/LatLonPointInPolygonQuery.java @@ -19,10 +19,10 @@ import java.io.IOException; import java.util.Arrays; +import org.apache.lucene.geo.Component2D; import org.apache.lucene.geo.GeoEncodingUtils; import org.apache.lucene.geo.Polygon; import org.apache.lucene.geo.Polygon2D; -import org.apache.lucene.geo.Rectangle; import org.apache.lucene.index.FieldInfo; import org.apache.lucene.index.LeafReader; import org.apache.lucene.index.LeafReaderContext; @@ -85,7 +85,7 @@ public void visit(QueryVisitor visitor) { } } - private IntersectVisitor getIntersectVisitor(DocIdSetBuilder result, Polygon2D tree, GeoEncodingUtils.PolygonPredicate polygonPredicate, + private IntersectVisitor getIntersectVisitor(DocIdSetBuilder result, Component2D tree, GeoEncodingUtils.PolygonPredicate polygonPredicate, byte[] minLat, byte[] maxLat, byte[] minLon, byte[] maxLon) { return new IntersectVisitor() { DocIdSetBuilder.BulkAdder adder; @@ -134,7 +134,7 @@ public Relation compare(byte[] minPackedValue, byte[] maxPackedValue) { double cellMaxLat = decodeLatitude(maxPackedValue, 0); double cellMaxLon = decodeLongitude(maxPackedValue, Integer.BYTES); - return tree.relate(cellMinLat, cellMaxLat, cellMinLon, cellMaxLon); + return tree.relate(cellMinLon, cellMaxLon, cellMinLat, cellMaxLat); } }; } @@ -142,20 +142,17 @@ public Relation compare(byte[] minPackedValue, byte[] maxPackedValue) { @Override public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException { + final Component2D tree = Polygon2D.create(polygons); + final GeoEncodingUtils.PolygonPredicate polygonPredicate = GeoEncodingUtils.createComponentPredicate(tree); // bounding box over all polygons, this can speed up tree intersection/cheaply improve approximation for complex multi-polygons - // these are pre-encoded with LatLonPoint's encoding - final Rectangle box = Rectangle.fromPolygon(polygons); final byte minLat[] = new byte[Integer.BYTES]; final byte maxLat[] = new byte[Integer.BYTES]; final byte minLon[] = new byte[Integer.BYTES]; final byte maxLon[] = new byte[Integer.BYTES]; - NumericUtils.intToSortableBytes(encodeLatitude(box.minLat), minLat, 0); - NumericUtils.intToSortableBytes(encodeLatitude(box.maxLat), maxLat, 0); - NumericUtils.intToSortableBytes(encodeLongitude(box.minLon), minLon, 0); - NumericUtils.intToSortableBytes(encodeLongitude(box.maxLon), maxLon, 0); - - final Polygon2D tree = Polygon2D.create(polygons); - final GeoEncodingUtils.PolygonPredicate polygonPredicate = GeoEncodingUtils.createPolygonPredicate(polygons, tree); + NumericUtils.intToSortableBytes(encodeLatitude(tree.getMinY()), minLat, 0); + NumericUtils.intToSortableBytes(encodeLatitude(tree.getMaxY()), maxLat, 0); + NumericUtils.intToSortableBytes(encodeLongitude(tree.getMinX()), minLon, 0); + NumericUtils.intToSortableBytes(encodeLongitude(tree.getMaxX()), maxLon, 0); return new ConstantScoreWeight(this, boost) { diff --git a/lucene/core/src/java/org/apache/lucene/geo/Component2D.java b/lucene/core/src/java/org/apache/lucene/geo/Component2D.java new file mode 100644 index 000000000000..10ced04ac3cf --- /dev/null +++ b/lucene/core/src/java/org/apache/lucene/geo/Component2D.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.lucene.geo; + +import org.apache.lucene.index.PointValues; + +import static org.apache.lucene.geo.GeoUtils.orient; + +/** + * 2D Geometry object that supports spatial relationships with bounding boxes, + * triangles and points. + * + * @lucene.internal + **/ +public interface Component2D { + + /** min X value for the component **/ + double getMinX(); + + /** max X value for the component **/ + double getMaxX(); + + /** min Y value for the component **/ + double getMinY(); + + /** max Y value for the component **/ + double getMaxY(); + + /** relates this component2D with a point **/ + boolean contains(double x, double y); + + /** relates this component2D with a bounding box **/ + PointValues.Relation relate(double minX, double maxX, double minY, double maxY); + + /** relates this component2D with a triangle **/ + PointValues.Relation relateTriangle(double minX, double maxX, double minY, double maxY, + double aX, double aY, double bX, double bY, double cX, double cY); + + /** relates this component2D with a triangle **/ + default PointValues.Relation relateTriangle(double aX, double aY, double bX, double bY, double cX, double cY) { + double minY = StrictMath.min(StrictMath.min(aY, bY), cY); + double minX = StrictMath.min(StrictMath.min(aX, bX), cX); + double maxY = StrictMath.max(StrictMath.max(aY, bY), cY); + double maxX = StrictMath.max(StrictMath.max(aX, bX), cX); + return relateTriangle(minX, maxX, minY, maxY, aX, aY, bX, bY, cX, cY); + } + + /** Compute whether the bounding boxes are disjoint **/ + static boolean disjoint(double minX1, double maxX1, double minY1, double maxY1, double minX2, double maxX2, double minY2, double maxY2) { + return (maxY1 < minY2 || minY1 > maxY2 || maxX1 < minX2 || minX1 > maxX2); + } + + /** Compute whether the first bounding box 1 is within the second bounding box **/ + static boolean within(double minX1, double maxX1, double minY1, double maxY1, double minX2, double maxX2, double minY2, double maxY2) { + return (minY2 <= minY1 && maxY2 >= maxY1 && minX2 <= minX1 && maxX2 >= maxX1); + } + + /** returns true if rectangle (defined by minX, maxX, minY, maxY) contains the X Y point */ + static boolean containsPoint(final double x, final double y, final double minX, final double maxX, final double minY, final double maxY) { + return x >= minX && x <= maxX && y >= minY && y <= maxY; + } + + /** + * Compute whether the given x, y point is in a triangle; uses the winding order method */ + static boolean pointInTriangle(double minX, double maxX, double minY, double maxY, double x, double y, double aX, double aY, double bX, double bY, double cX, double cY) { + //check the bounding box because if the triangle is degenerated, e.g points and lines, we need to filter out + //coplanar points that are not part of the triangle. + if (x >= minX && x <= maxX && y >= minY && y <= maxY) { + int a = orient(x, y, aX, aY, bX, bY); + int b = orient(x, y, bX, bY, cX, cY); + if (a == 0 || b == 0 || a < 0 == b < 0) { + int c = orient(x, y, cX, cY, aX, aY); + return c == 0 || (c < 0 == (b < 0 || a < 0)); + } + return false; + } else { + return false; + } + } + +} \ No newline at end of file diff --git a/lucene/core/src/java/org/apache/lucene/geo/ComponentTree.java b/lucene/core/src/java/org/apache/lucene/geo/ComponentTree.java new file mode 100644 index 000000000000..220c53d1ed72 --- /dev/null +++ b/lucene/core/src/java/org/apache/lucene/geo/ComponentTree.java @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.lucene.geo; + +import java.util.Comparator; + +import org.apache.lucene.index.PointValues.Relation; +import org.apache.lucene.util.ArrayUtil; + +/** + * 2D multi-component geometry implementation represented as an interval tree of components. + *
+ * Construction takes {@code O(n log n)} time for sorting and tree construction.
+ *
+ * @lucene.internal
+ */
+final class ComponentTree implements Component2D {
+ /** minimum latitude of this geometry's bounding box area */
+ private double minY;
+ /** maximum latitude of this geometry's bounding box area */
+ private double maxY;
+ /** minimum longitude of this geometry's bounding box area */
+ private double minX;
+ /** maximum longitude of this geometry's bounding box area */
+ private double maxX;
+ // child components, or null. Note internal nodes might mot have
+ // a consistent bounding box. Internal nodes should not be accessed
+ // outside if this class.
+ private Component2D left;
+ private Component2D right;
+ /** which dimension was this node split on */
+ // TODO: its implicit based on level, but boolean keeps code simple
+ final private boolean splitX;
+ /** root node of edge tree */
+ final private Component2D component;
+
+ protected ComponentTree(Component2D component, boolean splitX) {
+ this.minY = component.getMinY();
+ this.maxY = component.getMaxY();
+ this.minX = component.getMinX();
+ this.maxX = component.getMaxX();
+ this.component = component;
+ this.splitX = splitX;
+ }
+
+ @Override
+ public double getMinX() {
+ return minX;
+ }
+
+ @Override
+ public double getMaxX() {
+ return maxX;
+ }
+
+ @Override
+ public double getMinY() {
+ return minY;
+ }
+
+ @Override
+ public double getMaxY() {
+ return maxY;
+ }
+
+ @Override
+ public boolean contains(double x, double y) {
+ if (y <= this.maxY && x <= this.maxX) {
+ if (component.contains(x, y)) {
+ return true;
+ }
+ if (left != null) {
+ if (left.contains(x, y)) {
+ return true;
+ }
+ }
+ if (right != null && ((splitX == false && y >= this.component.getMinY()) || (splitX && x >= this.component.getMinX()))) {
+ if (right.contains(x, y)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /** Returns relation to the provided triangle */
+ @Override
+ public Relation relateTriangle(double minX, double maxX, double minY, double maxY,
+ double ax, double ay, double bx, double by, double cx, double cy) {
+ if (minY <= this.maxY && minX <= this.maxX) {
+ Relation relation = component.relateTriangle(minX, maxX, minY, maxY, ax, ay, bx, by, cx, cy);
+ if (relation != Relation.CELL_OUTSIDE_QUERY) {
+ return relation;
+ }
+ if (left != null) {
+ relation = left.relateTriangle(minX, maxX, minY, maxY, ax, ay, bx, by, cx, cy);
+ if (relation != Relation.CELL_OUTSIDE_QUERY) {
+ return relation;
+ }
+ }
+ if (right != null && ((splitX == false && maxY >= this.component.getMinY()) || (splitX && maxX >= this.component.getMinX()))) {
+ relation = right.relateTriangle(minX, maxX, minY, maxY, ax, ay, bx, by, cx, cy);
+ if (relation != Relation.CELL_OUTSIDE_QUERY) {
+ return relation;
+ }
+ }
+ }
+ return Relation.CELL_OUTSIDE_QUERY;
+ }
+
+ /** Returns relation to the provided rectangle */
+ @Override
+ public Relation relate(double minX, double maxX, double minY, double maxY) {
+ if (minY <= this.maxY && minX <= this.maxX) {
+ Relation relation = component.relate(minX, maxX, minY, maxY);
+ if (relation != Relation.CELL_OUTSIDE_QUERY) {
+ return relation;
+ }
+ if (left != null) {
+ relation = left.relate(minX, maxX, minY, maxY);
+ if (relation != Relation.CELL_OUTSIDE_QUERY) {
+ return relation;
+ }
+ }
+ if (right != null && ((splitX == false && maxY >= this.component.getMinY()) || (splitX && maxX >= this.component.getMinX()))) {
+ relation = right.relate(minX, maxX, minY, maxY);
+ if (relation != Relation.CELL_OUTSIDE_QUERY) {
+ return relation;
+ }
+ }
+ }
+ return Relation.CELL_OUTSIDE_QUERY;
+ }
+
+ /** Creates tree from provided components */
+ public static Component2D create(Component2D[] components) {
+ if (components.length == 1) {
+ return components[0];
+ }
+ ComponentTree root = createTree(components, 0, components.length - 1, false);
+ // pull up min values for the root node so it contains a consistent bounding box
+ for (Component2D component : components) {
+ root.minY = Math.min(root.minY, component.getMinY());
+ root.minX = Math.min(root.minX, component.getMinX());
+ }
+ return root;
+ }
+
+ /** Creates tree from sorted components (with range low and high inclusive) */
+ private static ComponentTree createTree(Component2D[] components, int low, int high, boolean splitX) {
+ if (low > high) {
+ return null;
+ }
+ final int mid = (low + high) >>> 1;
+ if (low < high) {
+ Comparator
+ * See
+ * https://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html for more information.
+ */
+ // ported to java from https://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html
+ // original code under the BSD license (https://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html#License%20to%20Use)
+ //
+ // Copyright (c) 1970-2003, Wm. Randolph Franklin
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+ // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
+ // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ //
+ // 1. Redistributions of source code must retain the above copyright
+ // notice, this list of conditions and the following disclaimers.
+ // 2. Redistributions in binary form must reproduce the above copyright
+ // notice in the documentation and/or other materials provided with
+ // the distribution.
+ // 3. The name of W. Randolph Franklin may not be used to endorse or
+ // promote products derived from this Software without specific
+ // prior written permission.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ // IN THE SOFTWARE.
+ protected boolean contains(double x, double y, AtomicBoolean isOnEdge) {
+ boolean res = false;
+ if (isOnEdge.get() == false && y <= this.max) {
+ if (y == this.y1 && y == this.y2 ||
+ (y <= this.y1 && y >= this.y2) != (y >= this.y1 && y <= this.y2)) {
+ if ((x == this.x1 && x == this.x2) ||
+ ((x <= this.x1 && x >= this.x2) != (x >= this.x1 && x <= this.x2) &&
+ GeoUtils.orient(this.x1, this.y1, this.x2, this.y2, x, y) == 0)) {
+ // if its on the boundary return true
+ isOnEdge.set(true);
+ return true;
+ } else if (this.y1 > y != this.y2 > y) {
+ res = x < (this.x2 - this.x1) * (y - this.y1) / (this.y2 - this.y1) + this.x1;
}
}
- if (right != null && ((splitX == false && maxLat >= this.minLat) || (splitX && maxLon >= this.minLon))) {
- relation = right.relate(minLat, maxLat, minLon, maxLon);
- if (relation != Relation.CELL_OUTSIDE_QUERY) {
- return relation;
- }
+ if (this.left != null) {
+ res ^= left.contains(x, y, isOnEdge);
}
- }
- return Relation.CELL_OUTSIDE_QUERY;
- }
-
- /** Returns relation to the provided rectangle for this component */
- protected abstract Relation componentRelate(double minLat, double maxLat, double minLon, double maxLon);
-
- /** Returns relation to the provided triangle for this component */
- protected abstract Relation componentRelateTriangle(double ax, double ay, double bx, double by, double cx, double cy);
-
-
- private Relation internalComponentRelateTriangle(double ax, double ay, double bx, double by, double cx, double cy) {
- // compute bounding box of triangle
- double minLat = StrictMath.min(StrictMath.min(ay, by), cy);
- double minLon = StrictMath.min(StrictMath.min(ax, bx), cx);
- double maxLat = StrictMath.max(StrictMath.max(ay, by), cy);
- double maxLon = StrictMath.max(StrictMath.max(ax, bx), cx);
- if (maxLon < this.minLon || minLon > this.maxLon || maxLat < this.minLat || minLat > this.maxLat) {
- return Relation.CELL_OUTSIDE_QUERY;
- } else if (bx == cx && by == cy) {
- return componentRelateTriangle(bx, by, ax, ay, cx, cy);
- } else if (ax == bx && ay == by) {
- return componentRelateTriangle(bx, by, cx, cy, ax, ay);
- }
- return componentRelateTriangle(ax, ay, bx, by, cx, cy);
- }
-
- /** Returns relation to the provided rectangle for this component */
- protected Relation internalComponentRelate(double minLat, double maxLat, double minLon, double maxLon) {
- // if the bounding boxes are disjoint then the shape does not cross
- if (maxLon < this.minLon || minLon > this.maxLon || maxLat < this.minLat || minLat > this.maxLat) {
- return Relation.CELL_OUTSIDE_QUERY;
- }
- // if the rectangle fully encloses us, we cross.
- if (minLat <= this.minLat && maxLat >= this.maxLat && minLon <= this.minLon && maxLon >= this.maxLon) {
- return Relation.CELL_CROSSES_QUERY;
+ if (this.right != null && y >= this.low) {
+ res ^= right.contains(x, y, isOnEdge);
+ }
}
- return componentRelate(minLat, maxLat, minLon, maxLon);
+ return isOnEdge.get() || res;
}
- /** Creates tree from sorted components (with range low and high inclusive) */
- protected static EdgeTree createTree(EdgeTree components[], int low, int high, boolean splitX) {
- if (low > high) {
- return null;
- }
- final int mid = (low + high) >>> 1;
- if (low < high) {
- Comparator
- * See
- * https://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html for more information.
- */
- // ported to java from https://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html
- // original code under the BSD license (https://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html#License%20to%20Use)
- //
- // Copyright (c) 1970-2003, Wm. Randolph Franklin
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- // documentation files (the "Software"), to deal in the Software without restriction, including without limitation
- // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
- // to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- //
- // 1. Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimers.
- // 2. Redistributions in binary form must reproduce the above copyright
- // notice in the documentation and/or other materials provided with
- // the distribution.
- // 3. The name of W. Randolph Franklin may not be used to endorse or
- // promote products derived from this Software without specific
- // prior written permission.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- private static boolean contains(Edge edge, double lat, double lon, AtomicBoolean isOnEdge) {
- boolean res = false;
- if (isOnEdge.get() == false && lat <= edge.max) {
- if (lat == edge.lat1 && lat == edge.lat2 ||
- (lat <= edge.lat1 && lat >= edge.lat2) != (lat >= edge.lat1 && lat <= edge.lat2)) {
- if ((lon == edge.lon1 && lon == edge.lon2) ||
- ((lon <= edge.lon1 && lon >= edge.lon2) != (lon >= edge.lon1 && lon <= edge.lon2) &&
- GeoUtils.orient(edge.lon1, edge.lat1, edge.lon2, edge.lat2, lon, lat) == 0)) {
- // if its on the boundary return true
- isOnEdge.set(true);
- return true;
- } else if (edge.lat1 > lat != edge.lat2 > lat) {
- res = lon < (edge.lon2 - edge.lon1) * (lat - edge.lat1) / (edge.lat2 - edge.lat1) + edge.lon1;
- }
- }
- if (edge.left != null) {
- res ^= contains(edge.left, lat, lon, isOnEdge);
- }
-
- if (edge.right != null && lat >= edge.low) {
- res ^= contains(edge.right, lat, lon, isOnEdge);
- }
- }
- return isOnEdge.get() || res;
+ return ComponentTree.create(components);
}
}
diff --git a/lucene/core/src/test/org/apache/lucene/geo/TestPolygon2D.java b/lucene/core/src/test/org/apache/lucene/geo/TestPolygon2D.java
index c43517b0a3a1..61cd2b51f337 100644
--- a/lucene/core/src/test/org/apache/lucene/geo/TestPolygon2D.java
+++ b/lucene/core/src/test/org/apache/lucene/geo/TestPolygon2D.java
@@ -35,7 +35,7 @@ public void testMultiPolygon() {
Polygon hole = new Polygon(new double[] { -10, -10, 10, 10, -10 }, new double[] { -10, 10, 10, -10, -10 });
Polygon outer = new Polygon(new double[] { -50, -50, 50, 50, -50 }, new double[] { -50, 50, 50, -50, -50 }, hole);
Polygon island = new Polygon(new double[] { -5, -5, 5, 5, -5 }, new double[] { -5, 5, 5, -5, -5 } );
- Polygon2D polygon = Polygon2D.create(outer, island);
+ Component2D polygon = Polygon2D.create(outer, island);
// contains(point)
assertTrue(polygon.contains(-2, 2)); // on the island
@@ -66,21 +66,21 @@ public void testPacMan() throws Exception {
double yMax = 1;//5;
// test cell crossing poly
- Polygon2D polygon = Polygon2D.create(new Polygon(py, px));
+ Component2D polygon = Polygon2D.create(new Polygon(py, px));
assertEquals(Relation.CELL_CROSSES_QUERY, polygon.relate(yMin, yMax, xMin, xMax));
}
public void testBoundingBox() throws Exception {
for (int i = 0; i < 100; i++) {
- Polygon2D polygon = Polygon2D.create(nextPolygon());
+ Component2D polygon = Polygon2D.create(nextPolygon());
for (int j = 0; j < 100; j++) {
double latitude = nextLatitude();
double longitude = nextLongitude();
// if the point is within poly, then it should be in our bounding box
- if (polygon.contains(latitude, longitude)) {
- assertTrue(latitude >= polygon.minLat && latitude <= polygon.maxLat);
- assertTrue(longitude >= polygon.minLon && longitude <= polygon.maxLon);
+ if (polygon.contains(longitude, latitude)) {
+ assertTrue(latitude >= polygon.getMinY() && latitude <= polygon.getMaxY());
+ assertTrue(longitude >= polygon.getMinX() && longitude <= polygon.getMaxX());
}
}
}
@@ -90,14 +90,14 @@ public void testBoundingBox() throws Exception {
public void testBoundingBoxEdgeCases() throws Exception {
for (int i = 0; i < 100; i++) {
Polygon polygon = nextPolygon();
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
for (int j = 0; j < 100; j++) {
double point[] = GeoTestUtil.nextPointNear(polygon);
double latitude = point[0];
double longitude = point[1];
// if the point is within poly, then it should be in our bounding box
- if (impl.contains(latitude, longitude)) {
+ if (impl.contains(longitude, latitude)) {
assertTrue(latitude >= polygon.minLat && latitude <= polygon.maxLat);
assertTrue(longitude >= polygon.minLon && longitude <= polygon.maxLon);
}
@@ -110,7 +110,7 @@ public void testContainsRandom() throws Exception {
int iters = atLeast(50);
for (int i = 0; i < iters; i++) {
Polygon polygon = nextPolygon();
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
for (int j = 0; j < 100; j++) {
Rectangle rectangle = GeoTestUtil.nextBoxNear(polygon);
@@ -147,12 +147,12 @@ public void testContainsRandom() throws Exception {
public void testContainsEdgeCases() throws Exception {
for (int i = 0; i < 1000; i++) {
Polygon polygon = nextPolygon();
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
for (int j = 0; j < 10; j++) {
Rectangle rectangle = GeoTestUtil.nextBoxNear(polygon);
// allowed to conservatively return false
- if (impl.relate(rectangle.minLat, rectangle.maxLat, rectangle.minLon, rectangle.maxLon) == Relation.CELL_INSIDE_QUERY) {
+ if (impl.relate(rectangle.minLon, rectangle.maxLon, rectangle.minLat, rectangle.maxLat) == Relation.CELL_INSIDE_QUERY) {
for (int k = 0; k < 100; k++) {
// this tests in our range but sometimes outside! so we have to double-check its really in other box
double point[] = GeoTestUtil.nextPointNear(rectangle);
@@ -160,7 +160,7 @@ public void testContainsEdgeCases() throws Exception {
double longitude = point[1];
// check for sure its in our box
if (latitude >= rectangle.minLat && latitude <= rectangle.maxLat && longitude >= rectangle.minLon && longitude <= rectangle.maxLon) {
- assertTrue(impl.contains(latitude, longitude));
+ assertTrue(impl.contains(longitude, latitude));
}
}
for (int k = 0; k < 20; k++) {
@@ -170,7 +170,7 @@ public void testContainsEdgeCases() throws Exception {
double longitude = point[1];
// check for sure its in our box
if (latitude >= rectangle.minLat && latitude <= rectangle.maxLat && longitude >= rectangle.minLon && longitude <= rectangle.maxLon) {
- assertTrue(impl.contains(latitude, longitude));
+ assertTrue(impl.contains(longitude, latitude));
}
}
}
@@ -183,12 +183,12 @@ public void testIntersectRandom() {
int iters = atLeast(10);
for (int i = 0; i < iters; i++) {
Polygon polygon = nextPolygon();
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
for (int j = 0; j < 100; j++) {
Rectangle rectangle = GeoTestUtil.nextBoxNear(polygon);
// allowed to conservatively return true.
- if (impl.relate(rectangle.minLat, rectangle.maxLat, rectangle.minLon, rectangle.maxLon) == Relation.CELL_OUTSIDE_QUERY) {
+ if (impl.relate(rectangle.minLon, rectangle.maxLon, rectangle.minLat, rectangle.maxLat) == Relation.CELL_OUTSIDE_QUERY) {
for (int k = 0; k < 1000; k++) {
double point[] = GeoTestUtil.nextPointNear(rectangle);
// this tests in our range but sometimes outside! so we have to double-check its really in other box
@@ -196,7 +196,7 @@ public void testIntersectRandom() {
double longitude = point[1];
// check for sure its in our box
if (latitude >= rectangle.minLat && latitude <= rectangle.maxLat && longitude >= rectangle.minLon && longitude <= rectangle.maxLon) {
- assertFalse(impl.contains(latitude, longitude));
+ assertFalse(impl.contains(longitude, latitude));
}
}
for (int k = 0; k < 100; k++) {
@@ -206,7 +206,7 @@ public void testIntersectRandom() {
double longitude = point[1];
// check for sure its in our box
if (latitude >= rectangle.minLat && latitude <= rectangle.maxLat && longitude >= rectangle.minLon && longitude <= rectangle.maxLon) {
- assertFalse(impl.contains(latitude, longitude));
+ assertFalse(impl.contains(longitude, latitude));
}
}
}
@@ -220,12 +220,12 @@ public void testIntersectRandom() {
public void testIntersectEdgeCases() {
for (int i = 0; i < 100; i++) {
Polygon polygon = nextPolygon();
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
for (int j = 0; j < 10; j++) {
Rectangle rectangle = GeoTestUtil.nextBoxNear(polygon);
// allowed to conservatively return false.
- if (impl.relate(rectangle.minLat, rectangle.maxLat, rectangle.minLon, rectangle.maxLon) == Relation.CELL_OUTSIDE_QUERY) {
+ if (impl.relate(rectangle.minLon, rectangle.maxLon, rectangle.minLat, rectangle.maxLat) == Relation.CELL_OUTSIDE_QUERY) {
for (int k = 0; k < 100; k++) {
// this tests in our range but sometimes outside! so we have to double-check its really in other box
double point[] = GeoTestUtil.nextPointNear(rectangle);
@@ -233,7 +233,7 @@ public void testIntersectEdgeCases() {
double longitude = point[1];
// check for sure its in our box
if (latitude >= rectangle.minLat && latitude <= rectangle.maxLat && longitude >= rectangle.minLon && longitude <= rectangle.maxLon) {
- assertFalse(impl.contains(latitude, longitude));
+ assertFalse(impl.contains(longitude, latitude));
}
}
for (int k = 0; k < 50; k++) {
@@ -243,7 +243,7 @@ public void testIntersectEdgeCases() {
double longitude = point[1];
// check for sure its in our box
if (latitude >= rectangle.minLat && latitude <= rectangle.maxLat && longitude >= rectangle.minLon && longitude <= rectangle.maxLon) {
- assertFalse(impl.contains(latitude, longitude));
+ assertFalse(impl.contains(longitude, latitude));
}
}
}
@@ -253,23 +253,23 @@ public void testIntersectEdgeCases() {
/** Tests edge case behavior with respect to insideness */
public void testEdgeInsideness() {
- Polygon2D poly = Polygon2D.create(new Polygon(new double[] { -2, -2, 2, 2, -2 }, new double[] { -2, 2, 2, -2, -2 }));
+ Component2D poly = Polygon2D.create(new Polygon(new double[] { -2, -2, 2, 2, -2 }, new double[] { -2, 2, 2, -2, -2 }));
assertTrue(poly.contains(-2, -2)); // bottom left corner: true
- assertTrue(poly.contains(-2, 2)); // bottom right corner: true
- assertTrue(poly.contains(2, -2)); // top left corner: true
+ assertTrue(poly.contains(2, -2)); // bottom right corner: true
+ assertTrue(poly.contains(-2, 2)); // top left corner: true
assertTrue(poly.contains(2, 2)); // top right corner: true
- assertTrue(poly.contains(-2, -1)); // bottom side: true
- assertTrue(poly.contains(-2, 0)); // bottom side: true
- assertTrue(poly.contains(-2, 1)); // bottom side: true
- assertTrue(poly.contains(2, -1)); // top side: true
- assertTrue(poly.contains(2, 0)); // top side: true
- assertTrue(poly.contains(2, 1)); // top side: true
- assertTrue(poly.contains(-1, 2)); // right side: true
- assertTrue(poly.contains(0, 2)); // right side: true
- assertTrue(poly.contains(1, 2)); // right side: true
- assertTrue(poly.contains(-1, -2)); // left side: true
- assertTrue(poly.contains(0, -2)); // left side: true
- assertTrue(poly.contains(1, -2)); // left side: true
+ assertTrue(poly.contains(-1, -2)); // bottom side: true
+ assertTrue(poly.contains(0, -2)); // bottom side: true
+ assertTrue(poly.contains(1, -2)); // bottom side: true
+ assertTrue(poly.contains(-1, 2)); // top side: true
+ assertTrue(poly.contains(0, 2)); // top side: true
+ assertTrue(poly.contains(1, 2)); // top side: true
+ assertTrue(poly.contains(2, -1)); // right side: true
+ assertTrue(poly.contains(2, 0)); // right side: true
+ assertTrue(poly.contains(2, 1)); // right side: true
+ assertTrue(poly.contains(-2, -1)); // left side: true
+ assertTrue(poly.contains(-2, 0)); // left side: true
+ assertTrue(poly.contains(-2, 1)); // left side: true
}
/** Tests current impl against original algorithm */
@@ -281,14 +281,14 @@ public void testContainsAgainstOriginal() {
while (polygon.getHoles().length > 0) {
polygon = nextPolygon();
}
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
// random lat/lons against polygon
for (int j = 0; j < 1000; j++) {
double point[] = GeoTestUtil.nextPointNear(polygon);
double latitude = point[0];
double longitude = point[1];
- boolean expected = GeoTestUtil.containsSlowly(polygon, latitude, longitude);
+ boolean expected = GeoTestUtil.containsSlowly(polygon, longitude, latitude);
assertEquals(expected, impl.contains(latitude, longitude));
}
}
@@ -298,7 +298,7 @@ public void testContainsAgainstOriginal() {
public void testRelateTriangle() {
for (int i = 0; i < 100; ++i) {
Polygon polygon = nextPolygon();
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
for (int j = 0; j < 100; j++) {
double[] a = nextPointNear(polygon);
@@ -306,7 +306,7 @@ public void testRelateTriangle() {
double[] c = nextPointNear(polygon);
// if the point is within poly, then triangle should not intersect
- if (impl.contains(a[0], a[1]) || impl.contains(b[0], b[1]) || impl.contains(c[0], c[1])) {
+ if (impl.contains(a[1], a[0]) || impl.contains(b[1], b[0]) || impl.contains(c[1], c[0])) {
assertTrue(impl.relateTriangle(a[1], a[0], b[1], b[0], c[1], c[0]) != Relation.CELL_OUTSIDE_QUERY);
}
}
@@ -315,7 +315,7 @@ public void testRelateTriangle() {
public void testRelateTriangleContainsPolygon() {
Polygon polygon = new Polygon(new double[]{0, 0, 1, 1, 0}, new double[]{0, 1, 1, 0, 0});
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
assertEquals(Relation.CELL_CROSSES_QUERY, impl.relateTriangle(-10 , -1, 2, -1, 10, 10));
}
@@ -327,7 +327,7 @@ public void testRelateTriangleEdgeCases() {
// random number of vertices
int numVertices = RandomNumbers.randomIntBetween(random(), 100, 1000);
Polygon polygon = createRegularPolygon(0, 0, randomRadius, numVertices);
- Polygon2D impl = Polygon2D.create(polygon);
+ Component2D impl = Polygon2D.create(polygon);
// create and test a simple tessellation
for (int j = 1; j < numVertices; ++j) {
@@ -342,7 +342,7 @@ public void testRelateTriangleEdgeCases() {
public void testLineCrossingPolygonPoints() {
Polygon p = new Polygon(new double[] {0, -1, 0, 1, 0}, new double[] {-1, 0, 1, 0, -1});
- Polygon2D polygon2D = Polygon2D.create(p);
+ Component2D polygon2D = Polygon2D.create(p);
Relation rel = polygon2D.relateTriangle(GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(-1.5)),
GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(0)),
GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(1.5)),
@@ -354,7 +354,7 @@ public void testLineCrossingPolygonPoints() {
public void testRandomLineCrossingPolygon() {
Polygon p = GeoTestUtil.createRegularPolygon(0, 0, 1000, TestUtil.nextInt(random(), 100, 10000));
- Polygon2D polygon2D = Polygon2D.create(p);
+ Component2D polygon2D = Polygon2D.create(p);
for (int i=0; i < 1000; i ++) {
double longitude = GeoTestUtil.nextLongitude();
double latitude = GeoTestUtil.nextLatitude();
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonShapeLineQuery.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonShapeLineQuery.java
index b6c300fd9425..04eebccef5a5 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonShapeLineQuery.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonShapeLineQuery.java
@@ -19,6 +19,7 @@
import java.util.Arrays;
import org.apache.lucene.document.ShapeField.QueryRelation;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.GeoEncodingUtils;
import org.apache.lucene.geo.Line;
import org.apache.lucene.geo.Line2D;
@@ -45,7 +46,7 @@
**/
final class LatLonShapeLineQuery extends ShapeQuery {
final Line[] lines;
- final private Line2D line2D;
+ final private Component2D line2D;
public LatLonShapeLineQuery(String field, QueryRelation queryRelation, Line... lines) {
super(field, queryRelation);
@@ -80,7 +81,7 @@ protected Relation relateRangeBBoxToQuery(int minXOffset, int minYOffset, byte[]
double maxLon = GeoEncodingUtils.decodeLongitude(NumericUtils.sortableBytesToInt(maxTriangle, maxXOffset));
// check internal node against query
- return line2D.relate(minLat, maxLat, minLon, maxLon);
+ return line2D.relate(minLon, maxLon, minLat, maxLat);
}
@Override
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonShapePolygonQuery.java b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonShapePolygonQuery.java
index 5ba47fa0f9ca..a4d996b68684 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/LatLonShapePolygonQuery.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/LatLonShapePolygonQuery.java
@@ -19,6 +19,7 @@
import java.util.Arrays;
import org.apache.lucene.document.ShapeField.QueryRelation;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.GeoEncodingUtils;
import org.apache.lucene.geo.Polygon;
import org.apache.lucene.geo.Polygon2D;
@@ -40,7 +41,7 @@
**/
final class LatLonShapePolygonQuery extends ShapeQuery {
final Polygon[] polygons;
- final private Polygon2D poly2D;
+ final private Component2D poly2D;
/**
* Creates a query that matches all indexed shapes to the provided polygons
@@ -74,7 +75,7 @@ protected Relation relateRangeBBoxToQuery(int minXOffset, int minYOffset, byte[]
double maxLon = GeoEncodingUtils.decodeLongitude(NumericUtils.sortableBytesToInt(maxTriangle, maxXOffset));
// check internal node against query
- return poly2D.relate(minLat, maxLat, minLon, maxLon);
+ return poly2D.relate(minLon, maxLon, minLat, maxLat);
}
@Override
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/XYShapeLineQuery.java b/lucene/sandbox/src/java/org/apache/lucene/document/XYShapeLineQuery.java
index 5f200daca1a4..52da2f238be6 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/XYShapeLineQuery.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/XYShapeLineQuery.java
@@ -19,6 +19,7 @@
import java.util.Arrays;
import org.apache.lucene.document.ShapeField.QueryRelation;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.Line2D;
import org.apache.lucene.geo.XYLine;
import org.apache.lucene.index.PointValues.Relation;
@@ -45,7 +46,7 @@
**/
final class XYShapeLineQuery extends ShapeQuery {
final XYLine[] lines;
- final private Line2D line2D;
+ final private Component2D line2D;
public XYShapeLineQuery(String field, QueryRelation queryRelation, XYLine... lines) {
super(field, queryRelation);
@@ -76,13 +77,13 @@ public XYShapeLineQuery(String field, QueryRelation queryRelation, XYLine... lin
@Override
protected Relation relateRangeBBoxToQuery(int minXOffset, int minYOffset, byte[] minTriangle,
int maxXOffset, int maxYOffset, byte[] maxTriangle) {
- double minLat = decode(NumericUtils.sortableBytesToInt(minTriangle, minYOffset));
- double minLon = decode(NumericUtils.sortableBytesToInt(minTriangle, minXOffset));
- double maxLat = decode(NumericUtils.sortableBytesToInt(maxTriangle, maxYOffset));
- double maxLon = decode(NumericUtils.sortableBytesToInt(maxTriangle, maxXOffset));
+ double minY = decode(NumericUtils.sortableBytesToInt(minTriangle, minYOffset));
+ double minX = decode(NumericUtils.sortableBytesToInt(minTriangle, minXOffset));
+ double maxY = decode(NumericUtils.sortableBytesToInt(maxTriangle, maxYOffset));
+ double maxX = decode(NumericUtils.sortableBytesToInt(maxTriangle, maxXOffset));
// check internal node against query
- return line2D.relate(minLat, maxLat, minLon, maxLon);
+ return line2D.relate(minX, maxX, minY, maxY);
}
@Override
diff --git a/lucene/sandbox/src/java/org/apache/lucene/document/XYShapePolygonQuery.java b/lucene/sandbox/src/java/org/apache/lucene/document/XYShapePolygonQuery.java
index 49835bdd6786..99acdb7b5232 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/document/XYShapePolygonQuery.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/document/XYShapePolygonQuery.java
@@ -19,7 +19,7 @@
import java.util.Arrays;
import org.apache.lucene.document.ShapeField.QueryRelation;
-import org.apache.lucene.geo.Polygon2D;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.XYEncodingUtils;
import org.apache.lucene.geo.XYPolygon;
import org.apache.lucene.geo.XYPolygon2D;
@@ -38,7 +38,7 @@
**/
final class XYShapePolygonQuery extends ShapeQuery {
final XYPolygon[] polygons;
- final private Polygon2D poly2D;
+ final private Component2D poly2D;
/**
* Creates a query that matches all indexed shapes to the provided polygons
@@ -74,7 +74,7 @@ protected Relation relateRangeBBoxToQuery(int minXOffset, int minYOffset, byte[]
double maxLon = XYEncodingUtils.decode(NumericUtils.sortableBytesToInt(maxTriangle, maxXOffset));
// check internal node against query
- return poly2D.relate(minLat, maxLat, minLon, maxLon);
+ return poly2D.relate(minLon, maxLon, minLat, maxLat);
}
@Override
diff --git a/lucene/sandbox/src/java/org/apache/lucene/geo/Line2D.java b/lucene/sandbox/src/java/org/apache/lucene/geo/Line2D.java
index 3c7f4d110515..15c923ee7918 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/geo/Line2D.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/geo/Line2D.java
@@ -18,8 +18,6 @@
import org.apache.lucene.index.PointValues.Relation;
-import static org.apache.lucene.geo.GeoUtils.orient;
-
/**
* 2D geo line implementation represented as a balanced interval tree of edges.
*
@@ -27,81 +25,123 @@
* {@link #relate relate()} are {@code O(n)}, but for most practical lines are much faster than brute force.
* @lucene.internal
*/
-public final class Line2D extends EdgeTree {
+public final class Line2D implements Component2D {
+
+ /** minimum latitude of this geometry's bounding box area */
+ final private double minY;
+ /** maximum latitude of this geometry's bounding box area */
+ final private double maxY;
+ /** minimum longitude of this geometry's bounding box area */
+ final private double minX;
+ /** maximum longitude of this geometry's bounding box area */
+ final private double maxX;
+ /** lines represented as a 2-d interval tree.*/
+ final private EdgeTree tree;
private Line2D(Line line) {
- super(line.minLat, line.maxLat, line.minLon, line.maxLon, line.getLats(), line.getLons());
+ this.minY = line.minLat;
+ this.maxY = line.maxLat;
+ this.minX = line.minLon;
+ this.maxX = line.maxLon;
+ this.tree = EdgeTree.createTree(line.getLons(), line.getLats());
}
private Line2D(XYLine line) {
- super(line.minY, line.maxY, line.minX, line.maxX, line.getY(), line.getX());
+ this.minY = line.minY;
+ this.maxY = line.maxY;
+ this.minX = line.minX;
+ this.maxX = line.maxX;
+ this.tree = EdgeTree.createTree(line.getX(), line.getY());
}
- /** create a Line2D edge tree from provided array of Linestrings */
- public static Line2D create(Line... lines) {
- Line2D components[] = new Line2D[lines.length];
- for (int i = 0; i < components.length; ++i) {
- components[i] = new Line2D(lines[i]);
- }
- return (Line2D)createTree(components, 0, components.length - 1, false);
+ @Override
+ public double getMinX() {
+ return minX;
}
- /** create a Line2D edge tree from provided array of Linestrings */
- public static Line2D create(XYLine... lines) {
- Line2D components[] = new Line2D[lines.length];
- for (int i = 0; i < components.length; ++i) {
- components[i] = new Line2D(lines[i]);
+ @Override
+ public double getMaxX() {
+ return maxX;
+ }
+
+ @Override
+ public double getMinY() {
+ return minY;
+ }
+
+ @Override
+ public double getMaxY() {
+ return maxY;
+ }
+
+ @Override
+ public boolean contains(double x, double y) {
+ if (Component2D.containsPoint(x, y, this.minX, this.maxX, this.minY, this.maxY)) {
+ return tree.isPointOnLine(x, y);
}
- return (Line2D)createTree(components, 0, components.length - 1, false);
+ return false;
}
@Override
- protected Relation componentRelate(double minLat, double maxLat, double minLon, double maxLon) {
- if (tree.crossesBox(minLat, maxLat, minLon, maxLon, true)) {
+ public Relation relate(double minX, double maxX, double minY, double maxY) {
+ if (Component2D.disjoint(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY)) {
+ return Relation.CELL_OUTSIDE_QUERY;
+ }
+ if (Component2D.within(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY)) {
+ return Relation.CELL_CROSSES_QUERY;
+ }
+ if (tree.crossesBox(minX, maxX, minY, maxY, true)) {
return Relation.CELL_CROSSES_QUERY;
}
return Relation.CELL_OUTSIDE_QUERY;
}
@Override
- protected Relation componentRelateTriangle(double ax, double ay, double bx, double by, double cx, double cy) {
+ public Relation relateTriangle(double minX, double maxX, double minY, double maxY,
+ double ax, double ay, double bx, double by, double cx, double cy) {
+ if (Component2D.disjoint(this.minX, this.maxX, this.minY, this.maxY, minX, maxX, minY, maxY)) {
+ return Relation.CELL_OUTSIDE_QUERY;
+ }
if (ax == bx && bx == cx && ay == by && by == cy) {
// indexed "triangle" is a point: check if point lies on any line segment
- if (isPointOnLine(tree, ax, ay)) {
+ if (tree.isPointOnLine(ax, ay)) {
return Relation.CELL_INSIDE_QUERY;
}
} else if ((ax == cx && ay == cy) || (bx == cx && by == cy)) {
// indexed "triangle" is a line:
- if (tree.crossesLine(ax, ay, bx, by)) {
+ if (tree.crossesLine(minX, maxX, minY, maxY, ax, ay, bx, by)) {
+ return Relation.CELL_CROSSES_QUERY;
+ }
+ return Relation.CELL_OUTSIDE_QUERY;
+ } else if ((ax == bx && ay == by)) {
+ // indexed "triangle" is a line:
+ if (tree.crossesLine(minX, maxX, minY, maxY, ax, ay, cx, cy)) {
return Relation.CELL_CROSSES_QUERY;
}
return Relation.CELL_OUTSIDE_QUERY;
- } else if (pointInTriangle(tree.lon1, tree.lat1, ax, ay, bx, by, cx, cy) == true ||
- tree.crossesTriangle(ax, ay, bx, by, cx, cy)) {
+ } else if (Component2D.pointInTriangle(minX, maxX, minY, maxY, tree.x1, tree.y1, ax, ay, bx, by, cx, cy) == true ||
+ tree.crossesTriangle(minX, maxX, minY, maxY, ax, ay, bx, by, cx, cy)) {
// indexed "triangle" is a triangle:
return Relation.CELL_CROSSES_QUERY;
}
return Relation.CELL_OUTSIDE_QUERY;
}
- /** returns true if the provided x, y point lies on the line */
- private boolean isPointOnLine(Edge tree, double x, double y) {
- if (y <= tree.max) {
- double minY = StrictMath.min(tree.lat1, tree.lat2);
- double maxY = StrictMath.max(tree.lat1, tree.lat2);
- double minX = StrictMath.min(tree.lon1, tree.lon2);
- double maxX = StrictMath.max(tree.lon1, tree.lon2);
- if (Rectangle.containsPoint(y, x, minY, maxY, minX, maxX) &&
- orient(tree.lon1, tree.lat1, tree.lon2, tree.lat2, x, y) == 0) {
- return true;
- }
- if (tree.left != null && isPointOnLine(tree.left, x, y)) {
- return true;
- }
- if (tree.right != null && maxY >= tree.low && isPointOnLine(tree.right, x, y)) {
- return true;
- }
+ /** create a Line2D edge tree from provided array of Linestrings */
+ public static Component2D create(Line... lines) {
+ Component2D components[] = new Component2D[lines.length];
+ for (int i = 0; i < components.length; ++i) {
+ components[i] = new Line2D(lines[i]);
}
- return false;
+ return ComponentTree.create(components);
+ }
+
+ /** create a Line2D edge tree from provided array of Linestrings */
+ public static Component2D create(XYLine... lines) {
+ Line2D components[] = new Line2D[lines.length];
+ for (int i = 0; i < components.length; ++i) {
+ components[i] = new Line2D(lines[i]);
+ }
+ return ComponentTree.create(components);
}
}
\ No newline at end of file
diff --git a/lucene/sandbox/src/java/org/apache/lucene/geo/XYPolygon2D.java b/lucene/sandbox/src/java/org/apache/lucene/geo/XYPolygon2D.java
index 1dba72bb11b8..cf5b1741de6f 100644
--- a/lucene/sandbox/src/java/org/apache/lucene/geo/XYPolygon2D.java
+++ b/lucene/sandbox/src/java/org/apache/lucene/geo/XYPolygon2D.java
@@ -23,22 +23,22 @@
*/
public class XYPolygon2D extends Polygon2D {
- protected XYPolygon2D(XYPolygon polygon, XYPolygon2D holes) {
- super(polygon.minY, polygon.maxY, polygon.minX, polygon.maxX, polygon.getPolyY(), polygon.getPolyX(), holes);
+ protected XYPolygon2D(XYPolygon polygon, Component2D holes) {
+ super(polygon.minX, polygon.maxX, polygon.minY, polygon.maxY, polygon.getPolyX(), polygon.getPolyY(), holes);
}
/** Builds a Polygon2D from multipolygon */
- public static XYPolygon2D create(XYPolygon... polygons) {
+ public static Component2D create(XYPolygon... polygons) {
XYPolygon2D components[] = new XYPolygon2D[polygons.length];
for (int i = 0; i < components.length; i++) {
XYPolygon gon = polygons[i];
XYPolygon gonHoles[] = gon.getHoles();
- XYPolygon2D holes = null;
+ Component2D holes = null;
if (gonHoles.length > 0) {
holes = create(gonHoles);
}
components[i] = new XYPolygon2D(gon, holes);
}
- return (XYPolygon2D)createTree(components, 0, components.length - 1, false);
+ return ComponentTree.create(components);
}
}
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/BaseLatLonShapeTestCase.java b/lucene/sandbox/src/test/org/apache/lucene/document/BaseLatLonShapeTestCase.java
index 5095bdc0403c..91b0706cf4d7 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/BaseLatLonShapeTestCase.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/BaseLatLonShapeTestCase.java
@@ -20,6 +20,7 @@
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
import org.apache.lucene.document.ShapeField.QueryRelation;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.GeoTestUtil;
import org.apache.lucene.geo.Line;
import org.apache.lucene.geo.Line2D;
@@ -66,12 +67,12 @@ protected Query newPolygonQuery(String field, QueryRelation queryRelation, Objec
}
@Override
- protected Line2D toLine2D(Object... lines) {
+ protected Component2D toLine2D(Object... lines) {
return Line2D.create(Arrays.stream(lines).toArray(Line[]::new));
}
@Override
- protected Polygon2D toPolygon2D(Object... polygons) {
+ protected Component2D toPolygon2D(Object... polygons) {
return Polygon2D.create(Arrays.stream(polygons).toArray(Polygon[]::new));
}
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/BaseShapeEncodingTestCase.java b/lucene/sandbox/src/test/org/apache/lucene/document/BaseShapeEncodingTestCase.java
index 5d7579f5f1bc..ee71047f048a 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/BaseShapeEncodingTestCase.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/BaseShapeEncodingTestCase.java
@@ -16,8 +16,8 @@
*/
package org.apache.lucene.document;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.GeoUtils;
-import org.apache.lucene.geo.Polygon2D;
import org.apache.lucene.index.PointValues;
import org.apache.lucene.util.LuceneTestCase;
@@ -35,7 +35,7 @@ public abstract class BaseShapeEncodingTestCase extends LuceneTestCase {
protected abstract double nextY();
protected abstract Object nextPolygon();
- protected abstract Polygon2D createPolygon2D(Object polygon);
+ protected abstract Component2D createPolygon2D(Object polygon);
//One shared point with MBR -> MinY, MinX
public void testPolygonEncodingMinLatMinLon() {
@@ -535,7 +535,7 @@ private void verifyEncoding(double ay, double ax, double by, double bx, double c
}
for (int i =0; i < 100; i ++) {
- Polygon2D polygon2D = createPolygon2D(nextPolygon());
+ Component2D polygon2D = createPolygon2D(nextPolygon());
PointValues.Relation originalRelation = polygon2D.relateTriangle(originalQuantize[1], originalQuantize[0], originalQuantize[3], originalQuantize[2], originalQuantize[5], originalQuantize[4]);
PointValues.Relation encodedRelation = polygon2D.relateTriangle(encodedQuantize[1], encodedQuantize[0], encodedQuantize[3], encodedQuantize[2], encodedQuantize[5], encodedQuantize[4]);
assertTrue(originalRelation == encodedRelation);
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/BaseShapeTestCase.java b/lucene/sandbox/src/test/org/apache/lucene/document/BaseShapeTestCase.java
index a7f53feaa315..615d802183ef 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/BaseShapeTestCase.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/BaseShapeTestCase.java
@@ -23,7 +23,7 @@
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
import org.apache.lucene.document.ShapeField.QueryRelation;
-import org.apache.lucene.geo.Line2D;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
@@ -188,9 +188,9 @@ protected Object randomQueryPolygon() {
/** factory method to create a new polygon query */
protected abstract Query newPolygonQuery(String field, QueryRelation queryRelation, Object... polygons);
- protected abstract Line2D toLine2D(Object... line);
+ protected abstract Component2D toLine2D(Object... line);
- protected abstract Object toPolygon2D(Object... polygon);
+ protected abstract Component2D toPolygon2D(Object... polygon);
private void verify(Object... shapes) throws Exception {
IndexWriterConfig iwc = newIndexWriterConfig();
@@ -372,7 +372,7 @@ protected void verifyRandomLineQueries(IndexReader reader, Object... shapes) thr
// line
Object queryLine = randomQueryLine(shapes);
- Line2D queryLine2D = toLine2D(queryLine);
+ Component2D queryLine2D = toLine2D(queryLine);
QueryRelation queryRelation = RandomPicks.randomFrom(random(), POINT_LINE_RELATIONS);
Query query = newLineQuery(FIELD_NAME, queryRelation, queryLine);
@@ -413,7 +413,7 @@ public void collect(int doc) throws IOException {
} else if (shapes[id] == null) {
expected = false;
} else {
- expected = VALIDATOR.setRelation(queryRelation).testLineQuery(queryLine2D, shapes[id]);
+ expected = VALIDATOR.setRelation(queryRelation).testComponentQuery(queryLine2D, shapes[id]);
}
if (hits.get(docID) != expected) {
@@ -463,7 +463,7 @@ protected void verifyRandomPolygonQueries(IndexReader reader, Object... shapes)
// Polygon
Object queryPolygon = randomQueryPolygon();
- Object queryPoly2D = toPolygon2D(queryPolygon);
+ Component2D queryPoly2D = toPolygon2D(queryPolygon);
QueryRelation queryRelation = RandomPicks.randomFrom(random(), QueryRelation.values());
Query query = newPolygonQuery(FIELD_NAME, queryRelation, queryPolygon);
@@ -504,7 +504,7 @@ public void collect(int doc) throws IOException {
} else if (shapes[id] == null) {
expected = false;
} else {
- expected = VALIDATOR.setRelation(queryRelation).testPolygonQuery(queryPoly2D, shapes[id]);
+ expected = VALIDATOR.setRelation(queryRelation).testComponentQuery(queryPoly2D, shapes[id]);
}
if (hits.get(docID) != expected) {
@@ -570,8 +570,7 @@ protected static abstract class Validator {
protected QueryRelation queryRelation = QueryRelation.INTERSECTS;
public abstract boolean testBBoxQuery(double minLat, double maxLat, double minLon, double maxLon, Object shape);
- public abstract boolean testLineQuery(Line2D line2d, Object shape);
- public abstract boolean testPolygonQuery(Object poly2d, Object shape);
+ public abstract boolean testComponentQuery(Component2D line2d, Object shape);
public Validator setRelation(QueryRelation relation) {
this.queryRelation = relation;
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/BaseXYShapeTestCase.java b/lucene/sandbox/src/test/org/apache/lucene/document/BaseXYShapeTestCase.java
index 0ef15c5983b2..bc65426c0885 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/BaseXYShapeTestCase.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/BaseXYShapeTestCase.java
@@ -20,6 +20,7 @@
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
import org.apache.lucene.document.ShapeField.QueryRelation;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.Line2D;
import org.apache.lucene.geo.ShapeTestUtil;
import org.apache.lucene.geo.XYLine;
@@ -58,12 +59,12 @@ protected Query newPolygonQuery(String field, QueryRelation queryRelation, Objec
}
@Override
- protected Line2D toLine2D(Object... lines) {
+ protected Component2D toLine2D(Object... lines) {
return Line2D.create(Arrays.stream(lines).toArray(XYLine[]::new));
}
@Override
- protected XYPolygon2D toPolygon2D(Object... polygons) {
+ protected Component2D toPolygon2D(Object... polygons) {
return XYPolygon2D.create(Arrays.stream(polygons).toArray(XYPolygon[]::new));
}
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonLineShapeQueries.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonLineShapeQueries.java
index fa31b00071e9..2bc809895180 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonLineShapeQueries.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonLineShapeQueries.java
@@ -19,11 +19,9 @@
import com.carrotsearch.randomizedtesting.generators.RandomNumbers;
import org.apache.lucene.document.ShapeField.QueryRelation;
-import org.apache.lucene.geo.EdgeTree;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.GeoTestUtil;
import org.apache.lucene.geo.Line;
-import org.apache.lucene.geo.Line2D;
-import org.apache.lucene.geo.Polygon2D;
import org.apache.lucene.geo.Rectangle;
import org.apache.lucene.geo.Rectangle2D;
import org.apache.lucene.index.PointValues.Relation;
@@ -98,20 +96,11 @@ public boolean testBBoxQuery(double minLat, double maxLat, double minLon, double
}
@Override
- public boolean testLineQuery(Line2D line2d, Object shape) {
- return testLine(line2d, (Line) shape);
- }
-
- @Override
- public boolean testPolygonQuery(Object poly2d, Object shape) {
- return testLine((Polygon2D)poly2d, (Line) shape);
- }
-
- private boolean testLine(EdgeTree queryPoly, Line line) {
-
+ public boolean testComponentQuery(Component2D component2D, Object shape) {
+ Line line = (Line) shape;
for (int i = 0, j = 1; j < line.numPoints(); ++i, ++j) {
double[] qTriangle = encoder.quantizeTriangle(line.getLon(i), line.getLat(i), true, line.getLon(j), line.getLat(j), true, line.getLon(i), line.getLat(i), true);
- Relation r = queryPoly.relateTriangle(qTriangle[1], qTriangle[0], qTriangle[3], qTriangle[2], qTriangle[5], qTriangle[4]);
+ Relation r = component2D.relateTriangle(qTriangle[1], qTriangle[0], qTriangle[3], qTriangle[2], qTriangle[5], qTriangle[4]);
if (queryRelation == QueryRelation.DISJOINT) {
if (r != Relation.CELL_OUTSIDE_QUERY) return false;
} else if (queryRelation == QueryRelation.WITHIN) {
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiLineShapeQueries.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiLineShapeQueries.java
index fc5bc91247bc..4416331e8ac8 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiLineShapeQueries.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiLineShapeQueries.java
@@ -20,8 +20,8 @@
import java.util.List;
import org.apache.lucene.document.ShapeField.QueryRelation;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.Line;
-import org.apache.lucene.geo.Line2D;
/** random bounding box, line, and polygon query tests for random indexed arrays of {@link Line} types */
public class TestLatLonMultiLineShapeQueries extends BaseLatLonShapeTestCase {
@@ -90,26 +90,10 @@ public boolean testBBoxQuery(double minLat, double maxLat, double minLon, double
}
@Override
- public boolean testLineQuery(Line2D query, Object shape) {
+ public boolean testComponentQuery(Component2D query, Object shape) {
Line[] lines = (Line[])shape;
for (Line l : lines) {
- boolean b = LINEVALIDATOR.testLineQuery(query, l);
- if (b == true && queryRelation == QueryRelation.INTERSECTS) {
- return true;
- } else if (b == false && queryRelation == QueryRelation.DISJOINT) {
- return false;
- } else if (b == false && queryRelation == QueryRelation.WITHIN) {
- return false;
- }
- }
- return queryRelation != QueryRelation.INTERSECTS;
- }
-
- @Override
- public boolean testPolygonQuery(Object query, Object shape) {
- Line[] lines = (Line[])shape;
- for (Line l : lines) {
- boolean b = LINEVALIDATOR.testPolygonQuery(query, l);
+ boolean b = LINEVALIDATOR.testComponentQuery(query, l);
if (b == true && queryRelation == QueryRelation.INTERSECTS) {
return true;
} else if (b == false && queryRelation == QueryRelation.DISJOINT) {
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiPointShapeQueries.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiPointShapeQueries.java
index 536e9c2178ec..8214bf039dec 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiPointShapeQueries.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiPointShapeQueries.java
@@ -20,7 +20,7 @@
import java.util.List;
import org.apache.lucene.document.ShapeField.QueryRelation;
-import org.apache.lucene.geo.Line2D;
+import org.apache.lucene.geo.Component2D;
/** random bounding box, line, and polygon query tests for random indexed arrays of {@code latitude, longitude} points */
public class TestLatLonMultiPointShapeQueries extends BaseLatLonShapeTestCase {
@@ -89,26 +89,10 @@ public boolean testBBoxQuery(double minLat, double maxLat, double minLon, double
}
@Override
- public boolean testLineQuery(Line2D query, Object shape) {
+ public boolean testComponentQuery(Component2D query, Object shape) {
Point[] points = (Point[]) shape;
for (Point p : points) {
- boolean b = POINTVALIDATOR.testLineQuery(query, p);
- if (b == true && queryRelation == QueryRelation.INTERSECTS) {
- return true;
- } else if (b == false && queryRelation == QueryRelation.DISJOINT) {
- return false;
- } else if (b == false && queryRelation == QueryRelation.WITHIN) {
- return false;
- }
- }
- return queryRelation != QueryRelation.INTERSECTS;
- }
-
- @Override
- public boolean testPolygonQuery(Object query, Object shape) {
- Point[] points = (Point[]) shape;
- for (Point p : points) {
- boolean b = POINTVALIDATOR.testPolygonQuery(query, p);
+ boolean b = POINTVALIDATOR.testComponentQuery(query, p);
if (b == true && queryRelation == QueryRelation.INTERSECTS) {
return true;
} else if (b == false && queryRelation == QueryRelation.DISJOINT) {
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiPolygonShapeQueries.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiPolygonShapeQueries.java
index bba9f97a5493..7436df8d96b8 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiPolygonShapeQueries.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonMultiPolygonShapeQueries.java
@@ -20,7 +20,7 @@
import java.util.List;
import org.apache.lucene.document.ShapeField.QueryRelation;
-import org.apache.lucene.geo.Line2D;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.Polygon;
import org.apache.lucene.geo.Tessellator;
@@ -102,26 +102,10 @@ public boolean testBBoxQuery(double minLat, double maxLat, double minLon, double
}
@Override
- public boolean testLineQuery(Line2D query, Object shape) {
+ public boolean testComponentQuery(Component2D query, Object shape) {
Polygon[] polygons = (Polygon[])shape;
for (Polygon p : polygons) {
- boolean b = POLYGONVALIDATOR.testLineQuery(query, p);
- if (b == true && queryRelation == QueryRelation.INTERSECTS) {
- return true;
- } else if (b == false && queryRelation == QueryRelation.DISJOINT) {
- return false;
- } else if (b == false && queryRelation == QueryRelation.WITHIN) {
- return false;
- }
- }
- return queryRelation != QueryRelation.INTERSECTS;
- }
-
- @Override
- public boolean testPolygonQuery(Object query, Object shape) {
- Polygon[] polygons = (Polygon[])shape;
- for (Polygon p : polygons) {
- boolean b = POLYGONVALIDATOR.testPolygonQuery(query, p);
+ boolean b = POLYGONVALIDATOR.testComponentQuery(query, p);
if (b == true && queryRelation == QueryRelation.INTERSECTS) {
return true;
} else if (b == false && queryRelation == QueryRelation.DISJOINT) {
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPointShapeQueries.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPointShapeQueries.java
index b3ab59b9b60b..4a8540bba842 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPointShapeQueries.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPointShapeQueries.java
@@ -18,11 +18,9 @@
import com.carrotsearch.randomizedtesting.generators.RandomNumbers;
import org.apache.lucene.document.ShapeField.QueryRelation;
-import org.apache.lucene.geo.EdgeTree;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.GeoTestUtil;
import org.apache.lucene.geo.Line;
-import org.apache.lucene.geo.Line2D;
-import org.apache.lucene.geo.Polygon2D;
import org.apache.lucene.index.PointValues.Relation;
/** random bounding box, line, and polygon query tests for random generated {@code latitude, longitude} points */
@@ -91,20 +89,12 @@ public boolean testBBoxQuery(double minLat, double maxLat, double minLon, double
}
@Override
- public boolean testLineQuery(Line2D line2d, Object shape) {
- return testPoint(line2d, (Point) shape);
- }
-
- @Override
- public boolean testPolygonQuery(Object poly2d, Object shape) {
- return testPoint((Polygon2D)poly2d, (Point) shape);
- }
-
- private boolean testPoint(EdgeTree tree, Point p) {
+ public boolean testComponentQuery(Component2D query, Object shape) {
+ Point p = (Point) shape;
double lat = encoder.quantizeY(p.lat);
double lon = encoder.quantizeX(p.lon);
// for consistency w/ the query we test the point as a triangle
- Relation r = tree.relateTriangle(lon, lat, lon, lat, lon, lat);
+ Relation r = query.relateTriangle(lon, lat, lon, lat, lon, lat);
if (queryRelation == QueryRelation.WITHIN) {
return r == Relation.CELL_INSIDE_QUERY;
} else if (queryRelation == QueryRelation.DISJOINT) {
diff --git a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPolygonShapeQueries.java b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPolygonShapeQueries.java
index 8fdbf5c182c3..b9e4a3ef40cf 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPolygonShapeQueries.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/document/TestLatLonPolygonShapeQueries.java
@@ -19,10 +19,8 @@
import java.util.List;
import org.apache.lucene.document.ShapeField.QueryRelation;
-import org.apache.lucene.geo.EdgeTree;
-import org.apache.lucene.geo.Line2D;
+import org.apache.lucene.geo.Component2D;
import org.apache.lucene.geo.Polygon;
-import org.apache.lucene.geo.Polygon2D;
import org.apache.lucene.geo.Rectangle;
import org.apache.lucene.geo.Rectangle2D;
import org.apache.lucene.geo.Tessellator;
@@ -89,22 +87,14 @@ public boolean testBBoxQuery(double minLat, double maxLat, double minLon, double
}
@Override
- public boolean testLineQuery(Line2D query, Object shape) {
- return testPolygon(query, (Polygon) shape);
- }
-
- @Override
- public boolean testPolygonQuery(Object query, Object shape) {
- return testPolygon((Polygon2D)query, (Polygon) shape);
- }
-
- private boolean testPolygon(EdgeTree tree, Polygon shape) {
+ public boolean testComponentQuery(Component2D query, Object o) {
+ Polygon shape = (Polygon) o;
List