mirror of https://github.com/apache/lucene.git
UCENE-9194: Simplify XYShapeXQuery API by adding a new abstract class called XYGeometry
This commit is contained in:
parent
9a19093586
commit
73dbf6d061
|
@ -147,6 +147,9 @@ Improvements
|
|||
* LUCENE-9123: Add new JapaneseTokenizer constructors with discardCompoundToken option that controls whether
|
||||
the tokenizer emits original (compound) tokens when the mode is not NORMAL. (Kazuaki Hiraga via Tomoko Uchida)
|
||||
|
||||
* LUCENE-9194: Simplify XYShapeXQuery API by adding a new abstract class called XYGeometry. Queries are
|
||||
executed with input objects that extend such interface. (Ignacio Vera)
|
||||
|
||||
Optimizations
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ import java.util.Arrays;
|
|||
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.GeoEncodingUtils;
|
||||
import org.apache.lucene.geo.LatLonGeometry;
|
||||
import org.apache.lucene.geo.Polygon;
|
||||
import org.apache.lucene.geo.Polygon2D;
|
||||
import org.apache.lucene.index.DocValues;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
import org.apache.lucene.index.SortedNumericDocValues;
|
||||
|
@ -104,7 +104,7 @@ public class LatLonDocValuesPointInPolygonQuery extends Query {
|
|||
|
||||
return new ConstantScoreWeight(this, boost) {
|
||||
|
||||
final Component2D tree = Polygon2D.create(polygons);
|
||||
final Component2D tree = LatLonGeometry.create(polygons);
|
||||
final GeoEncodingUtils.PolygonPredicate polygonPredicate = GeoEncodingUtils.createComponentPredicate(tree);
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,8 +21,8 @@ import java.util.Arrays;
|
|||
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.GeoEncodingUtils;
|
||||
import org.apache.lucene.geo.LatLonGeometry;
|
||||
import org.apache.lucene.geo.Polygon;
|
||||
import org.apache.lucene.geo.Polygon2D;
|
||||
import org.apache.lucene.index.FieldInfo;
|
||||
import org.apache.lucene.index.LeafReader;
|
||||
import org.apache.lucene.index.LeafReaderContext;
|
||||
|
@ -141,7 +141,7 @@ final class LatLonPointInPolygonQuery extends Query {
|
|||
@Override
|
||||
public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
|
||||
|
||||
final Component2D tree = Polygon2D.create(polygons);
|
||||
final Component2D tree = LatLonGeometry.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
|
||||
final byte minLat[] = new byte[Integer.BYTES];
|
||||
|
|
|
@ -22,6 +22,9 @@ import java.util.List;
|
|||
import org.apache.lucene.document.ShapeField.QueryRelation; // javadoc
|
||||
import org.apache.lucene.document.ShapeField.Triangle;
|
||||
import org.apache.lucene.geo.Tessellator;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.geo.XYPoint;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.index.PointValues; // javadoc
|
||||
import org.apache.lucene.geo.XYLine;
|
||||
import org.apache.lucene.geo.XYPolygon;
|
||||
|
@ -34,7 +37,7 @@ import static org.apache.lucene.geo.XYEncodingUtils.encode;
|
|||
/**
|
||||
* A cartesian shape utility class for indexing and searching geometries whose vertices are unitless x, y values.
|
||||
* <p>
|
||||
* This class defines six static factory methods for common indexing and search operations:
|
||||
* This class defines seven static factory methods for common indexing and search operations:
|
||||
* <ul>
|
||||
* <li>{@link #createIndexableFields(String, XYPolygon)} for indexing a cartesian polygon.
|
||||
* <li>{@link #createIndexableFields(String, XYLine)} for indexing a cartesian linestring.
|
||||
|
@ -42,6 +45,8 @@ import static org.apache.lucene.geo.XYEncodingUtils.encode;
|
|||
* <li>{@link #newBoxQuery newBoxQuery()} for matching cartesian shapes that have some {@link QueryRelation} with a bounding box.
|
||||
* <li>{@link #newBoxQuery newLineQuery()} for matching cartesian shapes that have some {@link QueryRelation} with a linestring.
|
||||
* <li>{@link #newBoxQuery newPolygonQuery()} for matching cartesian shapes that have some {@link QueryRelation} with a polygon.
|
||||
* <li>{@link #newGeometryQuery newGeometryQuery()} for matching cartesian shapes that have some {@link QueryRelation}
|
||||
* with one or more {@link XYGeometry}.
|
||||
* </ul>
|
||||
|
||||
* <b>WARNING</b>: Like {@link LatLonPoint}, vertex values are indexed with some loss of precision from the
|
||||
|
@ -88,43 +93,41 @@ public class XYShape {
|
|||
|
||||
/** create a query to find all cartesian shapes that intersect a defined bounding box **/
|
||||
public static Query newBoxQuery(String field, QueryRelation queryRelation, float minX, float maxX, float minY, float maxY) {
|
||||
return new XYShapeBoundingBoxQuery(field, queryRelation, minX, maxX, minY, maxY);
|
||||
XYRectangle rectangle = new XYRectangle(minX, maxX, minY, maxY);
|
||||
return newGeometryQuery(field, queryRelation, rectangle);
|
||||
}
|
||||
|
||||
/** create a query to find all cartesian shapes that intersect a provided linestring (or array of linestrings) **/
|
||||
public static Query newLineQuery(String field, QueryRelation queryRelation, XYLine... lines) {
|
||||
if (queryRelation == QueryRelation.CONTAINS && lines.length > 1) {
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
for (int i =0; i < lines.length; i++) {
|
||||
builder.add(newLineQuery(field, queryRelation, lines[i]), BooleanClause.Occur.MUST);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
return new XYShapeLineQuery(field, queryRelation, lines);
|
||||
return newGeometryQuery(field, queryRelation, lines);
|
||||
}
|
||||
|
||||
/** create a query to find all cartesian shapes that intersect a provided polygon (or array of polygons) **/
|
||||
public static Query newPolygonQuery(String field, QueryRelation queryRelation, XYPolygon... polygons) {
|
||||
if (queryRelation == QueryRelation.CONTAINS && polygons.length > 1) {
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
for (int i =0; i < polygons.length; i++) {
|
||||
builder.add(newPolygonQuery(field, queryRelation, polygons[i]), BooleanClause.Occur.MUST);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
return new XYShapePolygonQuery(field, queryRelation, polygons);
|
||||
return newGeometryQuery(field, queryRelation, polygons);
|
||||
}
|
||||
|
||||
/** create a query to find all indexed shapes that comply the {@link QueryRelation} with the provided point
|
||||
**/
|
||||
public static Query newPointQuery(String field, QueryRelation queryRelation, float[]... points) {
|
||||
if (queryRelation == QueryRelation.CONTAINS && points.length > 1) {
|
||||
XYPoint[] pointArray = new XYPoint[points.length];
|
||||
for (int i =0; i < points.length; i++) {
|
||||
pointArray[i] = new XYPoint(points[i][0], points[i][1]);
|
||||
}
|
||||
return newGeometryQuery(field, queryRelation, pointArray);
|
||||
}
|
||||
|
||||
/** create a query to find all indexed geo shapes that intersect a provided geometry collection
|
||||
* note: Components do not support dateline crossing
|
||||
**/
|
||||
public static Query newGeometryQuery(String field, QueryRelation queryRelation, XYGeometry... xyGeometries) {
|
||||
if (queryRelation == QueryRelation.CONTAINS && xyGeometries.length > 1) {
|
||||
BooleanQuery.Builder builder = new BooleanQuery.Builder();
|
||||
for (int i =0; i < points.length; i++) {
|
||||
builder.add(newPointQuery(field, queryRelation, points[i]), BooleanClause.Occur.MUST);
|
||||
for (int i = 0; i < xyGeometries.length; i++) {
|
||||
builder.add(newGeometryQuery(field, queryRelation, xyGeometries[i]), BooleanClause.Occur.MUST);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
return new XYShapePointQuery(field, queryRelation, points);
|
||||
return new XYShapeQuery(field, queryRelation, xyGeometries);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* 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.document;
|
||||
|
||||
import org.apache.lucene.document.ShapeField.QueryRelation;
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.geo.XYRectangle2D;
|
||||
import org.apache.lucene.index.PointValues.Relation;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
import static org.apache.lucene.geo.XYEncodingUtils.decode;
|
||||
|
||||
/**
|
||||
* Finds all previously indexed cartesian shapes that intersect the specified bounding box.
|
||||
*
|
||||
* <p>The field must be indexed using
|
||||
* {@link org.apache.lucene.document.XYShape#createIndexableFields} added per document.
|
||||
**/
|
||||
public class XYShapeBoundingBoxQuery extends ShapeQuery {
|
||||
final Component2D rectangle2D;
|
||||
final private XYRectangle rectangle;
|
||||
|
||||
/** construct a Bounding Box Query over cartesian geometries from the given ranges */
|
||||
public XYShapeBoundingBoxQuery(String field, QueryRelation queryRelation, double minX, double maxX, double minY, double maxY) {
|
||||
super(field, queryRelation);
|
||||
this.rectangle = new XYRectangle(minX, maxX, minY, maxY);
|
||||
this.rectangle2D = XYRectangle2D.create(this.rectangle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Relation relateRangeBBoxToQuery(int minXOffset, int minYOffset, byte[] minTriangle,
|
||||
int maxXOffset, int maxYOffset, byte[] maxTriangle) {
|
||||
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
|
||||
Relation rel = rectangle2D.relate(minX, maxX, minY, maxY);
|
||||
// TODO: Check if this really helps
|
||||
if (queryRelation == QueryRelation.INTERSECTS && rel == Relation.CELL_CROSSES_QUERY) {
|
||||
// for intersects we can restrict the conditions by using the inner box
|
||||
double innerMaxY = decode(NumericUtils.sortableBytesToInt(maxTriangle, minYOffset));
|
||||
if (rectangle2D.relate(minX, maxX, minY, innerMaxY) == Relation.CELL_INSIDE_QUERY) {
|
||||
return Relation.CELL_INSIDE_QUERY;
|
||||
}
|
||||
double innerMaX = decode(NumericUtils.sortableBytesToInt(maxTriangle, minXOffset));
|
||||
if (rectangle2D.relate(minX, innerMaX, minY, maxY) == Relation.CELL_INSIDE_QUERY) {
|
||||
return Relation.CELL_INSIDE_QUERY;
|
||||
}
|
||||
double innerMinY = decode(NumericUtils.sortableBytesToInt(minTriangle, maxYOffset));
|
||||
if (rectangle2D.relate(minX, maxX, innerMinY, maxY) == Relation.CELL_INSIDE_QUERY) {
|
||||
return Relation.CELL_INSIDE_QUERY;
|
||||
}
|
||||
double innerMinX = decode(NumericUtils.sortableBytesToInt(minTriangle, maxXOffset));
|
||||
if (rectangle2D.relate(innerMinX, maxX, minY, maxY) == Relation.CELL_INSIDE_QUERY) {
|
||||
return Relation.CELL_INSIDE_QUERY;
|
||||
}
|
||||
}
|
||||
return rel;
|
||||
}
|
||||
|
||||
/** returns true if the query matches the encoded triangle */
|
||||
@Override
|
||||
protected boolean queryMatches(byte[] t, ShapeField.DecodedTriangle scratchTriangle, QueryRelation queryRelation) {
|
||||
// decode indexed triangle
|
||||
ShapeField.decodeTriangle(t, scratchTriangle);
|
||||
|
||||
double aY = decode(scratchTriangle.aY);
|
||||
double aX = decode(scratchTriangle.aX);
|
||||
double bY = decode(scratchTriangle.bY);
|
||||
double bX = decode(scratchTriangle.bX);
|
||||
double cY = decode(scratchTriangle.cY);
|
||||
double cX = decode(scratchTriangle.cX);
|
||||
|
||||
switch (queryRelation) {
|
||||
case INTERSECTS: return rectangle2D.relateTriangle(aX, aY, bX, bY, cX, cY) != Relation.CELL_OUTSIDE_QUERY;
|
||||
case WITHIN: return rectangle2D.contains(aX, aY) && rectangle2D.contains(bX, bY) && rectangle2D.contains(cX, cY);
|
||||
case DISJOINT: return rectangle2D.relateTriangle(aX, aY, bX, bY, cX, cY) == Relation.CELL_OUTSIDE_QUERY;
|
||||
default: throw new IllegalArgumentException("Unsupported query type :[" + queryRelation + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D.WithinRelation queryWithin(byte[] t, ShapeField.DecodedTriangle scratchTriangle) {
|
||||
ShapeField.decodeTriangle(t, scratchTriangle);
|
||||
|
||||
double aY = decode(scratchTriangle.aY);
|
||||
double aX = decode(scratchTriangle.aX);
|
||||
double bY = decode(scratchTriangle.bY);
|
||||
double bX = decode(scratchTriangle.bX);
|
||||
double cY = decode(scratchTriangle.cY);
|
||||
double cX = decode(scratchTriangle.cX);
|
||||
|
||||
return rectangle2D.withinTriangle(aX, aY, scratchTriangle.ab, bX, bY, scratchTriangle.bc, cX, cY, scratchTriangle.ca);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return sameClassAs(o) && equalsTo(getClass().cast(o));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean equalsTo(Object o) {
|
||||
return super.equalsTo(o) && rectangle.equals(((XYShapeBoundingBoxQuery)o).rectangle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = super.hashCode();
|
||||
hash = 31 * hash + rectangle.hashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(String field) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(getClass().getSimpleName());
|
||||
sb.append(':');
|
||||
if (this.field.equals(field) == false) {
|
||||
sb.append(" field=");
|
||||
sb.append(this.field);
|
||||
sb.append(':');
|
||||
}
|
||||
sb.append(rectangle.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* 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.document;
|
||||
|
||||
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;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
import static org.apache.lucene.geo.XYEncodingUtils.decode;
|
||||
|
||||
/**
|
||||
* Finds all previously indexed cartesian shapes that intersect the specified arbitrary {@code XYLine}.
|
||||
* <p>
|
||||
* Note:
|
||||
* <ul>
|
||||
* <li>{@code QueryRelation.WITHIN} queries are not yet supported</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* todo:
|
||||
* <ul>
|
||||
* <li>Add distance support for buffered queries</li>
|
||||
* </ul>
|
||||
* <p>The field must be indexed using
|
||||
* {@link org.apache.lucene.document.XYShape#createIndexableFields} added per document.
|
||||
**/
|
||||
final class XYShapeLineQuery extends ShapeQuery {
|
||||
final XYLine[] lines;
|
||||
final private Component2D line2D;
|
||||
|
||||
/** construct a Line Query over cartesian geometries from the given line objects */
|
||||
public XYShapeLineQuery(String field, QueryRelation queryRelation, XYLine... lines) {
|
||||
super(field, queryRelation);
|
||||
/** line queries do not support within relations, only intersects and disjoint */
|
||||
if (queryRelation == QueryRelation.WITHIN) {
|
||||
throw new IllegalArgumentException("XYShapeLineQuery does not support " + QueryRelation.WITHIN + " queries");
|
||||
}
|
||||
|
||||
if (lines == null) {
|
||||
throw new IllegalArgumentException("lines must not be null");
|
||||
}
|
||||
if (lines.length == 0) {
|
||||
throw new IllegalArgumentException("lines must not be empty");
|
||||
}
|
||||
for (int i = 0; i < lines.length; ++i) {
|
||||
if (lines[i] == null) {
|
||||
throw new IllegalArgumentException("line[" + i + "] must not be null");
|
||||
} else if (lines[i].minX > lines[i].maxX) {
|
||||
throw new IllegalArgumentException("XYShapeLineQuery: minX cannot be greater than maxX.");
|
||||
} else if (lines[i].minY > lines[i].maxY) {
|
||||
throw new IllegalArgumentException("XYShapeLineQuery: minY cannot be greater than maxY.");
|
||||
}
|
||||
}
|
||||
this.lines = lines.clone();
|
||||
this.line2D = Line2D.create(lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Relation relateRangeBBoxToQuery(int minXOffset, int minYOffset, byte[] minTriangle,
|
||||
int maxXOffset, int maxYOffset, byte[] maxTriangle) {
|
||||
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(minX, maxX, minY, maxY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean queryMatches(byte[] t, ShapeField.DecodedTriangle scratchTriangle, QueryRelation queryRelation) {
|
||||
ShapeField.decodeTriangle(t, scratchTriangle);
|
||||
|
||||
double alat = decode(scratchTriangle.aY);
|
||||
double alon = decode(scratchTriangle.aX);
|
||||
double blat = decode(scratchTriangle.bY);
|
||||
double blon = decode(scratchTriangle.bX);
|
||||
double clat = decode(scratchTriangle.cY);
|
||||
double clon = decode(scratchTriangle.cX);
|
||||
|
||||
switch (queryRelation) {
|
||||
case INTERSECTS: return line2D.relateTriangle(alon, alat, blon, blat, clon, clat) != Relation.CELL_OUTSIDE_QUERY;
|
||||
case WITHIN: return line2D.relateTriangle(alon, alat, blon, blat, clon, clat) == Relation.CELL_INSIDE_QUERY;
|
||||
case DISJOINT: return line2D.relateTriangle(alon, alat, blon, blat, clon, clat) == Relation.CELL_OUTSIDE_QUERY;
|
||||
default: throw new IllegalArgumentException("Unsupported query type :[" + queryRelation + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D.WithinRelation queryWithin(byte[] t, ShapeField.DecodedTriangle scratchTriangle) {
|
||||
ShapeField.decodeTriangle(t, scratchTriangle);
|
||||
|
||||
double alat = decode(scratchTriangle.aY);
|
||||
double alon = decode(scratchTriangle.aX);
|
||||
double blat = decode(scratchTriangle.bY);
|
||||
double blon = decode(scratchTriangle.bX);
|
||||
double clat = decode(scratchTriangle.cY);
|
||||
double clon = decode(scratchTriangle.cX);
|
||||
|
||||
return line2D.withinTriangle(alon, alat, scratchTriangle.ab, blon, blat, scratchTriangle.bc, clon, clat, scratchTriangle.ca);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(String field) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(getClass().getSimpleName());
|
||||
sb.append(':');
|
||||
if (this.field.equals(field) == false) {
|
||||
sb.append(" field=");
|
||||
sb.append(this.field);
|
||||
sb.append(':');
|
||||
}
|
||||
sb.append("XYLine(").append(lines[0].toGeoJSON()).append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean equalsTo(Object o) {
|
||||
return super.equalsTo(o) && Arrays.equals(lines, ((XYShapeLineQuery)o).lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = super.hashCode();
|
||||
hash = 31 * hash + Arrays.hashCode(lines);
|
||||
return hash;
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
* 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.document;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.Point2D;
|
||||
import org.apache.lucene.geo.XYEncodingUtils;
|
||||
import org.apache.lucene.index.PointValues.Relation;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
import static org.apache.lucene.geo.XYEncodingUtils.decode;
|
||||
|
||||
/**
|
||||
* Finds all previously indexed shapes that intersect the specified bounding box.
|
||||
*
|
||||
* <p>The field must be indexed using
|
||||
* {@link XYShape#createIndexableFields} added per document.
|
||||
**/
|
||||
final class XYShapePointQuery extends ShapeQuery {
|
||||
final Component2D point2D;
|
||||
final float[][] points;
|
||||
|
||||
/** construct a Point or MultiPoint Query over cartesian geometries from the given point values */
|
||||
public XYShapePointQuery(String field, ShapeField.QueryRelation queryRelation, float[][] points) {
|
||||
super(field, queryRelation);
|
||||
this.points = points;
|
||||
this.point2D = Point2D.create(points);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Relation relateRangeBBoxToQuery(int minXOffset, int minYOffset, byte[] minTriangle,
|
||||
int maxXOffset, int maxYOffset, byte[] maxTriangle) {
|
||||
double minY = XYEncodingUtils.decode(NumericUtils.sortableBytesToInt(minTriangle, minYOffset));
|
||||
double minX = XYEncodingUtils.decode(NumericUtils.sortableBytesToInt(minTriangle, minXOffset));
|
||||
double maxY = XYEncodingUtils.decode(NumericUtils.sortableBytesToInt(maxTriangle, maxYOffset));
|
||||
double maxX = XYEncodingUtils.decode(NumericUtils.sortableBytesToInt(maxTriangle, maxXOffset));
|
||||
|
||||
// check internal node against query
|
||||
return point2D.relate(minX, maxX, minY, maxY);
|
||||
}
|
||||
|
||||
/** returns true if the query matches the encoded triangle */
|
||||
@Override
|
||||
protected boolean queryMatches(byte[] t, ShapeField.DecodedTriangle scratchTriangle, ShapeField.QueryRelation queryRelation) {
|
||||
ShapeField.decodeTriangle(t, scratchTriangle);
|
||||
|
||||
double aY = decode(scratchTriangle.aY);
|
||||
double aX = decode(scratchTriangle.aX);
|
||||
double bY = decode(scratchTriangle.bY);
|
||||
double bX = decode(scratchTriangle.bX);
|
||||
double cY = decode(scratchTriangle.cY);
|
||||
double cX = decode(scratchTriangle.cX);
|
||||
|
||||
switch (queryRelation) {
|
||||
case INTERSECTS:
|
||||
return point2D.relateTriangle(aX, aY, bX, bY, cX, cY) != Relation.CELL_OUTSIDE_QUERY;
|
||||
case WITHIN:
|
||||
return point2D.relateTriangle(aX, aY, bX, bY, cX, cY) == Relation.CELL_INSIDE_QUERY;
|
||||
case DISJOINT:
|
||||
return point2D.relateTriangle(aX, aY, bX, bY, cX, cY) == Relation.CELL_OUTSIDE_QUERY;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported query type :[" + queryRelation + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D.WithinRelation queryWithin(byte[] t, ShapeField.DecodedTriangle scratchTriangle) {
|
||||
ShapeField.decodeTriangle(t, scratchTriangle);
|
||||
|
||||
double aY = decode(scratchTriangle.aY);
|
||||
double aX = decode(scratchTriangle.aX);
|
||||
double bY = decode(scratchTriangle.bY);
|
||||
double bX = decode(scratchTriangle.bX);
|
||||
double cY = decode(scratchTriangle.cY);
|
||||
double cX = decode(scratchTriangle.cX);
|
||||
|
||||
return point2D.withinTriangle(aX, aY, scratchTriangle.ab, bX, bY, scratchTriangle.bc, cX, cY, scratchTriangle.ca);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return sameClassAs(o) && equalsTo(getClass().cast(o));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean equalsTo(Object o) {
|
||||
return super.equalsTo(o) && Arrays.equals(points, ((XYShapePointQuery)o).points);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = super.hashCode();
|
||||
hash = 31 * hash + Arrays.hashCode(points);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(String field) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(getClass().getSimpleName());
|
||||
sb.append(':');
|
||||
if (this.field.equals(field) == false) {
|
||||
sb.append(" field=");
|
||||
sb.append(this.field);
|
||||
sb.append(':');
|
||||
}
|
||||
sb.append("lat = " + points[0][0] + " , lon = " + points[0][1]);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -21,45 +21,29 @@ import java.util.Arrays;
|
|||
import org.apache.lucene.document.ShapeField.QueryRelation;
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.XYEncodingUtils;
|
||||
import org.apache.lucene.geo.XYPolygon;
|
||||
import org.apache.lucene.geo.XYPolygon2D;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.index.PointValues.Relation;
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
|
||||
import static org.apache.lucene.geo.XYEncodingUtils.decode;
|
||||
|
||||
/**
|
||||
* Finds all previously indexed cartesian shapes that intersect the specified arbitrary cartesian {@link XYPolygon}.
|
||||
* Finds all previously indexed cartesian shapes that comply the given {@link QueryRelation} with
|
||||
* the specified array of {@link XYGeometry}.
|
||||
*
|
||||
* <p>The field must be indexed using
|
||||
* {@link org.apache.lucene.document.XYShape#createIndexableFields} added per document.
|
||||
* <p>The field must be indexed using {@link XYShape#createIndexableFields} added per document.
|
||||
**/
|
||||
final class XYShapePolygonQuery extends ShapeQuery {
|
||||
final XYPolygon[] polygons;
|
||||
final private Component2D poly2D;
|
||||
final class XYShapeQuery extends ShapeQuery {
|
||||
final XYGeometry[] geometries;
|
||||
final private Component2D component2D;
|
||||
|
||||
/**
|
||||
* Creates a query that matches all indexed shapes to the provided polygons
|
||||
*/
|
||||
public XYShapePolygonQuery(String field, QueryRelation queryRelation, XYPolygon... polygons) {
|
||||
XYShapeQuery(String field, QueryRelation queryRelation, XYGeometry... geometries) {
|
||||
super(field, queryRelation);
|
||||
if (polygons == null) {
|
||||
throw new IllegalArgumentException("polygons must not be null");
|
||||
}
|
||||
if (polygons.length == 0) {
|
||||
throw new IllegalArgumentException("polygons must not be empty");
|
||||
}
|
||||
for (int i = 0; i < polygons.length; i++) {
|
||||
if (polygons[i] == null) {
|
||||
throw new IllegalArgumentException("polygon[" + i + "] must not be null");
|
||||
} else if (polygons[i].minX > polygons[i].maxX) {
|
||||
throw new IllegalArgumentException("XYShapePolygonQuery: minX cannot be greater than maxX.");
|
||||
} else if (polygons[i].minY > polygons[i].maxY) {
|
||||
throw new IllegalArgumentException("XYShapePolygonQuery: minY cannot be greater than maxY.");
|
||||
}
|
||||
}
|
||||
this.polygons = polygons.clone();
|
||||
this.poly2D = XYPolygon2D.create(polygons);
|
||||
this.component2D = XYGeometry.create(geometries);
|
||||
this.geometries = geometries.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,7 +56,7 @@ final class XYShapePolygonQuery extends ShapeQuery {
|
|||
double maxLon = XYEncodingUtils.decode(NumericUtils.sortableBytesToInt(maxTriangle, maxXOffset));
|
||||
|
||||
// check internal node against query
|
||||
return poly2D.relate(minLon, maxLon, minLat, maxLat);
|
||||
return component2D.relate(minLon, maxLon, minLat, maxLat);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,9 +71,9 @@ final class XYShapePolygonQuery extends ShapeQuery {
|
|||
double clon = decode(scratchTriangle.cX);
|
||||
|
||||
switch (queryRelation) {
|
||||
case INTERSECTS: return poly2D.relateTriangle(alon, alat, blon, blat, clon, clat) != Relation.CELL_OUTSIDE_QUERY;
|
||||
case WITHIN: return poly2D.relateTriangle(alon, alat, blon, blat, clon, clat) == Relation.CELL_INSIDE_QUERY;
|
||||
case DISJOINT: return poly2D.relateTriangle(alon, alat, blon, blat, clon, clat) == Relation.CELL_OUTSIDE_QUERY;
|
||||
case INTERSECTS: return component2D.relateTriangle(alon, alat, blon, blat, clon, clat) != Relation.CELL_OUTSIDE_QUERY;
|
||||
case WITHIN: return component2D.relateTriangle(alon, alat, blon, blat, clon, clat) == Relation.CELL_INSIDE_QUERY;
|
||||
case DISJOINT: return component2D.relateTriangle(alon, alat, blon, blat, clon, clat) == Relation.CELL_OUTSIDE_QUERY;
|
||||
default: throw new IllegalArgumentException("Unsupported query type :[" + queryRelation + "]");
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +89,7 @@ final class XYShapePolygonQuery extends ShapeQuery {
|
|||
double clat = decode(scratchTriangle.cY);
|
||||
double clon = decode(scratchTriangle.cX);
|
||||
|
||||
return poly2D.withinTriangle(alon, alat, scratchTriangle.ab, blon, blat, scratchTriangle.bc, clon, clat, scratchTriangle.ca);
|
||||
return component2D.withinTriangle(alon, alat, scratchTriangle.ab, blon, blat, scratchTriangle.bc, clon, clat, scratchTriangle.ca);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -118,19 +102,24 @@ final class XYShapePolygonQuery extends ShapeQuery {
|
|||
sb.append(this.field);
|
||||
sb.append(':');
|
||||
}
|
||||
sb.append("XYPolygon(").append(polygons[0].toGeoJSON()).append(")");
|
||||
sb.append("[");
|
||||
for (int i = 0; i < geometries.length; i++) {
|
||||
sb.append(geometries[i].toString());
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean equalsTo(Object o) {
|
||||
return super.equalsTo(o) && Arrays.equals(polygons, ((XYShapePolygonQuery)o).polygons);
|
||||
return super.equalsTo(o) && Arrays.equals(geometries, ((XYShapeQuery)o).geometries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = super.hashCode();
|
||||
hash = 31 * hash + Arrays.hashCode(polygons);
|
||||
hash = 31 * hash + Arrays.hashCode(geometries);
|
||||
return hash;
|
||||
}
|
||||
}
|
|
@ -25,17 +25,15 @@ import org.apache.lucene.util.ArrayUtil;
|
|||
* 2D multi-component geometry implementation represented as an interval tree of components.
|
||||
* <p>
|
||||
* 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 */
|
||||
/** minimum Y of this geometry's bounding box area */
|
||||
private double minY;
|
||||
/** maximum latitude of this geometry's bounding box area */
|
||||
/** maximum Y of this geometry's bounding box area */
|
||||
private double maxY;
|
||||
/** minimum longitude of this geometry's bounding box area */
|
||||
/** minimum X of this geometry's bounding box area */
|
||||
private double minX;
|
||||
/** maximum longitude of this geometry's bounding box area */
|
||||
/** maximum X 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
|
||||
|
@ -48,7 +46,7 @@ final class ComponentTree implements Component2D {
|
|||
/** root node of edge tree */
|
||||
final private Component2D component;
|
||||
|
||||
protected ComponentTree(Component2D component, boolean splitX) {
|
||||
private ComponentTree(Component2D component, boolean splitX) {
|
||||
this.minY = component.getMinY();
|
||||
this.maxY = component.getMaxY();
|
||||
this.minX = component.getMinX();
|
||||
|
@ -97,7 +95,6 @@ final class ComponentTree implements Component2D {
|
|||
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) {
|
||||
|
@ -131,7 +128,6 @@ final class ComponentTree implements Component2D {
|
|||
return component.withinTriangle(minX, maxX, minY, maxY, aX, aY, ab, bX, bY, bc, cX, cY, ca);
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
|
@ -156,7 +152,7 @@ final class ComponentTree implements Component2D {
|
|||
}
|
||||
|
||||
/** Creates tree from provided components */
|
||||
public static Component2D create(Component2D[] components) {
|
||||
static Component2D create(Component2D[] components) {
|
||||
if (components.length == 1) {
|
||||
return components[0];
|
||||
}
|
||||
|
|
|
@ -23,45 +23,39 @@ import static org.apache.lucene.geo.GeoUtils.lineCrossesLineWithBoundary;
|
|||
import static org.apache.lucene.geo.GeoUtils.orient;
|
||||
|
||||
/**
|
||||
* 2D line/polygon geometry implementation represented as a balanced interval tree of edges.
|
||||
* Internal tree node: represents geometry edge from [x1, y1] to [x2, y2].
|
||||
* The sort value is {@code low}, which is the minimum y of the edge.
|
||||
* {@code max} stores the maximum y of this edge or any children.
|
||||
* <p>
|
||||
* Construction takes {@code O(n log n)} time for sorting and tree construction.
|
||||
* {@link #relate relate()} are {@code O(n)}, but for most
|
||||
* Methods are {@code O(n)}, but for most
|
||||
* practical lines and polygons are much faster than brute force.
|
||||
* @lucene.internal
|
||||
*/
|
||||
/**
|
||||
* Internal tree node: represents geometry edge from lat1,lon1 to lat2,lon2.
|
||||
* The sort value is {@code low}, which is the minimum latitude of the edge.
|
||||
* {@code max} stores the maximum latitude of this edge or any children.
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class EdgeTree {
|
||||
// lat-lon pair (in original order) of the two vertices
|
||||
final double y1, y2;
|
||||
final double x1, x2;
|
||||
/** min of this edge */
|
||||
final double low;
|
||||
/** max latitude of this edge or any children */
|
||||
double max;
|
||||
/** left child edge, or null */
|
||||
EdgeTree left;
|
||||
/** right child edge, or null */
|
||||
EdgeTree right;
|
||||
/** helper bytes to signal if a point is on an edge, it is within the edge tree or disjoint */
|
||||
final private static byte FALSE = 0x00;
|
||||
final private static byte TRUE = 0x01;
|
||||
final private static byte ON_EDGE = 0x02;
|
||||
final class EdgeTree {
|
||||
// X-Y pair (in original order) of the two vertices
|
||||
final double y1, y2;
|
||||
final double x1, x2;
|
||||
/** min Y of this edge */
|
||||
final double low;
|
||||
/** max Y of this edge or any children */
|
||||
double max;
|
||||
/** left child edge, or null */
|
||||
EdgeTree left;
|
||||
/** right child edge, or null */
|
||||
EdgeTree right;
|
||||
/** helper bytes to signal if a point is on an edge, it is within the edge tree or disjoint */
|
||||
final private static byte FALSE = 0x00;
|
||||
final private static byte TRUE = 0x01;
|
||||
final private static byte ON_EDGE = 0x02;
|
||||
|
||||
EdgeTree(double x1, double y1, double x2, double y2, double low, double max) {
|
||||
this.y1 = y1;
|
||||
this.x1 = x1;
|
||||
this.y2 = y2;
|
||||
this.x2 = x2;
|
||||
this.low = low;
|
||||
this.max = max;
|
||||
}
|
||||
private EdgeTree(double x1, double y1, double x2, double y2, double low, double max) {
|
||||
this.y1 = y1;
|
||||
this.x1 = x1;
|
||||
this.y2 = y2;
|
||||
this.x2 = x2;
|
||||
this.low = low;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the point is on an edge or crosses the edge subtree an odd number
|
||||
|
@ -135,7 +129,7 @@ public class EdgeTree {
|
|||
}
|
||||
|
||||
/** returns true if the provided x, y point lies on the line */
|
||||
protected boolean isPointOnLine(double x, double y) {
|
||||
boolean isPointOnLine(double x, double y) {
|
||||
if (y <= max) {
|
||||
double a1x = x1;
|
||||
double a1y = y1;
|
||||
|
@ -160,7 +154,7 @@ public class EdgeTree {
|
|||
|
||||
|
||||
/** Returns true if the triangle crosses any edge in this edge subtree */
|
||||
protected boolean crossesTriangle(double minX, double maxX, double minY, double maxY,
|
||||
boolean crossesTriangle(double minX, double maxX, double minY, double maxY,
|
||||
double ax, double ay, double bx, double by, double cx, double cy, boolean includeBoundary) {
|
||||
if (minY <= max) {
|
||||
double dy = y1;
|
||||
|
@ -204,7 +198,7 @@ public class EdgeTree {
|
|||
}
|
||||
|
||||
/** Returns true if the box crosses any edge in this edge subtree */
|
||||
protected boolean crossesBox(double minX, double maxX, double minY, double maxY, boolean includeBoundary) {
|
||||
boolean crossesBox(double minX, double maxX, double minY, double maxY, boolean includeBoundary) {
|
||||
// we just have to cross one edge to answer the question, so we descend the tree and return when we do.
|
||||
if (minY <= max) {
|
||||
// we compute line intersections of every polygon edge with every box line.
|
||||
|
@ -261,7 +255,7 @@ public class EdgeTree {
|
|||
}
|
||||
|
||||
/** Returns true if the line crosses any edge in this edge subtree */
|
||||
protected boolean crossesLine(double minX, double maxX, double minY, double maxY, double a2x, double a2y, double b2x, double b2y, boolean includeBoundary) {
|
||||
boolean crossesLine(double minX, double maxX, double minY, double maxY, double a2x, double a2y, double b2x, double b2y, boolean includeBoundary) {
|
||||
if (minY <= max) {
|
||||
double a1x = x1;
|
||||
double a1y = y1;
|
||||
|
@ -297,7 +291,7 @@ public class EdgeTree {
|
|||
* Creates an edge interval tree from a set of geometry vertices.
|
||||
* @return root node of the tree.
|
||||
*/
|
||||
protected static EdgeTree createTree(double[] x, double[] y) {
|
||||
static EdgeTree createTree(double[] x, double[] y) {
|
||||
EdgeTree edges[] = new EdgeTree[x.length - 1];
|
||||
for (int i = 1; i < x.length; i++) {
|
||||
double x1 = x[i-1];
|
||||
|
|
|
@ -23,17 +23,16 @@ import org.apache.lucene.index.PointValues.Relation;
|
|||
* <p>
|
||||
* Line {@code Line2D} Construction takes {@code O(n log n)} time for sorting and tree construction.
|
||||
* {@link #relate relate()} are {@code O(n)}, but for most practical lines are much faster than brute force.
|
||||
* @lucene.internal
|
||||
*/
|
||||
public final class Line2D implements Component2D {
|
||||
final class Line2D implements Component2D {
|
||||
|
||||
/** minimum latitude of this geometry's bounding box area */
|
||||
/** minimum Y of this geometry's bounding box area */
|
||||
final private double minY;
|
||||
/** maximum latitude of this geometry's bounding box area */
|
||||
/** maximum Y of this geometry's bounding box area */
|
||||
final private double maxY;
|
||||
/** minimum longitude of this geometry's bounding box area */
|
||||
/** minimum X of this geometry's bounding box area */
|
||||
final private double minX;
|
||||
/** maximum longitude of this geometry's bounding box area */
|
||||
/** maximum X of this geometry's bounding box area */
|
||||
final private double maxX;
|
||||
/** lines represented as a 2-d interval tree.*/
|
||||
final private EdgeTree tree;
|
||||
|
@ -184,21 +183,13 @@ public final class Line2D implements Component2D {
|
|||
return relation;
|
||||
}
|
||||
|
||||
/** 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 ComponentTree.create(components);
|
||||
/** create a Line2D from the provided LatLon Linestring */
|
||||
static Component2D create(Line line) {
|
||||
return new Line2D(line);
|
||||
}
|
||||
|
||||
/** 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);
|
||||
/** create a Line2D from the provided XY Linestring */
|
||||
static Component2D create(XYLine line) {
|
||||
return new Line2D(line);
|
||||
}
|
||||
}
|
|
@ -56,9 +56,7 @@ public final class Point extends LatLonGeometry {
|
|||
|
||||
@Override
|
||||
protected Component2D toComponent2D() {
|
||||
double qLat = GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(lat));
|
||||
double qLon = GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(lon));
|
||||
return Point2D.create(new double[] {qLat, qLon});
|
||||
return Point2D.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,15 +21,13 @@ import org.apache.lucene.index.PointValues;
|
|||
|
||||
/**
|
||||
* 2D point implementation containing geo spatial logic.
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class Point2D implements Component2D {
|
||||
final class Point2D implements Component2D {
|
||||
|
||||
final private double x;
|
||||
final private double y;
|
||||
|
||||
Point2D(double x, double y) {
|
||||
private Point2D(double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
@ -88,22 +86,14 @@ public class Point2D implements Component2D {
|
|||
return WithinRelation.DISJOINT;
|
||||
}
|
||||
|
||||
/** create a Point2D component tree from provided array of LatLon points. */
|
||||
public static Component2D create(double[]... points) {
|
||||
Point2D components[] = new Point2D[points.length];
|
||||
for (int i = 0; i < components.length; ++i) {
|
||||
components[i] = new Point2D(GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(points[i][1]))
|
||||
, GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(points[i][0])));
|
||||
}
|
||||
return ComponentTree.create(components);
|
||||
/** create a Point2D component tree from a LatLon point */
|
||||
static Component2D create(Point point) {
|
||||
return new Point2D(GeoEncodingUtils.decodeLongitude(GeoEncodingUtils.encodeLongitude(point.getLon())),
|
||||
GeoEncodingUtils.decodeLatitude(GeoEncodingUtils.encodeLatitude(point.getLat())));
|
||||
}
|
||||
|
||||
/** create a Point2D component tree from provided array of XY points. */
|
||||
public static Component2D create(float[]... xyPoints) {
|
||||
Point2D components[] = new Point2D[xyPoints.length];
|
||||
for (int i = 0; i < components.length; ++i) {
|
||||
components[i] = new Point2D(xyPoints[i][0], xyPoints[i][1]);
|
||||
}
|
||||
return ComponentTree.create(components);
|
||||
/** create a Point2D component tree from a XY point */
|
||||
static Component2D create(XYPoint xyPoint) {
|
||||
return new Point2D(xyPoint.getX(), xyPoint.getY());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,24 +23,23 @@ import org.apache.lucene.index.PointValues.Relation;
|
|||
* <p>
|
||||
* Loosely based on the algorithm described in <a href="http://www-ma2.upc.es/geoc/Schirra-pointPolygon.pdf">
|
||||
* http://www-ma2.upc.es/geoc/Schirra-pointPolygon.pdf</a>.
|
||||
* @lucene.internal
|
||||
*/
|
||||
|
||||
public class Polygon2D implements Component2D {
|
||||
/** minimum latitude of this geometry's bounding box area */
|
||||
final class Polygon2D implements Component2D {
|
||||
/** minimum Y of this geometry's bounding box area */
|
||||
final private double minY;
|
||||
/** maximum latitude of this geometry's bounding box area */
|
||||
/** maximum Y of this geometry's bounding box area */
|
||||
final private double maxY;
|
||||
/** minimum longitude of this geometry's bounding box area */
|
||||
/** minimum X of this geometry's bounding box area */
|
||||
final private double minX;
|
||||
/** maximum longitude of this geometry's bounding box area */
|
||||
/** maximum X of this geometry's bounding box area */
|
||||
final private double maxX;
|
||||
/** tree of holes, or null */
|
||||
final protected Component2D holes;
|
||||
/** Edges of the polygon represented as a 2-d interval tree.*/
|
||||
final EdgeTree tree;
|
||||
|
||||
protected Polygon2D(final double minX, final double maxX, final double minY, final double maxY, double[] x, double[] y, Component2D holes) {
|
||||
private Polygon2D(final double minX, final double maxX, final double minY, final double maxY, double[] x, double[] y, Component2D holes) {
|
||||
this.minY = minY;
|
||||
this.maxY = maxY;
|
||||
this.minX = minX;
|
||||
|
@ -49,6 +48,10 @@ public class Polygon2D implements Component2D {
|
|||
this.tree = EdgeTree.createTree(x, y);
|
||||
}
|
||||
|
||||
private Polygon2D(XYPolygon polygon, Component2D holes) {
|
||||
this(polygon.minX, polygon.maxX, polygon.minY, polygon.maxY, polygon.getPolyX(), polygon.getPolyY(), holes);
|
||||
}
|
||||
|
||||
protected Polygon2D(Polygon polygon, Component2D holes) {
|
||||
this(polygon.minLon, polygon.maxLon, polygon.minLat, polygon.maxLat, polygon.getPolyLons(), polygon.getPolyLats(), holes);
|
||||
}
|
||||
|
@ -312,18 +315,24 @@ public class Polygon2D implements Component2D {
|
|||
return containsCount;
|
||||
}
|
||||
|
||||
/** Builds a Polygon2D from multipolygon */
|
||||
public static Component2D create(Polygon... polygons) {
|
||||
Component2D components[] = new Component2D[polygons.length];
|
||||
for (int i = 0; i < components.length; i++) {
|
||||
Polygon gon = polygons[i];
|
||||
Polygon gonHoles[] = gon.getHoles();
|
||||
Component2D holes = null;
|
||||
if (gonHoles.length > 0) {
|
||||
holes = create(gonHoles);
|
||||
}
|
||||
components[i] = new Polygon2D(gon, holes);
|
||||
/** Builds a Polygon2D from LatLon polygon */
|
||||
static Component2D create(Polygon polygon) {
|
||||
Polygon gonHoles[] = polygon.getHoles();
|
||||
Component2D holes = null;
|
||||
if (gonHoles.length > 0) {
|
||||
holes = LatLonGeometry.create(gonHoles);
|
||||
}
|
||||
return ComponentTree.create(components);
|
||||
return new Polygon2D(polygon, holes);
|
||||
}
|
||||
|
||||
/** Builds a Polygon2D from XY polygon */
|
||||
static Component2D create(XYPolygon polygon) {
|
||||
XYPolygon gonHoles[] = polygon.getHoles();
|
||||
Component2D holes = null;
|
||||
if (gonHoles.length > 0) {
|
||||
holes = XYGeometry.create(gonHoles);
|
||||
}
|
||||
return new Polygon2D(polygon, holes);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Cartesian Geometry object.
|
||||
**/
|
||||
public abstract class XYGeometry {
|
||||
|
||||
/** get a Component2D from this object */
|
||||
protected abstract Component2D toComponent2D();
|
||||
|
||||
/** Creates a Component2D from the provided XYGeometries array */
|
||||
public static Component2D create(XYGeometry... xyGeometries) {
|
||||
if (xyGeometries == null) {
|
||||
throw new IllegalArgumentException("geometries must not be null");
|
||||
}
|
||||
if (xyGeometries.length == 0) {
|
||||
throw new IllegalArgumentException("geometries must not be empty");
|
||||
}
|
||||
if (xyGeometries.length == 1) {
|
||||
if (xyGeometries[0] == null) {
|
||||
throw new IllegalArgumentException("geometries[0] must not be null");
|
||||
}
|
||||
return xyGeometries[0].toComponent2D();
|
||||
}
|
||||
Component2D[] components = new Component2D[xyGeometries.length];
|
||||
for (int i = 0; i < xyGeometries.length; i++) {
|
||||
if (xyGeometries[i] == null) {
|
||||
throw new IllegalArgumentException("geometries[" + i + "] must not be null");
|
||||
}
|
||||
components[i] = xyGeometries[i].toComponent2D();
|
||||
}
|
||||
return ComponentTree.create(components);
|
||||
}
|
||||
}
|
|
@ -19,10 +19,10 @@ package org.apache.lucene.geo;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Represents a line in cartesian space. You can construct the Line directly with {@code double[]}, {@code double[]} x, y arrays
|
||||
* Represents a line in cartesian space. You can construct the Line directly with {@code float[]}, {@code float[]} x, y arrays
|
||||
* coordinates.
|
||||
*/
|
||||
public class XYLine {
|
||||
public class XYLine extends XYGeometry {
|
||||
/** array of x coordinates */
|
||||
private final double[] x;
|
||||
/** array of y coordinates */
|
||||
|
@ -30,7 +30,7 @@ public class XYLine {
|
|||
|
||||
/** minimum x of this line's bounding box */
|
||||
public final double minX;
|
||||
/** maximum x of this line's bounding box */
|
||||
/** maximum y of this line's bounding box */
|
||||
public final double maxX;
|
||||
/** minimum y of this line's bounding box */
|
||||
public final double minY;
|
||||
|
@ -38,7 +38,7 @@ public class XYLine {
|
|||
public final double maxY;
|
||||
|
||||
/**
|
||||
* Creates a new Line from the supplied x/y array.
|
||||
* Creates a new Line from the supplied X/Y array.
|
||||
*/
|
||||
public XYLine(float[] x, float[] y) {
|
||||
if (x == null) {
|
||||
|
@ -103,6 +103,19 @@ public class XYLine {
|
|||
return y.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D toComponent2D() {
|
||||
return Line2D.create(this);
|
||||
}
|
||||
|
||||
public String toGeoJSON() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
sb.append(Polygon.verticesToGeoJSON(x, y));
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
@ -132,13 +145,4 @@ public class XYLine {
|
|||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** prints polygons as geojson */
|
||||
public String toGeoJSON() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
sb.append(Polygon.verticesToGeoJSON(x, y));
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Represents a point on the earth's surface. You can construct the point directly with {@code double}
|
||||
* coordinates.
|
||||
* <p>
|
||||
* NOTES:
|
||||
* <ol>
|
||||
* <li>latitude/longitude values must be in decimal degrees.
|
||||
* <li>For more advanced GeoSpatial indexing and query operations see the {@code spatial-extras} module
|
||||
* </ol>
|
||||
*/
|
||||
public final class XYPoint extends XYGeometry {
|
||||
|
||||
/** latitude coordinate */
|
||||
private final double x;
|
||||
/** longitude coordinate */
|
||||
private final double y;
|
||||
|
||||
/**
|
||||
* Creates a new Point from the supplied latitude/longitude.
|
||||
*/
|
||||
public XYPoint(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/** Returns latitude value at given index */
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Returns longitude value at given index */
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D toComponent2D() {
|
||||
return Point2D.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof XYPoint)) return false;
|
||||
XYPoint point = (XYPoint) o;
|
||||
return point.x == x && point.y == y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Double.hashCode(x);
|
||||
result = 31 * result + Double.hashCode(y);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Point(");
|
||||
sb.append(x);
|
||||
sb.append(",");
|
||||
sb.append(y);
|
||||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
|
@ -19,10 +19,10 @@ package org.apache.lucene.geo;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Represents a polygon in cartesian space. You can construct the Polygon directly with {@code double[]}, {@code double[]} x, y arrays
|
||||
* Represents a polygon in cartesian space. You can construct the Polygon directly with {@code float[]}, {@code float[]} x, y arrays
|
||||
* coordinates.
|
||||
*/
|
||||
public class XYPolygon {
|
||||
public final class XYPolygon extends XYGeometry {
|
||||
private final double[] x;
|
||||
private final double[] y;
|
||||
private final XYPolygon[] holes;
|
||||
|
@ -145,6 +145,23 @@ public class XYPolygon {
|
|||
return holes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D toComponent2D() {
|
||||
return Polygon2D.create(this);
|
||||
}
|
||||
|
||||
public String toGeoJSON() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
sb.append(Polygon.verticesToGeoJSON(y, x));
|
||||
for (XYPolygon hole : holes) {
|
||||
sb.append(",");
|
||||
sb.append(Polygon.verticesToGeoJSON(hole.y, hole.x));
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
|
@ -183,17 +200,4 @@ public class XYPolygon {
|
|||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** prints polygons as geojson */
|
||||
public String toGeoJSON() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[");
|
||||
sb.append(Polygon.verticesToGeoJSON(y, x));
|
||||
for (XYPolygon hole : holes) {
|
||||
sb.append(",");
|
||||
sb.append(Polygon.verticesToGeoJSON(hole.y, hole.x));
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 2D cartesian polygon implementation represented as a balanced interval tree of edges.
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class XYPolygon2D extends Polygon2D {
|
||||
|
||||
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 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();
|
||||
Component2D holes = null;
|
||||
if (gonHoles.length > 0) {
|
||||
holes = create(gonHoles);
|
||||
}
|
||||
components[i] = new XYPolygon2D(gon, holes);
|
||||
}
|
||||
return ComponentTree.create(components);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.lucene.geo;
|
||||
|
||||
/** Represents a x/y cartesian rectangle. */
|
||||
public class XYRectangle {
|
||||
public final class XYRectangle extends XYGeometry {
|
||||
/** minimum x value */
|
||||
public final double minX;
|
||||
/** minimum y value */
|
||||
|
@ -37,6 +37,11 @@ public class XYRectangle {
|
|||
assert minY <= maxY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D toComponent2D() {
|
||||
return XYRectangle2D.create(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
|
|
@ -24,17 +24,15 @@ import static org.apache.lucene.geo.GeoUtils.orient;
|
|||
|
||||
/**
|
||||
* 2D rectangle implementation containing cartesian spatial logic.
|
||||
*
|
||||
* @lucene.internal
|
||||
*/
|
||||
public class XYRectangle2D implements Component2D {
|
||||
final class XYRectangle2D implements Component2D {
|
||||
|
||||
private final double minX;
|
||||
private final double maxX;
|
||||
private final double minY;
|
||||
private final double maxY;
|
||||
|
||||
protected XYRectangle2D(double minX, double maxX, double minY, double maxY) {
|
||||
private XYRectangle2D(double minX, double maxX, double minY, double maxY) {
|
||||
this.minX = minX;
|
||||
this.maxX = maxX;
|
||||
this.minY = minY;
|
||||
|
@ -235,15 +233,11 @@ public class XYRectangle2D implements Component2D {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
/** create a component2D from provided array of rectangles */
|
||||
public static Component2D create(XYRectangle... rectangles) {
|
||||
XYRectangle2D[] components = new XYRectangle2D[rectangles.length];
|
||||
for (int i = 0; i < components.length; ++i) {
|
||||
components[i] = new XYRectangle2D(XYEncodingUtils.decode(XYEncodingUtils.encode(rectangles[i].minX)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangles[i].maxX)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangles[i].minY)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangles[i].maxY)));
|
||||
}
|
||||
return ComponentTree.create(components);
|
||||
/** create a component2D from the provided XY rectangle */
|
||||
static Component2D create(XYRectangle rectangle) {
|
||||
return new XYRectangle2D(XYEncodingUtils.decode(XYEncodingUtils.encode(rectangle.minX)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangle.maxX)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangle.minY)),
|
||||
XYEncodingUtils.decode(XYEncodingUtils.encode(rectangle.maxY)));
|
||||
}
|
||||
}
|
|
@ -22,11 +22,9 @@ 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.LatLonGeometry;
|
||||
import org.apache.lucene.geo.Line;
|
||||
import org.apache.lucene.geo.Line2D;
|
||||
import org.apache.lucene.geo.Point2D;
|
||||
import org.apache.lucene.geo.Polygon;
|
||||
import org.apache.lucene.geo.Polygon2D;
|
||||
import org.apache.lucene.geo.Rectangle;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.QueryUtils;
|
||||
|
@ -75,17 +73,22 @@ public abstract class BaseLatLonShapeTestCase extends BaseShapeTestCase {
|
|||
|
||||
@Override
|
||||
protected Component2D toLine2D(Object... lines) {
|
||||
return Line2D.create(Arrays.stream(lines).toArray(Line[]::new));
|
||||
return LatLonGeometry.create(Arrays.stream(lines).toArray(Line[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D toPolygon2D(Object... polygons) {
|
||||
return Polygon2D.create(Arrays.stream(polygons).toArray(Polygon[]::new));
|
||||
return LatLonGeometry.create(Arrays.stream(polygons).toArray(Polygon[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D toPoint2D(Object... points) {
|
||||
return Point2D.create(Arrays.stream(points).toArray(double[][]::new));
|
||||
double[][] p = Arrays.stream(points).toArray(double[][]::new);
|
||||
org.apache.lucene.geo.Point[] pointArray = new org.apache.lucene.geo.Point[points.length];
|
||||
for (int i =0; i < points.length; i++) {
|
||||
pointArray[i] = new org.apache.lucene.geo.Point(p[i][0], p[i][1]);
|
||||
}
|
||||
return LatLonGeometry.create(pointArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -388,5 +391,4 @@ public abstract class BaseLatLonShapeTestCase extends BaseShapeTestCase {
|
|||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,12 +22,11 @@ import java.util.Random;
|
|||
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.Point2D;
|
||||
import org.apache.lucene.geo.ShapeTestUtil;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.geo.XYLine;
|
||||
import org.apache.lucene.geo.XYPoint;
|
||||
import org.apache.lucene.geo.XYPolygon;
|
||||
import org.apache.lucene.geo.XYPolygon2D;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.util.TestUtil;
|
||||
|
@ -68,17 +67,22 @@ public abstract class BaseXYShapeTestCase extends BaseShapeTestCase {
|
|||
|
||||
@Override
|
||||
protected Component2D toPoint2D(Object... points) {
|
||||
return Point2D.create(Arrays.stream(points).toArray(float[][]::new));
|
||||
float[][] p = Arrays.stream(points).toArray(float[][]::new);
|
||||
XYPoint[] pointArray = new XYPoint[points.length];
|
||||
for (int i =0; i < points.length; i++) {
|
||||
pointArray[i] = new XYPoint(p[i][0], p[i][1]);
|
||||
}
|
||||
return XYGeometry.create(pointArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D toLine2D(Object... lines) {
|
||||
return Line2D.create(Arrays.stream(lines).toArray(XYLine[]::new));
|
||||
return XYGeometry.create(Arrays.stream(lines).toArray(XYLine[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Component2D toPolygon2D(Object... polygons) {
|
||||
return XYPolygon2D.create(Arrays.stream(polygons).toArray(XYPolygon[]::new));
|
||||
return XYGeometry.create(Arrays.stream(polygons).toArray(XYPolygon[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,10 +21,9 @@ import org.apache.lucene.document.ShapeField.QueryRelation;
|
|||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.GeoEncodingUtils;
|
||||
import org.apache.lucene.geo.GeoTestUtil;
|
||||
import org.apache.lucene.geo.LatLonGeometry;
|
||||
import org.apache.lucene.geo.Line;
|
||||
import org.apache.lucene.geo.Line2D;
|
||||
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;
|
||||
|
@ -515,7 +514,7 @@ public class TestLatLonShape extends LuceneTestCase {
|
|||
double blon = -52.67048754768767;
|
||||
Polygon polygon = new Polygon(new double[] {-14.448264200949083, 0, 0, -14.448264200949083, -14.448264200949083},
|
||||
new double[] {0.9999999403953552, 0.9999999403953552, 124.50086371762484, 124.50086371762484, 0.9999999403953552});
|
||||
Component2D polygon2D = Polygon2D.create(polygon);
|
||||
Component2D polygon2D = LatLonGeometry.create(polygon);
|
||||
PointValues.Relation rel = polygon2D.relateTriangle(
|
||||
quantizeLon(alon), quantizeLat(blat),
|
||||
quantizeLon(blon), quantizeLat(blat),
|
||||
|
@ -533,7 +532,7 @@ public class TestLatLonShape extends LuceneTestCase {
|
|||
|
||||
public void testTriangleTouchingEdges() {
|
||||
Polygon p = new Polygon(new double[] {0, 0, 1, 1, 0}, new double[] {0, 1, 1, 0, 0});
|
||||
Component2D polygon2D = Polygon2D.create(p);
|
||||
Component2D polygon2D = LatLonGeometry.create(p);
|
||||
//3 shared points
|
||||
PointValues.Relation rel = polygon2D.relateTriangle(
|
||||
quantizeLon(0.5), quantizeLat(0),
|
||||
|
@ -633,7 +632,7 @@ public class TestLatLonShape extends LuceneTestCase {
|
|||
|
||||
public void testTriangleCrossingPolygonVertices() {
|
||||
Polygon p = new Polygon(new double[] {0, 0, -5, -10, -5, 0}, new double[] {-1, 1, 5, 0, -5, -1});
|
||||
Component2D polygon2D = Polygon2D.create(p);
|
||||
Component2D polygon2D = LatLonGeometry.create(p);
|
||||
PointValues.Relation rel = polygon2D.relateTriangle(
|
||||
quantizeLon(-5), quantizeLat(0),
|
||||
quantizeLon(10), quantizeLat(0),
|
||||
|
@ -643,7 +642,7 @@ public class TestLatLonShape extends LuceneTestCase {
|
|||
|
||||
public void testLineCrossingPolygonVertices() {
|
||||
Polygon p = new Polygon(new double[] {0, -1, 0, 1, 0}, new double[] {-1, 0, 1, 0, -1});
|
||||
Component2D polygon2D = Polygon2D.create(p);
|
||||
Component2D polygon2D = LatLonGeometry.create(p);
|
||||
PointValues.Relation rel = polygon2D.relateTriangle(
|
||||
quantizeLon(-1.5), quantizeLat(0),
|
||||
quantizeLon(1.5), quantizeLat(0),
|
||||
|
@ -653,7 +652,7 @@ public class TestLatLonShape extends LuceneTestCase {
|
|||
|
||||
public void testLineSharedLine() {
|
||||
Line l = new Line(new double[] {0, 0, 0, 0}, new double[] {-2, -1, 0, 1});
|
||||
Component2D l2d = Line2D.create(l);
|
||||
Component2D l2d = LatLonGeometry.create(l);
|
||||
PointValues.Relation r = l2d.relateTriangle(
|
||||
quantizeLon(-5), quantizeLat(0),
|
||||
quantizeLon(5), quantizeLat(0),
|
||||
|
|
|
@ -19,8 +19,8 @@ package org.apache.lucene.document;
|
|||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.GeoEncodingUtils;
|
||||
import org.apache.lucene.geo.GeoTestUtil;
|
||||
import org.apache.lucene.geo.LatLonGeometry;
|
||||
import org.apache.lucene.geo.Polygon;
|
||||
import org.apache.lucene.geo.Polygon2D;
|
||||
|
||||
/** Test case for LatLonShape encoding */
|
||||
public class TestLatLonShapeEncoding extends BaseShapeEncodingTestCase {
|
||||
|
@ -62,6 +62,6 @@ public class TestLatLonShapeEncoding extends BaseShapeEncodingTestCase {
|
|||
|
||||
@Override
|
||||
protected Component2D createPolygon2D(Object polygon) {
|
||||
return Polygon2D.create((Polygon)polygon);
|
||||
return LatLonGeometry.create((Polygon)polygon);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ import java.util.Random;
|
|||
import org.apache.lucene.document.ShapeField.QueryRelation;
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.ShapeTestUtil;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.geo.XYLine;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.geo.XYRectangle2D;
|
||||
import org.apache.lucene.index.PointValues.Relation;
|
||||
|
||||
/** random cartesian bounding box, line, and polygon query tests for random generated cartesian {@link XYLine} types */
|
||||
|
@ -80,7 +80,7 @@ public class TestXYLineShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYRectangle2D.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@ import java.util.List;
|
|||
|
||||
import org.apache.lucene.document.ShapeField.QueryRelation;
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.geo.XYLine;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.geo.XYRectangle2D;
|
||||
|
||||
/** random cartesian bounding box, line, and polygon query tests for random indexed arrays of cartesian {@link XYLine} types */
|
||||
public class TestXYMultiLineShapeQueries extends BaseXYShapeTestCase {
|
||||
|
@ -76,7 +76,7 @@ public class TestXYMultiLineShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYRectangle2D.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@ import java.util.List;
|
|||
|
||||
import org.apache.lucene.document.ShapeField.QueryRelation;
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.geo.XYRectangle2D;
|
||||
|
||||
/** random cartesian bounding box, line, and polygon query tests for random indexed arrays of {@code x, y} points */
|
||||
public class TestXYMultiPointShapeQueries extends BaseXYShapeTestCase {
|
||||
|
@ -75,7 +75,7 @@ public class TestXYMultiPointShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYRectangle2D.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import org.apache.lucene.geo.Component2D;
|
|||
import org.apache.lucene.geo.Tessellator;
|
||||
import org.apache.lucene.geo.XYPolygon;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.geo.XYRectangle2D;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
/** random cartesian bounding box, line, and polygon query tests for random indexed arrays of cartesian {@link XYPolygon} types */
|
||||
|
@ -115,7 +115,7 @@ public class TestXYMultiPolygonShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYRectangle2D.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,9 @@ import java.util.Random;
|
|||
import org.apache.lucene.document.ShapeField.QueryRelation;
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.ShapeTestUtil;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.geo.XYLine;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.geo.XYRectangle2D;
|
||||
import org.apache.lucene.index.PointValues.Relation;
|
||||
|
||||
/** random cartesian bounding box, line, and polygon query tests for random generated {@code x, y} points */
|
||||
|
@ -80,7 +80,7 @@ public class TestXYPointShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYRectangle2D.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@ import java.util.List;
|
|||
import org.apache.lucene.document.ShapeField.QueryRelation;
|
||||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.Tessellator;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.geo.XYPolygon;
|
||||
import org.apache.lucene.geo.XYRectangle;
|
||||
import org.apache.lucene.geo.XYRectangle2D;
|
||||
import org.apache.lucene.index.PointValues.Relation;
|
||||
|
||||
/** random cartesian bounding box, line, and polygon query tests for random indexed {@link XYPolygon} types */
|
||||
|
@ -66,7 +66,7 @@ public class TestXYPolygonShapeQueries extends BaseXYShapeTestCase {
|
|||
|
||||
@Override
|
||||
public boolean testBBoxQuery(double minY, double maxY, double minX, double maxX, Object shape) {
|
||||
Component2D rectangle2D = XYRectangle2D.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
Component2D rectangle2D = XYGeometry.create(new XYRectangle(minX, maxX, minY, maxY));
|
||||
return testComponentQuery(rectangle2D, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ package org.apache.lucene.document;
|
|||
import org.apache.lucene.geo.Component2D;
|
||||
import org.apache.lucene.geo.ShapeTestUtil;
|
||||
import org.apache.lucene.geo.XYEncodingUtils;
|
||||
import org.apache.lucene.geo.XYGeometry;
|
||||
import org.apache.lucene.geo.XYPolygon;
|
||||
import org.apache.lucene.geo.XYPolygon2D;
|
||||
|
||||
/** tests XYShape encoding */
|
||||
public class TestXYShapeEncoding extends BaseShapeEncodingTestCase {
|
||||
|
@ -61,6 +61,6 @@ public class TestXYShapeEncoding extends BaseShapeEncodingTestCase {
|
|||
|
||||
@Override
|
||||
protected Component2D createPolygon2D(Object polygon) {
|
||||
return XYPolygon2D.create((XYPolygon)polygon);
|
||||
return XYGeometry.create((XYPolygon)polygon);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.lucene.util.LuceneTestCase;
|
|||
public class TestPoint2D extends LuceneTestCase {
|
||||
|
||||
public void testTriangleDisjoint() {
|
||||
Component2D point2D = Point2D.create(new double[] {0, 0});
|
||||
Component2D point2D = Point2D.create(new Point(0, 0));
|
||||
double ax = 4;
|
||||
double ay = 4;
|
||||
double bx = 5;
|
||||
|
@ -36,7 +36,7 @@ public class TestPoint2D extends LuceneTestCase {
|
|||
}
|
||||
|
||||
public void testTriangleIntersects() {
|
||||
Component2D point2D = Point2D.create(new double[] {0, 0});
|
||||
Component2D point2D = Point2D.create(new Point(0, 0));
|
||||
double ax = 0.0;
|
||||
double ay = 0.0;
|
||||
double bx = 1;
|
||||
|
@ -49,7 +49,7 @@ public class TestPoint2D extends LuceneTestCase {
|
|||
}
|
||||
|
||||
public void testTriangleContains() {
|
||||
Component2D point2D = Point2D.create(new double[] {0, 0});
|
||||
Component2D point2D = Point2D.create(new Point(0, 0));
|
||||
double ax = 0.0;
|
||||
double ay = 0.0;
|
||||
double bx = 0;
|
||||
|
@ -63,7 +63,7 @@ public class TestPoint2D extends LuceneTestCase {
|
|||
|
||||
|
||||
public void testRandomTriangles() {
|
||||
Component2D point2D = Point2D.create(new double[] {GeoTestUtil.nextLatitude(), GeoTestUtil.nextLongitude()});
|
||||
Component2D point2D = Point2D.create(new Point(GeoTestUtil.nextLatitude(), GeoTestUtil.nextLongitude()));
|
||||
|
||||
for (int i =0; i < 100; i++) {
|
||||
double ax = GeoTestUtil.nextLongitude();
|
||||
|
|
|
@ -35,7 +35,7 @@ public class TestPolygon2D extends LuceneTestCase {
|
|||
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 } );
|
||||
Component2D polygon = Polygon2D.create(outer, island);
|
||||
Component2D polygon = LatLonGeometry.create(outer, island);
|
||||
|
||||
// contains(point)
|
||||
assertTrue(polygon.contains(-2, 2)); // on the island
|
||||
|
|
Loading…
Reference in New Issue