Merge pull request #15010 from cbuescher/refactor-shapebuilders
Make remaining ShapeBuilders implement Writeable
This commit is contained in:
commit
2f97ff0925
|
@ -25,26 +25,17 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
public class EnvelopeBuilder extends ShapeBuilder {
|
||||
|
||||
public static final GeoShapeType TYPE = GeoShapeType.ENVELOPE;
|
||||
|
||||
public static final EnvelopeBuilder PROTOTYPE = new EnvelopeBuilder();
|
||||
|
||||
protected Coordinate topLeft;
|
||||
protected Coordinate bottomRight;
|
||||
|
||||
public EnvelopeBuilder() {
|
||||
this(Orientation.RIGHT);
|
||||
}
|
||||
|
||||
public EnvelopeBuilder(Orientation orientation) {
|
||||
super(orientation);
|
||||
}
|
||||
private Coordinate topLeft;
|
||||
private Coordinate bottomRight;
|
||||
|
||||
public EnvelopeBuilder topLeft(Coordinate topLeft) {
|
||||
this.topLeft = topLeft;
|
||||
|
@ -55,6 +46,10 @@ public class EnvelopeBuilder extends ShapeBuilder {
|
|||
return topLeft(coordinate(longitude, latitude));
|
||||
}
|
||||
|
||||
public Coordinate topLeft() {
|
||||
return this.topLeft;
|
||||
}
|
||||
|
||||
public EnvelopeBuilder bottomRight(Coordinate bottomRight) {
|
||||
this.bottomRight = bottomRight;
|
||||
return this;
|
||||
|
@ -64,11 +59,14 @@ public class EnvelopeBuilder extends ShapeBuilder {
|
|||
return bottomRight(coordinate(longitude, latitude));
|
||||
}
|
||||
|
||||
public Coordinate bottomRight() {
|
||||
return this.bottomRight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(FIELD_TYPE, TYPE.shapeName());
|
||||
builder.field(FIELD_ORIENTATION, orientation.name().toLowerCase(Locale.ROOT));
|
||||
builder.startArray(FIELD_COORDINATES);
|
||||
toXContent(builder, topLeft);
|
||||
toXContent(builder, bottomRight);
|
||||
|
@ -88,7 +86,7 @@ public class EnvelopeBuilder extends ShapeBuilder {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(orientation, topLeft, bottomRight);
|
||||
return Objects.hash(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,22 +98,19 @@ public class EnvelopeBuilder extends ShapeBuilder {
|
|||
return false;
|
||||
}
|
||||
EnvelopeBuilder other = (EnvelopeBuilder) obj;
|
||||
return Objects.equals(orientation, other.orientation) &&
|
||||
Objects.equals(topLeft, other.topLeft) &&
|
||||
return Objects.equals(topLeft, other.topLeft) &&
|
||||
Objects.equals(bottomRight, other.bottomRight);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeBoolean(orientation == Orientation.RIGHT);
|
||||
writeCoordinateTo(topLeft, out);
|
||||
writeCoordinateTo(bottomRight, out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnvelopeBuilder readFrom(StreamInput in) throws IOException {
|
||||
Orientation orientation = in.readBoolean() ? Orientation.RIGHT : Orientation.LEFT;
|
||||
return new EnvelopeBuilder(orientation)
|
||||
return new EnvelopeBuilder()
|
||||
.topLeft(readCoordinateFrom(in))
|
||||
.bottomRight(readCoordinateFrom(in));
|
||||
}
|
||||
|
|
|
@ -20,28 +20,26 @@
|
|||
package org.elasticsearch.common.geo.builders;
|
||||
|
||||
import com.spatial4j.core.shape.Shape;
|
||||
|
||||
import org.elasticsearch.common.geo.XShapeCollection;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class GeometryCollectionBuilder extends ShapeBuilder {
|
||||
|
||||
public static final GeoShapeType TYPE = GeoShapeType.GEOMETRYCOLLECTION;
|
||||
|
||||
public static final GeometryCollectionBuilder PROTOTYPE = new GeometryCollectionBuilder();
|
||||
|
||||
protected final ArrayList<ShapeBuilder> shapes = new ArrayList<>();
|
||||
|
||||
public GeometryCollectionBuilder() {
|
||||
this(Orientation.RIGHT);
|
||||
}
|
||||
|
||||
public GeometryCollectionBuilder(Orientation orientation) {
|
||||
super(orientation);
|
||||
}
|
||||
|
||||
public GeometryCollectionBuilder shape(ShapeBuilder shape) {
|
||||
this.shapes.add(shape);
|
||||
return this;
|
||||
|
@ -132,4 +130,39 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
|
|||
//note: ShapeCollection is probably faster than a Multi* geom.
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(shapes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
GeometryCollectionBuilder other = (GeometryCollectionBuilder) obj;
|
||||
return Objects.equals(shapes, other.shapes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeVInt(shapes.size());
|
||||
for (ShapeBuilder shape : shapes) {
|
||||
out.writeShape(shape);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeometryCollectionBuilder readFrom(StreamInput in) throws IOException {
|
||||
GeometryCollectionBuilder geometryCollectionBuilder = new GeometryCollectionBuilder();
|
||||
int shapes = in.readVInt();
|
||||
for (int i = 0; i < shapes; i++) {
|
||||
geometryCollectionBuilder.shape(in.readShape());
|
||||
}
|
||||
return geometryCollectionBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,8 +22,12 @@ package org.elasticsearch.common.geo.builders;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import com.spatial4j.core.shape.Shape;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
|
@ -34,6 +38,8 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
|
|||
|
||||
public static final GeoShapeType TYPE = GeoShapeType.LINESTRING;
|
||||
|
||||
public static final LineStringBuilder PROTOTYPE = new LineStringBuilder();
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
|
@ -139,4 +145,39 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
|
|||
}
|
||||
return coordinates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(points);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
LineStringBuilder other = (LineStringBuilder) obj;
|
||||
return Objects.equals(points, other.points);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeVInt(points.size());
|
||||
for (Coordinate point : points) {
|
||||
writeCoordinateTo(point, out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LineStringBuilder readFrom(StreamInput in) throws IOException {
|
||||
LineStringBuilder lineStringBuilder = new LineStringBuilder();
|
||||
int size = in.readVInt();
|
||||
for (int i=0; i < size; i++) {
|
||||
lineStringBuilder.point(readCoordinateFrom(in));
|
||||
}
|
||||
return lineStringBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.elasticsearch.common.geo.builders;
|
||||
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import com.spatial4j.core.shape.Shape;
|
||||
|
@ -29,11 +31,14 @@ import com.vividsolutions.jts.geom.LineString;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MultiLineStringBuilder extends ShapeBuilder {
|
||||
|
||||
public static final GeoShapeType TYPE = GeoShapeType.MULTILINESTRING;
|
||||
|
||||
public static final MultiLineStringBuilder PROTOTYPE = new MultiLineStringBuilder();
|
||||
|
||||
private final ArrayList<LineStringBuilder> lines = new ArrayList<>();
|
||||
|
||||
public MultiLineStringBuilder linestring(LineStringBuilder line) {
|
||||
|
@ -41,6 +46,10 @@ public class MultiLineStringBuilder extends ShapeBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
public MultiLineStringBuilder linestring(Coordinate[] coordinates) {
|
||||
return this.linestring(new LineStringBuilder().points(coordinates));
|
||||
}
|
||||
|
||||
public Coordinate[][] coordinates() {
|
||||
Coordinate[][] result = new Coordinate[lines.size()][];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
|
@ -92,4 +101,39 @@ public class MultiLineStringBuilder extends ShapeBuilder {
|
|||
}
|
||||
return jtsGeometry(geometry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MultiLineStringBuilder other = (MultiLineStringBuilder) obj;
|
||||
return Objects.equals(lines, other.lines);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeVInt(lines.size());
|
||||
for (LineStringBuilder line : lines) {
|
||||
line.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiLineStringBuilder readFrom(StreamInput in) throws IOException {
|
||||
MultiLineStringBuilder multiLineStringBuilder = new MultiLineStringBuilder();
|
||||
int size = in.readVInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
multiLineStringBuilder.linestring(LineStringBuilder.PROTOTYPE.readFrom(in));
|
||||
}
|
||||
return multiLineStringBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,18 +22,22 @@ package org.elasticsearch.common.geo.builders;
|
|||
import com.spatial4j.core.shape.Point;
|
||||
import com.spatial4j.core.shape.Shape;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import org.elasticsearch.common.geo.XShapeCollection;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import org.elasticsearch.common.geo.XShapeCollection;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
|
||||
|
||||
|
||||
public static final GeoShapeType TYPE = GeoShapeType.MULTIPOINT;
|
||||
|
||||
public final static MultiPointBuilder PROTOTYPE = new MultiPointBuilder();
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
|
@ -52,7 +56,7 @@ public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
|
|||
for (Coordinate coord : points) {
|
||||
shapes.add(SPATIAL_CONTEXT.makePoint(coord.x, coord.y));
|
||||
}
|
||||
XShapeCollection multiPoints = new XShapeCollection<>(shapes, SPATIAL_CONTEXT);
|
||||
XShapeCollection<Point> multiPoints = new XShapeCollection<>(shapes, SPATIAL_CONTEXT);
|
||||
multiPoints.setPointsOnly(true);
|
||||
return multiPoints;
|
||||
}
|
||||
|
@ -61,4 +65,39 @@ public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
|
|||
public GeoShapeType type() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(points);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MultiPointBuilder other = (MultiPointBuilder) obj;
|
||||
return Objects.equals(points, other.points);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
out.writeVInt(points.size());
|
||||
for (Coordinate point : points) {
|
||||
writeCoordinateTo(point, out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiPointBuilder readFrom(StreamInput in) throws IOException {
|
||||
MultiPointBuilder multiPointBuilder = new MultiPointBuilder();
|
||||
int size = in.readVInt();
|
||||
for (int i=0; i < size; i++) {
|
||||
multiPointBuilder.point(readCoordinateFrom(in));
|
||||
}
|
||||
return multiPointBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,12 @@ package org.elasticsearch.common.geo.builders;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.elasticsearch.common.geo.XShapeCollection;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import com.spatial4j.core.shape.Shape;
|
||||
|
@ -32,26 +36,50 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
public class MultiPolygonBuilder extends ShapeBuilder {
|
||||
|
||||
public static final GeoShapeType TYPE = GeoShapeType.MULTIPOLYGON;
|
||||
public static final MultiPolygonBuilder PROTOTYPE = new MultiPolygonBuilder();
|
||||
|
||||
protected final ArrayList<PolygonBuilder> polygons = new ArrayList<>();
|
||||
private final ArrayList<PolygonBuilder> polygons = new ArrayList<>();
|
||||
|
||||
private Orientation orientation = Orientation.RIGHT;
|
||||
|
||||
public MultiPolygonBuilder() {
|
||||
this(Orientation.RIGHT);
|
||||
}
|
||||
|
||||
public MultiPolygonBuilder(Orientation orientation) {
|
||||
super(orientation);
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
public Orientation orientation() {
|
||||
return this.orientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a shallow copy of the polygon to the multipolygon. This will apply the orientation of the
|
||||
* {@link MultiPolygonBuilder} to the polygon if polygon has different orientation.
|
||||
*/
|
||||
public MultiPolygonBuilder polygon(PolygonBuilder polygon) {
|
||||
this.polygons.add(polygon);
|
||||
PolygonBuilder pb = new PolygonBuilder(this.orientation);
|
||||
pb.points(polygon.shell().coordinates(false));
|
||||
for (LineStringBuilder hole : polygon.holes()) {
|
||||
pb.hole(hole);
|
||||
}
|
||||
this.polygons.add(pb);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the list of polygons
|
||||
*/
|
||||
public ArrayList<PolygonBuilder> polygons() {
|
||||
return polygons;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(FIELD_TYPE, TYPE.shapeName());
|
||||
builder.field(FIELD_ORIENTATION, orientation.name().toLowerCase(Locale.ROOT));
|
||||
builder.startArray(FIELD_COORDINATES);
|
||||
for(PolygonBuilder polygon : polygons) {
|
||||
builder.startArray();
|
||||
|
@ -89,4 +117,41 @@ public class MultiPolygonBuilder extends ShapeBuilder {
|
|||
return new XShapeCollection<>(shapes, SPATIAL_CONTEXT);
|
||||
//note: ShapeCollection is probably faster than a Multi* geom.
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(polygons, orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
MultiPolygonBuilder other = (MultiPolygonBuilder) obj;
|
||||
return Objects.equals(polygons, other.polygons) &&
|
||||
Objects.equals(orientation, other.orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
orientation.writeTo(out);
|
||||
out.writeVInt(polygons.size());
|
||||
for (PolygonBuilder polygon : polygons) {
|
||||
polygon.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiPolygonBuilder readFrom(StreamInput in) throws IOException {
|
||||
MultiPolygonBuilder polyBuilder = new MultiPolygonBuilder(Orientation.readFrom(in));
|
||||
int holes = in.readVInt();
|
||||
for (int i = 0; i < holes; i++) {
|
||||
polyBuilder.polygon(PolygonBuilder.PROTOTYPE.readFrom(in));
|
||||
}
|
||||
return polyBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
public class PointBuilder extends ShapeBuilder {
|
||||
|
||||
public static final GeoShapeType TYPE = GeoShapeType.POINT;
|
||||
|
||||
public static final PointBuilder PROTOTYPE = new PointBuilder();
|
||||
|
||||
private Coordinate coordinate;
|
||||
|
|
|
@ -29,6 +29,8 @@ import com.vividsolutions.jts.geom.MultiPolygon;
|
|||
import com.vividsolutions.jts.geom.Polygon;
|
||||
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
|
@ -39,6 +41,9 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The {@link PolygonBuilder} implements the groundwork to create polygons. This contains
|
||||
|
@ -48,6 +53,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
public class PolygonBuilder extends ShapeBuilder {
|
||||
|
||||
public static final GeoShapeType TYPE = GeoShapeType.POLYGON;
|
||||
public static final PolygonBuilder PROTOTYPE = new PolygonBuilder();
|
||||
|
||||
private static final Coordinate[][] EMPTY = new Coordinate[0][];
|
||||
|
||||
private Orientation orientation = Orientation.RIGHT;
|
||||
|
||||
// line string defining the shell of the polygon
|
||||
private LineStringBuilder shell;
|
||||
|
@ -56,7 +66,7 @@ public class PolygonBuilder extends ShapeBuilder {
|
|||
private final ArrayList<LineStringBuilder> holes = new ArrayList<>();
|
||||
|
||||
public PolygonBuilder() {
|
||||
this(new ArrayList<Coordinate>(), Orientation.RIGHT);
|
||||
this(Orientation.RIGHT);
|
||||
}
|
||||
|
||||
public PolygonBuilder(Orientation orientation) {
|
||||
|
@ -64,10 +74,14 @@ public class PolygonBuilder extends ShapeBuilder {
|
|||
}
|
||||
|
||||
public PolygonBuilder(ArrayList<Coordinate> points, Orientation orientation) {
|
||||
super(orientation);
|
||||
this.orientation = orientation;
|
||||
this.shell = new LineStringBuilder().points(points);
|
||||
}
|
||||
|
||||
public Orientation orientation() {
|
||||
return this.orientation;
|
||||
}
|
||||
|
||||
public PolygonBuilder point(double longitude, double latitude) {
|
||||
shell.point(longitude, latitude);
|
||||
return this;
|
||||
|
@ -103,6 +117,20 @@ public class PolygonBuilder extends ShapeBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of holes defined for this polygon
|
||||
*/
|
||||
public List<LineStringBuilder> holes() {
|
||||
return this.holes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of points of the shell for this polygon
|
||||
*/
|
||||
public LineStringBuilder shell() {
|
||||
return this.shell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the shell of the polygon
|
||||
*/
|
||||
|
@ -175,6 +203,7 @@ public class PolygonBuilder extends ShapeBuilder {
|
|||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
builder.field(FIELD_TYPE, TYPE.shapeName());
|
||||
builder.field(FIELD_ORIENTATION, orientation.name().toLowerCase(Locale.ROOT));
|
||||
builder.startArray(FIELD_COORDINATES);
|
||||
coordinatesArray(builder, params);
|
||||
builder.endArray();
|
||||
|
@ -357,8 +386,6 @@ public class PolygonBuilder extends ShapeBuilder {
|
|||
return result;
|
||||
}
|
||||
|
||||
private static final Coordinate[][] EMPTY = new Coordinate[0][];
|
||||
|
||||
private static Coordinate[][] holes(Edge[] holes, int numHoles) {
|
||||
if (numHoles == 0) {
|
||||
return EMPTY;
|
||||
|
@ -663,4 +690,44 @@ public class PolygonBuilder extends ShapeBuilder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(shell, holes, orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PolygonBuilder other = (PolygonBuilder) obj;
|
||||
return Objects.equals(shell, other.shell) &&
|
||||
Objects.equals(holes, other.holes) &&
|
||||
Objects.equals(orientation, other.orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
orientation.writeTo(out);
|
||||
shell.writeTo(out);
|
||||
out.writeVInt(holes.size());
|
||||
for (LineStringBuilder hole : holes) {
|
||||
hole.writeTo(out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PolygonBuilder readFrom(StreamInput in) throws IOException {
|
||||
PolygonBuilder polyBuilder = new PolygonBuilder(Orientation.readFrom(in));
|
||||
polyBuilder.shell = LineStringBuilder.PROTOTYPE.readFrom(in);
|
||||
int holes = in.readVInt();
|
||||
for (int i = 0; i < holes; i++) {
|
||||
polyBuilder.hole(LineStringBuilder.PROTOTYPE.readFrom(in));
|
||||
}
|
||||
return polyBuilder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,16 +77,10 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
/** @see com.spatial4j.core.shape.jts.JtsGeometry#index() */
|
||||
protected final boolean autoIndexJtsGeometry = true;//may want to turn off once SpatialStrategy impls do it.
|
||||
|
||||
protected Orientation orientation = Orientation.RIGHT;
|
||||
|
||||
protected ShapeBuilder() {
|
||||
|
||||
}
|
||||
|
||||
protected ShapeBuilder(Orientation orientation) {
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
protected static Coordinate coordinate(double longitude, double latitude) {
|
||||
return new Coordinate(longitude, latitude);
|
||||
}
|
||||
|
@ -186,22 +180,6 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
return new Coordinate(in.readDouble(), in.readDouble());
|
||||
}
|
||||
|
||||
public static Orientation orientationFromString(String orientation) {
|
||||
orientation = orientation.toLowerCase(Locale.ROOT);
|
||||
switch (orientation) {
|
||||
case "right":
|
||||
case "counterclockwise":
|
||||
case "ccw":
|
||||
return Orientation.RIGHT;
|
||||
case "left":
|
||||
case "clockwise":
|
||||
case "cw":
|
||||
return Orientation.LEFT;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown orientation [" + orientation + "]");
|
||||
}
|
||||
}
|
||||
|
||||
protected static Coordinate shift(Coordinate coordinate, double dateline) {
|
||||
if (dateline == 0) {
|
||||
return coordinate;
|
||||
|
@ -408,6 +386,30 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
public static final Orientation COUNTER_CLOCKWISE = Orientation.RIGHT;
|
||||
public static final Orientation CW = Orientation.LEFT;
|
||||
public static final Orientation CCW = Orientation.RIGHT;
|
||||
|
||||
public void writeTo (StreamOutput out) throws IOException {
|
||||
out.writeBoolean(this == Orientation.RIGHT);
|
||||
}
|
||||
|
||||
public static Orientation readFrom (StreamInput in) throws IOException {
|
||||
return in.readBoolean() ? Orientation.RIGHT : Orientation.LEFT;
|
||||
}
|
||||
|
||||
public static Orientation fromString(String orientation) {
|
||||
orientation = orientation.toLowerCase(Locale.ROOT);
|
||||
switch (orientation) {
|
||||
case "right":
|
||||
case "counterclockwise":
|
||||
case "ccw":
|
||||
return Orientation.RIGHT;
|
||||
case "left":
|
||||
case "clockwise":
|
||||
case "cw":
|
||||
return Orientation.LEFT;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown orientation [" + orientation + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final String FIELD_TYPE = "type";
|
||||
|
@ -498,7 +500,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
radius = Distance.parseDistance(parser.text());
|
||||
} else if (FIELD_ORIENTATION.equals(fieldName)) {
|
||||
parser.nextToken();
|
||||
requestedOrientation = orientationFromString(parser.text());
|
||||
requestedOrientation = Orientation.fromString(parser.text());
|
||||
} else {
|
||||
parser.nextToken();
|
||||
parser.skipChildren();
|
||||
|
@ -524,7 +526,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
case POLYGON: return parsePolygon(node, requestedOrientation, coerce);
|
||||
case MULTIPOLYGON: return parseMultiPolygon(node, requestedOrientation, coerce);
|
||||
case CIRCLE: return parseCircle(node, radius);
|
||||
case ENVELOPE: return parseEnvelope(node, requestedOrientation);
|
||||
case ENVELOPE: return parseEnvelope(node);
|
||||
case GEOMETRYCOLLECTION: return geometryCollections;
|
||||
default:
|
||||
throw new ElasticsearchParseException("shape type [{}] not included", shapeType);
|
||||
|
@ -550,7 +552,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
return ShapeBuilders.newCircleBuilder().center(coordinates.coordinate).radius(radius);
|
||||
}
|
||||
|
||||
protected static EnvelopeBuilder parseEnvelope(CoordinateNode coordinates, final Orientation orientation) {
|
||||
protected static EnvelopeBuilder parseEnvelope(CoordinateNode coordinates) {
|
||||
// validate the coordinate array for envelope type
|
||||
if (coordinates.children.size() != 2) {
|
||||
throw new ElasticsearchParseException("invalid number of points [{}] provided for " +
|
||||
|
@ -564,7 +566,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
uL = new Coordinate(Math.min(uL.x, lR.x), Math.max(uL.y, lR.y));
|
||||
lR = new Coordinate(Math.max(uLtmp.x, lR.x), Math.min(uLtmp.y, lR.y));
|
||||
}
|
||||
return ShapeBuilders.newEnvelope(orientation).topLeft(uL).bottomRight(lR);
|
||||
return ShapeBuilders.newEnvelope().topLeft(uL).bottomRight(lR);
|
||||
}
|
||||
|
||||
protected static void validateMultiPointNode(CoordinateNode coordinates) {
|
||||
|
@ -684,8 +686,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
}
|
||||
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
GeometryCollectionBuilder geometryCollection = ShapeBuilders.newGeometryCollection( (mapper == null) ? Orientation.RIGHT : mapper
|
||||
.fieldType().orientation());
|
||||
GeometryCollectionBuilder geometryCollection = ShapeBuilders.newGeometryCollection();
|
||||
while (token != XContentParser.Token.END_ARRAY) {
|
||||
ShapeBuilder shapeBuilder = GeoShapeType.parse(parser);
|
||||
geometryCollection.shape(shapeBuilder);
|
||||
|
@ -700,15 +701,4 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
|
|||
public String getWriteableName() {
|
||||
return type().shapeName();
|
||||
}
|
||||
|
||||
// NORELEASE this should be deleted as soon as all shape builders implement writable
|
||||
@Override
|
||||
public void writeTo(StreamOutput out) throws IOException {
|
||||
}
|
||||
|
||||
// NORELEASE this should be deleted as soon as all shape builders implement writable
|
||||
@Override
|
||||
public ShapeBuilder readFrom(StreamInput in) throws IOException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.common.geo.builders;
|
||||
|
||||
import org.elasticsearch.common.geo.ShapesAvailability;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
|
||||
/**
|
||||
* Register the shape builder prototypes with the {@link NamedWriteableRegistry}
|
||||
*/
|
||||
public class ShapeBuilderRegistry {
|
||||
|
||||
@Inject
|
||||
public ShapeBuilderRegistry(NamedWriteableRegistry namedWriteableRegistry) {
|
||||
if (ShapesAvailability.JTS_AVAILABLE && ShapesAvailability.SPATIAL4J_AVAILABLE) {
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, PointBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, CircleBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, EnvelopeBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, MultiPointBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, LineStringBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, MultiLineStringBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, PolygonBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, MultiPolygonBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, GeometryCollectionBuilder.PROTOTYPE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -110,15 +110,6 @@ public class ShapeBuilders {
|
|||
return new GeometryCollectionBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new GeometryCollection
|
||||
*
|
||||
* @return a new {@link GeometryCollectionBuilder}
|
||||
*/
|
||||
public static GeometryCollectionBuilder newGeometryCollection(ShapeBuilder.Orientation orientation) {
|
||||
return new GeometryCollectionBuilder(orientation);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a new Circle
|
||||
*
|
||||
|
@ -136,13 +127,4 @@ public class ShapeBuilders {
|
|||
public static EnvelopeBuilder newEnvelope() {
|
||||
return new EnvelopeBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* create a new rectangle
|
||||
*
|
||||
* @return a new {@link EnvelopeBuilder}
|
||||
*/
|
||||
public static EnvelopeBuilder newEnvelope(ShapeBuilder.Orientation orientation) {
|
||||
return new EnvelopeBuilder(orientation);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.elasticsearch.common.Strings;
|
|||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
|
||||
|
@ -629,6 +629,13 @@ public abstract class StreamInput extends InputStream {
|
|||
return readNamedWriteable(QueryBuilder.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a {@link ShapeBuilder} from the current stream
|
||||
*/
|
||||
public ShapeBuilder readShape() throws IOException {
|
||||
return readNamedWriteable(ShapeBuilder.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a {@link org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder} from the current stream
|
||||
*/
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.elasticsearch.Version;
|
|||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.geo.GeoPoint;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
|
||||
|
@ -618,6 +619,13 @@ public abstract class StreamOutput extends OutputStream {
|
|||
writeNamedWriteable(queryBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a {@link ShapeBuilder} to the current stream
|
||||
*/
|
||||
public void writeShape(ShapeBuilder shapeBuilder) throws IOException {
|
||||
writeNamedWriteable(shapeBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a {@link ScoreFunctionBuilder} to the current stream
|
||||
*/
|
||||
|
|
|
@ -184,7 +184,7 @@ public class GeoShapeFieldMapper extends FieldMapper {
|
|||
builder.fieldType().setDistanceErrorPct(Double.parseDouble(fieldNode.toString()));
|
||||
iterator.remove();
|
||||
} else if (Names.ORIENTATION.equals(fieldName)) {
|
||||
builder.fieldType().setOrientation(ShapeBuilder.orientationFromString(fieldNode.toString()));
|
||||
builder.fieldType().setOrientation(ShapeBuilder.Orientation.fromString(fieldNode.toString()));
|
||||
iterator.remove();
|
||||
} else if (Names.STRATEGY.equals(fieldName)) {
|
||||
builder.fieldType().setStrategyName(fieldNode.toString());
|
||||
|
|
|
@ -31,19 +31,16 @@ import org.elasticsearch.action.get.GetRequest;
|
|||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.geo.ShapeRelation;
|
||||
import org.elasticsearch.common.geo.ShapesAvailability;
|
||||
import org.elasticsearch.common.geo.SpatialStrategy;
|
||||
import org.elasticsearch.common.geo.builders.PointBuilder;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||
import org.elasticsearch.index.mapper.geo.GeoShapeFieldMapper;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
|
@ -61,13 +58,11 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
public static final String DEFAULT_SHAPE_FIELD_NAME = "shape";
|
||||
public static final ShapeRelation DEFAULT_SHAPE_RELATION = ShapeRelation.INTERSECTS;
|
||||
|
||||
static final GeoShapeQueryBuilder PROTOTYPE = new GeoShapeQueryBuilder("field", new BytesArray(new byte[1]));
|
||||
static final GeoShapeQueryBuilder PROTOTYPE = new GeoShapeQueryBuilder("field", new PointBuilder());
|
||||
|
||||
private final String fieldName;
|
||||
|
||||
// TODO make the ShapeBuilder and subclasses Writable and implement hashCode
|
||||
// and Equals so ShapeBuilder can be used here
|
||||
private BytesReference shapeBytes;
|
||||
private ShapeBuilder shape;
|
||||
|
||||
private SpatialStrategy strategy;
|
||||
|
||||
|
@ -88,7 +83,7 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
* @param shape
|
||||
* Shape used in the Query
|
||||
*/
|
||||
public GeoShapeQueryBuilder(String fieldName, ShapeBuilder shape) throws IOException {
|
||||
public GeoShapeQueryBuilder(String fieldName, ShapeBuilder shape) {
|
||||
this(fieldName, shape, null, null);
|
||||
}
|
||||
|
||||
|
@ -105,37 +100,21 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
* Index type of the indexed Shapes
|
||||
*/
|
||||
public GeoShapeQueryBuilder(String fieldName, String indexedShapeId, String indexedShapeType) {
|
||||
this(fieldName, (BytesReference) null, indexedShapeId, indexedShapeType);
|
||||
this(fieldName, (ShapeBuilder) null, indexedShapeId, indexedShapeType);
|
||||
}
|
||||
|
||||
GeoShapeQueryBuilder(String fieldName, BytesReference shapeBytes) {
|
||||
this(fieldName, shapeBytes, null, null);
|
||||
}
|
||||
|
||||
private GeoShapeQueryBuilder(String fieldName, ShapeBuilder shape, String indexedShapeId, String indexedShapeType) throws IOException {
|
||||
this(fieldName, new BytesArray(new byte[1]), indexedShapeId, indexedShapeType);
|
||||
if (shape != null) {
|
||||
this.shapeBytes = shape.buildAsBytes(XContentType.JSON);
|
||||
if (this.shapeBytes.length() == 0) {
|
||||
throw new IllegalArgumentException("shape must not be empty");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("shape must not be null");
|
||||
}
|
||||
}
|
||||
|
||||
private GeoShapeQueryBuilder(String fieldName, BytesReference shapeBytes, String indexedShapeId, String indexedShapeType) {
|
||||
private GeoShapeQueryBuilder(String fieldName, ShapeBuilder shape, String indexedShapeId, String indexedShapeType) {
|
||||
if (fieldName == null) {
|
||||
throw new IllegalArgumentException("fieldName is required");
|
||||
}
|
||||
if ((shapeBytes == null || shapeBytes.length() == 0) && indexedShapeId == null) {
|
||||
if (shape == null && indexedShapeId == null) {
|
||||
throw new IllegalArgumentException("either shapeBytes or indexedShapeId and indexedShapeType are required");
|
||||
}
|
||||
if (indexedShapeId != null && indexedShapeType == null) {
|
||||
throw new IllegalArgumentException("indexedShapeType is required if indexedShapeId is specified");
|
||||
}
|
||||
this.fieldName = fieldName;
|
||||
this.shapeBytes = shapeBytes;
|
||||
this.shape = shape;
|
||||
this.indexedShapeId = indexedShapeId;
|
||||
this.indexedShapeType = indexedShapeType;
|
||||
}
|
||||
|
@ -148,10 +127,10 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the JSON bytes for the shape used in the Query
|
||||
* @return the shape used in the Query
|
||||
*/
|
||||
public BytesReference shapeBytes() {
|
||||
return shapeBytes;
|
||||
public ShapeBuilder shape() {
|
||||
return shape;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -258,15 +237,11 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
|
||||
@Override
|
||||
protected Query doToQuery(QueryShardContext context) throws IOException {
|
||||
ShapeBuilder shape;
|
||||
if (shapeBytes == null) {
|
||||
ShapeBuilder shapeToQuery = shape;
|
||||
if (shapeToQuery == null) {
|
||||
GetRequest getRequest = new GetRequest(indexedShapeIndex, indexedShapeType, indexedShapeId);
|
||||
getRequest.copyContextAndHeadersFrom(SearchContext.current());
|
||||
shape = fetch(context.getClient(), getRequest, indexedShapePath);
|
||||
} else {
|
||||
XContentParser shapeParser = XContentHelper.createParser(shapeBytes);
|
||||
shapeParser.nextToken();
|
||||
shape = ShapeBuilder.parse(shapeParser);
|
||||
shapeToQuery = fetch(context.getClient(), getRequest, indexedShapePath);
|
||||
}
|
||||
MappedFieldType fieldType = context.fieldMapper(fieldName);
|
||||
if (fieldType == null) {
|
||||
|
@ -291,12 +266,12 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
// in this case, execute disjoint as exists && !intersects
|
||||
BooleanQuery.Builder bool = new BooleanQuery.Builder();
|
||||
Query exists = ExistsQueryBuilder.newFilter(context, fieldName);
|
||||
Query intersects = strategy.makeQuery(getArgs(shape, ShapeRelation.INTERSECTS));
|
||||
Query intersects = strategy.makeQuery(getArgs(shapeToQuery, ShapeRelation.INTERSECTS));
|
||||
bool.add(exists, BooleanClause.Occur.MUST);
|
||||
bool.add(intersects, BooleanClause.Occur.MUST_NOT);
|
||||
query = new ConstantScoreQuery(bool.build());
|
||||
} else {
|
||||
query = new ConstantScoreQuery(strategy.makeQuery(getArgs(shape, relation)));
|
||||
query = new ConstantScoreQuery(strategy.makeQuery(getArgs(shapeToQuery, relation)));
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
@ -378,11 +353,9 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
builder.field(GeoShapeQueryParser.STRATEGY_FIELD.getPreferredName(), strategy.getStrategyName());
|
||||
}
|
||||
|
||||
if (shapeBytes != null) {
|
||||
if (shape != null) {
|
||||
builder.field(GeoShapeQueryParser.SHAPE_FIELD.getPreferredName());
|
||||
XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(shapeBytes);
|
||||
parser.nextToken();
|
||||
builder.copyCurrentStructure(parser);
|
||||
shape.toXContent(builder, params);
|
||||
} else {
|
||||
builder.startObject(GeoShapeQueryParser.INDEXED_SHAPE_FIELD.getPreferredName())
|
||||
.field(GeoShapeQueryParser.SHAPE_ID_FIELD.getPreferredName(), indexedShapeId)
|
||||
|
@ -412,8 +385,7 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
String fieldName = in.readString();
|
||||
GeoShapeQueryBuilder builder;
|
||||
if (in.readBoolean()) {
|
||||
BytesReference shapeBytes = in.readBytesReference();
|
||||
builder = new GeoShapeQueryBuilder(fieldName, shapeBytes);
|
||||
builder = new GeoShapeQueryBuilder(fieldName, in.readShape());
|
||||
} else {
|
||||
String indexedShapeId = in.readOptionalString();
|
||||
String indexedShapeType = in.readOptionalString();
|
||||
|
@ -437,10 +409,10 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
@Override
|
||||
protected void doWriteTo(StreamOutput out) throws IOException {
|
||||
out.writeString(fieldName);
|
||||
boolean hasShapeBytes = shapeBytes != null;
|
||||
out.writeBoolean(hasShapeBytes);
|
||||
if (hasShapeBytes) {
|
||||
out.writeBytesReference(shapeBytes);
|
||||
boolean hasShape = shape != null;
|
||||
out.writeBoolean(hasShape);
|
||||
if (hasShape) {
|
||||
out.writeShape(shape);
|
||||
} else {
|
||||
out.writeOptionalString(indexedShapeId);
|
||||
out.writeOptionalString(indexedShapeType);
|
||||
|
@ -464,14 +436,14 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
|
|||
&& Objects.equals(indexedShapePath, other.indexedShapePath)
|
||||
&& Objects.equals(indexedShapeType, other.indexedShapeType)
|
||||
&& Objects.equals(relation, other.relation)
|
||||
&& Objects.equals(shapeBytes, other.shapeBytes)
|
||||
&& Objects.equals(shape, other.shape)
|
||||
&& Objects.equals(strategy, other.strategy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(fieldName, indexedShapeId, indexedShapeIndex,
|
||||
indexedShapePath, indexedShapeType, relation, shapeBytes, strategy);
|
||||
indexedShapePath, indexedShapeType, relation, shape, strategy);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,11 +22,9 @@ package org.elasticsearch.index.query;
|
|||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.geo.ShapeRelation;
|
||||
import org.elasticsearch.common.geo.SpatialStrategy;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -54,7 +52,7 @@ public class GeoShapeQueryParser implements QueryParser<GeoShapeQueryBuilder> {
|
|||
String fieldName = null;
|
||||
ShapeRelation shapeRelation = null;
|
||||
SpatialStrategy strategy = null;
|
||||
BytesReference shape = null;
|
||||
ShapeBuilder shape = null;
|
||||
|
||||
String id = null;
|
||||
String type = null;
|
||||
|
@ -79,8 +77,7 @@ public class GeoShapeQueryParser implements QueryParser<GeoShapeQueryBuilder> {
|
|||
currentFieldName = parser.currentName();
|
||||
token = parser.nextToken();
|
||||
if (parseContext.parseFieldMatcher().match(currentFieldName, SHAPE_FIELD)) {
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder().copyCurrentStructure(parser);
|
||||
shape = builder.bytes();
|
||||
shape = ShapeBuilder.parse(parser);
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, STRATEGY_FIELD)) {
|
||||
String strategyName = parser.text();
|
||||
strategy = SpatialStrategy.fromString(strategyName);
|
||||
|
|
|
@ -22,18 +22,86 @@ package org.elasticsearch.indices;
|
|||
import org.elasticsearch.action.update.UpdateHelper;
|
||||
import org.elasticsearch.cluster.metadata.MetaDataIndexUpgradeService;
|
||||
import org.elasticsearch.common.geo.ShapesAvailability;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilderRegistry;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.util.ExtensionPoint;
|
||||
import org.elasticsearch.index.NodeServicesProvider;
|
||||
import org.elasticsearch.index.mapper.Mapper;
|
||||
import org.elasticsearch.index.mapper.MetadataFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.*;
|
||||
import org.elasticsearch.index.mapper.core.BinaryFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.BooleanFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.ByteFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.CompletionFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.DateFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.DoubleFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.FloatFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.IntegerFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.LongFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.ShortFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.StringFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.TokenCountFieldMapper;
|
||||
import org.elasticsearch.index.mapper.core.TypeParsers;
|
||||
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
|
||||
import org.elasticsearch.index.mapper.geo.GeoShapeFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.*;
|
||||
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.FieldNamesFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.IdFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.IndexFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.ParentFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.RoutingFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.SourceFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.TTLFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.TimestampFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.TypeFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.UidFieldMapper;
|
||||
import org.elasticsearch.index.mapper.internal.VersionFieldMapper;
|
||||
import org.elasticsearch.index.mapper.ip.IpFieldMapper;
|
||||
import org.elasticsearch.index.mapper.object.ObjectMapper;
|
||||
import org.elasticsearch.index.query.*;
|
||||
import org.elasticsearch.index.query.BoolQueryParser;
|
||||
import org.elasticsearch.index.query.BoostingQueryParser;
|
||||
import org.elasticsearch.index.query.CommonTermsQueryParser;
|
||||
import org.elasticsearch.index.query.ConstantScoreQueryParser;
|
||||
import org.elasticsearch.index.query.DisMaxQueryParser;
|
||||
import org.elasticsearch.index.query.ExistsQueryParser;
|
||||
import org.elasticsearch.index.query.FieldMaskingSpanQueryParser;
|
||||
import org.elasticsearch.index.query.FuzzyQueryParser;
|
||||
import org.elasticsearch.index.query.GeoBoundingBoxQueryParser;
|
||||
import org.elasticsearch.index.query.GeoDistanceQueryParser;
|
||||
import org.elasticsearch.index.query.GeoDistanceRangeQueryParser;
|
||||
import org.elasticsearch.index.query.GeoPolygonQueryParser;
|
||||
import org.elasticsearch.index.query.GeoShapeQueryParser;
|
||||
import org.elasticsearch.index.query.GeohashCellQuery;
|
||||
import org.elasticsearch.index.query.HasChildQueryParser;
|
||||
import org.elasticsearch.index.query.HasParentQueryParser;
|
||||
import org.elasticsearch.index.query.IdsQueryParser;
|
||||
import org.elasticsearch.index.query.IndicesQueryParser;
|
||||
import org.elasticsearch.index.query.MatchAllQueryParser;
|
||||
import org.elasticsearch.index.query.MatchNoneQueryParser;
|
||||
import org.elasticsearch.index.query.MatchQueryParser;
|
||||
import org.elasticsearch.index.query.MoreLikeThisQueryParser;
|
||||
import org.elasticsearch.index.query.MultiMatchQueryParser;
|
||||
import org.elasticsearch.index.query.NestedQueryParser;
|
||||
import org.elasticsearch.index.query.PrefixQueryParser;
|
||||
import org.elasticsearch.index.query.QueryParser;
|
||||
import org.elasticsearch.index.query.QueryStringQueryParser;
|
||||
import org.elasticsearch.index.query.RangeQueryParser;
|
||||
import org.elasticsearch.index.query.RegexpQueryParser;
|
||||
import org.elasticsearch.index.query.ScriptQueryParser;
|
||||
import org.elasticsearch.index.query.SimpleQueryStringParser;
|
||||
import org.elasticsearch.index.query.SpanContainingQueryParser;
|
||||
import org.elasticsearch.index.query.SpanFirstQueryParser;
|
||||
import org.elasticsearch.index.query.SpanMultiTermQueryParser;
|
||||
import org.elasticsearch.index.query.SpanNearQueryParser;
|
||||
import org.elasticsearch.index.query.SpanNotQueryParser;
|
||||
import org.elasticsearch.index.query.SpanOrQueryParser;
|
||||
import org.elasticsearch.index.query.SpanTermQueryParser;
|
||||
import org.elasticsearch.index.query.SpanWithinQueryParser;
|
||||
import org.elasticsearch.index.query.TemplateQueryParser;
|
||||
import org.elasticsearch.index.query.TermQueryParser;
|
||||
import org.elasticsearch.index.query.TermsQueryParser;
|
||||
import org.elasticsearch.index.query.TypeQueryParser;
|
||||
import org.elasticsearch.index.query.WildcardQueryParser;
|
||||
import org.elasticsearch.index.query.WrapperQueryParser;
|
||||
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryParser;
|
||||
import org.elasticsearch.index.termvectors.TermVectorsService;
|
||||
import org.elasticsearch.indices.cache.query.IndicesQueryCache;
|
||||
|
@ -122,7 +190,7 @@ public class IndicesModule extends AbstractModule {
|
|||
registerQueryParser(ExistsQueryParser.class);
|
||||
registerQueryParser(MatchNoneQueryParser.class);
|
||||
|
||||
if (ShapesAvailability.JTS_AVAILABLE) {
|
||||
if (ShapesAvailability.JTS_AVAILABLE && ShapesAvailability.SPATIAL4J_AVAILABLE) {
|
||||
registerQueryParser(GeoShapeQueryParser.class);
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +214,7 @@ public class IndicesModule extends AbstractModule {
|
|||
registerMapper(CompletionFieldMapper.CONTENT_TYPE, new CompletionFieldMapper.TypeParser());
|
||||
registerMapper(GeoPointFieldMapper.CONTENT_TYPE, new GeoPointFieldMapper.TypeParser());
|
||||
|
||||
if (ShapesAvailability.JTS_AVAILABLE) {
|
||||
if (ShapesAvailability.JTS_AVAILABLE && ShapesAvailability.SPATIAL4J_AVAILABLE) {
|
||||
registerMapper(GeoShapeFieldMapper.CONTENT_TYPE, new GeoShapeFieldMapper.TypeParser());
|
||||
}
|
||||
}
|
||||
|
@ -218,6 +286,7 @@ public class IndicesModule extends AbstractModule {
|
|||
bind(IndicesFieldDataCacheListener.class).asEagerSingleton();
|
||||
bind(TermVectorsService.class).asEagerSingleton();
|
||||
bind(NodeServicesProvider.class).asEagerSingleton();
|
||||
bind(ShapeBuilderRegistry.class).asEagerSingleton();
|
||||
}
|
||||
|
||||
// public for testing
|
||||
|
|
|
@ -23,14 +23,20 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
|||
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.xcontent.*;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> extends ESTestCase {
|
||||
|
||||
|
@ -47,6 +53,12 @@ public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> exte
|
|||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, PointBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, CircleBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, EnvelopeBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, MultiPointBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, LineStringBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, MultiLineStringBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, PolygonBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, MultiPolygonBuilder.PROTOTYPE);
|
||||
namedWriteableRegistry.registerPrototype(ShapeBuilder.class, GeometryCollectionBuilder.PROTOTYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +75,7 @@ public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> exte
|
|||
/**
|
||||
* mutate the given shape so the returned shape is different
|
||||
*/
|
||||
protected abstract SB mutate(SB original) throws IOException;
|
||||
protected abstract SB createMutation(SB original) throws IOException;
|
||||
|
||||
/**
|
||||
* Test that creates new shape from a random test shape and checks both for equality
|
||||
|
@ -89,19 +101,21 @@ public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> exte
|
|||
/**
|
||||
* Test serialization and deserialization of the test shape.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testSerialization() throws IOException {
|
||||
for (int runs = 0; runs < NUMBER_OF_TESTBUILDERS; runs++) {
|
||||
SB testShape = createTestShapeBuilder();
|
||||
SB deserializedShape = copyShape(testShape);
|
||||
assertEquals(deserializedShape, testShape);
|
||||
assertEquals(deserializedShape.hashCode(), testShape.hashCode());
|
||||
assertNotSame(deserializedShape, testShape);
|
||||
SB deserializedShape = (SB) copyShape(testShape);
|
||||
assertEquals(testShape, deserializedShape);
|
||||
assertEquals(testShape.hashCode(), deserializedShape.hashCode());
|
||||
assertNotSame(testShape, deserializedShape);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test equality and hashCode properties
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testEqualsAndHashcode() throws IOException {
|
||||
for (int runs = 0; runs < NUMBER_OF_TESTBUILDERS; runs++) {
|
||||
SB firstShape = createTestShapeBuilder();
|
||||
|
@ -110,15 +124,15 @@ public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> exte
|
|||
assertTrue("shape is not equal to self", firstShape.equals(firstShape));
|
||||
assertThat("same shape's hashcode returns different values if called multiple times", firstShape.hashCode(),
|
||||
equalTo(firstShape.hashCode()));
|
||||
assertThat("different shapes should not be equal", mutate(firstShape), not(equalTo(firstShape)));
|
||||
assertThat("different shapes should not be equal", createMutation(firstShape), not(equalTo(firstShape)));
|
||||
|
||||
SB secondShape = copyShape(firstShape);
|
||||
SB secondShape = (SB) copyShape(firstShape);
|
||||
assertTrue("shape is not equal to self", secondShape.equals(secondShape));
|
||||
assertTrue("shape is not equal to its copy", firstShape.equals(secondShape));
|
||||
assertTrue("equals is not symmetric", secondShape.equals(firstShape));
|
||||
assertThat("shape copy's hashcode is different from original hashcode", secondShape.hashCode(), equalTo(firstShape.hashCode()));
|
||||
|
||||
SB thirdShape = copyShape(secondShape);
|
||||
SB thirdShape = (SB) copyShape(secondShape);
|
||||
assertTrue("shape is not equal to self", thirdShape.equals(thirdShape));
|
||||
assertTrue("shape is not equal to its copy", secondShape.equals(thirdShape));
|
||||
assertThat("shape copy's hashcode is different from original hashcode", secondShape.hashCode(), equalTo(thirdShape.hashCode()));
|
||||
|
@ -129,14 +143,12 @@ public abstract class AbstractShapeBuilderTestCase<SB extends ShapeBuilder> exte
|
|||
}
|
||||
}
|
||||
|
||||
protected SB copyShape(SB original) throws IOException {
|
||||
static ShapeBuilder copyShape(ShapeBuilder original) throws IOException {
|
||||
try (BytesStreamOutput output = new BytesStreamOutput()) {
|
||||
original.writeTo(output);
|
||||
try (StreamInput in = new NamedWriteableAwareStreamInput(StreamInput.wrap(output.bytes()), namedWriteableRegistry)) {
|
||||
ShapeBuilder prototype = (ShapeBuilder) namedWriteableRegistry.getPrototype(ShapeBuilder.class, original.getWriteableName());
|
||||
@SuppressWarnings("unchecked")
|
||||
SB copy = (SB) prototype.readFrom(in);
|
||||
return copy;
|
||||
return prototype.readFrom(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,20 +25,20 @@ import org.elasticsearch.common.unit.DistanceUnit;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
public class CirlceBuilderTests extends AbstractShapeBuilderTestCase<CircleBuilder> {
|
||||
public class CircleBuilderTests extends AbstractShapeBuilderTestCase<CircleBuilder> {
|
||||
|
||||
@Override
|
||||
protected CircleBuilder createTestShapeBuilder() {
|
||||
double centerX = randomDoubleBetween(-180, 180, false);
|
||||
double centerY = randomDoubleBetween(-90, 90, false);
|
||||
return new CircleBuilder()
|
||||
.center(new Coordinate(centerX, centerY))
|
||||
.radius(randomDoubleBetween(0.1, 10.0, false), randomFrom(DistanceUnit.values()));
|
||||
return createRandomShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CircleBuilder mutate(CircleBuilder original) throws IOException {
|
||||
CircleBuilder mutation = copyShape(original);
|
||||
protected CircleBuilder createMutation(CircleBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static CircleBuilder mutate(CircleBuilder original) throws IOException {
|
||||
CircleBuilder mutation = (CircleBuilder) copyShape(original);
|
||||
double radius = original.radius();
|
||||
DistanceUnit unit = original.unit();
|
||||
|
||||
|
@ -55,4 +55,12 @@ public class CirlceBuilderTests extends AbstractShapeBuilderTestCase<CircleBuild
|
|||
}
|
||||
return mutation.radius(radius, unit);
|
||||
}
|
||||
|
||||
static CircleBuilder createRandomShape() {
|
||||
double centerX = randomDoubleBetween(-180, 180, false);
|
||||
double centerY = randomDoubleBetween(-90, 90, false);
|
||||
return new CircleBuilder()
|
||||
.center(new Coordinate(centerX, centerY))
|
||||
.radius(randomDoubleBetween(0.1, 10.0, false), randomFrom(DistanceUnit.values()));
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@ package org.elasticsearch.common.geo.builders;
|
|||
import com.spatial4j.core.shape.Rectangle;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -31,36 +30,39 @@ public class EnvelopeBuilderTests extends AbstractShapeBuilderTestCase<EnvelopeB
|
|||
|
||||
@Override
|
||||
protected EnvelopeBuilder createTestShapeBuilder() {
|
||||
EnvelopeBuilder envelope = new EnvelopeBuilder(randomFrom(Orientation.values()));
|
||||
return createRandomShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EnvelopeBuilder createMutation(EnvelopeBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static EnvelopeBuilder mutate(EnvelopeBuilder original) throws IOException {
|
||||
EnvelopeBuilder mutation = (EnvelopeBuilder) copyShape(original);
|
||||
// move one corner to the middle of original
|
||||
switch (randomIntBetween(0, 3)) {
|
||||
case 0:
|
||||
mutation.topLeft(new Coordinate(randomDoubleBetween(-180.0, original.bottomRight().x, true), original.topLeft().y));
|
||||
break;
|
||||
case 1:
|
||||
mutation.topLeft(new Coordinate(original.topLeft().x, randomDoubleBetween(original.bottomRight().y, 90.0, true)));
|
||||
break;
|
||||
case 2:
|
||||
mutation.bottomRight(new Coordinate(randomDoubleBetween(original.topLeft().x, 180.0, true), original.bottomRight().y));
|
||||
break;
|
||||
case 3:
|
||||
mutation.bottomRight(new Coordinate(original.bottomRight().x, randomDoubleBetween(-90.0, original.topLeft().y, true)));
|
||||
break;
|
||||
}
|
||||
return mutation;
|
||||
}
|
||||
|
||||
static EnvelopeBuilder createRandomShape() {
|
||||
EnvelopeBuilder envelope = new EnvelopeBuilder();
|
||||
Rectangle box = RandomShapeGenerator.xRandomRectangle(getRandom(), RandomShapeGenerator.xRandomPoint(getRandom()));
|
||||
envelope.topLeft(box.getMinX(), box.getMaxY())
|
||||
.bottomRight(box.getMaxX(), box.getMinY());
|
||||
return envelope;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EnvelopeBuilder mutate(EnvelopeBuilder original) throws IOException {
|
||||
EnvelopeBuilder mutation = copyShape(original);
|
||||
if (randomBoolean()) {
|
||||
// toggle orientation
|
||||
mutation.orientation = (original.orientation == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
|
||||
} else {
|
||||
// move one corner to the middle of original
|
||||
switch (randomIntBetween(0, 3)) {
|
||||
case 0:
|
||||
mutation.topLeft(new Coordinate(randomDoubleBetween(-180.0, original.bottomRight.x, true), original.topLeft.y));
|
||||
break;
|
||||
case 1:
|
||||
mutation.topLeft(new Coordinate(original.topLeft.x, randomDoubleBetween(original.bottomRight.y, 90.0, true)));
|
||||
break;
|
||||
case 2:
|
||||
mutation.bottomRight(new Coordinate(randomDoubleBetween(original.topLeft.x, 180.0, true), original.bottomRight.y));
|
||||
break;
|
||||
case 3:
|
||||
mutation.bottomRight(new Coordinate(original.bottomRight.x, randomDoubleBetween(-90.0, original.topLeft.y, true)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mutation;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.common.geo.builders;
|
||||
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class GeometryCollectionBuilderTests extends AbstractShapeBuilderTestCase<GeometryCollectionBuilder> {
|
||||
|
||||
@Override
|
||||
protected GeometryCollectionBuilder createTestShapeBuilder() {
|
||||
GeometryCollectionBuilder geometryCollection = new GeometryCollectionBuilder();
|
||||
int shapes = randomIntBetween(0, 8);
|
||||
for (int i = 0; i < shapes; i++) {
|
||||
switch (randomIntBetween(0, 7)) {
|
||||
case 0:
|
||||
geometryCollection.shape(PointBuilderTests.createRandomShape());
|
||||
break;
|
||||
case 1:
|
||||
geometryCollection.shape(CircleBuilderTests.createRandomShape());
|
||||
break;
|
||||
case 2:
|
||||
geometryCollection.shape(EnvelopeBuilderTests.createRandomShape());
|
||||
break;
|
||||
case 3:
|
||||
geometryCollection.shape(LineStringBuilderTests.createRandomShape());
|
||||
break;
|
||||
case 4:
|
||||
geometryCollection.shape(MultiLineStringBuilderTests.createRandomShape());
|
||||
break;
|
||||
case 5:
|
||||
geometryCollection.shape(MultiPolygonBuilderTests.createRandomShape());
|
||||
break;
|
||||
case 6:
|
||||
geometryCollection.shape(MultiPointBuilderTests.createRandomShape());
|
||||
break;
|
||||
case 7:
|
||||
geometryCollection.shape(PolygonBuilderTests.createRandomShape());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return geometryCollection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GeometryCollectionBuilder createMutation(GeometryCollectionBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static GeometryCollectionBuilder mutate(GeometryCollectionBuilder original) throws IOException {
|
||||
GeometryCollectionBuilder mutation = (GeometryCollectionBuilder) copyShape(original);
|
||||
if (mutation.shapes.size() > 0) {
|
||||
int shapePosition = randomIntBetween(0, mutation.shapes.size() - 1);
|
||||
ShapeBuilder shapeToChange = mutation.shapes.get(shapePosition);
|
||||
switch (shapeToChange.type()) {
|
||||
case POINT:
|
||||
shapeToChange = PointBuilderTests.mutate((PointBuilder) shapeToChange);
|
||||
break;
|
||||
case CIRCLE:
|
||||
shapeToChange = CircleBuilderTests.mutate((CircleBuilder) shapeToChange);
|
||||
break;
|
||||
case ENVELOPE:
|
||||
shapeToChange = EnvelopeBuilderTests.mutate((EnvelopeBuilder) shapeToChange);
|
||||
break;
|
||||
case LINESTRING:
|
||||
shapeToChange = LineStringBuilderTests.mutate((LineStringBuilder) shapeToChange);
|
||||
break;
|
||||
case MULTILINESTRING:
|
||||
shapeToChange = MultiLineStringBuilderTests.mutate((MultiLineStringBuilder) shapeToChange);
|
||||
break;
|
||||
case MULTIPOLYGON:
|
||||
shapeToChange = MultiPolygonBuilderTests.mutate((MultiPolygonBuilder) shapeToChange);
|
||||
break;
|
||||
case MULTIPOINT:
|
||||
shapeToChange = MultiPointBuilderTests.mutate((MultiPointBuilder) shapeToChange);
|
||||
break;
|
||||
case POLYGON:
|
||||
shapeToChange = PolygonBuilderTests.mutate((PolygonBuilder) shapeToChange);
|
||||
break;
|
||||
case GEOMETRYCOLLECTION:
|
||||
throw new UnsupportedOperationException("GeometryCollection should not be nested inside each other");
|
||||
}
|
||||
mutation.shapes.set(shapePosition, shapeToChange);
|
||||
} else {
|
||||
mutation.shape(RandomShapeGenerator.createShape(getRandom()));
|
||||
}
|
||||
return mutation;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.common.geo.builders;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class LineStringBuilderTests extends AbstractShapeBuilderTestCase<LineStringBuilder> {
|
||||
|
||||
@Override
|
||||
protected LineStringBuilder createTestShapeBuilder() {
|
||||
return createRandomShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LineStringBuilder createMutation(LineStringBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static LineStringBuilder mutate(LineStringBuilder original) throws IOException {
|
||||
LineStringBuilder mutation = (LineStringBuilder) copyShape(original);
|
||||
Coordinate[] coordinates = original.coordinates(false);
|
||||
Coordinate coordinate = randomFrom(coordinates);
|
||||
if (randomBoolean()) {
|
||||
if (coordinate.x != 0.0) {
|
||||
coordinate.x = coordinate.x / 2;
|
||||
} else {
|
||||
coordinate.x = randomDoubleBetween(-180.0, 180.0, true);
|
||||
}
|
||||
} else {
|
||||
if (coordinate.y != 0.0) {
|
||||
coordinate.y = coordinate.y / 2;
|
||||
} else {
|
||||
coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
|
||||
}
|
||||
}
|
||||
return mutation.points(coordinates);
|
||||
}
|
||||
|
||||
static LineStringBuilder createRandomShape() {
|
||||
LineStringBuilder lsb = (LineStringBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.LINESTRING);
|
||||
if (randomBoolean()) {
|
||||
lsb.close();
|
||||
}
|
||||
return lsb;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.common.geo.builders;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class MultiLineStringBuilderTests extends AbstractShapeBuilderTestCase<MultiLineStringBuilder> {
|
||||
|
||||
@Override
|
||||
protected MultiLineStringBuilder createTestShapeBuilder() {
|
||||
return createRandomShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MultiLineStringBuilder createMutation(MultiLineStringBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static MultiLineStringBuilder mutate(MultiLineStringBuilder original) throws IOException {
|
||||
MultiLineStringBuilder mutation = (MultiLineStringBuilder) copyShape(original);
|
||||
Coordinate[][] coordinates = mutation.coordinates();
|
||||
int lineToChange = randomInt(coordinates.length - 1);
|
||||
for (int i = 0; i < coordinates.length; i++) {
|
||||
Coordinate[] line = coordinates[i];
|
||||
if (i == lineToChange) {
|
||||
Coordinate coordinate = randomFrom(line);
|
||||
if (randomBoolean()) {
|
||||
if (coordinate.x != 0.0) {
|
||||
coordinate.x = coordinate.x / 2;
|
||||
} else {
|
||||
coordinate.x = randomDoubleBetween(-180.0, 180.0, true);
|
||||
}
|
||||
} else {
|
||||
if (coordinate.y != 0.0) {
|
||||
coordinate.y = coordinate.y / 2;
|
||||
} else {
|
||||
coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mutation;
|
||||
}
|
||||
|
||||
static MultiLineStringBuilder createRandomShape() {
|
||||
return (MultiLineStringBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.MULTILINESTRING);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.common.geo.builders;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class MultiPointBuilderTests extends AbstractShapeBuilderTestCase<MultiPointBuilder> {
|
||||
|
||||
@Override
|
||||
protected MultiPointBuilder createTestShapeBuilder() {
|
||||
return createRandomShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MultiPointBuilder createMutation(MultiPointBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static MultiPointBuilder mutate(MultiPointBuilder original) throws IOException {
|
||||
MultiPointBuilder mutation = (MultiPointBuilder) copyShape(original);
|
||||
Coordinate[] coordinates = original.coordinates(false);
|
||||
Coordinate coordinate = randomFrom(coordinates);
|
||||
if (randomBoolean()) {
|
||||
if (coordinate.x != 0.0) {
|
||||
coordinate.x = coordinate.x / 2;
|
||||
} else {
|
||||
coordinate.x = randomDoubleBetween(-180.0, 180.0, true);
|
||||
}
|
||||
} else {
|
||||
if (coordinate.y != 0.0) {
|
||||
coordinate.y = coordinate.y / 2;
|
||||
} else {
|
||||
coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
|
||||
}
|
||||
}
|
||||
return mutation.points(coordinates);
|
||||
}
|
||||
|
||||
static MultiPointBuilder createRandomShape() {
|
||||
return (MultiPointBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.MULTIPOINT);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.common.geo.builders;
|
||||
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class MultiPolygonBuilderTests extends AbstractShapeBuilderTestCase<MultiPolygonBuilder> {
|
||||
|
||||
@Override
|
||||
protected MultiPolygonBuilder createTestShapeBuilder() {
|
||||
return createRandomShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MultiPolygonBuilder createMutation(MultiPolygonBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static MultiPolygonBuilder mutate(MultiPolygonBuilder original) throws IOException {
|
||||
MultiPolygonBuilder mutation;
|
||||
if (randomBoolean()) {
|
||||
mutation = new MultiPolygonBuilder(original.orientation() == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
|
||||
for (PolygonBuilder pb : original.polygons()) {
|
||||
mutation.polygon((PolygonBuilder) copyShape(pb));
|
||||
}
|
||||
} else {
|
||||
mutation = (MultiPolygonBuilder) copyShape(original);
|
||||
if (mutation.polygons().size() > 0) {
|
||||
int polyToChange = randomInt(mutation.polygons().size() - 1);
|
||||
mutation.polygons().set(polyToChange, PolygonBuilderTests.mutatePolygonBuilder(mutation.polygons().get(polyToChange)));
|
||||
} else {
|
||||
mutation.polygon((PolygonBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POLYGON));
|
||||
}
|
||||
}
|
||||
return mutation;
|
||||
}
|
||||
|
||||
static MultiPolygonBuilder createRandomShape() {
|
||||
MultiPolygonBuilder mpb = new MultiPolygonBuilder(randomFrom(Orientation.values()));
|
||||
int polys = randomIntBetween(0, 10);
|
||||
for (int i = 0; i < polys; i++) {
|
||||
PolygonBuilder pgb = (PolygonBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POLYGON);
|
||||
mpb.polygon(pgb);
|
||||
}
|
||||
return mpb;
|
||||
}
|
||||
}
|
|
@ -24,15 +24,27 @@ import com.vividsolutions.jts.geom.Coordinate;
|
|||
import org.elasticsearch.test.geo.RandomShapeGenerator;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PointBuilderTests extends AbstractShapeBuilderTestCase<PointBuilder> {
|
||||
|
||||
@Override
|
||||
protected PointBuilder createTestShapeBuilder() {
|
||||
return (PointBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POINT);
|
||||
return createRandomShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PointBuilder mutate(PointBuilder original) {
|
||||
return new PointBuilder().coordinate(new Coordinate(original.longitude()/2, original.latitude()/2));
|
||||
protected PointBuilder createMutation(PointBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static PointBuilder mutate(PointBuilder original) {
|
||||
return new PointBuilder().coordinate(new Coordinate(original.longitude() / 2, original.latitude() / 2));
|
||||
}
|
||||
|
||||
static PointBuilder createRandomShape() {
|
||||
return (PointBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POINT);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch 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.elasticsearch.common.geo.builders;
|
||||
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilder.Orientation;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator;
|
||||
import org.elasticsearch.test.geo.RandomShapeGenerator.ShapeType;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBuilder> {
|
||||
|
||||
@Override
|
||||
protected PolygonBuilder createTestShapeBuilder() {
|
||||
return createRandomShape();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PolygonBuilder createMutation(PolygonBuilder original) throws IOException {
|
||||
return mutate(original);
|
||||
}
|
||||
|
||||
static PolygonBuilder mutate(PolygonBuilder original) throws IOException {
|
||||
PolygonBuilder mutation = (PolygonBuilder) copyShape(original);
|
||||
return mutatePolygonBuilder(mutation);
|
||||
}
|
||||
|
||||
static PolygonBuilder mutatePolygonBuilder(PolygonBuilder pb) {
|
||||
if (randomBoolean()) {
|
||||
pb = polyWithOposingOrientation(pb);
|
||||
} else {
|
||||
// change either point in shell or in random hole
|
||||
LineStringBuilder lineToChange;
|
||||
if (randomBoolean() || pb.holes().size() == 0) {
|
||||
lineToChange = pb.shell();
|
||||
} else {
|
||||
lineToChange = randomFrom(pb.holes());
|
||||
}
|
||||
Coordinate coordinate = randomFrom(lineToChange.coordinates(false));
|
||||
if (randomBoolean()) {
|
||||
if (coordinate.x != 0.0) {
|
||||
coordinate.x = coordinate.x / 2;
|
||||
} else {
|
||||
coordinate.x = randomDoubleBetween(-180.0, 180.0, true);
|
||||
}
|
||||
} else {
|
||||
if (coordinate.y != 0.0) {
|
||||
coordinate.y = coordinate.y / 2;
|
||||
} else {
|
||||
coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an input polygon and returns an identical one, only with opposing orientation setting.
|
||||
* This is done so we don't have to expose a setter for orientation in the actual class
|
||||
*/
|
||||
private static PolygonBuilder polyWithOposingOrientation(PolygonBuilder pb) {
|
||||
PolygonBuilder mutation = new PolygonBuilder(pb.orientation() == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
|
||||
mutation.points(pb.shell().coordinates(false));
|
||||
for (LineStringBuilder hole : pb.holes()) {
|
||||
mutation.hole(hole);
|
||||
}
|
||||
return mutation;
|
||||
}
|
||||
|
||||
static PolygonBuilder createRandomShape() {
|
||||
PolygonBuilder pgb = (PolygonBuilder) RandomShapeGenerator.createShape(getRandom(), ShapeType.POLYGON);
|
||||
if (randomBoolean()) {
|
||||
pgb = polyWithOposingOrientation(pgb);
|
||||
}
|
||||
return pgb;
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ import org.elasticsearch.common.bytes.BytesArray;
|
|||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.compress.CompressedXContent;
|
||||
import org.elasticsearch.common.geo.builders.ShapeBuilderRegistry;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.inject.ModulesBuilder;
|
||||
|
@ -191,6 +192,7 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
|
|||
// skip services
|
||||
bindQueryParsersExtension();
|
||||
bindMapperExtension();
|
||||
bind(ShapeBuilderRegistry.class).asEagerSingleton();
|
||||
}
|
||||
},
|
||||
new ScriptModule(settings) {
|
||||
|
|
|
@ -59,14 +59,11 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
|
|||
protected GeoShapeQueryBuilder doCreateTestQueryBuilder() {
|
||||
ShapeType shapeType = ShapeType.randomType(getRandom());
|
||||
ShapeBuilder shape = RandomShapeGenerator.createShapeWithin(getRandom(), null, shapeType);
|
||||
|
||||
GeoShapeQueryBuilder builder;
|
||||
clearShapeFields();
|
||||
if (randomBoolean()) {
|
||||
try {
|
||||
builder = new GeoShapeQueryBuilder(GEO_SHAPE_FIELD_NAME, shape);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
builder = new GeoShapeQueryBuilder(GEO_SHAPE_FIELD_NAME, shape);
|
||||
} else {
|
||||
indexedShapeToReturn = shape;
|
||||
indexedShapeId = randomAsciiOfLengthBetween(3, 20);
|
||||
|
@ -225,17 +222,17 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
|
|||
|
||||
public void testFromJson() throws IOException {
|
||||
String json =
|
||||
"{\n" +
|
||||
" \"geo_shape\" : {\n" +
|
||||
" \"location\" : {\n" +
|
||||
" \"shape\" : {\n" +
|
||||
" \"type\" : \"envelope\",\n" +
|
||||
" \"coordinates\" : [ [ 13.0, 53.0 ], [ 14.0, 52.0 ] ]\n" +
|
||||
" },\n" +
|
||||
" \"relation\" : \"intersects\"\n" +
|
||||
" },\n" +
|
||||
" \"boost\" : 42.0\n" +
|
||||
" }\n" +
|
||||
"{\n" +
|
||||
" \"geo_shape\" : {\n" +
|
||||
" \"location\" : {\n" +
|
||||
" \"shape\" : {\n" +
|
||||
" \"type\" : \"envelope\",\n" +
|
||||
" \"coordinates\" : [ [ 13.0, 53.0 ], [ 14.0, 52.0 ] ]\n" +
|
||||
" },\n" +
|
||||
" \"relation\" : \"intersects\"\n" +
|
||||
" },\n" +
|
||||
" \"boost\" : 42.0\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
GeoShapeQueryBuilder parsed = (GeoShapeQueryBuilder) parseQuery(json);
|
||||
checkGeneratedJson(json, parsed);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch.search.geo;
|
||||
|
||||
import com.spatial4j.core.shape.Rectangle;
|
||||
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.common.geo.ShapeRelation;
|
||||
|
@ -47,7 +48,10 @@ import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomPoint;
|
|||
import static org.elasticsearch.test.geo.RandomShapeGenerator.xRandomRectangle;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class GeoShapeQueryTests extends ESSingleNodeTestCase {
|
||||
public void testNullShape() throws Exception {
|
||||
|
@ -396,6 +400,12 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
|
|||
.setPostFilter(filter).get();
|
||||
assertSearchResponse(result);
|
||||
assertHitCount(result, 1);
|
||||
// no shape
|
||||
filter = QueryBuilders.geoShapeQuery("location", ShapeBuilders.newGeometryCollection());
|
||||
result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery())
|
||||
.setPostFilter(filter).get();
|
||||
assertSearchResponse(result);
|
||||
assertHitCount(result, 0);
|
||||
}
|
||||
|
||||
public void testPointsOnly() throws Exception {
|
||||
|
|
Loading…
Reference in New Issue