diff --git a/src/main/java/org/elasticsearch/common/geo/builders/BasePolygonBuilder.java b/src/main/java/org/elasticsearch/common/geo/builders/BasePolygonBuilder.java index e2b7cceccdd..4de36b60e05 100644 --- a/src/main/java/org/elasticsearch/common/geo/builders/BasePolygonBuilder.java +++ b/src/main/java/org/elasticsearch/common/geo/builders/BasePolygonBuilder.java @@ -19,21 +19,15 @@ package org.elasticsearch.common.geo.builders; +import com.spatial4j.core.shape.Shape; +import com.vividsolutions.jts.geom.*; +import org.elasticsearch.common.xcontent.XContentBuilder; + import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; -import org.elasticsearch.common.xcontent.XContentBuilder; - -import com.spatial4j.core.shape.Shape; -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.GeometryFactory; -import com.vividsolutions.jts.geom.LinearRing; -import com.vividsolutions.jts.geom.MultiPolygon; -import com.vividsolutions.jts.geom.Polygon; - /** * The {@link BasePolygonBuilder} implements the groundwork to create polygons. This contains * Methods to wrap polygons at the dateline and building shapes from the data held by the @@ -358,7 +352,10 @@ public abstract class BasePolygonBuilder> extend LOGGER.debug("Holes: " + Arrays.toString(holes)); } for (int i = 0; i < numHoles; i++) { - final Edge current = holes[i]; + final Edge current = new Edge(holes[i].coordinate, holes[i].next); + // the edge intersects with itself at its own coordinate. We need intersect to be set this way so the binary search + // will get the correct position in the edge list and therefore the correct component to add the hole + current.intersect = current.coordinate; final int intersections = intersections(current.coordinate.x, edges); final int pos = Arrays.binarySearch(edges, 0, intersections, current, INTERSECTION_ORDER); assert pos < 0 : "illegal state: two edges cross the datum at the same position"; diff --git a/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java b/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java index 9bb1505db40..f2c0802fee6 100644 --- a/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java +++ b/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java @@ -25,6 +25,7 @@ import com.spatial4j.core.shape.Shape; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Polygon; +import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder; import org.elasticsearch.test.ElasticsearchTestCase; import org.junit.Test; @@ -192,5 +193,45 @@ public class ShapeBuilderTests extends ElasticsearchTestCase { assertMultiLineString(shape); } + @Test + public void testDateline() { + // view shape at https://gist.github.com/anonymous/7f1bb6d7e9cd72f5977c + // expect 3 polygons, 1 with a hole + // a giant c shape + PolygonBuilder builder = ShapeBuilder.newPolygon() + .point(-186,0) + .point(-176,0) + .point(-176,3) + .point(-183,3) + .point(-183,5) + .point(-176,5) + .point(-176,8) + .point(-186,8) + .point(-186,0); + + // 3/4 of an embedded 'c', crossing dateline once + builder.hole() + .point(-185,1) + .point(-181,1) + .point(-181,2) + .point(-184,2) + .point(-184,6) + .point(-178,6) + .point(-178,7) + .point(-185,7) + .point(-185,1); + + // embedded hole right of the dateline + builder.hole() + .point(-179,1) + .point(-177,1) + .point(-177,2) + .point(-179,2) + .point(-179,1); + + Shape shape = builder.close().build(); + + assertMultiPolygon(shape); + } }