Adding unit test for self intersecting polygons. Relevant to #7751 even/odd discussion

Updating documentation to describe polygon ambiguity and vertex ordering.
This commit is contained in:
Nicholas Knize 2014-12-10 15:32:30 -06:00
parent 437afd6f45
commit ac0e37449e
3 changed files with 55 additions and 2 deletions

View File

@ -157,7 +157,7 @@ units, which default to `METERS`.
For all types, both the inner `type` and `coordinates` fields are
required.
Note: In GeoJSON, and therefore Elasticsearch, the correct *coordinate
In GeoJSON, and therefore Elasticsearch, the correct *coordinate
order is longitude, latitude (X, Y)* within coordinate arrays. This
differs from many Geospatial APIs (e.g., Google Maps) that generally
use the colloquial latitude, longitude (Y, X).
@ -235,6 +235,36 @@ arrays represent the interior shapes ("holes"):
}
--------------------------------------------------
*IMPORTANT NOTE:* GeoJSON does not mandate a specific order for vertices thus ambiguous
polygons around the dateline and poles are possible. To alleviate ambiguity
the Open Geospatial Consortium (OGC)
http://www.opengeospatial.org/standards/sfa[Simple Feature Access] specification
defines the following vertex ordering:
* Outer Ring - Counterclockwise
* Inner Ring(s) / Holes - Clockwise
For polygons that do not cross the dateline, vertex order will not matter in
Elasticsearch. For polygons that do cross the dateline, Elasticsearch requires
vertex orderinging comply with the OGC specification. Otherwise, an unintended polygon
may be created and unexpected query/filter results will be returned.
The following provides an example of an ambiguous polygon. Elasticsearch will apply
OGC standards to eliminate ambiguity resulting in a polygon that crosses the dateline.
[source,js]
--------------------------------------------------
{
"location" : {
"type" : "polygon",
"coordinates" : [
[ [-177.0, 10.0], [176.0, 15.0], [172.0, 0.0], [176.0, -15.0], [-177.0, -10.0], [-177.0, 10.0] ],
[ [178.2, 8.2], [-178.8, 8.2], [-180.8, -8.8], [178.2, 8.8] ]
]
}
}
--------------------------------------------------
[float]
===== http://www.geojson.org/geojson-spec.html#id5[MultiPoint]

View File

@ -19,6 +19,7 @@
package org.elasticsearch.common.geo;
import com.spatial4j.core.exception.InvalidShapeException;
import com.spatial4j.core.shape.Circle;
import com.spatial4j.core.shape.Rectangle;
import com.spatial4j.core.shape.Shape;
@ -430,6 +431,28 @@ public class GeoJSONShapeParserTests extends ElasticsearchTestCase {
assertGeometryEquals(jtsGeom(expected), polygonGeoJson);
}
@Test
public void testParse_selfCrossingPolygon() throws IOException {
// test self crossing ccw poly not crossing dateline
String polygonGeoJson = XContentFactory.jsonBuilder().startObject().field("type", "Polygon")
.startArray("coordinates")
.startArray()
.startArray().value(176.0).value(15.0).endArray()
.startArray().value(-177.0).value(10.0).endArray()
.startArray().value(-177.0).value(-10.0).endArray()
.startArray().value(176.0).value(-15.0).endArray()
.startArray().value(-177.0).value(15.0).endArray()
.startArray().value(172.0).value(0.0).endArray()
.startArray().value(176.0).value(15.0).endArray()
.endArray()
.endArray()
.endObject().string();
XContentParser parser = JsonXContent.jsonXContent.createParser(polygonGeoJson);
parser.nextToken();
ElasticsearchGeoAssertions.assertValidException(parser, InvalidShapeException.class);
}
@Test
public void testParse_multiPoint() throws IOException {
String multiPointGeoJson = XContentFactory.jsonBuilder().startObject().field("type", "MultiPoint")

View File

@ -251,7 +251,7 @@ public class ElasticsearchGeoAssertions {
public static void assertValidException(XContentParser parser, Class expectedException) {
try {
ShapeBuilder.parse(parser);
ShapeBuilder.parse(parser).build();
Assert.fail("process completed successfully when " + expectedException.getName() + " expected");
} catch (Exception e) {
assert(e.getClass().equals(expectedException)):