Skip to content

Commit

Permalink
Handle properly indexing rectangles that crosses the dateline (#53810) (
Browse files Browse the repository at this point in the history
#53947)

When indexing a rectangle that crosses the dateline, we are currently not
handling it properly and we index a polygon that do not cross the dateline.
This changes generates two polygons wrapping the dateline.
  • Loading branch information
iverase authored Mar 23, 2020
1 parent cde8725 commit efd1838
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.elasticsearch.common.geo.GeoPolygonDecomposer;
import org.elasticsearch.common.geo.GeoShapeUtils;
import org.elasticsearch.common.geo.GeoShapeType;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.geometry.Circle;
import org.elasticsearch.geometry.Geometry;
import org.elasticsearch.geometry.GeometryCollection;
Expand Down Expand Up @@ -261,7 +262,15 @@ public Void visit(Polygon polygon) {

@Override
public Void visit(Rectangle r) {
addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(r)));
if (r.getMinLon() > r.getMaxLon()) {
Rectangle left = new Rectangle(r.getMinLon(), GeoUtils.MAX_LON, r.getMaxLat(), r.getMinLat());
addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(left)));
Rectangle right = new Rectangle(GeoUtils.MIN_LON, r.getMaxLon(), r.getMaxLat(), r.getMinLat());
addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(right)));

} else {
addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(r)));
}
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.elasticsearch.common.geo;

import org.apache.lucene.index.IndexableField;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
Expand All @@ -33,6 +34,7 @@
import org.elasticsearch.geometry.MultiPolygon;
import org.elasticsearch.geometry.Point;
import org.elasticsearch.geometry.Polygon;
import org.elasticsearch.geometry.Rectangle;
import org.elasticsearch.index.mapper.GeoShapeIndexer;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
Expand Down Expand Up @@ -292,6 +294,24 @@ public void testMultiPoint() {
assertEquals(indexed, indexer.prepareForIndexing(multiPoint));
}

public void testRectangle() {
Rectangle indexed = new Rectangle(-179, -178, 10, -10);
Geometry processed = indexer.prepareForIndexing(indexed);
assertEquals(indexed, processed);

// a rectangle is broken into two triangles
List<IndexableField> fields = indexer.indexShape(null, indexed);
assertEquals(fields.size(), 2);

indexed = new Rectangle(179, -179, 10, -10);
processed = indexer.prepareForIndexing(indexed);
assertEquals(indexed, processed);

// a rectangle crossing the dateline is broken into 4 triangles
fields = indexer.indexShape(null, indexed);
assertEquals(fields.size(), 4);
}

public void testPolygon() {
Polygon polygon = new Polygon(new LinearRing(new double[]{160, 200, 200, 160, 160}, new double[]{10, 10, 20, 20, 10}));
Geometry indexed = new MultiPolygon(Arrays.asList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -799,4 +799,23 @@ public void testDistanceQuery() throws Exception {
assertEquals(0, response.getHits().getTotalHits().value);
}

public void testIndexRectangleSpanningDateLine() throws Exception {
String mapping = Strings.toString(createRandomMapping());

client().admin().indices().prepareCreate("test").addMapping("type1", mapping, XContentType.JSON).get();
ensureGreen();

EnvelopeBuilder envelopeBuilder = new EnvelopeBuilder(new Coordinate(178, 10), new Coordinate(-178, -10));

XContentBuilder docSource = envelopeBuilder.toXContent(jsonBuilder().startObject().field("geo"), null).endObject();
client().prepareIndex("test", "type1", "1").setSource(docSource).setRefreshPolicy(IMMEDIATE).get();

ShapeBuilder filterShape = new PointBuilder(179, 0);

GeoShapeQueryBuilder geoShapeQueryBuilder = QueryBuilders.geoShapeQuery("geo", filterShape);
geoShapeQueryBuilder.relation(ShapeRelation.INTERSECTS);
SearchResponse result = client().prepareSearch("test").setQuery(geoShapeQueryBuilder).get();
assertSearchResponse(result);
assertHitCount(result, 1);
}
}

0 comments on commit efd1838

Please sign in to comment.