From 30721c240014afa9c7751c06d500a250177740b4 Mon Sep 17 00:00:00 2001 From: iverase Date: Thu, 19 Mar 2020 16:28:54 +0100 Subject: [PATCH 1/3] Handle properly indexing rectangles that crosses the dateline --- .../index/mapper/GeoShapeIndexer.java | 11 +++++++++- .../search/geo/GeoShapeQueryTests.java | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java index 9a103471a21a3..4eca7087acb0e 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java @@ -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; @@ -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.getMaxX(), GeoUtils.MAX_LON, r.getMaxY(), r.getMinY()); + addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(left))); + Rectangle right = new Rectangle(GeoUtils.MIN_LON, r.getMaxLon(), r.getMaxY(), r.getMinY()); + addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(right))); + + } else { + addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(r))); + } return null; } diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java index 032c6d68766be..eca23aba9eab0 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -791,4 +791,24 @@ public void testDistanceQuery() throws Exception { .get(); assertEquals(0, response.getHits().getTotalHits().value); } + + public void testIndexRectangleSpanningDateLine() throws Exception { + String mapping = Strings.toString(createRandomMapping()); + + client().admin().indices().prepareCreate("test").setMapping(mapping).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").setId("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); + } } From 6cb8bc697c87a360073f9b239afebe189a40cbe6 Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 20 Mar 2020 16:50:59 +0100 Subject: [PATCH 2/3] use Lat / Lon consistently --- .../java/org/elasticsearch/index/mapper/GeoShapeIndexer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java index 4eca7087acb0e..4dc368612c9aa 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java @@ -263,9 +263,9 @@ public Void visit(Polygon polygon) { @Override public Void visit(Rectangle r) { if (r.getMinLon() > r.getMaxLon()) { - Rectangle left = new Rectangle(r.getMaxX(), GeoUtils.MAX_LON, r.getMaxY(), r.getMinY()); + 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.getMaxY(), r.getMinY()); + Rectangle right = new Rectangle(GeoUtils.MIN_LON, r.getMaxLon(), r.getMaxLat(), r.getMinLat()); addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(right))); } else { From 10591385108a95e5c959a09096822d703c8725ba Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 20 Mar 2020 17:05:32 +0100 Subject: [PATCH 3/3] add test in GeometryIndexerTests --- .../common/geo/GeometryIndexerTests.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java b/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java index f5828aad13ee1..ddee41639cd3c 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java @@ -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; @@ -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; @@ -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 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(