Skip to content

Commit

Permalink
Geo: Issue with polygons near date line
Browse files Browse the repository at this point in the history
If a polygon is constructed which overlaps the date line but has a hole which lies entirely one to one side of the date line, JTS error saying that the hole is not within the bounds of the polygon because the code which splits the polygon either side of the date line does not add the hole to the correct component of the final set of polygons.  The fix ensures this selection happens correctly.

Closes #6179
  • Loading branch information
colings86 committed Jun 2, 2014
1 parent ea80b38 commit a23e4ae
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 11 deletions.
Expand Up @@ -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
Expand Down Expand Up @@ -358,7 +352,10 @@ private static void assign(Edge[] holes, Coordinate[][] points, int numHoles, Ed
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";
Expand Down
41 changes: 41 additions & 0 deletions src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java
Expand Up @@ -25,6 +25,7 @@
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;
Expand Down Expand Up @@ -192,5 +193,45 @@ public void testLineStringWrapping() {
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);
}
}

0 comments on commit a23e4ae

Please sign in to comment.