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 3e8dd4590b983..94f511a774cad 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeIndexer.java @@ -262,13 +262,29 @@ public Void visit(Polygon polygon) { @Override public Void visit(Rectangle 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 { + if (r.getMinLon() > r.getMaxLon()) { + if (r.getMinLon() == GeoUtils.MAX_LON) { + Line line = new Line(new double[] {GeoUtils.MAX_LON, GeoUtils.MAX_LON}, new double[] {r.getMaxLat(), r.getMinLat()}); + visit(line); + } else { + Rectangle left = new Rectangle(r.getMinLon(), GeoUtils.MAX_LON, r.getMaxLat(), r.getMinLat()); + visit(left); + } + if (r.getMaxLon() == GeoUtils.MIN_LON) { + Line line = new Line(new double[] {GeoUtils.MIN_LON, GeoUtils.MIN_LON}, new double[] {r.getMaxLat(), r.getMinLat()}); + visit(line); + } else { + Rectangle right = new Rectangle(GeoUtils.MIN_LON, r.getMaxLon(), r.getMaxLat(), r.getMinLat()); + visit(right); + } + } else if (r.getMinLon() == r.getMaxLon() || r.getMinLat() == r.getMaxLat()) { + if (r.getMinLat() == r.getMaxLat()) { + addFields(LatLonShape.createIndexableFields(name, r.getMinLat(), r.getMinLon())); + } else { + Line line = new Line(new double[]{r.getMinLon(), r.getMaxLon()}, new double[]{r.getMaxLat(), r.getMinLat()}); + visit(line); + } + } else { addFields(LatLonShape.createIndexableFields(name, GeoShapeUtils.toLucenePolygon(r))); } return null; 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 ba4191c0570e8..67bc0f8f84319 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/GeometryIndexerTests.java @@ -316,6 +316,66 @@ public void testRectangle() { assertEquals(fields.size(), 4); } + public void testDegeneratedRectangles() { + Rectangle indexed = new Rectangle(-179, -179, 10, -10); + Geometry processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // Rectangle is a line + List fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 1); + + indexed = new Rectangle(-179, -178, 10, 10); + processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // Rectangle is a line + fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 1); + + indexed = new Rectangle(-179, -179, 10, 10); + processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // Rectangle is a point + fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 1); + + indexed = new Rectangle(180, -179, 10, -10); + processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // Rectangle crossing the dateline, one side is a line + fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 3); + + indexed = new Rectangle(180, -179, 10, 10); + processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // Rectangle crossing the dateline, one side is a point, + // other side a line + fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 2); + + indexed = new Rectangle(-178, -180, 10, -10); + processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // Rectangle crossing the dateline, one side is a line + fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 3); + + indexed = new Rectangle(-178, -180, 10, 10); + processed = indexer.prepareForIndexing(indexed); + assertEquals(indexed, processed); + + // Rectangle crossing the dateline, one side is a point, + // other side a line + fields = indexer.indexShape(null, indexed); + assertEquals(fields.size(), 2); + } + 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(