diff --git a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java index f0f202049db..944ce39b97d 100644 --- a/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java +++ b/lucene/spatial3d/src/java/org/apache/lucene/spatial3d/Geo3DPoint.java @@ -22,6 +22,8 @@ import java.util.ArrayList; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; import org.apache.lucene.index.PointValues; +import org.apache.lucene.geo.Polygon; +import org.apache.lucene.geo.GeoUtils; import org.apache.lucene.spatial3d.geom.Vector; import org.apache.lucene.spatial3d.geom.GeoPoint; import org.apache.lucene.spatial3d.geom.GeoShape; @@ -30,6 +32,8 @@ import org.apache.lucene.spatial3d.geom.GeoCircleFactory; import org.apache.lucene.spatial3d.geom.GeoBBoxFactory; import org.apache.lucene.spatial3d.geom.GeoPolygonFactory; import org.apache.lucene.spatial3d.geom.GeoPath; +import org.apache.lucene.spatial3d.geom.GeoCompositePolygon; +import org.apache.lucene.spatial3d.geom.GeoPolygon; import org.apache.lucene.search.Query; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.NumericUtils; @@ -64,8 +68,8 @@ public final class Geo3DPoint extends Field { */ public Geo3DPoint(String name, double latitude, double longitude) { super(name, TYPE); - checkLatitude(latitude); - checkLongitude(longitude); + GeoUtils.checkLatitude(latitude); + GeoUtils.checkLongitude(longitude); // Translate latitude/longitude to x,y,z: final GeoPoint point = new GeoPoint(PlanetModel.WGS84, fromDegrees(latitude), fromDegrees(longitude)); fillFieldsData(point.x, point.y, point.z); @@ -94,8 +98,8 @@ public final class Geo3DPoint extends Field { * @throws IllegalArgumentException if {@code field} is null, location has invalid coordinates, or radius is invalid. */ public static Query newDistanceQuery(final String field, final double latitude, final double longitude, final double radiusMeters) { - checkLatitude(latitude); - checkLongitude(longitude); + GeoUtils.checkLatitude(latitude); + GeoUtils.checkLongitude(longitude); final GeoShape shape = GeoCircleFactory.makeGeoCircle(PlanetModel.WGS84, fromDegrees(latitude), fromDegrees(longitude), fromMeters(radiusMeters)); return newShapeQuery(field, shape); } @@ -113,10 +117,10 @@ public final class Geo3DPoint extends Field { * @throws IllegalArgumentException if {@code field} is null, or the box has invalid coordinates. */ public static Query newBoxQuery(final String field, final double minLatitude, final double maxLatitude, final double minLongitude, final double maxLongitude) { - checkLatitude(minLatitude); - checkLongitude(minLongitude); - checkLatitude(maxLatitude); - checkLongitude(maxLongitude); + GeoUtils.checkLatitude(minLatitude); + GeoUtils.checkLongitude(minLongitude); + GeoUtils.checkLatitude(maxLatitude); + GeoUtils.checkLongitude(maxLongitude); final GeoShape shape = GeoBBoxFactory.makeGeoBBox(PlanetModel.WGS84, fromDegrees(maxLatitude), fromDegrees(minLatitude), fromDegrees(minLongitude), fromDegrees(maxLongitude)); return newShapeQuery(field, shape); @@ -125,36 +129,28 @@ public final class Geo3DPoint extends Field { /** * Create a query for matching a polygon. *
- * The supplied {@code polyLatitudes}/{@code polyLongitudes} must be clockwise or counter-clockwise.
+ * The supplied {@code polygons} must be clockwise on the outside level, counterclockwise on the next level in, etc.
* @param field field name. must not be null.
- * @param polyLatitudes latitude values for points of the polygon: must be within standard +/-90 coordinate bounds.
- * @param polyLongitudes longitude values for points of the polygon: must be within standard +/-180 coordinate bounds.
+ * @param polygons is the list of polygons to use to construct the query; must be at least one.
* @return query matching points within this polygon
*/
- public static Query newPolygonQuery(final String field, final double[] polyLatitudes, final double[] polyLongitudes) {
- if (polyLatitudes.length != polyLongitudes.length) {
- throw new IllegalArgumentException("same number of latitudes and longitudes required");
+ public static Query newPolygonQuery(final String field, final Polygon... polygons) {
+ if (polygons.length < 1) {
+ throw new IllegalArgumentException("need at least one polygon");
}
- if (polyLatitudes.length < 4) {
- throw new IllegalArgumentException("need three or more points");
+ final GeoShape shape;
+ if (polygons.length == 1) {
+ shape = fromPolygon(polygons[0], false);
+ } else {
+ final GeoCompositePolygon poly = new GeoCompositePolygon();
+ for (final Polygon p : polygons) {
+ poly.addShape(fromPolygon(p, false));
+ }
+ shape = poly;
}
- if (polyLatitudes[0] != polyLatitudes[polyLatitudes.length-1] || polyLongitudes[0] != polyLongitudes[polyLongitudes.length-1]) {
- throw new IllegalArgumentException("last point must equal first point");
- }
-
- final List
@@ -172,14 +168,47 @@ public final class Geo3DPoint extends Field {
for (int i = 0; i < pathLatitudes.length; i++) {
final double latitude = pathLatitudes[i];
final double longitude = pathLongitudes[i];
- checkLatitude(latitude);
- checkLongitude(longitude);
+ GeoUtils.checkLatitude(latitude);
+ GeoUtils.checkLongitude(longitude);
points[i] = new GeoPoint(PlanetModel.WGS84, fromDegrees(latitude), fromDegrees(longitude));
}
final GeoShape shape = new GeoPath(PlanetModel.WGS84, fromMeters(pathWidthMeters), points);
return newShapeQuery(field, shape);
}
+ /**
+ * Convert a Polygon object into a GeoPolygon.
+ * This method uses
+ * @param polygon is the Polygon object.
+ * @param reverseMe is true if the order of the points should be reversed.
+ * @return the GeoPolygon.
+ */
+ protected static GeoPolygon fromPolygon(final Polygon polygon, final boolean reverseMe) {
+ // First, assemble the "holes". The geo3d convention is to use the same polygon sense on the inner ring as the
+ // outer ring, so we process these recursively with reverseMe flipped.
+ final Polygon[] theHoles = polygon.getHoles();
+ final List