Skip to content

Commit 0a50821

Browse files
authored
Geo: Do not normalize the longitude with value -180 for Lucene shapes (#37299)
Lucene based shapes should not normalize the longitude value -180 to 180.
1 parent 360c430 commit 0a50821

File tree

3 files changed

+89
-2
lines changed

3 files changed

+89
-2
lines changed

server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ protected static org.apache.lucene.geo.Polygon polygonLucene(Coordinate[][] poly
342342
holes = new org.apache.lucene.geo.Polygon[polygon.length - 1];
343343
for (int i = 0; i < holes.length; ++i) {
344344
Coordinate[] coords = polygon[i+1];
345+
//We do not have holes on the dateline as they get eliminated
346+
//when breaking the polygon around it.
345347
double[] x = new double[coords.length];
346348
double[] y = new double[coords.length];
347349
for (int c = 0; c < coords.length; ++c) {
@@ -357,7 +359,9 @@ protected static org.apache.lucene.geo.Polygon polygonLucene(Coordinate[][] poly
357359
double[] x = new double[shell.length];
358360
double[] y = new double[shell.length];
359361
for (int i = 0; i < shell.length; ++i) {
360-
x[i] = normalizeLon(shell[i].x);
362+
//Lucene Tessellator treats different +180 and -180 and we should keep the sign.
363+
//normalizeLon method excludes -180.
364+
x[i] = Math.abs(shell[i].x) > 180 ? normalizeLon(shell[i].x) : shell[i].x;
361365
y[i] = normalizeLat(shell[i].y);
362366
}
363367

server/src/test/java/org/elasticsearch/common/geo/GeoJsonShapeParserTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ public void testParseGeometryCollection() throws IOException {
11261126
),
11271127
new org.apache.lucene.geo.Polygon(
11281128
new double[] {12.142857142857142d, -12.142857142857142d, -10d, 10d, 12.142857142857142d},
1129-
new double[] {180d, 180d, -177d, -177d, 180d}
1129+
new double[] {-180d, -180d, -177d, -177d, -180d}
11301130
)
11311131
};
11321132
assertGeometryEquals(luceneExpected, geometryCollectionGeoJson, false);

server/src/test/java/org/elasticsearch/search/geo/GeoShapeIntegrationIT.java

+83
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.cluster.ClusterState;
2323
import org.elasticsearch.cluster.routing.IndexShardRoutingTable;
2424
import org.elasticsearch.common.Strings;
25+
import org.elasticsearch.common.geo.builders.PointBuilder;
2526
import org.elasticsearch.common.geo.builders.ShapeBuilder;
2627
import org.elasticsearch.common.xcontent.XContentFactory;
2728
import org.elasticsearch.common.xcontent.XContentType;
@@ -158,6 +159,88 @@ public void testIndexShapeRouting() throws Exception {
158159
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
159160
}
160161

162+
public void testIndexPolygonDateLine() throws Exception {
163+
String mappingVector = "{\n" +
164+
" \"properties\": {\n" +
165+
" \"shape\": {\n" +
166+
" \"type\": \"geo_shape\"\n" +
167+
" }\n" +
168+
" }\n" +
169+
" }";
170+
171+
String mappingQuad = "{\n" +
172+
" \"properties\": {\n" +
173+
" \"shape\": {\n" +
174+
" \"type\": \"geo_shape\",\n" +
175+
" \"tree\": \"quadtree\"\n" +
176+
" }\n" +
177+
" }\n" +
178+
" }";
179+
180+
181+
// create index
182+
assertAcked(client().admin().indices().prepareCreate("vector").addMapping("doc", mappingVector, XContentType.JSON).get());
183+
ensureGreen();
184+
185+
assertAcked(client().admin().indices().prepareCreate("quad").addMapping("doc", mappingQuad, XContentType.JSON).get());
186+
ensureGreen();
187+
188+
String source = "{\n" +
189+
" \"shape\" : \"POLYGON((179 0, -179 0, -179 2, 179 2, 179 0))\""+
190+
"}";
191+
192+
indexRandom(true, client().prepareIndex("quad", "doc", "0").setSource(source, XContentType.JSON));
193+
indexRandom(true, client().prepareIndex("vector", "doc", "0").setSource(source, XContentType.JSON));
194+
195+
SearchResponse searchResponse = client().prepareSearch("quad").setQuery(
196+
geoShapeQuery("shape", new PointBuilder(-179.75, 1))
197+
).get();
198+
199+
200+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
201+
202+
searchResponse = client().prepareSearch("quad").setQuery(
203+
geoShapeQuery("shape", new PointBuilder(90, 1))
204+
).get();
205+
206+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(0L));
207+
208+
searchResponse = client().prepareSearch("quad").setQuery(
209+
geoShapeQuery("shape", new PointBuilder(-180, 1))
210+
).get();
211+
212+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
213+
searchResponse = client().prepareSearch("quad").setQuery(
214+
geoShapeQuery("shape", new PointBuilder(180, 1))
215+
).get();
216+
217+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
218+
219+
searchResponse = client().prepareSearch("vector").setQuery(
220+
geoShapeQuery("shape", new PointBuilder(90, 1))
221+
).get();
222+
223+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(0L));
224+
225+
searchResponse = client().prepareSearch("vector").setQuery(
226+
geoShapeQuery("shape", new PointBuilder(-179.75, 1))
227+
).get();
228+
229+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
230+
231+
searchResponse = client().prepareSearch("vector").setQuery(
232+
geoShapeQuery("shape", new PointBuilder(-180, 1))
233+
).get();
234+
235+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
236+
237+
searchResponse = client().prepareSearch("vector").setQuery(
238+
geoShapeQuery("shape", new PointBuilder(180, 1))
239+
).get();
240+
241+
assertThat(searchResponse.getHits().getTotalHits().value, equalTo(1L));
242+
}
243+
161244
private String findNodeName(String index) {
162245
ClusterState state = client().admin().cluster().prepareState().get().getState();
163246
IndexShardRoutingTable shard = state.getRoutingTable().index(index).shard(0);

0 commit comments

Comments
 (0)