use of org.locationtech.spatial4j.exception.InvalidShapeException in project elasticsearch by elastic.
the class RandomShapeGenerator method createShape.
private static ShapeBuilder createShape(Random r, Point nearPoint, Rectangle within, ShapeType st) throws InvalidShapeException {
ShapeBuilder shape;
short i = 0;
do {
shape = createShape(r, nearPoint, within, st, ST_VALIDATE);
if (shape != null) {
return shape;
}
} while (++i != 100);
throw new InvalidShapeException("Unable to create a valid random shape with provided seed");
}
use of org.locationtech.spatial4j.exception.InvalidShapeException in project lucene-solr by apache.
the class SpatialUtils method parseRectangle.
/**
* Parses {@code str} in the format of '[minPoint TO maxPoint]' where {@code minPoint} is the lower left corner
* and maxPoint is the upper-right corner of the bounding box. Both corners may optionally be wrapped with a quote
* and then it's parsed via {@link #parsePoint(String, org.locationtech.spatial4j.context.SpatialContext)}.
* @param str Non-null; may *not* have leading or trailing spaces
* @param ctx Non-null
* @return the Rectangle
* @throws InvalidShapeException If for any reason there was a problem parsing the string or creating the rectangle.
*/
public static Rectangle parseRectangle(String str, SpatialContext ctx) throws InvalidShapeException {
//note we don't do generic whitespace, just a literal space char detection
try {
int toIdx = str.indexOf(" TO ");
if (toIdx == -1 || str.charAt(0) != '[' || str.charAt(str.length() - 1) != ']') {
throw new InvalidShapeException("expecting '[bottomLeft TO topRight]'");
}
String leftPart = unwrapQuotes(str.substring(1, toIdx).trim());
String rightPart = unwrapQuotes(str.substring(toIdx + " TO ".length(), str.length() - 1).trim());
return ctx.makeRectangle(parsePoint(leftPart, ctx), parsePoint(rightPart, ctx));
} catch (InvalidShapeException e) {
throw e;
} catch (Exception e) {
throw new InvalidShapeException(e.toString(), e);
}
}
use of org.locationtech.spatial4j.exception.InvalidShapeException in project elasticsearch by elastic.
the class PolygonBuilder method concat.
/**
* Concatenate a set of points to a polygon
*
* @param component
* component id of the polygon
* @param direction
* direction of the ring
* @param points
* list of points to concatenate
* @param pointOffset
* index of the first point
* @param edges
* Array of edges to write the result to
* @param edgeOffset
* index of the first edge in the result
* @param length
* number of points to use
* @return the edges creates
*/
private static Edge[] concat(int component, boolean direction, Coordinate[] points, final int pointOffset, Edge[] edges, final int edgeOffset, int length) {
assert edges.length >= length + edgeOffset;
assert points.length >= length + pointOffset;
edges[edgeOffset] = new Edge(points[pointOffset], null);
for (int i = 1; i < length; i++) {
if (direction) {
edges[edgeOffset + i] = new Edge(points[pointOffset + i], edges[edgeOffset + i - 1]);
edges[edgeOffset + i].component = component;
} else if (!edges[edgeOffset + i - 1].coordinate.equals(points[pointOffset + i])) {
edges[edgeOffset + i - 1].next = edges[edgeOffset + i] = new Edge(points[pointOffset + i], null);
edges[edgeOffset + i - 1].component = component;
} else {
throw new InvalidShapeException("Provided shape has duplicate consecutive coordinates at: " + points[pointOffset + i]);
}
}
if (direction) {
edges[edgeOffset].setNext(edges[edgeOffset + length - 1]);
edges[edgeOffset].component = component;
} else {
edges[edgeOffset + length - 1].setNext(edges[edgeOffset]);
edges[edgeOffset + length - 1].component = component;
}
return edges;
}
use of org.locationtech.spatial4j.exception.InvalidShapeException 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.locationtech.spatial4j.exception.InvalidShapeException 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 + "]");
}
}
Aggregations