use of org.elasticsearch.common.geo.builders.LineStringBuilder in project elasticsearch by elastic.
the class ShapeBuilderTests method testShapeWithHoleAtEdgeEndPoints.
public void testShapeWithHoleAtEdgeEndPoints() {
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-4, 2).coordinate(4, 2).coordinate(6, 0).coordinate(4, -2).coordinate(-4, -2).coordinate(-6, 0).coordinate(-4, 2));
builder.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(4, 1).coordinate(4, -1).coordinate(-4, -1).coordinate(-4, 1).coordinate(4, 1)));
Shape shape = builder.close().build();
assertPolygon(shape);
}
use of org.elasticsearch.common.geo.builders.LineStringBuilder in project elasticsearch by elastic.
the class RandomShapeGenerator method createShape.
/**
* Creates a random shape useful for randomized testing, NOTE: exercise caution when using this to build random GeometryCollections
* as creating a large random number of random shapes can result in massive resource consumption
* see: {@link GeoShapeQueryTests#testShapeFilterWithRandomGeoCollection}
*
* The following options are included
* @param nearPoint Create a shape near a provided point
* @param within Create a shape within the provided rectangle (note: if not null this will override the provided point)
* @param st Create a random shape of the provided type
* @return the ShapeBuilder for a random shape
*/
private static ShapeBuilder createShape(Random r, Point nearPoint, Rectangle within, ShapeType st, boolean validate) throws InvalidShapeException {
if (st == null) {
st = ShapeType.randomType(r);
}
if (within == null) {
within = xRandomRectangle(r, nearPoint);
}
// inside non overlapping bounding rectangles
switch(st) {
case POINT:
Point p = xRandomPointIn(r, within);
PointBuilder pb = new PointBuilder().coordinate(new Coordinate(p.getX(), p.getY(), Double.NaN));
return pb;
case MULTIPOINT:
case LINESTRING:
// for random testing having a maximum number of 10 points for a line string is more than sufficient
// if this number gets out of hand, the number of self intersections for a linestring can become
// (n^2-n)/2 and computing the relation intersection matrix will become NP-Hard
int numPoints = RandomNumbers.randomIntBetween(r, 3, 10);
CoordinatesBuilder coordinatesBuilder = new CoordinatesBuilder();
for (int i = 0; i < numPoints; ++i) {
p = xRandomPointIn(r, within);
coordinatesBuilder.coordinate(p.getX(), p.getY());
}
CoordinateCollection pcb = (st == ShapeType.MULTIPOINT) ? new MultiPointBuilder(coordinatesBuilder.build()) : new LineStringBuilder(coordinatesBuilder);
return pcb;
case MULTILINESTRING:
MultiLineStringBuilder mlsb = new MultiLineStringBuilder();
for (int i = 0; i < RandomNumbers.randomIntBetween(r, 1, 10); ++i) {
mlsb.linestring((LineStringBuilder) createShape(r, nearPoint, within, ShapeType.LINESTRING, false));
}
return mlsb;
case POLYGON:
numPoints = RandomNumbers.randomIntBetween(r, 5, 25);
Coordinate[] coordinates = new Coordinate[numPoints];
for (int i = 0; i < numPoints; ++i) {
p = (Point) createShape(r, nearPoint, within, ShapeType.POINT, false).build();
coordinates[i] = new Coordinate(p.getX(), p.getY());
}
// random point order or random linestrings can lead to invalid self-crossing polygons,
// compute the convex hull for a set of points to ensure polygon does not self cross
Geometry shell = new ConvexHull(coordinates, ctx.getGeometryFactory()).getConvexHull();
Coordinate[] shellCoords = shell.getCoordinates();
// when all else fails, use the bounding box as the polygon
if (shellCoords.length < 3) {
shellCoords = new Coordinate[4];
shellCoords[0] = new Coordinate(within.getMinX(), within.getMinY());
shellCoords[1] = new Coordinate(within.getMinX(), within.getMaxY());
shellCoords[2] = new Coordinate(within.getMaxX(), within.getMaxY());
shellCoords[3] = new Coordinate(within.getMaxX(), within.getMinY());
}
PolygonBuilder pgb = new PolygonBuilder(new CoordinatesBuilder().coordinates(shellCoords).close());
if (validate) {
// The validate flag will check for these possibilities and bail if an incorrect geometry is created
try {
pgb.build();
} catch (AssertionError | InvalidShapeException e) {
// or InvalidShapeException
return null;
}
}
return pgb;
default:
throw new ElasticsearchException("Unable to create shape of type [" + st + "]");
}
}
use of org.elasticsearch.common.geo.builders.LineStringBuilder in project elasticsearch by elastic.
the class GeoFilterIT method testShapeBuilders.
public void testShapeBuilders() {
try {
// self intersection polygon
ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-10, -10).coordinate(10, 10).coordinate(-10, 10).coordinate(10, -10).close()).build();
fail("Self intersection not detected");
} catch (InvalidShapeException e) {
}
// polygon with hole
ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close())).build();
try {
// polygon with overlapping hole
ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 11).coordinate(5, 11).coordinate(5, -5).close())).build();
fail("Self intersection not detected");
} catch (InvalidShapeException e) {
}
try {
// polygon with intersection holes
ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close())).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -6).coordinate(5, -6).coordinate(5, -4).coordinate(-5, -4).close())).build();
fail("Intersection of holes not detected");
} catch (InvalidShapeException e) {
}
try {
// Common line in polygon
ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(-5, 10).coordinate(-5, -5).coordinate(-5, 20).coordinate(10, 20).coordinate(10, -10).close()).build();
fail("Self intersection not detected");
} catch (InvalidShapeException e) {
}
// Multipolygon: polygon with hole and polygon within the whole
ShapeBuilders.newMultiPolygon().polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close()))).polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(-4, -4).coordinate(-4, 4).coordinate(4, 4).coordinate(4, -4).close())).build();
}
use of org.elasticsearch.common.geo.builders.LineStringBuilder in project elasticsearch by elastic.
the class GeoFilterIT method testShapeRelations.
public void testShapeRelations() throws Exception {
assertTrue("Intersect relation is not supported", intersectSupport);
assertTrue("Disjoint relation is not supported", disjointSupport);
assertTrue("within relation is not supported", withinSupport);
String mapping = XContentFactory.jsonBuilder().startObject().startObject("polygon").startObject("properties").startObject("area").field("type", "geo_shape").field("tree", "geohash").endObject().endObject().endObject().endObject().string();
CreateIndexRequestBuilder mappingRequest = client().admin().indices().prepareCreate("shapes").addMapping("polygon", mapping, XContentType.JSON);
mappingRequest.execute().actionGet();
client().admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet();
// 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
// the second polygon of size 4x4 equidistant from all sites
MultiPolygonBuilder polygon = ShapeBuilders.newMultiPolygon().polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close()))).polygon(new PolygonBuilder(new CoordinatesBuilder().coordinate(-4, -4).coordinate(-4, 4).coordinate(4, 4).coordinate(4, -4).close()));
BytesReference data = jsonBuilder().startObject().field("area", polygon).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data, XContentType.JSON).execute().actionGet();
client().admin().indices().prepareRefresh().execute().actionGet();
// Point in polygon
SearchResponse result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(3, 3))).execute().actionGet();
assertHitCount(result, 1);
assertFirstHit(result, hasId("1"));
// Point in polygon hole
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(4.5, 4.5))).execute().actionGet();
assertHitCount(result, 0);
// by definition the border of a polygon belongs to the inner
// so the border of a polygons hole also belongs to the inner
// of the polygon NOT the hole
// Point on polygon border
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(10.0, 5.0))).execute().actionGet();
assertHitCount(result, 1);
assertFirstHit(result, hasId("1"));
// Point on hole border
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(5.0, 2.0))).execute().actionGet();
assertHitCount(result, 1);
assertFirstHit(result, hasId("1"));
if (disjointSupport) {
// Point not in polygon
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoDisjointQuery("area", ShapeBuilders.newPoint(3, 3))).execute().actionGet();
assertHitCount(result, 0);
// Point in polygon hole
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoDisjointQuery("area", ShapeBuilders.newPoint(4.5, 4.5))).execute().actionGet();
assertHitCount(result, 1);
assertFirstHit(result, hasId("1"));
}
// Create a polygon that fills the empty area of the polygon defined above
PolygonBuilder inverse = ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close()).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-4, -4).coordinate(-4, 4).coordinate(4, 4).coordinate(4, -4).close()));
data = jsonBuilder().startObject().field("area", inverse).endObject().bytes();
client().prepareIndex("shapes", "polygon", "2").setSource(data, XContentType.JSON).execute().actionGet();
client().admin().indices().prepareRefresh().execute().actionGet();
// re-check point on polygon hole
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(4.5, 4.5))).execute().actionGet();
assertHitCount(result, 1);
assertFirstHit(result, hasId("2"));
// Create Polygon with hole and common edge
PolygonBuilder builder = ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(10, 5).coordinate(10, -5).close()));
if (withinSupport) {
// Polygon WithIn Polygon
builder = ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(-30, -30).coordinate(-30, 30).coordinate(30, 30).coordinate(30, -30).close());
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoWithinQuery("area", builder)).execute().actionGet();
assertHitCount(result, 2);
}
// Create a polygon crossing longitude 180.
builder = ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close());
data = jsonBuilder().startObject().field("area", builder).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data, XContentType.JSON).execute().actionGet();
client().admin().indices().prepareRefresh().execute().actionGet();
// Create a polygon crossing longitude 180 with hole.
builder = ShapeBuilders.newPolygon(new CoordinatesBuilder().coordinate(170, -10).coordinate(190, -10).coordinate(190, 10).coordinate(170, 10).close()).hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(175, -5).coordinate(185, -5).coordinate(185, 5).coordinate(175, 5).close()));
data = jsonBuilder().startObject().field("area", builder).endObject().bytes();
client().prepareIndex("shapes", "polygon", "1").setSource(data, XContentType.JSON).execute().actionGet();
client().admin().indices().prepareRefresh().execute().actionGet();
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(174, -4))).execute().actionGet();
assertHitCount(result, 1);
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(-174, -4))).execute().actionGet();
assertHitCount(result, 1);
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(180, -4))).execute().actionGet();
assertHitCount(result, 0);
result = client().prepareSearch().setQuery(matchAllQuery()).setPostFilter(QueryBuilders.geoIntersectionQuery("area", ShapeBuilders.newPoint(180, -6))).execute().actionGet();
assertHitCount(result, 1);
}
Aggregations