Merge pull request #14529 from cbuescher/introduce-shapebuilders

Geo: Moving static factory methods to ShapeBuilders
This commit is contained in:
Christoph Büscher 2015-11-17 11:08:35 +01:00
commit d6a756fbe2
9 changed files with 260 additions and 220 deletions

View File

@ -41,7 +41,7 @@ import java.io.IOException;
import java.util.*; import java.util.*;
/** /**
* Basic class for building GeoJSON shapes like Polygons, Linestrings, etc * Basic class for building GeoJSON shapes like Polygons, Linestrings, etc
*/ */
public abstract class ShapeBuilder extends ToXContentToBytes { public abstract class ShapeBuilder extends ToXContentToBytes {
@ -97,122 +97,10 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
return jtsGeometry; return jtsGeometry;
} }
/**
* Create a new point
*
* @param longitude longitude of the point
* @param latitude latitude of the point
* @return a new {@link PointBuilder}
*/
public static PointBuilder newPoint(double longitude, double latitude) {
return newPoint(new Coordinate(longitude, latitude));
}
/**
* Create a new {@link PointBuilder} from a {@link Coordinate}
* @param coordinate coordinate defining the position of the point
* @return a new {@link PointBuilder}
*/
public static PointBuilder newPoint(Coordinate coordinate) {
return new PointBuilder().coordinate(coordinate);
}
/**
* Create a new set of points
* @return new {@link MultiPointBuilder}
*/
public static MultiPointBuilder newMultiPoint() {
return new MultiPointBuilder();
}
/**
* Create a new lineString
* @return a new {@link LineStringBuilder}
*/
public static LineStringBuilder newLineString() {
return new LineStringBuilder();
}
/**
* Create a new Collection of lineStrings
* @return a new {@link MultiLineStringBuilder}
*/
public static MultiLineStringBuilder newMultiLinestring() {
return new MultiLineStringBuilder();
}
/**
* Create a new Polygon
* @return a new {@link PointBuilder}
*/
public static PolygonBuilder newPolygon() {
return new PolygonBuilder();
}
/**
* Create a new Polygon
* @return a new {@link PointBuilder}
*/
public static PolygonBuilder newPolygon(Orientation orientation) {
return new PolygonBuilder(orientation);
}
/**
* Create a new Collection of polygons
* @return a new {@link MultiPolygonBuilder}
*/
public static MultiPolygonBuilder newMultiPolygon() {
return new MultiPolygonBuilder();
}
/**
* Create a new Collection of polygons
* @return a new {@link MultiPolygonBuilder}
*/
public static MultiPolygonBuilder newMultiPolygon(Orientation orientation) {
return new MultiPolygonBuilder(orientation);
}
/**
* Create a new GeometryCollection
* @return a new {@link GeometryCollectionBuilder}
*/
public static GeometryCollectionBuilder newGeometryCollection() {
return new GeometryCollectionBuilder();
}
/**
* Create a new GeometryCollection
* @return a new {@link GeometryCollectionBuilder}
*/
public static GeometryCollectionBuilder newGeometryCollection(Orientation orientation) {
return new GeometryCollectionBuilder(orientation);
}
/**
* create a new Circle
* @return a new {@link CircleBuilder}
*/
public static CircleBuilder newCircleBuilder() {
return new CircleBuilder();
}
/**
* create a new rectangle
* @return a new {@link EnvelopeBuilder}
*/
public static EnvelopeBuilder newEnvelope() { return new EnvelopeBuilder(); }
/**
* create a new rectangle
* @return a new {@link EnvelopeBuilder}
*/
public static EnvelopeBuilder newEnvelope(Orientation orientation) { return new EnvelopeBuilder(orientation); }
/** /**
* Create a new Shape from this builder. Since calling this method could change the * Create a new Shape from this builder. Since calling this method could change the
* defined shape. (by inserting new coordinates or change the position of points) * defined shape. (by inserting new coordinates or change the position of points)
* the builder looses its validity. So this method should only be called once on a builder * the builder looses its validity. So this method should only be called once on a builder
* @return new {@link Shape} defined by the builder * @return new {@link Shape} defined by the builder
*/ */
public abstract Shape build(); public abstract Shape build();
@ -220,7 +108,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
/** /**
* Recursive method which parses the arrays of coordinates used to define * Recursive method which parses the arrays of coordinates used to define
* Shapes * Shapes
* *
* @param parser * @param parser
* Parser that will be read from * Parser that will be read from
* @return CoordinateNode representing the start of the coordinate tree * @return CoordinateNode representing the start of the coordinate tree
@ -232,8 +120,8 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
XContentParser.Token token = parser.nextToken(); XContentParser.Token token = parser.nextToken();
// Base cases // Base cases
if (token != XContentParser.Token.START_ARRAY && if (token != XContentParser.Token.START_ARRAY &&
token != XContentParser.Token.END_ARRAY && token != XContentParser.Token.END_ARRAY &&
token != XContentParser.Token.VALUE_NULL) { token != XContentParser.Token.VALUE_NULL) {
double lon = parser.doubleValue(); double lon = parser.doubleValue();
token = parser.nextToken(); token = parser.nextToken();
@ -317,7 +205,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
/** /**
* Calculate the intersection of a line segment and a vertical dateline. * Calculate the intersection of a line segment and a vertical dateline.
* *
* @param p1 * @param p1
* start-point of the line segment * start-point of the line segment
* @param p2 * @param p2
@ -347,7 +235,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
* Calculate all intersections of line segments and a vertical line. The * Calculate all intersections of line segments and a vertical line. The
* Array of edges will be ordered asc by the y-coordinate of the * Array of edges will be ordered asc by the y-coordinate of the
* intersections of edges. * intersections of edges.
* *
* @param dateline * @param dateline
* x-coordinate of the dateline * x-coordinate of the dateline
* @param edges * @param edges
@ -360,7 +248,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
for (int i = 0; i < edges.length; i++) { for (int i = 0; i < edges.length; i++) {
Coordinate p1 = edges[i].coordinate; Coordinate p1 = edges[i].coordinate;
Coordinate p2 = edges[i].next.coordinate; Coordinate p2 = edges[i].next.coordinate;
assert !Double.isNaN(p2.x) && !Double.isNaN(p1.x); assert !Double.isNaN(p2.x) && !Double.isNaN(p1.x);
edges[i].intersect = Edge.MAX_COORDINATE; edges[i].intersect = Edge.MAX_COORDINATE;
double position = intersection(p1, p2, dateline); double position = intersection(p1, p2, dateline);
@ -386,7 +274,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
/** /**
* Creates a new leaf CoordinateNode * Creates a new leaf CoordinateNode
* *
* @param coordinate * @param coordinate
* Coordinate for the Node * Coordinate for the Node
*/ */
@ -397,7 +285,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
/** /**
* Creates a new parent CoordinateNode * Creates a new parent CoordinateNode
* *
* @param children * @param children
* Children of the Node * Children of the Node
*/ */
@ -427,7 +315,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
/** /**
* This helper class implements a linked list for {@link Coordinate}. It contains * This helper class implements a linked list for {@link Coordinate}. It contains
* fields for a dateline intersection and component id * fields for a dateline intersection and component id
*/ */
protected static final class Edge { protected static final class Edge {
Coordinate coordinate; // coordinate of the start point Coordinate coordinate; // coordinate of the start point
@ -500,7 +388,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
/** /**
* Concatenate a set of points to a polygon * Concatenate a set of points to a polygon
* *
* @param component * @param component
* component id of the polygon * component id of the polygon
* @param direction * @param direction
@ -547,7 +435,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
/** /**
* Create a connected list of a list of coordinates * Create a connected list of a list of coordinates
* *
* @param points * @param points
* array of point * array of point
* @param offset * @param offset
@ -567,7 +455,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
final int next = (offset + ((top + 1) % length)); final int next = (offset + ((top + 1) % length));
boolean orientation = points[offset + prev].x > points[offset + next].x; boolean orientation = points[offset + prev].x > points[offset + next].x;
// OGC requires shell as ccw (Right-Handedness) and holes as cw (Left-Handedness) // OGC requires shell as ccw (Right-Handedness) and holes as cw (Left-Handedness)
// since GeoJSON doesn't specify (and doesn't need to) GEO core will assume OGC standards // since GeoJSON doesn't specify (and doesn't need to) GEO core will assume OGC standards
// thus if orientation is computed as cw, the logic will translate points across dateline // thus if orientation is computed as cw, the logic will translate points across dateline
// and convert to a right handed system // and convert to a right handed system
@ -576,7 +464,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
double[] range = range(points, offset, length); double[] range = range(points, offset, length);
final double rng = range[1] - range[0]; final double rng = range[1] - range[0];
// translate the points if the following is true // translate the points if the following is true
// 1. shell orientation is cw and range is greater than a hemisphere (180 degrees) but not spanning 2 hemispheres // 1. shell orientation is cw and range is greater than a hemisphere (180 degrees) but not spanning 2 hemispheres
// (translation would result in a collapsed poly) // (translation would result in a collapsed poly)
// 2. the shell of the candidate hole has been translated (to preserve the coordinate system) // 2. the shell of the candidate hole has been translated (to preserve the coordinate system)
boolean incorrectOrientation = component == 0 && handedness != orientation; boolean incorrectOrientation = component == 0 && handedness != orientation;
@ -595,7 +483,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
} }
/** /**
* Transforms coordinates in the eastern hemisphere (-180:0) to a (180:360) range * Transforms coordinates in the eastern hemisphere (-180:0) to a (180:360) range
*/ */
protected static void translate(Coordinate[] points) { protected static void translate(Coordinate[] points) {
for (Coordinate c : points) { for (Coordinate c : points) {
@ -607,7 +495,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
/** /**
* Set the intersection of this line segment to the given position * Set the intersection of this line segment to the given position
* *
* @param position * @param position
* position of the intersection [0..1] * position of the intersection [0..1]
* @return the {@link Coordinate} of the intersection * @return the {@link Coordinate} of the intersection
@ -770,7 +658,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
throw new ElasticsearchParseException("shape type [{}] not included", shapeType); throw new ElasticsearchParseException("shape type [{}] not included", shapeType);
} }
} }
protected static void validatePointNode(CoordinateNode node) { protected static void validatePointNode(CoordinateNode node) {
if (node.isEmpty()) { if (node.isEmpty()) {
throw new ElasticsearchParseException("invalid number of points (0) provided when expecting a single coordinate ([lat, lng])"); throw new ElasticsearchParseException("invalid number of points (0) provided when expecting a single coordinate ([lat, lng])");
@ -783,11 +671,11 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
protected static PointBuilder parsePoint(CoordinateNode node) { protected static PointBuilder parsePoint(CoordinateNode node) {
validatePointNode(node); validatePointNode(node);
return newPoint(node.coordinate); return ShapeBuilders.newPoint(node.coordinate);
} }
protected static CircleBuilder parseCircle(CoordinateNode coordinates, Distance radius) { protected static CircleBuilder parseCircle(CoordinateNode coordinates, Distance radius) {
return newCircleBuilder().center(coordinates.coordinate).radius(radius); return ShapeBuilders.newCircleBuilder().center(coordinates.coordinate).radius(radius);
} }
protected static EnvelopeBuilder parseEnvelope(CoordinateNode coordinates, final Orientation orientation) { protected static EnvelopeBuilder parseEnvelope(CoordinateNode coordinates, final Orientation orientation) {
@ -804,7 +692,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
uL = new Coordinate(Math.min(uL.x, lR.x), Math.max(uL.y, lR.y)); 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)); lR = new Coordinate(Math.max(uLtmp.x, lR.x), Math.min(uLtmp.y, lR.y));
} }
return newEnvelope(orientation).topLeft(uL).bottomRight(lR); return ShapeBuilders.newEnvelope(orientation).topLeft(uL).bottomRight(lR);
} }
protected static void validateMultiPointNode(CoordinateNode coordinates) { protected static void validateMultiPointNode(CoordinateNode coordinates) {
@ -842,7 +730,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
throw new ElasticsearchParseException("invalid number of points in LineString (found [{}] - must be >= 2)", coordinates.children.size()); throw new ElasticsearchParseException("invalid number of points in LineString (found [{}] - must be >= 2)", coordinates.children.size());
} }
LineStringBuilder line = newLineString(); LineStringBuilder line = ShapeBuilders.newLineString();
for (CoordinateNode node : coordinates.children) { for (CoordinateNode node : coordinates.children) {
line.point(node.coordinate); line.point(node.coordinate);
} }
@ -850,7 +738,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
} }
protected static MultiLineStringBuilder parseMultiLine(CoordinateNode coordinates) { protected static MultiLineStringBuilder parseMultiLine(CoordinateNode coordinates) {
MultiLineStringBuilder multiline = newMultiLinestring(); MultiLineStringBuilder multiline = ShapeBuilders.newMultiLinestring();
for (CoordinateNode node : coordinates.children) { for (CoordinateNode node : coordinates.children) {
multiline.linestring(parseLineString(node)); multiline.linestring(parseLineString(node));
} }
@ -903,13 +791,13 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
protected static MultiPolygonBuilder parseMultiPolygon(CoordinateNode coordinates, final Orientation orientation, protected static MultiPolygonBuilder parseMultiPolygon(CoordinateNode coordinates, final Orientation orientation,
final boolean coerce) { final boolean coerce) {
MultiPolygonBuilder polygons = newMultiPolygon(orientation); MultiPolygonBuilder polygons = ShapeBuilders.newMultiPolygon(orientation);
for (CoordinateNode node : coordinates.children) { for (CoordinateNode node : coordinates.children) {
polygons.polygon(parsePolygon(node, orientation, coerce)); polygons.polygon(parsePolygon(node, orientation, coerce));
} }
return polygons; return polygons;
} }
/** /**
* Parse the geometries array of a GeometryCollection * Parse the geometries array of a GeometryCollection
* *
@ -922,16 +810,16 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
if (parser.currentToken() != XContentParser.Token.START_ARRAY) { if (parser.currentToken() != XContentParser.Token.START_ARRAY) {
throw new ElasticsearchParseException("geometries must be an array of geojson objects"); throw new ElasticsearchParseException("geometries must be an array of geojson objects");
} }
XContentParser.Token token = parser.nextToken(); XContentParser.Token token = parser.nextToken();
GeometryCollectionBuilder geometryCollection = newGeometryCollection( (mapper == null) ? Orientation.RIGHT : mapper GeometryCollectionBuilder geometryCollection = ShapeBuilders.newGeometryCollection( (mapper == null) ? Orientation.RIGHT : mapper
.fieldType().orientation()); .fieldType().orientation());
while (token != XContentParser.Token.END_ARRAY) { while (token != XContentParser.Token.END_ARRAY) {
ShapeBuilder shapeBuilder = GeoShapeType.parse(parser); ShapeBuilder shapeBuilder = GeoShapeType.parse(parser);
geometryCollection.shape(shapeBuilder); geometryCollection.shape(shapeBuilder);
token = parser.nextToken(); token = parser.nextToken();
} }
return geometryCollection; return geometryCollection;
} }
} }

View File

@ -0,0 +1,148 @@
/*
* 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;
/**
* A collection of static methods for creating ShapeBuilders.
*/
public class ShapeBuilders {
/**
* Create a new point
*
* @param longitude longitude of the point
* @param latitude latitude of the point
* @return a new {@link PointBuilder}
*/
public static PointBuilder newPoint(double longitude, double latitude) {
return ShapeBuilders.newPoint(new Coordinate(longitude, latitude));
}
/**
* Create a new {@link PointBuilder} from a {@link Coordinate}
* @param coordinate coordinate defining the position of the point
* @return a new {@link PointBuilder}
*/
public static PointBuilder newPoint(Coordinate coordinate) {
return new PointBuilder().coordinate(coordinate);
}
/**
* Create a new set of points
* @return new {@link MultiPointBuilder}
*/
public static MultiPointBuilder newMultiPoint() {
return new MultiPointBuilder();
}
/**
* Create a new lineString
* @return a new {@link LineStringBuilder}
*/
public static LineStringBuilder newLineString() {
return new LineStringBuilder();
}
/**
* Create a new Collection of lineStrings
* @return a new {@link MultiLineStringBuilder}
*/
public static MultiLineStringBuilder newMultiLinestring() {
return new MultiLineStringBuilder();
}
/**
* Create a new Polygon
* @return a new {@link PointBuilder}
*/
public static PolygonBuilder newPolygon() {
return new PolygonBuilder();
}
/**
* Create a new Polygon
* @return a new {@link PointBuilder}
*/
public static PolygonBuilder newPolygon(ShapeBuilder.Orientation orientation) {
return new PolygonBuilder(orientation);
}
/**
* Create a new Collection of polygons
* @return a new {@link MultiPolygonBuilder}
*/
public static MultiPolygonBuilder newMultiPolygon() {
return new MultiPolygonBuilder();
}
/**
* Create a new Collection of polygons
* @return a new {@link MultiPolygonBuilder}
*/
public static MultiPolygonBuilder newMultiPolygon(ShapeBuilder.Orientation orientation) {
return new MultiPolygonBuilder(orientation);
}
/**
* Create a new GeometryCollection
* @return a new {@link GeometryCollectionBuilder}
*/
public static GeometryCollectionBuilder newGeometryCollection() {
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
*
* @return a new {@link CircleBuilder}
*/
public static CircleBuilder newCircleBuilder() {
return new CircleBuilder();
}
/**
* create a new rectangle
*
* @return a new {@link EnvelopeBuilder}
*/
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);
}
}

View File

@ -31,6 +31,7 @@ import com.vividsolutions.jts.geom.Polygon;
import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import static org.elasticsearch.test.hamcrest.ElasticsearchGeoAssertions.assertMultiLineString; import static org.elasticsearch.test.hamcrest.ElasticsearchGeoAssertions.assertMultiLineString;
@ -43,13 +44,13 @@ import static org.hamcrest.Matchers.containsString;
public class ShapeBuilderTests extends ESTestCase { public class ShapeBuilderTests extends ESTestCase {
public void testNewPoint() { public void testNewPoint() {
Point point = ShapeBuilder.newPoint(-100, 45).build(); Point point = ShapeBuilders.newPoint(-100, 45).build();
assertEquals(-100D, point.getX(), 0.0d); assertEquals(-100D, point.getX(), 0.0d);
assertEquals(45D, point.getY(), 0.0d); assertEquals(45D, point.getY(), 0.0d);
} }
public void testNewRectangle() { public void testNewRectangle() {
Rectangle rectangle = ShapeBuilder.newEnvelope().topLeft(-45, 30).bottomRight(45, -30).build(); Rectangle rectangle = ShapeBuilders.newEnvelope().topLeft(-45, 30).bottomRight(45, -30).build();
assertEquals(-45D, rectangle.getMinX(), 0.0d); assertEquals(-45D, rectangle.getMinX(), 0.0d);
assertEquals(-30D, rectangle.getMinY(), 0.0d); assertEquals(-30D, rectangle.getMinY(), 0.0d);
assertEquals(45D, rectangle.getMaxX(), 0.0d); assertEquals(45D, rectangle.getMaxX(), 0.0d);
@ -57,7 +58,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testNewPolygon() { public void testNewPolygon() {
Polygon polygon = ShapeBuilder.newPolygon() Polygon polygon = ShapeBuilders.newPolygon()
.point(-45, 30) .point(-45, 30)
.point(45, 30) .point(45, 30)
.point(45, -30) .point(45, -30)
@ -72,7 +73,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testNewPolygon_coordinate() { public void testNewPolygon_coordinate() {
Polygon polygon = ShapeBuilder.newPolygon() Polygon polygon = ShapeBuilders.newPolygon()
.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)) .point(new Coordinate(45, -30))
@ -87,7 +88,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testNewPolygon_coordinates() { public void testNewPolygon_coordinates() {
Polygon polygon = ShapeBuilder.newPolygon() Polygon polygon = ShapeBuilders.newPolygon()
.points(new Coordinate(-45, 30), new Coordinate(45, 30), new Coordinate(45, -30), new Coordinate(-45, -30), new Coordinate(-45, 30)).toPolygon(); .points(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(); LineString exterior = polygon.getExteriorRing();
@ -99,7 +100,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testLineStringBuilder() { public void testLineStringBuilder() {
// Building a simple LineString // Building a simple LineString
ShapeBuilder.newLineString() ShapeBuilders.newLineString()
.point(-130.0, 55.0) .point(-130.0, 55.0)
.point(-130.0, -40.0) .point(-130.0, -40.0)
.point(-15.0, -40.0) .point(-15.0, -40.0)
@ -110,7 +111,7 @@ public class ShapeBuilderTests extends ESTestCase {
.point(-110.0, 55.0).build(); .point(-110.0, 55.0).build();
// Building a linestring that needs to be wrapped // Building a linestring that needs to be wrapped
ShapeBuilder.newLineString() ShapeBuilders.newLineString()
.point(100.0, 50.0) .point(100.0, 50.0)
.point(110.0, -40.0) .point(110.0, -40.0)
.point(240.0, -40.0) .point(240.0, -40.0)
@ -122,7 +123,7 @@ public class ShapeBuilderTests extends ESTestCase {
.build(); .build();
// Building a lineString on the dateline // Building a lineString on the dateline
ShapeBuilder.newLineString() ShapeBuilders.newLineString()
.point(-180.0, 80.0) .point(-180.0, 80.0)
.point(-180.0, 40.0) .point(-180.0, 40.0)
.point(-180.0, -40.0) .point(-180.0, -40.0)
@ -130,7 +131,7 @@ public class ShapeBuilderTests extends ESTestCase {
.build(); .build();
// Building a lineString on the dateline // Building a lineString on the dateline
ShapeBuilder.newLineString() ShapeBuilders.newLineString()
.point(180.0, 80.0) .point(180.0, 80.0)
.point(180.0, 40.0) .point(180.0, 40.0)
.point(180.0, -40.0) .point(180.0, -40.0)
@ -139,7 +140,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testMultiLineString() { public void testMultiLineString() {
ShapeBuilder.newMultiLinestring() ShapeBuilders.newMultiLinestring()
.linestring() .linestring()
.point(-100.0, 50.0) .point(-100.0, 50.0)
.point(50.0, 50.0) .point(50.0, 50.0)
@ -156,7 +157,7 @@ public class ShapeBuilderTests extends ESTestCase {
// LineString that needs to be wrappped // LineString that needs to be wrappped
ShapeBuilder.newMultiLinestring() ShapeBuilders.newMultiLinestring()
.linestring() .linestring()
.point(150.0, 60.0) .point(150.0, 60.0)
.point(200.0, 60.0) .point(200.0, 60.0)
@ -174,7 +175,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testPolygonSelfIntersection() { public void testPolygonSelfIntersection() {
try { try {
ShapeBuilder.newPolygon() ShapeBuilders.newPolygon()
.point(-40.0, 50.0) .point(-40.0, 50.0)
.point(40.0, 50.0) .point(40.0, 50.0)
.point(-40.0, -50.0) .point(-40.0, -50.0)
@ -188,31 +189,31 @@ public class ShapeBuilderTests extends ESTestCase {
public void testGeoCircle() { public void testGeoCircle() {
double earthCircumference = 40075016.69; double earthCircumference = 40075016.69;
Circle circle = ShapeBuilder.newCircleBuilder().center(0, 0).radius("100m").build(); Circle circle = ShapeBuilders.newCircleBuilder().center(0, 0).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals(new PointImpl(0, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); assertEquals(new PointImpl(0, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
circle = ShapeBuilder.newCircleBuilder().center(+180, 0).radius("100m").build(); circle = ShapeBuilders.newCircleBuilder().center(+180, 0).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals(new PointImpl(180, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); assertEquals(new PointImpl(180, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
circle = ShapeBuilder.newCircleBuilder().center(-180, 0).radius("100m").build(); circle = ShapeBuilders.newCircleBuilder().center(-180, 0).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals(new PointImpl(-180, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); assertEquals(new PointImpl(-180, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
circle = ShapeBuilder.newCircleBuilder().center(0, 90).radius("100m").build(); circle = ShapeBuilders.newCircleBuilder().center(0, 90).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals(new PointImpl(0, 90, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); assertEquals(new PointImpl(0, 90, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
circle = ShapeBuilder.newCircleBuilder().center(0, -90).radius("100m").build(); circle = ShapeBuilders.newCircleBuilder().center(0, -90).radius("100m").build();
assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals(new PointImpl(0, -90, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); assertEquals(new PointImpl(0, -90, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
double randomLat = (randomDouble() * 180) - 90; double randomLat = (randomDouble() * 180) - 90;
double randomLon = (randomDouble() * 360) - 180; double randomLon = (randomDouble() * 360) - 180;
double randomRadius = randomIntBetween(1, (int) earthCircumference / 4); double randomRadius = randomIntBetween(1, (int) earthCircumference / 4);
circle = ShapeBuilder.newCircleBuilder().center(randomLon, randomLat).radius(randomRadius + "m").build(); circle = ShapeBuilders.newCircleBuilder().center(randomLon, randomLat).radius(randomRadius + "m").build();
assertEquals((360 * randomRadius) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals((360 * randomRadius) / earthCircumference, circle.getRadius(), 0.00000001);
assertEquals(new PointImpl(randomLon, randomLat, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); assertEquals(new PointImpl(randomLon, randomLat, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter());
} }
public void testPolygonWrapping() { public void testPolygonWrapping() {
Shape shape = ShapeBuilder.newPolygon() Shape shape = ShapeBuilders.newPolygon()
.point(-150.0, 65.0) .point(-150.0, 65.0)
.point(-250.0, 65.0) .point(-250.0, 65.0)
.point(-250.0, -65.0) .point(-250.0, -65.0)
@ -223,7 +224,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testLineStringWrapping() { public void testLineStringWrapping() {
Shape shape = ShapeBuilder.newLineString() Shape shape = ShapeBuilders.newLineString()
.point(-150.0, 65.0) .point(-150.0, 65.0)
.point(-250.0, 65.0) .point(-250.0, 65.0)
.point(-250.0, -65.0) .point(-250.0, -65.0)
@ -238,7 +239,7 @@ public class ShapeBuilderTests extends ESTestCase {
// expected results: 3 polygons, 1 with a hole // expected results: 3 polygons, 1 with a hole
// a giant c shape // a giant c shape
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(174,0) .point(174,0)
.point(-176,0) .point(-176,0)
.point(-176,3) .point(-176,3)
@ -279,7 +280,7 @@ public class ShapeBuilderTests extends ESTestCase {
// expected results: 3 polygons, 1 with a hole // expected results: 3 polygons, 1 with a hole
// a giant c shape // a giant c shape
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(-186,0) .point(-186,0)
.point(-176,0) .point(-176,0)
.point(-176,3) .point(-176,3)
@ -315,7 +316,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testComplexShapeWithHole() { public void testComplexShapeWithHole() {
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(-85.0018514,37.1311314) .point(-85.0018514,37.1311314)
.point(-85.0016645,37.1315293) .point(-85.0016645,37.1315293)
.point(-85.0016246,37.1317069) .point(-85.0016246,37.1317069)
@ -388,7 +389,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testShapeWithHoleAtEdgeEndPoints() { public void testShapeWithHoleAtEdgeEndPoints() {
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(-4, 2) .point(-4, 2)
.point(4, 2) .point(4, 2)
.point(6, 0) .point(6, 0)
@ -409,7 +410,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testShapeWithPointOnDateline() { public void testShapeWithPointOnDateline() {
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(180, 0) .point(180, 0)
.point(176, 4) .point(176, 4)
.point(176, -4) .point(176, -4)
@ -421,7 +422,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithEdgeAlongDateline() { public void testShapeWithEdgeAlongDateline() {
// test case 1: test the positive side of the dateline // test case 1: test the positive side of the dateline
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(180, 0) .point(180, 0)
.point(176, 4) .point(176, 4)
.point(180, -4) .point(180, -4)
@ -431,7 +432,7 @@ public class ShapeBuilderTests extends ESTestCase {
assertPolygon(shape); assertPolygon(shape);
// test case 2: test the negative side of the dateline // test case 2: test the negative side of the dateline
builder = ShapeBuilder.newPolygon() builder = ShapeBuilders.newPolygon()
.point(-176, 4) .point(-176, 4)
.point(-180, 0) .point(-180, 0)
.point(-180, -4) .point(-180, -4)
@ -443,7 +444,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithBoundaryHoles() { public void testShapeWithBoundaryHoles() {
// test case 1: test the positive side of the dateline // test case 1: test the positive side of the dateline
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(-177, 10) .point(-177, 10)
.point(176, 15) .point(176, 15)
.point(172, 0) .point(172, 0)
@ -460,7 +461,7 @@ public class ShapeBuilderTests extends ESTestCase {
assertMultiPolygon(shape); assertMultiPolygon(shape);
// test case 2: test the negative side of the dateline // test case 2: test the negative side of the dateline
builder = ShapeBuilder.newPolygon() builder = ShapeBuilders.newPolygon()
.point(-176, 15) .point(-176, 15)
.point(179, 10) .point(179, 10)
.point(179, -10) .point(179, -10)
@ -478,7 +479,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithTangentialHole() { public void testShapeWithTangentialHole() {
// test a shape with one tangential (shared) vertex (should pass) // test a shape with one tangential (shared) vertex (should pass)
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(179, 10) .point(179, 10)
.point(168, 15) .point(168, 15)
.point(164, 0) .point(164, 0)
@ -497,7 +498,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithInvalidTangentialHole() { public void testShapeWithInvalidTangentialHole() {
// test a shape with one invalid tangential (shared) vertex (should throw exception) // test a shape with one invalid tangential (shared) vertex (should throw exception)
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(179, 10) .point(179, 10)
.point(168, 15) .point(168, 15)
.point(164, 0) .point(164, 0)
@ -520,7 +521,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testBoundaryShapeWithTangentialHole() { public void testBoundaryShapeWithTangentialHole() {
// test a shape with one tangential (shared) vertex for each hole (should pass) // test a shape with one tangential (shared) vertex for each hole (should pass)
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(-177, 10) .point(-177, 10)
.point(176, 15) .point(176, 15)
.point(172, 0) .point(172, 0)
@ -544,7 +545,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testBoundaryShapeWithInvalidTangentialHole() { public void testBoundaryShapeWithInvalidTangentialHole() {
// test shape with two tangential (shared) vertices (should throw exception) // test shape with two tangential (shared) vertices (should throw exception)
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(-177, 10) .point(-177, 10)
.point(176, 15) .point(176, 15)
.point(172, 0) .point(172, 0)
@ -569,7 +570,7 @@ public class ShapeBuilderTests extends ESTestCase {
* Test an enveloping polygon around the max mercator bounds * Test an enveloping polygon around the max mercator bounds
*/ */
public void testBoundaryShape() { public void testBoundaryShape() {
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(-180, 90) .point(-180, 90)
.point(180, 90) .point(180, 90)
.point(180, -90) .point(180, -90)
@ -582,7 +583,7 @@ public class ShapeBuilderTests extends ESTestCase {
public void testShapeWithAlternateOrientation() { public void testShapeWithAlternateOrientation() {
// cw: should produce a multi polygon spanning hemispheres // cw: should produce a multi polygon spanning hemispheres
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(180, 0) .point(180, 0)
.point(176, 4) .point(176, 4)
.point(-176, 4) .point(-176, 4)
@ -592,7 +593,7 @@ public class ShapeBuilderTests extends ESTestCase {
assertPolygon(shape); assertPolygon(shape);
// cw: geo core will convert to ccw across the dateline // cw: geo core will convert to ccw across the dateline
builder = ShapeBuilder.newPolygon() builder = ShapeBuilders.newPolygon()
.point(180, 0) .point(180, 0)
.point(-176, 4) .point(-176, 4)
.point(176, 4) .point(176, 4)
@ -604,7 +605,7 @@ public class ShapeBuilderTests extends ESTestCase {
} }
public void testInvalidShapeWithConsecutiveDuplicatePoints() { public void testInvalidShapeWithConsecutiveDuplicatePoints() {
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(180, 0) .point(180, 0)
.point(176, 4) .point(176, 4)
.point(176, 4) .point(176, 4)

View File

@ -20,12 +20,13 @@
package org.elasticsearch.index.mapper.externalvalues; package org.elasticsearch.index.mapper.externalvalues;
import com.spatial4j.core.shape.Point; import com.spatial4j.core.shape.Point;
import org.apache.lucene.document.Field; import org.apache.lucene.document.Field;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Iterators; import org.elasticsearch.common.collect.Iterators;
import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.mapper.ContentPath; import org.elasticsearch.index.mapper.ContentPath;
@ -201,7 +202,7 @@ public class ExternalMapper extends FieldMapper {
pointMapper.parse(context.createExternalValueContext(point)); pointMapper.parse(context.createExternalValueContext(point));
// Let's add a Dummy Shape // Let's add a Dummy Shape
Point shape = ShapeBuilder.newPoint(-100, 45).build(); Point shape = ShapeBuilders.newPoint(-100, 45).build();
shapeMapper.parse(context.createExternalValueContext(shape)); shapeMapper.parse(context.createExternalValueContext(shape));
context = context.createExternalValueContext(generatedValue); context = context.createExternalValueContext(generatedValue);

View File

@ -21,7 +21,7 @@ package org.elasticsearch.index.mapper.externalvalues;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.Plugin;
@ -69,7 +69,7 @@ public class ExternalValuesMapperIntegrationIT extends ESIntegTestCase {
assertThat(response.getHits().totalHits(), equalTo((long) 1)); assertThat(response.getHits().totalHits(), equalTo((long) 1));
response = client().prepareSearch("test-idx") response = client().prepareSearch("test-idx")
.setPostFilter(QueryBuilders.geoShapeQuery("field.shape", ShapeBuilder.newPoint(-100, 45)).relation(ShapeRelation.WITHIN)) .setPostFilter(QueryBuilders.geoShapeQuery("field.shape", ShapeBuilders.newPoint(-100, 45)).relation(ShapeRelation.WITHIN))
.execute().actionGet(); .execute().actionGet();
assertThat(response.getHits().totalHits(), equalTo((long) 1)); assertThat(response.getHits().totalHits(), equalTo((long) 1));

View File

@ -30,6 +30,7 @@ import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.SpatialStrategy; import org.elasticsearch.common.geo.SpatialStrategy;
import org.elasticsearch.common.geo.builders.EnvelopeBuilder; import org.elasticsearch.common.geo.builders.EnvelopeBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.common.xcontent.json.JsonXContent;
@ -217,7 +218,7 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
// see #3878 // see #3878
public void testThatXContentSerializationInsideOfArrayWorks() throws Exception { public void testThatXContentSerializationInsideOfArrayWorks() throws Exception {
EnvelopeBuilder envelopeBuilder = ShapeBuilder.newEnvelope().topLeft(0, 0).bottomRight(10, 10); EnvelopeBuilder envelopeBuilder = ShapeBuilders.newEnvelope().topLeft(0, 0).bottomRight(10, 10);
GeoShapeQueryBuilder geoQuery = QueryBuilders.geoShapeQuery("searchGeometry", envelopeBuilder); GeoShapeQueryBuilder geoQuery = QueryBuilders.geoShapeQuery("searchGeometry", envelopeBuilder);
JsonXContent.contentBuilder().startArray().value(geoQuery).endArray(); JsonXContent.contentBuilder().startArray().value(geoQuery).endArray();
} }

View File

@ -23,7 +23,7 @@ import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.common.geo.GeoDistance; import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.query.MoreLikeThisQueryBuilder.Item; import org.elasticsearch.index.query.MoreLikeThisQueryBuilder.Item;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder; import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
@ -175,7 +175,7 @@ public class QueryDSLDocumentationTests extends ESTestCase {
public void testGeoShape() throws IOException { public void testGeoShape() throws IOException {
GeoShapeQueryBuilder qb = geoShapeQuery( GeoShapeQueryBuilder qb = geoShapeQuery(
"pin.location", "pin.location",
ShapeBuilder.newMultiPoint() ShapeBuilders.newMultiPoint()
.point(0, 0) .point(0, 0)
.point(0, 10) .point(0, 10)
.point(10, 10) .point(10, 10)

View File

@ -44,7 +44,7 @@ import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.geo.builders.MultiPolygonBuilder; import org.elasticsearch.common.geo.builders.MultiPolygonBuilder;
import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.PolygonBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.io.Streams; import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
@ -116,7 +116,7 @@ public class GeoFilterIT extends ESIntegTestCase {
public void testShapeBuilders() { public void testShapeBuilders() {
try { try {
// self intersection polygon // self intersection polygon
ShapeBuilder.newPolygon() ShapeBuilders.newPolygon()
.point(-10, -10) .point(-10, -10)
.point(10, 10) .point(10, 10)
.point(-10, 10) .point(-10, 10)
@ -127,7 +127,7 @@ public class GeoFilterIT extends ESIntegTestCase {
} }
// polygon with hole // polygon with hole
ShapeBuilder.newPolygon() ShapeBuilders.newPolygon()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
.hole() .hole()
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5) .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
@ -135,7 +135,7 @@ public class GeoFilterIT extends ESIntegTestCase {
try { try {
// polygon with overlapping hole // polygon with overlapping hole
ShapeBuilder.newPolygon() ShapeBuilders.newPolygon()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
.hole() .hole()
.point(-5, -5).point(-5, 11).point(5, 11).point(5, -5) .point(-5, -5).point(-5, 11).point(5, 11).point(5, -5)
@ -147,7 +147,7 @@ public class GeoFilterIT extends ESIntegTestCase {
try { try {
// polygon with intersection holes // polygon with intersection holes
ShapeBuilder.newPolygon() ShapeBuilders.newPolygon()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
.hole() .hole()
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5) .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
@ -162,7 +162,7 @@ public class GeoFilterIT extends ESIntegTestCase {
try { try {
// Common line in polygon // Common line in polygon
ShapeBuilder.newPolygon() ShapeBuilders.newPolygon()
.point(-10, -10) .point(-10, -10)
.point(-10, 10) .point(-10, 10)
.point(-5, 10) .point(-5, 10)
@ -192,7 +192,7 @@ public class GeoFilterIT extends ESIntegTestCase {
// } catch (InvalidShapeException e) {} // } catch (InvalidShapeException e) {}
// Multipolygon: polygon with hole and polygon within the whole // Multipolygon: polygon with hole and polygon within the whole
ShapeBuilder.newMultiPolygon() ShapeBuilders.newMultiPolygon()
.polygon() .polygon()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
.hole() .hole()
@ -247,7 +247,7 @@ public class GeoFilterIT extends ESIntegTestCase {
// Create a multipolygon with two polygons. The first is an rectangle of size 10x10 // Create a multipolygon with two polygons. The first is an rectangle of size 10x10
// with a hole of size 5x5 equidistant from all sides. This hole in turn contains // with a hole of size 5x5 equidistant from all sides. This hole in turn contains
// the second polygon of size 4x4 equidistant from all sites // the second polygon of size 4x4 equidistant from all sites
MultiPolygonBuilder polygon = ShapeBuilder.newMultiPolygon() MultiPolygonBuilder polygon = ShapeBuilders.newMultiPolygon()
.polygon() .polygon()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
.hole() .hole()
@ -266,7 +266,7 @@ public class GeoFilterIT extends ESIntegTestCase {
// Point in polygon // Point in polygon
SearchResponse result = client().prepareSearch() SearchResponse result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(3, 3))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(3, 3)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 1); assertHitCount(result, 1);
assertFirstHit(result, hasId("1")); assertFirstHit(result, hasId("1"));
@ -274,7 +274,7 @@ public class GeoFilterIT extends ESIntegTestCase {
// Point in polygon hole // Point in polygon hole
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(4.5, 4.5))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(4.5, 4.5)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 0); assertHitCount(result, 0);
@ -285,7 +285,7 @@ public class GeoFilterIT extends ESIntegTestCase {
// Point on polygon border // Point on polygon border
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(10.0, 5.0))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(10.0, 5.0)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 1); assertHitCount(result, 1);
assertFirstHit(result, hasId("1")); assertFirstHit(result, hasId("1"));
@ -293,7 +293,7 @@ public class GeoFilterIT extends ESIntegTestCase {
// Point on hole border // Point on hole border
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(5.0, 2.0))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(5.0, 2.0)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 1); assertHitCount(result, 1);
assertFirstHit(result, hasId("1")); assertFirstHit(result, hasId("1"));
@ -302,21 +302,21 @@ public class GeoFilterIT extends ESIntegTestCase {
// Point not in polygon // Point not in polygon
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoDisjointQuery("area", ShapeBuilder.newPoint(3, 3))) .setPostFilter(QueryBuilders.geoDisjointQuery("area", ShapeBuilders.newPoint(3, 3)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 0); assertHitCount(result, 0);
// Point in polygon hole // Point in polygon hole
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoDisjointQuery("area", ShapeBuilder.newPoint(4.5, 4.5))) .setPostFilter(QueryBuilders.geoDisjointQuery("area", ShapeBuilders.newPoint(4.5, 4.5)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 1); assertHitCount(result, 1);
assertFirstHit(result, hasId("1")); assertFirstHit(result, hasId("1"));
} }
// Create a polygon that fills the empty area of the polygon defined above // Create a polygon that fills the empty area of the polygon defined above
PolygonBuilder inverse = ShapeBuilder.newPolygon() PolygonBuilder inverse = ShapeBuilders.newPolygon()
.point(-5, -5).point(-5, 5).point(5, 5).point(5, -5) .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
.hole() .hole()
.point(-4, -4).point(-4, 4).point(4, 4).point(4, -4) .point(-4, -4).point(-4, 4).point(4, 4).point(4, -4)
@ -330,13 +330,13 @@ public class GeoFilterIT extends ESIntegTestCase {
// re-check point on polygon hole // re-check point on polygon hole
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(4.5, 4.5))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(4.5, 4.5)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 1); assertHitCount(result, 1);
assertFirstHit(result, hasId("2")); assertFirstHit(result, hasId("2"));
// Create Polygon with hole and common edge // Create Polygon with hole and common edge
PolygonBuilder builder = ShapeBuilder.newPolygon() PolygonBuilder builder = ShapeBuilders.newPolygon()
.point(-10, -10).point(-10, 10).point(10, 10).point(10, -10) .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
.hole() .hole()
.point(-5, -5).point(-5, 5).point(10, 5).point(10, -5) .point(-5, -5).point(-5, 5).point(10, 5).point(10, -5)
@ -345,7 +345,7 @@ public class GeoFilterIT extends ESIntegTestCase {
if (withinSupport) { if (withinSupport) {
// Polygon WithIn Polygon // Polygon WithIn Polygon
builder = ShapeBuilder.newPolygon() builder = ShapeBuilders.newPolygon()
.point(-30, -30).point(-30, 30).point(30, 30).point(30, -30).close(); .point(-30, -30).point(-30, 30).point(30, 30).point(30, -30).close();
result = client().prepareSearch() result = client().prepareSearch()
@ -356,7 +356,7 @@ public class GeoFilterIT extends ESIntegTestCase {
} }
// Create a polygon crossing longitude 180. // Create a polygon crossing longitude 180.
builder = ShapeBuilder.newPolygon() builder = ShapeBuilders.newPolygon()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10) .point(170, -10).point(190, -10).point(190, 10).point(170, 10)
.close(); .close();
@ -365,7 +365,7 @@ public class GeoFilterIT extends ESIntegTestCase {
client().admin().indices().prepareRefresh().execute().actionGet(); client().admin().indices().prepareRefresh().execute().actionGet();
// Create a polygon crossing longitude 180 with hole. // Create a polygon crossing longitude 180 with hole.
builder = ShapeBuilder.newPolygon() builder = ShapeBuilders.newPolygon()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10) .point(170, -10).point(190, -10).point(190, 10).point(170, 10)
.hole().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close() .hole().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close()
.close(); .close();
@ -376,25 +376,25 @@ public class GeoFilterIT extends ESIntegTestCase {
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(174, -4))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(174, -4)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 1); assertHitCount(result, 1);
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(-174, -4))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(-174, -4)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 1); assertHitCount(result, 1);
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(180, -4))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(180, -4)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 0); assertHitCount(result, 0);
result = client().prepareSearch() result = client().prepareSearch()
.setQuery(matchAllQuery()) .setQuery(matchAllQuery())
.setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilder.newPoint(180, -6))) .setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(180, -6)))
.execute().actionGet(); .execute().actionGet();
assertHitCount(result, 1); assertHitCount(result, 1);
} }

View File

@ -27,6 +27,7 @@ import org.elasticsearch.cluster.routing.IndexShardRoutingTable;
import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder; import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.geo.builders.ShapeBuilders;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.IndexService; import org.elasticsearch.index.IndexService;
@ -96,7 +97,7 @@ public class GeoShapeIntegrationIT extends ESIntegTestCase {
.endObject() .endObject()
.endObject())); .endObject()));
ShapeBuilder shape = ShapeBuilder.newEnvelope().topLeft(-45, 45).bottomRight(45, -45); ShapeBuilder shape = ShapeBuilders.newEnvelope().topLeft(-45, 45).bottomRight(45, -45);
SearchResponse searchResponse = client().prepareSearch() SearchResponse searchResponse = client().prepareSearch()
.setQuery(geoIntersectionQuery("location", shape)) .setQuery(geoIntersectionQuery("location", shape))
@ -141,7 +142,7 @@ public class GeoShapeIntegrationIT extends ESIntegTestCase {
.endObject())); .endObject()));
ShapeBuilder query = ShapeBuilder.newEnvelope().topLeft(-122.88, 48.62).bottomRight(-122.82, 48.54); ShapeBuilder query = ShapeBuilders.newEnvelope().topLeft(-122.88, 48.62).bottomRight(-122.82, 48.54);
// This search would fail if both geoshape indexing and geoshape filtering // This search would fail if both geoshape indexing and geoshape filtering
// used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes. // used the bottom-level optimization in SpatialPrefixTree#recursiveGetNodes.
@ -166,7 +167,7 @@ public class GeoShapeIntegrationIT extends ESIntegTestCase {
createIndex("shapes"); createIndex("shapes");
ensureGreen(); ensureGreen();
ShapeBuilder shape = ShapeBuilder.newEnvelope().topLeft(-45, 45).bottomRight(45, -45); ShapeBuilder shape = ShapeBuilders.newEnvelope().topLeft(-45, 45).bottomRight(45, -45);
indexRandom(true, indexRandom(true,
client().prepareIndex("shapes", "shape_type", "Big_Rectangle").setSource(jsonBuilder().startObject() client().prepareIndex("shapes", "shape_type", "Big_Rectangle").setSource(jsonBuilder().startObject()
@ -199,13 +200,13 @@ public class GeoShapeIntegrationIT extends ESIntegTestCase {
} }
public void testReusableBuilder() throws IOException { public void testReusableBuilder() throws IOException {
ShapeBuilder polygon = ShapeBuilder.newPolygon() ShapeBuilder polygon = ShapeBuilders.newPolygon()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10) .point(170, -10).point(190, -10).point(190, 10).point(170, 10)
.hole().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close() .hole().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close()
.close(); .close();
assertUnmodified(polygon); assertUnmodified(polygon);
ShapeBuilder linestring = ShapeBuilder.newLineString() ShapeBuilder linestring = ShapeBuilders.newLineString()
.point(170, -10).point(190, -10).point(190, 10).point(170, 10); .point(170, -10).point(190, -10).point(190, 10).point(170, 10);
assertUnmodified(linestring); assertUnmodified(linestring);
} }
@ -355,9 +356,9 @@ public class GeoShapeIntegrationIT extends ESIntegTestCase {
GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery( GeoShapeQueryBuilder filter = QueryBuilders.geoShapeQuery(
"location", "location",
ShapeBuilder.newGeometryCollection() ShapeBuilders.newGeometryCollection()
.polygon( .polygon(
ShapeBuilder.newPolygon().point(99.0, -1.0).point(99.0, 3.0).point(103.0, 3.0).point(103.0, -1.0) ShapeBuilders.newPolygon().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))).relation(ShapeRelation.INTERSECTS); .point(99.0, -1.0))).relation(ShapeRelation.INTERSECTS);
SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) SearchResponse result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get(); .setPostFilter(filter).get();
@ -365,17 +366,17 @@ public class GeoShapeIntegrationIT extends ESIntegTestCase {
assertHitCount(result, 1); assertHitCount(result, 1);
filter = QueryBuilders.geoShapeQuery( filter = QueryBuilders.geoShapeQuery(
"location", "location",
ShapeBuilder.newGeometryCollection().polygon( ShapeBuilders.newGeometryCollection().polygon(
ShapeBuilder.newPolygon().point(199.0, -11.0).point(199.0, 13.0).point(193.0, 13.0).point(193.0, -11.0) ShapeBuilders.newPolygon().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))).relation(ShapeRelation.INTERSECTS); .point(199.0, -11.0))).relation(ShapeRelation.INTERSECTS);
result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get(); .setPostFilter(filter).get();
assertSearchResponse(result); assertSearchResponse(result);
assertHitCount(result, 0); assertHitCount(result, 0);
filter = QueryBuilders.geoShapeQuery("location", ShapeBuilder.newGeometryCollection() filter = QueryBuilders.geoShapeQuery("location", ShapeBuilders.newGeometryCollection()
.polygon(ShapeBuilder.newPolygon().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)) .polygon(ShapeBuilders.newPolygon().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))
.polygon( .polygon(
ShapeBuilder.newPolygon().point(199.0, -11.0).point(199.0, 13.0).point(193.0, 13.0).point(193.0, -11.0) ShapeBuilders.newPolygon().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))).relation(ShapeRelation.INTERSECTS); .point(199.0, -11.0))).relation(ShapeRelation.INTERSECTS);
result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()) result = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery())
.setPostFilter(filter).get(); .setPostFilter(filter).get();