Rename PointCollectionBuilder to CoordinatesBuilder

Also renaming internal methods to reflect that they are dealing with
jts coordinates. Also renamed the list() to build() method for creating
the coordinates lists and adding constructors to PolygonBuilder that
take CoordinatesBuilders and implicitely call build() on them.
This commit is contained in:
Christoph Büscher 2016-01-12 11:43:04 +01:00
parent 57c579e7b7
commit ff2593e74a
21 changed files with 665 additions and 619 deletions

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Circle;
import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.DistanceUnit;
@ -35,7 +36,7 @@ public class CircleBuilder extends ShapeBuilder {
public static final String FIELD_RADIUS = "radius";
public static final GeoShapeType TYPE = GeoShapeType.CIRCLE;
public static final CircleBuilder PROTOTYPE = new CircleBuilder();
static final CircleBuilder PROTOTYPE = new CircleBuilder();
private DistanceUnit unit = DistanceUnit.DEFAULT;
private double radius;

View File

@ -29,22 +29,23 @@ import java.util.Collection;
import java.util.List;
/**
* The {@link PointCollection} is an abstract base implementation for all GeoShapes. It simply handles a set of points.
* The {@link CoordinateCollection} is an abstract base implementation for {@link LineStringBuilder} and {@link MultiPointBuilder}.
* It holds a common list of {@link Coordinate}, provides setters for adding elements to the list and can render this to XContent.
*/
public abstract class PointCollection<E extends PointCollection<E>> extends ShapeBuilder {
public abstract class CoordinateCollection<E extends CoordinateCollection<E>> extends ShapeBuilder {
protected final List<Coordinate> points;
protected final List<Coordinate> coordinates;
/**
* Construct a new collection of points.
* @param points an initial list of points
* @throws IllegalArgumentException if points is <tt>null</tt> or empty
* Construct a new collection of coordinates.
* @param coordinates an initial list of coordinates
* @throws IllegalArgumentException if coordinates is <tt>null</tt> or empty
*/
protected PointCollection(List<Coordinate> points) {
if (points == null || points.size() == 0) {
protected CoordinateCollection(List<Coordinate> coordinates) {
if (coordinates == null || coordinates.size() == 0) {
throw new IllegalArgumentException("cannot create point collection with empty set of points");
}
this.points = points;
this.coordinates = coordinates;
}
@SuppressWarnings("unchecked")
@ -53,54 +54,54 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
}
/**
* Add a new point to the collection
* Add a new coordinate to the collection
* @param longitude longitude of the coordinate
* @param latitude latitude of the coordinate
* @return this
*/
public E point(double longitude, double latitude) {
return this.point(coordinate(longitude, latitude));
public E coordinate(double longitude, double latitude) {
return this.coordinate(new Coordinate(longitude, latitude));
}
/**
* Add a new point to the collection
* Add a new coordinate to the collection
* @param coordinate coordinate of the point
* @return this
*/
public E point(Coordinate coordinate) {
this.points.add(coordinate);
public E coordinate(Coordinate coordinate) {
this.coordinates.add(coordinate);
return thisRef();
}
/**
* Add a array of points to the collection
* Add a array of coordinates to the collection
*
* @param coordinates array of {@link Coordinate}s to add
* @return this
*/
public E points(Coordinate...coordinates) {
return this.points(Arrays.asList(coordinates));
public E coordinates(Coordinate...coordinates) {
return this.coordinates(Arrays.asList(coordinates));
}
/**
* Add a collection of points to the collection
* Add a collection of coordinates to the collection
*
* @param coordinates array of {@link Coordinate}s to add
* @return this
*/
public E points(Collection<? extends Coordinate> coordinates) {
this.points.addAll(coordinates);
public E coordinates(Collection<? extends Coordinate> coordinates) {
this.coordinates.addAll(coordinates);
return thisRef();
}
/**
* Copy all points to a new Array
* Copy all coordinate to a new Array
*
* @param closed if set to true the first point of the array is repeated as last element
* @return Array of coordinates
*/
protected Coordinate[] coordinates(boolean closed) {
Coordinate[] result = points.toArray(new Coordinate[points.size() + (closed?1:0)]);
Coordinate[] result = coordinates.toArray(new Coordinate[coordinates.size() + (closed?1:0)]);
if(closed) {
result[result.length-1] = result[0];
}
@ -116,14 +117,14 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
*/
protected XContentBuilder coordinatesToXcontent(XContentBuilder builder, boolean closed) throws IOException {
builder.startArray();
for(Coordinate point : points) {
toXContent(builder, point);
for(Coordinate coord : coordinates) {
toXContent(builder, coord);
}
if(closed) {
Coordinate start = points.get(0);
Coordinate end = points.get(points.size()-1);
Coordinate start = coordinates.get(0);
Coordinate end = coordinates.get(coordinates.size()-1);
if(start.x != end.x || start.y != end.y) {
toXContent(builder, points.get(0));
toXContent(builder, coordinates.get(0));
}
}
builder.endArray();

View File

@ -27,60 +27,60 @@ import java.util.Collection;
import java.util.List;
/**
* A builder for a list of points (of {@link Coordinate} type).
* Enables chaining of individual points either as long/lat pairs
* A builder for a list of coordinates.
* Enables chaining of individual coordinates either as long/lat pairs
* or as {@link Coordinate} elements, arrays or collections.
*/
public class PointListBuilder {
public class CoordinatesBuilder {
private final List<Coordinate> points = new ArrayList<>();
/**
* Add a new point to the collection
* @param longitude longitude of the coordinate
* @param latitude latitude of the coordinate
* Add a new coordinate to the collection
* @param coordinate the coordinate to add
* @return this
*/
public PointListBuilder point(double longitude, double latitude) {
return this.point(new Coordinate(longitude, latitude));
}
/**
* Add a new point to the collection
* @param coordinate coordinate of the point
* @return this
*/
public PointListBuilder point(Coordinate coordinate) {
public CoordinatesBuilder coordinate(Coordinate coordinate) {
this.points.add(coordinate);
return this;
}
/**
* Add a array of points to the collection
*
* @param coordinates array of {@link Coordinate}s to add
* Add a new coordinate to the collection
* @param longitude longitude of the coordinate
* @param latitude latitude of the coordinate
* @return this
*/
public PointListBuilder points(Coordinate...coordinates) {
return this.points(Arrays.asList(coordinates));
public CoordinatesBuilder coordinate(double longitude, double latitude) {
return this.coordinate(new Coordinate(longitude, latitude));
}
/**
* Add a collection of points to the collection
* Add an array of coordinates to the current coordinates
*
* @param coordinates array of {@link Coordinate}s to add
* @return this
*/
public PointListBuilder points(Collection<? extends Coordinate> coordinates) {
public CoordinatesBuilder coordinates(Coordinate...coordinates) {
return this.coordinates(Arrays.asList(coordinates));
}
/**
* Add a collection of coordinates to the current coordinates
*
* @param coordinates collection of {@link Coordinate}s to add
* @return this
*/
public CoordinatesBuilder coordinates(Collection<? extends Coordinate> coordinates) {
this.points.addAll(coordinates);
return this;
}
/**
* Closes the current list of points by adding the starting point as the end point
* if they are not already the same
* Makes a closed ring out of the current coordinates by adding the starting point as the end point.
* Will have no effect of starting and end point are already the same coordinate.
*/
public PointListBuilder close() {
public CoordinatesBuilder close() {
Coordinate start = points.get(0);
Coordinate end = points.get(points.size()-1);
if(start.x != end.x || start.y != end.y) {
@ -90,9 +90,9 @@ public class PointListBuilder {
}
/**
* @return the current list of points
* @return a list containing the current coordinates
*/
public List<Coordinate> list() {
public List<Coordinate> build() {
return new ArrayList<>(this.points);
}
}

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Rectangle;
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;
@ -32,7 +33,7 @@ public class EnvelopeBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.ENVELOPE;
public static final EnvelopeBuilder PROTOTYPE = new EnvelopeBuilder(new Coordinate(-1.0, 1.0), new Coordinate(1.0, -1.0));
static final EnvelopeBuilder PROTOTYPE = new EnvelopeBuilder(new Coordinate(-1.0, 1.0), new Coordinate(1.0, -1.0));
private Coordinate topLeft;
private Coordinate bottomRight;

View File

@ -20,6 +20,7 @@
package org.elasticsearch.common.geo.builders;
import com.spatial4j.core.shape.Shape;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.geo.XShapeCollection;
import org.elasticsearch.common.io.stream.StreamInput;
@ -35,7 +36,7 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.GEOMETRYCOLLECTION;
public static final GeometryCollectionBuilder PROTOTYPE = new GeometryCollectionBuilder();
static final GeometryCollectionBuilder PROTOTYPE = new GeometryCollectionBuilder();
protected final ArrayList<ShapeBuilder> shapes = new ArrayList<>();

View File

@ -24,14 +24,6 @@ import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
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.Arrays;
import java.util.Objects;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -43,25 +35,29 @@ import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class LineStringBuilder extends PointCollection<LineStringBuilder> {
public class LineStringBuilder extends CoordinateCollection<LineStringBuilder> {
/**
* Construct a new LineString.
* Per GeoJSON spec (http://geojson.org/geojson-spec.html#linestring)
* a LineString must contain two or more positions
* @param points the initial list of points
* @throw {@link IllegalArgumentException} if there are less then two points defined
* a LineString must contain two or more coordinates
* @param coordinates the initial list of coordinates
* @throw {@link IllegalArgumentException} if there are less then two coordinates defined
*/
public LineStringBuilder(List<Coordinate> points) {
super(points);
if (points.size() < 2) {
throw new IllegalArgumentException("invalid number of points in LineString (found [" + points.size()+ "] - must be >= 2)");
public LineStringBuilder(List<Coordinate> coordinates) {
super(coordinates);
if (coordinates.size() < 2) {
throw new IllegalArgumentException("invalid number of points in LineString (found [" + coordinates.size()+ "] - must be >= 2)");
}
}
public LineStringBuilder(CoordinatesBuilder coordinates) {
this(coordinates.build());
}
public static final GeoShapeType TYPE = GeoShapeType.LINESTRING;
public static final LineStringBuilder PROTOTYPE = new LineStringBuilder(new PointListBuilder().point(0.0, 0.0).point(1.0, 1.0).list());
static final LineStringBuilder PROTOTYPE = new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0).coordinate(1.0, 1.0));
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
@ -74,13 +70,14 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
}
/**
* Closes the current lineString by adding the starting point as the end point
* Closes the current lineString by adding the starting point as the end point.
* This will have no effect if starting and end point are already the same.
*/
public LineStringBuilder close() {
Coordinate start = points.get(0);
Coordinate end = points.get(points.size()-1);
Coordinate start = coordinates.get(0);
Coordinate end = coordinates.get(coordinates.size() - 1);
if(start.x != end.x || start.y != end.y) {
points.add(start);
coordinates.add(start);
}
return this;
}
@ -92,7 +89,7 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
@Override
public Shape build() {
Coordinate[] coordinates = points.toArray(new Coordinate[points.size()]);
Coordinate[] coordinates = this.coordinates.toArray(new Coordinate[this.coordinates.size()]);
Geometry geometry;
if(wrapdateline) {
ArrayList<LineString> strings = decompose(FACTORY, coordinates, new ArrayList<LineString>());
@ -171,7 +168,7 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
@Override
public int hashCode() {
return Objects.hash(points);
return Objects.hash(coordinates);
}
@Override
@ -183,25 +180,25 @@ public class LineStringBuilder extends PointCollection<LineStringBuilder> {
return false;
}
LineStringBuilder other = (LineStringBuilder) obj;
return Objects.equals(points, other.points);
return Objects.equals(coordinates, other.coordinates);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(points.size());
for (Coordinate point : points) {
out.writeVInt(coordinates.size());
for (Coordinate point : coordinates) {
writeCoordinateTo(point, out);
}
}
@Override
public LineStringBuilder readFrom(StreamInput in) throws IOException {
PointListBuilder pl = new PointListBuilder();
CoordinatesBuilder coordinates = new CoordinatesBuilder();
int size = in.readVInt();
for (int i=0; i < size; i++) {
pl.point(readCoordinateFrom(in));
coordinates.coordinate(readCoordinateFrom(in));
}
LineStringBuilder lineStringBuilder = new LineStringBuilder(pl.list());
LineStringBuilder lineStringBuilder = new LineStringBuilder(coordinates);
return lineStringBuilder;
}
}

View File

@ -23,9 +23,6 @@ import com.spatial4j.core.shape.Shape;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -40,7 +37,7 @@ public class MultiLineStringBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.MULTILINESTRING;
public static final MultiLineStringBuilder PROTOTYPE = new MultiLineStringBuilder();
static final MultiLineStringBuilder PROTOTYPE = new MultiLineStringBuilder();
private final ArrayList<LineStringBuilder> lines = new ArrayList<>();
@ -49,10 +46,6 @@ public class MultiLineStringBuilder extends ShapeBuilder {
return this;
}
public MultiLineStringBuilder linestring(Coordinate[] coordinates) {
return this.linestring(new LineStringBuilder(new PointListBuilder().points(coordinates).list()));
}
public Coordinate[][] coordinates() {
Coordinate[][] result = new Coordinate[lines.size()][];
for (int i = 0; i < result.length; i++) {

View File

@ -22,6 +22,7 @@ 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.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@ -29,22 +30,21 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
public class MultiPointBuilder extends CoordinateCollection<MultiPointBuilder> {
public static final GeoShapeType TYPE = GeoShapeType.MULTIPOINT;
public final static MultiPointBuilder PROTOTYPE = new MultiPointBuilder(Arrays.asList(new Coordinate[]{new Coordinate(0.0, 0.0)}));
final static MultiPointBuilder PROTOTYPE = new MultiPointBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0).build());
/**
* Create a new {@link MultiPointBuilder}.
* @param points needs at least two points to be valid, otherwise will throw an exception
* @param coordinates needs at least two coordinates to be valid, otherwise will throw an exception
*/
public MultiPointBuilder(List<Coordinate> points) {
super(points);
public MultiPointBuilder(List<Coordinate> coordinates) {
super(coordinates);
}
@Override
@ -61,8 +61,8 @@ public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
public Shape build() {
//Could wrap JtsGeometry but probably slower due to conversions to/from JTS in relate()
//MultiPoint geometry = FACTORY.createMultiPoint(points.toArray(new Coordinate[points.size()]));
List<Point> shapes = new ArrayList<>(points.size());
for (Coordinate coord : points) {
List<Point> shapes = new ArrayList<>(coordinates.size());
for (Coordinate coord : coordinates) {
shapes.add(SPATIAL_CONTEXT.makePoint(coord.x, coord.y));
}
XShapeCollection<Point> multiPoints = new XShapeCollection<>(shapes, SPATIAL_CONTEXT);
@ -77,7 +77,7 @@ public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
@Override
public int hashCode() {
return Objects.hash(points);
return Objects.hash(coordinates);
}
@Override
@ -89,13 +89,13 @@ public class MultiPointBuilder extends PointCollection<MultiPointBuilder> {
return false;
}
MultiPointBuilder other = (MultiPointBuilder) obj;
return Objects.equals(points, other.points);
return Objects.equals(coordinates, other.coordinates);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(points.size());
for (Coordinate point : points) {
out.writeVInt(coordinates.size());
for (Coordinate point : coordinates) {
writeCoordinateTo(point, out);
}
}

View File

@ -29,7 +29,6 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@ -37,7 +36,7 @@ import java.util.Objects;
public class MultiPolygonBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.MULTIPOLYGON;
public static final MultiPolygonBuilder PROTOTYPE = new MultiPolygonBuilder();
static final MultiPolygonBuilder PROTOTYPE = new MultiPolygonBuilder();
private final ArrayList<PolygonBuilder> polygons = new ArrayList<>();
@ -60,7 +59,7 @@ public class MultiPolygonBuilder extends ShapeBuilder {
* {@link MultiPolygonBuilder} to the polygon if polygon has different orientation.
*/
public MultiPolygonBuilder polygon(PolygonBuilder polygon) {
PolygonBuilder pb = new PolygonBuilder(Arrays.asList(polygon.shell().coordinates(false)), this.orientation);
PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder().coordinates(polygon.shell().coordinates(false)), this.orientation);
for (LineStringBuilder hole : polygon.holes()) {
pb.hole(hole);
}

View File

@ -32,7 +32,7 @@ import java.util.Objects;
public class PointBuilder extends ShapeBuilder {
public static final GeoShapeType TYPE = GeoShapeType.POINT;
public static final PointBuilder PROTOTYPE = new PointBuilder();
static final PointBuilder PROTOTYPE = new PointBuilder();
private Coordinate coordinate;

View File

@ -27,6 +27,7 @@ import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
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;
@ -52,8 +53,8 @@ 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(new PointListBuilder().point(0.0, 0.0).point(0.0, 1.0)
.point(1.0, 0.0).point(0.0, 0.0).list());
static final PolygonBuilder PROTOTYPE = new PolygonBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0).coordinate(0.0, 1.0)
.coordinate(1.0, 0.0).coordinate(0.0, 0.0));
private static final Coordinate[][] EMPTY = new Coordinate[0][];
@ -65,17 +66,25 @@ public class PolygonBuilder extends ShapeBuilder {
// List of line strings defining the holes of the polygon
private final ArrayList<LineStringBuilder> holes = new ArrayList<>();
public PolygonBuilder(List<Coordinate> points, Orientation orientation) {
this(points, orientation, false);
}
public PolygonBuilder(List<Coordinate> points, Orientation orientation, boolean coerce) {
public PolygonBuilder(LineStringBuilder lineString, Orientation orientation, boolean coerce) {
this.orientation = orientation;
this.shell = validateLinearRing(new LineStringBuilder(points), coerce);
if (coerce) {
lineString.close();
}
validateLinearRing(lineString);
this.shell = lineString;
}
public PolygonBuilder(List<Coordinate> points) {
this(points, Orientation.RIGHT);
public PolygonBuilder(LineStringBuilder lineString, Orientation orientation) {
this(lineString, orientation, false);
}
public PolygonBuilder(CoordinatesBuilder coordinates, Orientation orientation) {
this(new LineStringBuilder(coordinates), orientation, false);
}
public PolygonBuilder(CoordinatesBuilder coordinates) {
this(coordinates, Orientation.RIGHT);
}
public Orientation orientation() {
@ -94,11 +103,15 @@ public class PolygonBuilder extends ShapeBuilder {
/**
* Add a new hole to the polygon
* @param hole linear ring defining the hole
* @param coerce if set to true, will close the hole by adding starting point as end point
* @param coerce if set to true, it will try to close the hole by adding starting point as end point
* @return this
*/
public PolygonBuilder hole(LineStringBuilder hole, boolean coerce) {
holes.add(validateLinearRing(hole, coerce));
if (coerce) {
hole.close();
}
validateLinearRing(hole);
holes.add(hole);
return this;
}
@ -124,36 +137,30 @@ public class PolygonBuilder extends ShapeBuilder {
return this;
}
private static LineStringBuilder validateLinearRing(LineStringBuilder linestring, boolean coerce) {
private static void validateLinearRing(LineStringBuilder lineString) {
/**
* Per GeoJSON spec (http://geojson.org/geojson-spec.html#linestring)
* A LinearRing is closed LineString with 4 or more positions. The first and last positions
* are equivalent (they represent equivalent points). Though a LinearRing is not explicitly
* represented as a GeoJSON geometry type, it is referred to in the Polygon geometry type definition.
*/
int numValidPts;
List<Coordinate> points = linestring.points;
if (points.size() < (numValidPts = (coerce) ? 3 : 4)) {
List<Coordinate> points = lineString.coordinates;
if (points.size() < 4) {
throw new IllegalArgumentException(
"invalid number of points in LinearRing (found [" + points.size() + "] - must be >= " + numValidPts + ")");
"invalid number of points in LinearRing (found [" + points.size() + "] - must be >= 4)");
}
if (!points.get(0).equals(points.get(points.size() - 1))) {
if (coerce) {
points.add(points.get(0));
} else {
throw new IllegalArgumentException("invalid LinearRing found (coordinates are not closed)");
}
}
return linestring;
}
/**
* Validates only 1 vertex is tangential (shared) between the interior and exterior of a polygon
*/
protected void validateHole(LineStringBuilder shell, LineStringBuilder hole) {
HashSet<Coordinate> exterior = Sets.newHashSet(shell.points);
HashSet<Coordinate> interior = Sets.newHashSet(hole.points);
HashSet<Coordinate> exterior = Sets.newHashSet(shell.coordinates);
HashSet<Coordinate> interior = Sets.newHashSet(hole.coordinates);
exterior.retainAll(interior);
if (exterior.size() >= 2) {
throw new InvalidShapeException("Invalid polygon, interior cannot share more than one point with the exterior");
@ -171,9 +178,9 @@ public class PolygonBuilder extends ShapeBuilder {
* @return coordinates of the polygon
*/
public Coordinate[][][] coordinates() {
int numEdges = shell.points.size()-1; // Last point is repeated
int numEdges = shell.coordinates.size()-1; // Last point is repeated
for (int i = 0; i < holes.size(); i++) {
numEdges += holes.get(i).points.size()-1;
numEdges += holes.get(i).coordinates.size()-1;
validateHole(shell, this.holes.get(i));
}
@ -236,11 +243,11 @@ public class PolygonBuilder extends ShapeBuilder {
}
protected Polygon toPolygon(GeometryFactory factory) {
final LinearRing shell = linearRing(factory, this.shell.points);
final LinearRing shell = linearRing(factory, this.shell.coordinates);
final LinearRing[] holes = new LinearRing[this.holes.size()];
Iterator<LineStringBuilder> iterator = this.holes.iterator();
for (int i = 0; iterator.hasNext(); i++) {
holes[i] = linearRing(factory, iterator.next().points);
holes[i] = linearRing(factory, iterator.next().coordinates);
}
return factory.createPolygon(shell, holes);
}
@ -731,9 +738,9 @@ public class PolygonBuilder extends ShapeBuilder {
@Override
public PolygonBuilder readFrom(StreamInput in) throws IOException {
LineStringBuilder shell = LineStringBuilder.PROTOTYPE.readFrom(in);
LineStringBuilder shell = LineStringBuilder.PROTOTYPE.readFrom(in);
Orientation orientation = Orientation.readFrom(in);
PolygonBuilder polyBuilder = new PolygonBuilder(shell.points, orientation);
PolygonBuilder polyBuilder = new PolygonBuilder(shell, orientation);
int holes = in.readVInt();
for (int i = 0; i < holes; i++) {
polyBuilder.hole(LineStringBuilder.PROTOTYPE.readFrom(in));

View File

@ -26,6 +26,7 @@ import com.spatial4j.core.shape.jts.JtsGeometry;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.support.ToXContentToBytes;
import org.elasticsearch.common.io.stream.NamedWriteable;
@ -86,11 +87,6 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
protected final boolean autoIndexJtsGeometry = true;//may want to turn off once SpatialStrategy impls do it.
protected ShapeBuilder() {
}
protected static Coordinate coordinate(double longitude, double latitude) {
return new Coordinate(longitude, latitude);
}
protected JtsGeometry jtsGeometry(Geometry geom) {
@ -594,11 +590,11 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
protected static MultiPointBuilder parseMultiPoint(CoordinateNode coordinates) {
validateMultiPointNode(coordinates);
PointListBuilder points = new PointListBuilder();
CoordinatesBuilder points = new CoordinatesBuilder();
for (CoordinateNode node : coordinates.children) {
points.point(node.coordinate);
points.coordinate(node.coordinate);
}
return new MultiPointBuilder(points.list());
return new MultiPointBuilder(points.build());
}
protected static LineStringBuilder parseLineString(CoordinateNode coordinates) {
@ -611,11 +607,11 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
throw new ElasticsearchParseException("invalid number of points in LineString (found [{}] - must be >= 2)", coordinates.children.size());
}
PointListBuilder line = new PointListBuilder();
CoordinatesBuilder line = new CoordinatesBuilder();
for (CoordinateNode node : coordinates.children) {
line.point(node.coordinate);
line.coordinate(node.coordinate);
}
return ShapeBuilders.newLineString(line.list());
return ShapeBuilders.newLineString(line);
}
protected static MultiLineStringBuilder parseMultiLine(CoordinateNode coordinates) {
@ -663,7 +659,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes implements NamedWri
}
LineStringBuilder shell = parseLinearRing(coordinates.children.get(0), coerce);
PolygonBuilder polygon = new PolygonBuilder(shell.points, orientation);
PolygonBuilder polygon = new PolygonBuilder(shell, orientation);
for (int i = 1; i < coordinates.children.size(); i++) {
polygon.hole(parseLinearRing(coordinates.children.get(i), coerce));
}

View File

@ -64,6 +64,14 @@ public class ShapeBuilders {
return new LineStringBuilder(list);
}
/**
* Create a new lineString
* @return a new {@link LineStringBuilder}
*/
public static LineStringBuilder newLineString(CoordinatesBuilder coordinates) {
return new LineStringBuilder(coordinates);
}
/**
* Create a new Collection of lineStrings
* @return a new {@link MultiLineStringBuilder}
@ -73,10 +81,18 @@ public class ShapeBuilders {
}
/**
* Create a new Polygon
* @return a new {@link PointBuilder}
* Create a new PolygonBuilder
* @return a new {@link PolygonBuilder}
*/
public static PolygonBuilder newPolygon(List<Coordinate> shell) {
return new PolygonBuilder(new CoordinatesBuilder().coordinates(shell));
}
/**
* Create a new PolygonBuilder
* @return a new {@link PolygonBuilder}
*/
public static PolygonBuilder newPolygon(CoordinatesBuilder shell) {
return new PolygonBuilder(shell);
}

View File

@ -28,8 +28,9 @@ import com.spatial4j.core.shape.impl.PointImpl;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Polygon;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder;
import org.elasticsearch.common.geo.builders.PointListBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
@ -59,12 +60,12 @@ public class ShapeBuilderTests extends ESTestCase {
}
public void testNewPolygon() {
Polygon polygon = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-45, 30)
.point(45, 30)
.point(45, -30)
.point(-45, -30)
.point(-45, 30).list()).toPolygon();
Polygon polygon = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-45, 30)
.coordinate(45, 30)
.coordinate(45, -30)
.coordinate(-45, -30)
.coordinate(-45, 30)).toPolygon();
LineString exterior = polygon.getExteriorRing();
assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30));
@ -74,12 +75,12 @@ public class ShapeBuilderTests extends ESTestCase {
}
public void testNewPolygon_coordinate() {
Polygon polygon = ShapeBuilders.newPolygon(new PointListBuilder()
.point(new Coordinate(-45, 30))
.point(new Coordinate(45, 30))
.point(new Coordinate(45, -30))
.point(new Coordinate(-45, -30))
.point(new Coordinate(-45, 30)).list()).toPolygon();
Polygon polygon = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(new Coordinate(-45, 30))
.coordinate(new Coordinate(45, 30))
.coordinate(new Coordinate(45, -30))
.coordinate(new Coordinate(-45, -30))
.coordinate(new Coordinate(-45, 30))).toPolygon();
LineString exterior = polygon.getExteriorRing();
assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30));
@ -89,9 +90,9 @@ public class ShapeBuilderTests extends ESTestCase {
}
public void testNewPolygon_coordinates() {
Polygon polygon = ShapeBuilders.newPolygon(new PointListBuilder()
.points(new Coordinate(-45, 30), new Coordinate(45, 30), new Coordinate(45, -30), new Coordinate(-45, -30), new Coordinate(-45, 30))
.list()).toPolygon();
Polygon polygon = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinates(new Coordinate(-45, 30), new Coordinate(45, 30), new Coordinate(45, -30), new Coordinate(-45, -30), new Coordinate(-45, 30))
).toPolygon();
LineString exterior = polygon.getExteriorRing();
assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30));
@ -102,92 +103,92 @@ public class ShapeBuilderTests extends ESTestCase {
public void testLineStringBuilder() {
// Building a simple LineString
ShapeBuilders.newLineString(new PointListBuilder()
.point(-130.0, 55.0)
.point(-130.0, -40.0)
.point(-15.0, -40.0)
.point(-20.0, 50.0)
.point(-45.0, 50.0)
.point(-45.0, -15.0)
.point(-110.0, -15.0)
.point(-110.0, 55.0).list()).build();
ShapeBuilders.newLineString(new CoordinatesBuilder()
.coordinate(-130.0, 55.0)
.coordinate(-130.0, -40.0)
.coordinate(-15.0, -40.0)
.coordinate(-20.0, 50.0)
.coordinate(-45.0, 50.0)
.coordinate(-45.0, -15.0)
.coordinate(-110.0, -15.0)
.coordinate(-110.0, 55.0)).build();
// Building a linestring that needs to be wrapped
ShapeBuilders.newLineString(new PointListBuilder()
.point(100.0, 50.0)
.point(110.0, -40.0)
.point(240.0, -40.0)
.point(230.0, 60.0)
.point(200.0, 60.0)
.point(200.0, -30.0)
.point(130.0, -30.0)
.point(130.0, 60.0)
.list())
ShapeBuilders.newLineString(new CoordinatesBuilder()
.coordinate(100.0, 50.0)
.coordinate(110.0, -40.0)
.coordinate(240.0, -40.0)
.coordinate(230.0, 60.0)
.coordinate(200.0, 60.0)
.coordinate(200.0, -30.0)
.coordinate(130.0, -30.0)
.coordinate(130.0, 60.0)
)
.build();
// Building a lineString on the dateline
ShapeBuilders.newLineString(new PointListBuilder()
.point(-180.0, 80.0)
.point(-180.0, 40.0)
.point(-180.0, -40.0)
.point(-180.0, -80.0)
.list())
ShapeBuilders.newLineString(new CoordinatesBuilder()
.coordinate(-180.0, 80.0)
.coordinate(-180.0, 40.0)
.coordinate(-180.0, -40.0)
.coordinate(-180.0, -80.0)
)
.build();
// Building a lineString on the dateline
ShapeBuilders.newLineString(new PointListBuilder()
.point(180.0, 80.0)
.point(180.0, 40.0)
.point(180.0, -40.0)
.point(180.0, -80.0)
.list())
ShapeBuilders.newLineString(new CoordinatesBuilder()
.coordinate(180.0, 80.0)
.coordinate(180.0, 40.0)
.coordinate(180.0, -40.0)
.coordinate(180.0, -80.0)
)
.build();
}
public void testMultiLineString() {
ShapeBuilders.newMultiLinestring()
.linestring(new LineStringBuilder(new PointListBuilder()
.point(-100.0, 50.0)
.point(50.0, 50.0)
.point(50.0, 20.0)
.point(-100.0, 20.0)
.list())
.linestring(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-100.0, 50.0)
.coordinate(50.0, 50.0)
.coordinate(50.0, 20.0)
.coordinate(-100.0, 20.0)
)
)
.linestring(new LineStringBuilder(new PointListBuilder()
.point(-100.0, 20.0)
.point(50.0, 20.0)
.point(50.0, 0.0)
.point(-100.0, 0.0)
.list())
.linestring(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-100.0, 20.0)
.coordinate(50.0, 20.0)
.coordinate(50.0, 0.0)
.coordinate(-100.0, 0.0)
)
)
.build();
// LineString that needs to be wrappped
ShapeBuilders.newMultiLinestring()
.linestring(new LineStringBuilder(new PointListBuilder()
.point(150.0, 60.0)
.point(200.0, 60.0)
.point(200.0, 40.0)
.point(150.0, 40.0)
.list())
.linestring(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(150.0, 60.0)
.coordinate(200.0, 60.0)
.coordinate(200.0, 40.0)
.coordinate(150.0, 40.0)
)
)
.linestring(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(150.0, 20.0)
.coordinate(200.0, 20.0)
.coordinate(200.0, 0.0)
.coordinate(150.0, 0.0)
)
.linestring(new LineStringBuilder(new PointListBuilder()
.point(150.0, 20.0)
.point(200.0, 20.0)
.point(200.0, 0.0)
.point(150.0, 0.0)
.list())
)
.build();
}
public void testPolygonSelfIntersection() {
try {
ShapeBuilders.newPolygon(new PointListBuilder()
.point(-40.0, 50.0)
.point(40.0, 50.0)
.point(-40.0, -50.0)
.point(40.0, -50.0).close().list())
ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-40.0, 50.0)
.coordinate(40.0, 50.0)
.coordinate(-40.0, -50.0)
.coordinate(40.0, -50.0).close())
.build();
fail("Expected InvalidShapeException");
} catch (InvalidShapeException e) {
@ -221,26 +222,26 @@ public class ShapeBuilderTests extends ESTestCase {
}
public void testPolygonWrapping() {
Shape shape = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-150.0, 65.0)
.point(-250.0, 65.0)
.point(-250.0, -65.0)
.point(-150.0, -65.0)
Shape shape = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-150.0, 65.0)
.coordinate(-250.0, 65.0)
.coordinate(-250.0, -65.0)
.coordinate(-150.0, -65.0)
.close()
.list())
)
.build();
assertMultiPolygon(shape);
}
public void testLineStringWrapping() {
Shape shape = ShapeBuilders.newLineString(new PointListBuilder()
.point(-150.0, 65.0)
.point(-250.0, 65.0)
.point(-250.0, -65.0)
.point(-150.0, -65.0)
Shape shape = ShapeBuilders.newLineString(new CoordinatesBuilder()
.coordinate(-150.0, 65.0)
.coordinate(-250.0, 65.0)
.coordinate(-250.0, -65.0)
.coordinate(-150.0, -65.0)
.close()
.list())
)
.build();
assertMultiLineString(shape);
}
@ -251,39 +252,39 @@ public class ShapeBuilderTests extends ESTestCase {
// expected results: 3 polygons, 1 with a hole
// a giant c shape
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(174,0)
.point(-176,0)
.point(-176,3)
.point(177,3)
.point(177,5)
.point(-176,5)
.point(-176,8)
.point(174,8)
.point(174,0)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(174,0)
.coordinate(-176,0)
.coordinate(-176,3)
.coordinate(177,3)
.coordinate(177,5)
.coordinate(-176,5)
.coordinate(-176,8)
.coordinate(174,8)
.coordinate(174,0)
);
// 3/4 of an embedded 'c', crossing dateline once
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(175, 1)
.point(175, 7)
.point(-178, 7)
.point(-178, 6)
.point(176, 6)
.point(176, 2)
.point(179, 2)
.point(179,1)
.point(175, 1)
.list()));
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(175, 1)
.coordinate(175, 7)
.coordinate(-178, 7)
.coordinate(-178, 6)
.coordinate(176, 6)
.coordinate(176, 2)
.coordinate(179, 2)
.coordinate(179,1)
.coordinate(175, 1)
));
// embedded hole right of the dateline
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(-179, 1)
.point(-179, 2)
.point(-177, 2)
.point(-177,1)
.point(-179,1)
.list()));
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-179, 1)
.coordinate(-179, 2)
.coordinate(-177, 2)
.coordinate(-177,1)
.coordinate(-179,1)
));
Shape shape = builder.close().build();
assertMultiPolygon(shape);
@ -295,114 +296,114 @@ public class ShapeBuilderTests extends ESTestCase {
// expected results: 3 polygons, 1 with a hole
// a giant c shape
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-186,0)
.point(-176,0)
.point(-176,3)
.point(-183,3)
.point(-183,5)
.point(-176,5)
.point(-176,8)
.point(-186,8)
.point(-186,0)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-186,0)
.coordinate(-176,0)
.coordinate(-176,3)
.coordinate(-183,3)
.coordinate(-183,5)
.coordinate(-176,5)
.coordinate(-176,8)
.coordinate(-186,8)
.coordinate(-186,0)
);
// 3/4 of an embedded 'c', crossing dateline once
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(-185,1)
.point(-181,1)
.point(-181,2)
.point(-184,2)
.point(-184,6)
.point(-178,6)
.point(-178,7)
.point(-185,7)
.point(-185,1)
.list()));
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-185,1)
.coordinate(-181,1)
.coordinate(-181,2)
.coordinate(-184,2)
.coordinate(-184,6)
.coordinate(-178,6)
.coordinate(-178,7)
.coordinate(-185,7)
.coordinate(-185,1)
));
// embedded hole right of the dateline
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(-179,1)
.point(-177,1)
.point(-177,2)
.point(-179,2)
.point(-179,1)
.list()));
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-179,1)
.coordinate(-177,1)
.coordinate(-177,2)
.coordinate(-179,2)
.coordinate(-179,1)
));
Shape shape = builder.close().build();
assertMultiPolygon(shape);
}
public void testComplexShapeWithHole() {
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-85.0018514,37.1311314)
.point(-85.0016645,37.1315293)
.point(-85.0016246,37.1317069)
.point(-85.0016526,37.1318183)
.point(-85.0017119,37.1319196)
.point(-85.0019371,37.1321182)
.point(-85.0019972,37.1322115)
.point(-85.0019942,37.1323234)
.point(-85.0019543,37.1324336)
.point(-85.001906,37.1324985)
.point(-85.001834,37.1325497)
.point(-85.0016965,37.1325907)
.point(-85.0016011,37.1325873)
.point(-85.0014816,37.1325353)
.point(-85.0011755,37.1323509)
.point(-85.000955,37.1322802)
.point(-85.0006241,37.1322529)
.point(-85.0000002,37.1322307)
.point(-84.9994,37.1323001)
.point(-84.999109,37.1322864)
.point(-84.998934,37.1322415)
.point(-84.9988639,37.1321888)
.point(-84.9987841,37.1320944)
.point(-84.9987208,37.131954)
.point(-84.998736,37.1316611)
.point(-84.9988091,37.131334)
.point(-84.9989283,37.1311337)
.point(-84.9991943,37.1309198)
.point(-84.9993573,37.1308459)
.point(-84.9995888,37.1307924)
.point(-84.9998746,37.130806)
.point(-85.0000002,37.1308358)
.point(-85.0004984,37.1310658)
.point(-85.0008008,37.1311625)
.point(-85.0009461,37.1311684)
.point(-85.0011373,37.1311515)
.point(-85.0016455,37.1310491)
.point(-85.0018514,37.1311314)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-85.0018514,37.1311314)
.coordinate(-85.0016645,37.1315293)
.coordinate(-85.0016246,37.1317069)
.coordinate(-85.0016526,37.1318183)
.coordinate(-85.0017119,37.1319196)
.coordinate(-85.0019371,37.1321182)
.coordinate(-85.0019972,37.1322115)
.coordinate(-85.0019942,37.1323234)
.coordinate(-85.0019543,37.1324336)
.coordinate(-85.001906,37.1324985)
.coordinate(-85.001834,37.1325497)
.coordinate(-85.0016965,37.1325907)
.coordinate(-85.0016011,37.1325873)
.coordinate(-85.0014816,37.1325353)
.coordinate(-85.0011755,37.1323509)
.coordinate(-85.000955,37.1322802)
.coordinate(-85.0006241,37.1322529)
.coordinate(-85.0000002,37.1322307)
.coordinate(-84.9994,37.1323001)
.coordinate(-84.999109,37.1322864)
.coordinate(-84.998934,37.1322415)
.coordinate(-84.9988639,37.1321888)
.coordinate(-84.9987841,37.1320944)
.coordinate(-84.9987208,37.131954)
.coordinate(-84.998736,37.1316611)
.coordinate(-84.9988091,37.131334)
.coordinate(-84.9989283,37.1311337)
.coordinate(-84.9991943,37.1309198)
.coordinate(-84.9993573,37.1308459)
.coordinate(-84.9995888,37.1307924)
.coordinate(-84.9998746,37.130806)
.coordinate(-85.0000002,37.1308358)
.coordinate(-85.0004984,37.1310658)
.coordinate(-85.0008008,37.1311625)
.coordinate(-85.0009461,37.1311684)
.coordinate(-85.0011373,37.1311515)
.coordinate(-85.0016455,37.1310491)
.coordinate(-85.0018514,37.1311314)
);
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(-85.0000002,37.1317672)
.point(-85.0001983,37.1317538)
.point(-85.0003378,37.1317582)
.point(-85.0004697,37.131792)
.point(-85.0008048,37.1319439)
.point(-85.0009342,37.1319838)
.point(-85.0010184,37.1319463)
.point(-85.0010618,37.13184)
.point(-85.0010057,37.1315102)
.point(-85.000977,37.1314403)
.point(-85.0009182,37.1313793)
.point(-85.0005366,37.1312209)
.point(-85.000224,37.1311466)
.point(-85.000087,37.1311356)
.point(-85.0000002,37.1311433)
.point(-84.9995021,37.1312336)
.point(-84.9993308,37.1312859)
.point(-84.9992567,37.1313252)
.point(-84.9991868,37.1314277)
.point(-84.9991593,37.1315381)
.point(-84.9991841,37.1316527)
.point(-84.9992329,37.1317117)
.point(-84.9993527,37.1317788)
.point(-84.9994931,37.1318061)
.point(-84.9996815,37.1317979)
.point(-85.0000002,37.1317672)
.list())
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-85.0000002,37.1317672)
.coordinate(-85.0001983,37.1317538)
.coordinate(-85.0003378,37.1317582)
.coordinate(-85.0004697,37.131792)
.coordinate(-85.0008048,37.1319439)
.coordinate(-85.0009342,37.1319838)
.coordinate(-85.0010184,37.1319463)
.coordinate(-85.0010618,37.13184)
.coordinate(-85.0010057,37.1315102)
.coordinate(-85.000977,37.1314403)
.coordinate(-85.0009182,37.1313793)
.coordinate(-85.0005366,37.1312209)
.coordinate(-85.000224,37.1311466)
.coordinate(-85.000087,37.1311356)
.coordinate(-85.0000002,37.1311433)
.coordinate(-84.9995021,37.1312336)
.coordinate(-84.9993308,37.1312859)
.coordinate(-84.9992567,37.1313252)
.coordinate(-84.9991868,37.1314277)
.coordinate(-84.9991593,37.1315381)
.coordinate(-84.9991841,37.1316527)
.coordinate(-84.9992329,37.1317117)
.coordinate(-84.9993527,37.1317788)
.coordinate(-84.9994931,37.1318061)
.coordinate(-84.9996815,37.1317979)
.coordinate(-85.0000002,37.1317672)
)
);
Shape shape = builder.close().build();
@ -410,35 +411,35 @@ public class ShapeBuilderTests extends ESTestCase {
}
public void testShapeWithHoleAtEdgeEndPoints() {
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-4, 2)
.point(4, 2)
.point(6, 0)
.point(4, -2)
.point(-4, -2)
.point(-6, 0)
.point(-4, 2)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-4, 2)
.coordinate(4, 2)
.coordinate(6, 0)
.coordinate(4, -2)
.coordinate(-4, -2)
.coordinate(-6, 0)
.coordinate(-4, 2)
);
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(4, 1)
.point(4, -1)
.point(-4, -1)
.point(-4, 1)
.point(4, 1)
.list()));
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(4, 1)
.coordinate(4, -1)
.coordinate(-4, -1)
.coordinate(-4, 1)
.coordinate(4, 1)
));
Shape shape = builder.close().build();
assertPolygon(shape);
}
public void testShapeWithPointOnDateline() {
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(180, 0)
.point(176, 4)
.point(176, -4)
.point(180, 0)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(180, 0)
.coordinate(176, 4)
.coordinate(176, -4)
.coordinate(180, 0)
);
Shape shape = builder.close().build();
assertPolygon(shape);
@ -446,23 +447,23 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithEdgeAlongDateline() {
// test case 1: test the positive side of the dateline
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(180, 0)
.point(176, 4)
.point(180, -4)
.point(180, 0)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(180, 0)
.coordinate(176, 4)
.coordinate(180, -4)
.coordinate(180, 0)
);
Shape shape = builder.close().build();
assertPolygon(shape);
// test case 2: test the negative side of the dateline
builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-176, 4)
.point(-180, 0)
.point(-180, -4)
.point(-176, 4)
.list());
builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-176, 4)
.coordinate(-180, 0)
.coordinate(-180, -4)
.coordinate(-176, 4)
);
shape = builder.close().build();
assertPolygon(shape);
@ -470,85 +471,85 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithBoundaryHoles() {
// test case 1: test the positive side of the dateline
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-177, 10)
.point(176, 15)
.point(172, 0)
.point(176, -15)
.point(-177, -10)
.point(-177, 10)
.list());
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(176, 10)
.point(180, 5)
.point(180, -5)
.point(176, -10)
.point(176, 10)
.list()));
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-177, 10)
.coordinate(176, 15)
.coordinate(172, 0)
.coordinate(176, -15)
.coordinate(-177, -10)
.coordinate(-177, 10)
);
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(176, 10)
.coordinate(180, 5)
.coordinate(180, -5)
.coordinate(176, -10)
.coordinate(176, 10)
));
Shape shape = builder.close().build();
assertMultiPolygon(shape);
// test case 2: test the negative side of the dateline
builder = ShapeBuilders.newPolygon(
new PointListBuilder()
.point(-176, 15)
.point(179, 10)
.point(179, -10)
.point(-176, -15)
.point(-172, 0)
new CoordinatesBuilder()
.coordinate(-176, 15)
.coordinate(179, 10)
.coordinate(179, -10)
.coordinate(-176, -15)
.coordinate(-172, 0)
.close()
.list());
);
builder.hole(new LineStringBuilder(
new PointListBuilder()
.point(-176, 10)
.point(-176, -10)
.point(-180, -5)
.point(-180, 5)
.point(-176, 10)
new CoordinatesBuilder()
.coordinate(-176, 10)
.coordinate(-176, -10)
.coordinate(-180, -5)
.coordinate(-180, 5)
.coordinate(-176, 10)
.close()
.list()));
));
shape = builder.close().build();
assertMultiPolygon(shape);
}
public void testShapeWithTangentialHole() {
// test a shape with one tangential (shared) vertex (should pass)
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(179, 10)
.point(168, 15)
.point(164, 0)
.point(166, -15)
.point(179, -10)
.point(179, 10)
.list());
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(-177, 10)
.point(-178, -10)
.point(-180, -5)
.point(-180, 5)
.point(-177, 10)
.list()));
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(179, 10)
.coordinate(168, 15)
.coordinate(164, 0)
.coordinate(166, -15)
.coordinate(179, -10)
.coordinate(179, 10)
);
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-177, 10)
.coordinate(-178, -10)
.coordinate(-180, -5)
.coordinate(-180, 5)
.coordinate(-177, 10)
));
Shape shape = builder.close().build();
assertMultiPolygon(shape);
}
public void testShapeWithInvalidTangentialHole() {
// test a shape with one invalid tangential (shared) vertex (should throw exception)
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(179, 10)
.point(168, 15)
.point(164, 0)
.point(166, -15)
.point(179, -10)
.point(179, 10)
.list());
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(164, 0)
.point(175, 10)
.point(175, 5)
.point(179, -10)
.point(164, 0)
.list()));
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(179, 10)
.coordinate(168, 15)
.coordinate(164, 0)
.coordinate(166, -15)
.coordinate(179, -10)
.coordinate(179, 10)
);
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(164, 0)
.coordinate(175, 10)
.coordinate(175, 5)
.coordinate(179, -10)
.coordinate(164, 0)
));
try {
builder.close().build();
fail("Expected InvalidShapeException");
@ -559,48 +560,48 @@ public class ShapeBuilderTests extends ESTestCase {
public void testBoundaryShapeWithTangentialHole() {
// test a shape with one tangential (shared) vertex for each hole (should pass)
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-177, 10)
.point(176, 15)
.point(172, 0)
.point(176, -15)
.point(-177, -10)
.point(-177, 10)
.list());
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(-177, 10)
.point(-178, -10)
.point(-180, -5)
.point(-180, 5)
.point(-177, 10)
.list()));
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(172, 0)
.point(176, 10)
.point(176, -5)
.point(172, 0)
.list()));
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-177, 10)
.coordinate(176, 15)
.coordinate(172, 0)
.coordinate(176, -15)
.coordinate(-177, -10)
.coordinate(-177, 10)
);
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-177, 10)
.coordinate(-178, -10)
.coordinate(-180, -5)
.coordinate(-180, 5)
.coordinate(-177, 10)
));
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(172, 0)
.coordinate(176, 10)
.coordinate(176, -5)
.coordinate(172, 0)
));
Shape shape = builder.close().build();
assertMultiPolygon(shape);
}
public void testBoundaryShapeWithInvalidTangentialHole() {
// test shape with two tangential (shared) vertices (should throw exception)
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-177, 10)
.point(176, 15)
.point(172, 0)
.point(176, -15)
.point(-177, -10)
.point(-177, 10)
.list());
builder.hole(new LineStringBuilder(new PointListBuilder()
.point(-177, 10)
.point(172, 0)
.point(180, -5)
.point(176, -10)
.point(-177, 10)
.list()));
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-177, 10)
.coordinate(176, 15)
.coordinate(172, 0)
.coordinate(176, -15)
.coordinate(-177, -10)
.coordinate(-177, 10)
);
builder.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-177, 10)
.coordinate(172, 0)
.coordinate(180, -5)
.coordinate(176, -10)
.coordinate(-177, 10)
));
try {
builder.close().build();
fail("Expected InvalidShapeException");
@ -613,12 +614,12 @@ public class ShapeBuilderTests extends ESTestCase {
* Test an enveloping polygon around the max mercator bounds
*/
public void testBoundaryShape() {
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-180, 90)
.point(180, 90)
.point(180, -90)
.point(-180, 90)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-180, 90)
.coordinate(180, 90)
.coordinate(180, -90)
.coordinate(-180, 90)
);
Shape shape = builder.close().build();
@ -627,23 +628,23 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithAlternateOrientation() {
// cw: should produce a multi polygon spanning hemispheres
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(180, 0)
.point(176, 4)
.point(-176, 4)
.point(180, 0)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(180, 0)
.coordinate(176, 4)
.coordinate(-176, 4)
.coordinate(180, 0)
);
Shape shape = builder.close().build();
assertPolygon(shape);
// cw: geo core will convert to ccw across the dateline
builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(180, 0)
.point(-176, 4)
.point(176, 4)
.point(180, 0)
.list());
builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(180, 0)
.coordinate(-176, 4)
.coordinate(176, 4)
.coordinate(180, 0)
);
shape = builder.close().build();
@ -651,13 +652,13 @@ public class ShapeBuilderTests extends ESTestCase {
}
public void testInvalidShapeWithConsecutiveDuplicatePoints() {
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(180, 0)
.point(176, 4)
.point(176, 4)
.point(-176, 4)
.point(180, 0)
.list());
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(180, 0)
.coordinate(176, 4)
.coordinate(176, 4)
.coordinate(-176, 4)
.coordinate(180, 0)
);
try {
builder.close().build();
fail("Expected InvalidShapeException");

View File

@ -20,10 +20,12 @@
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;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
@ -31,21 +33,21 @@ public class LineStringBuilderTests extends AbstractShapeBuilderTestCase<LineStr
public void testInvalidConstructorArgs() {
try {
new LineStringBuilder(null);
new LineStringBuilder((List<Coordinate>) null);
fail("Exception expected");
} catch (IllegalArgumentException e) {
assertThat("cannot create point collection with empty set of points", equalTo(e.getMessage()));
}
try {
new LineStringBuilder(new PointListBuilder().list());
new LineStringBuilder(new CoordinatesBuilder());
fail("Exception expected");
} catch (IllegalArgumentException e) {
assertThat("cannot create point collection with empty set of points", equalTo(e.getMessage()));
}
try {
new LineStringBuilder(new PointListBuilder().point(0.0, 0.0).list());
new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0));
fail("Exception expected");
} catch (IllegalArgumentException e) {
assertThat("invalid number of points in LineString (found [1] - must be >= 2)", equalTo(e.getMessage()));
@ -79,7 +81,7 @@ public class LineStringBuilderTests extends AbstractShapeBuilderTestCase<LineStr
coordinate.y = randomDoubleBetween(-90.0, 90.0, true);
}
}
return mutation.points(coordinates);
return mutation.coordinates(coordinates);
}
static LineStringBuilder createRandomShape() {

View File

@ -38,14 +38,14 @@ public class MultiPointBuilderTests extends AbstractShapeBuilderTestCase<MultiPo
}
try {
new MultiPointBuilder(new PointListBuilder().list());
new MultiPointBuilder(new CoordinatesBuilder().build());
fail("IllegalArgumentException expected");
} catch (IllegalArgumentException e) {
assertThat("cannot create point collection with empty set of points", equalTo(e.getMessage()));
}
// one point is minimum
new MultiPointBuilder(new PointListBuilder().point(0.0, 0.0).list());
new MultiPointBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0).build());
}
@Override
@ -79,7 +79,7 @@ public class MultiPointBuilderTests extends AbstractShapeBuilderTestCase<MultiPo
} else {
coordinates = new Coordinate[]{new Coordinate(1.0, 1.0)};
}
return mutation.points(coordinates);
return mutation.coordinates(coordinates);
}
static MultiPointBuilder createRandomShape() {

View File

@ -20,12 +20,15 @@
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;
import static org.hamcrest.Matchers.equalTo;
public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBuilder> {
@Override
@ -77,7 +80,7 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
* 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.shell().points, pb.orientation() == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
PolygonBuilder mutation = new PolygonBuilder(pb.shell(), pb.orientation() == Orientation.LEFT ? Orientation.RIGHT : Orientation.LEFT);
for (LineStringBuilder hole : pb.holes()) {
mutation.hole(hole);
}
@ -91,4 +94,33 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase<PolygonBui
}
return pgb;
}
public void testCoerceShell() {
try{
new PolygonBuilder(new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0)
.coordinate(1.0, 0.0).coordinate(1.0, 1.0).build()), Orientation.RIGHT);
fail("should raise validation exception");
} catch (IllegalArgumentException e) {
assertEquals("invalid number of points in LinearRing (found [3] - must be >= 4)", e.getMessage());
}
PolygonBuilder pb = new PolygonBuilder(new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0)
.coordinate(1.0, 0.0).coordinate(1.0, 1.0).build()), Orientation.RIGHT, true);
assertThat("Shell should have been closed via coerce", pb.shell().coordinates(false).length, equalTo(4));
}
public void testCoerceHole() {
PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder().coordinate(0.0, 0.0)
.coordinate(2.0, 0.0).coordinate(2.0, 2.0).coordinate(0.0, 0.0));
try{
pb.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0,0.0).coordinate(1.0,0.0).coordinate(1.0,1.0).build()));
fail("should raise validation exception");
} catch (IllegalArgumentException e) {
assertEquals("invalid number of points in LinearRing (found [3] - must be >= 4)", e.getMessage());
}
pb.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(0.0,0.0).coordinate(1.0,0.0).coordinate(1.0,1.0).build()), true);
assertThat("hole should have been closed via coerce", pb.holes().get(0).coordinates(false).length, equalTo(4));
}
}

View File

@ -23,7 +23,7 @@ import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.PointListBuilder;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder.Item;
@ -176,13 +176,13 @@ public class QueryDSLDocumentationTests extends ESTestCase {
GeoShapeQueryBuilder qb = geoShapeQuery(
"pin.location",
ShapeBuilders.newMultiPoint(
new PointListBuilder()
.point(0, 0)
.point(0, 10)
.point(10, 10)
.point(10, 0)
.point(0, 0)
.list()));
new CoordinatesBuilder()
.coordinate(0, 0)
.coordinate(0, 10)
.coordinate(10, 10)
.coordinate(10, 0)
.coordinate(0, 0)
.build()));
qb.relation(ShapeRelation.WITHIN);
qb = geoShapeQuery(

View File

@ -23,6 +23,7 @@ import com.spatial4j.core.context.SpatialContext;
import com.spatial4j.core.distance.DistanceUtils;
import com.spatial4j.core.exception.InvalidShapeException;
import com.spatial4j.core.shape.Shape;
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs;
@ -40,9 +41,9 @@ import org.elasticsearch.common.Priority;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder;
import org.elasticsearch.common.geo.builders.MultiPolygonBuilder;
import org.elasticsearch.common.geo.builders.PointListBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.io.Streams;
@ -120,29 +121,28 @@ public class GeoFilterIT extends ESIntegTestCase {
public void testShapeBuilders() {
try {
// self intersection polygon
ShapeBuilders.newPolygon(new PointListBuilder()
.point(-10, -10)
.point(10, 10)
.point(-10, 10)
.point(10, -10)
.close()
.list())
ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-10, -10)
.coordinate(10, 10)
.coordinate(-10, 10)
.coordinate(10, -10)
.close())
.build();
fail("Self intersection not detected");
} catch (InvalidShapeException e) {
}
// polygon with hole
ShapeBuilders.newPolygon(new PointListBuilder()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10).close().list())
.hole(new LineStringBuilder(new PointListBuilder().point(-5, -5).point(-5, 5).point(5, 5).point(5, -5).close().list()))
ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close()))
.build();
try {
// polygon with overlapping hole
ShapeBuilders.newPolygon(new PointListBuilder()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10).close().list())
.hole(new LineStringBuilder(new PointListBuilder()
.point(-5, -5).point(-5, 11).point(5, 11).point(5, -5).close().list()))
ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-5, -5).coordinate(-5, 11).coordinate(5, 11).coordinate(5, -5).close()))
.build();
fail("Self intersection not detected");
@ -151,10 +151,10 @@ public class GeoFilterIT extends ESIntegTestCase {
try {
// polygon with intersection holes
ShapeBuilders.newPolygon(new PointListBuilder()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10).close().list())
.hole(new LineStringBuilder(new PointListBuilder().point(-5, -5).point(-5, 5).point(5, 5).point(5, -5).close().list()))
.hole(new LineStringBuilder(new PointListBuilder().point(-5, -6).point(5, -6).point(5, -4).point(-5, -4).close().list()))
ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close()))
.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -6).coordinate(5, -6).coordinate(5, -4).coordinate(-5, -4).close()))
.build();
fail("Intersection of holes not detected");
} catch (InvalidShapeException e) {
@ -162,16 +162,15 @@ public class GeoFilterIT extends ESIntegTestCase {
try {
// Common line in polygon
ShapeBuilders.newPolygon(new PointListBuilder()
.point(-10, -10)
.point(-10, 10)
.point(-5, 10)
.point(-5, -5)
.point(-5, 20)
.point(10, 20)
.point(10, -10)
.close()
.list())
ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-10, -10)
.coordinate(-10, 10)
.coordinate(-5, 10)
.coordinate(-5, -5)
.coordinate(-5, 20)
.coordinate(10, 20)
.coordinate(10, -10)
.close())
.build();
fail("Self intersection not detected");
} catch (InvalidShapeException e) {
@ -181,21 +180,21 @@ public class GeoFilterIT extends ESIntegTestCase {
ShapeBuilders
.newMultiPolygon()
.polygon(new PolygonBuilder(
new PointListBuilder().point(-10, -10)
.point(-10, 10)
.point(10, 10)
.point(10, -10).close().list())
new CoordinatesBuilder().coordinate(-10, -10)
.coordinate(-10, 10)
.coordinate(10, 10)
.coordinate(10, -10).close())
.hole(new LineStringBuilder(
new PointListBuilder().point(-5, -5)
.point(-5, 5)
.point(5, 5)
.point(5, -5).close().list())))
new CoordinatesBuilder().coordinate(-5, -5)
.coordinate(-5, 5)
.coordinate(5, 5)
.coordinate(5, -5).close())))
.polygon(new PolygonBuilder(
new PointListBuilder()
.point(-4, -4)
.point(-4, 4)
.point(4, 4)
.point(4, -4).close().list()))
new CoordinatesBuilder()
.coordinate(-4, -4)
.coordinate(-4, 4)
.coordinate(4, 4)
.coordinate(4, -4).close()))
.build();
}
@ -225,11 +224,11 @@ public class GeoFilterIT extends ESIntegTestCase {
// the second polygon of size 4x4 equidistant from all sites
MultiPolygonBuilder polygon = ShapeBuilders.newMultiPolygon()
.polygon(new PolygonBuilder(
new PointListBuilder().point(-10, -10).point(-10, 10).point(10, 10).point(10, -10).close().list())
.hole(new LineStringBuilder(new PointListBuilder()
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5).close().list())))
new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close())))
.polygon(new PolygonBuilder(
new PointListBuilder().point(-4, -4).point(-4, 4).point(4, 4).point(4, -4).close().list()));
new CoordinatesBuilder().coordinate(-4, -4).coordinate(-4, 4).coordinate(4, 4).coordinate(4, -4).close()));
BytesReference data = jsonBuilder().startObject().field("area", polygon).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet();
@ -288,10 +287,10 @@ public class GeoFilterIT extends ESIntegTestCase {
}
// Create a polygon that fills the empty area of the polygon defined above
PolygonBuilder inverse = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5).close().list())
PolygonBuilder inverse = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close())
.hole(new LineStringBuilder(
new PointListBuilder().point(-4, -4).point(-4, 4).point(4, 4).point(4, -4).close().list()));
new CoordinatesBuilder().coordinate(-4, -4).coordinate(-4, 4).coordinate(4, 4).coordinate(4, -4).close()));
data = jsonBuilder().startObject().field("area", inverse).endObject().bytes();
client().prepareIndex("shapes", "polygon", "2").setSource(data).execute().actionGet();
@ -306,15 +305,15 @@ public class GeoFilterIT extends ESIntegTestCase {
assertFirstHit(result, hasId("2"));
// Create Polygon with hole and common edge
PolygonBuilder builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10).close().list())
.hole(new LineStringBuilder(new PointListBuilder()
.point(-5, -5).point(-5, 5).point(10, 5).point(10, -5).close().list()));
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close())
.hole(new LineStringBuilder(new CoordinatesBuilder()
.coordinate(-5, -5).coordinate(-5, 5).coordinate(10, 5).coordinate(10, -5).close()));
if (withinSupport) {
// Polygon WithIn Polygon
builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(-30, -30).point(-30, 30).point(30, 30).point(30, -30).close().list());
builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(-30, -30).coordinate(-30, 30).coordinate(30, 30).coordinate(30, -30).close());
result = client().prepareSearch()
.setQuery(matchAllQuery())
@ -324,17 +323,17 @@ public class GeoFilterIT extends ESIntegTestCase {
}
// Create a polygon crossing longitude 180.
builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10).close().list());
builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close());
data = jsonBuilder().startObject().field("area", builder).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet();
client().admin().indices().prepareRefresh().execute().actionGet();
// Create a polygon crossing longitude 180 with hole.
builder = ShapeBuilders.newPolygon(new PointListBuilder()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10).close().list())
.hole(new LineStringBuilder(new PointListBuilder().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close().list()));
builder = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close())
.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(175, -5).coordinate(185, -5).coordinate(185, 5).coordinate(175, 5).close()));
data = jsonBuilder().startObject().field("area", builder).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data).execute().actionGet();

View File

@ -25,10 +25,10 @@ import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.EnvelopeBuilder;
import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder;
import org.elasticsearch.common.geo.builders.PointListBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -198,13 +198,13 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
}
public void testReusableBuilder() throws IOException {
ShapeBuilder polygon = ShapeBuilders.newPolygon(new PointListBuilder()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10).close().list())
.hole(new LineStringBuilder(new PointListBuilder().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close().list()));
ShapeBuilder polygon = ShapeBuilders.newPolygon(new CoordinatesBuilder()
.coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close())
.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(175, -5).coordinate(185, -5).coordinate(185, 5).coordinate(175, 5).close()));
assertUnmodified(polygon);
ShapeBuilder linestring = ShapeBuilders.newLineString(new PointListBuilder()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10).close().list());
ShapeBuilder linestring = ShapeBuilders.newLineString(new CoordinatesBuilder()
.coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close());
assertUnmodified(linestring);
}
@ -377,8 +377,8 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
"location",
ShapeBuilders.newGeometryCollection()
.polygon(
ShapeBuilders.newPolygon(new PointListBuilder().point(99.0, -1.0).point(99.0, 3.0).point(103.0, 3.0).point(103.0, -1.0)
.point(99.0, -1.0).list()))).relation(ShapeRelation.INTERSECTS);
ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0).coordinate(103.0, -1.0)
.coordinate(99.0, -1.0)))).relation(ShapeRelation.INTERSECTS);
SearchResponse result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get();
assertSearchResponse(result);
@ -386,17 +386,17 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
filter = QueryBuilders.geoShapeQuery(
"location",
ShapeBuilders.newGeometryCollection().polygon(
ShapeBuilders.newPolygon(new PointListBuilder().point(199.0, -11.0).point(199.0, 13.0).point(193.0, 13.0).point(193.0, -11.0)
.point(199.0, -11.0).list()))).relation(ShapeRelation.INTERSECTS);
ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0).coordinate(193.0, 13.0).coordinate(193.0, -11.0)
.coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS);
result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get();
assertSearchResponse(result);
assertHitCount(result, 0);
filter = QueryBuilders.geoShapeQuery("location", ShapeBuilders.newGeometryCollection()
.polygon(ShapeBuilders.newPolygon(new PointListBuilder().point(99.0, -1.0).point(99.0, 3.0).point(103.0, 3.0).point(103.0, -1.0).point(99.0, -1.0).list()))
.polygon(ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(99.0, -1.0).coordinate(99.0, 3.0).coordinate(103.0, 3.0).coordinate(103.0, -1.0).coordinate(99.0, -1.0)))
.polygon(
ShapeBuilders.newPolygon(new PointListBuilder().point(199.0, -11.0).point(199.0, 13.0).point(193.0, 13.0).point(193.0, -11.0)
.point(199.0, -11.0).list()))).relation(ShapeRelation.INTERSECTS);
ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(199.0, -11.0).coordinate(199.0, 13.0).coordinate(193.0, 13.0).coordinate(193.0, -11.0)
.coordinate(199.0, -11.0)))).relation(ShapeRelation.INTERSECTS);
result = client().prepareSearch("test").setTypes("type").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get();
assertSearchResponse(result);

View File

@ -31,13 +31,13 @@ import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.geo.builders.CoordinateCollection;
import org.elasticsearch.common.geo.builders.CoordinatesBuilder;
import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
import org.elasticsearch.common.geo.builders.LineStringBuilder;
import org.elasticsearch.common.geo.builders.MultiLineStringBuilder;
import org.elasticsearch.common.geo.builders.MultiPointBuilder;
import org.elasticsearch.common.geo.builders.PointBuilder;
import org.elasticsearch.common.geo.builders.PointCollection;
import org.elasticsearch.common.geo.builders.PointListBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.search.geo.GeoShapeQueryTests;
@ -189,12 +189,12 @@ public class RandomShapeGenerator extends RandomGeoGenerator {
// if this number gets out of hand, the number of self intersections for a linestring can become
// (n^2-n)/2 and computing the relation intersection matrix will become NP-Hard
int numPoints = RandomInts.randomIntBetween(r, 3, 10);
PointListBuilder pl = new PointListBuilder();
CoordinatesBuilder coordinatesBuilder = new CoordinatesBuilder();
for (int i=0; i<numPoints; ++i) {
p = xRandomPointIn(r, within);
pl.point(p.getX(), p.getY());
coordinatesBuilder.coordinate(p.getX(), p.getY());
}
PointCollection pcb = (st == ShapeType.MULTIPOINT) ? new MultiPointBuilder(pl.list()) : new LineStringBuilder(pl.list());
CoordinateCollection pcb = (st == ShapeType.MULTIPOINT) ? new MultiPointBuilder(coordinatesBuilder.build()) : new LineStringBuilder(coordinatesBuilder);
return pcb;
case MULTILINESTRING:
MultiLineStringBuilder mlsb = new MultiLineStringBuilder();
@ -222,7 +222,7 @@ public class RandomShapeGenerator extends RandomGeoGenerator {
shellCoords[2] = new Coordinate(within.getMaxX(), within.getMaxY());
shellCoords[3] = new Coordinate(within.getMaxX(), within.getMinY());
}
PolygonBuilder pgb = new PolygonBuilder(new PointListBuilder().points(shellCoords).close().list());
PolygonBuilder pgb = new PolygonBuilder(new CoordinatesBuilder().coordinates(shellCoords).close());
if (validate) {
// This test framework builds semi-random geometry (in the sense that points are not truly random due to spatial
// auto-correlation) As a result of the semi-random nature of the geometry, one can not predict the orientation