Geo: Moving static factory methods to ShapeBuilders

Currently the abstract ShapeBuilder class serves too many different
purposes, making it hard to refactor and maintain the code. In order
to reduce the size and responsibilities, this PR moved all the
static factory methods used as a shortcut to create new shape builders
out to a new ShapeBuilders class, similar to how QueryBuilders is
used already.
This commit is contained in:
Christoph Büscher 2015-11-04 12:25:57 +01:00
parent a34b555fff
commit 0623684521
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();