19
19
package org .elasticsearch .common .geo ;
20
20
21
21
import org .elasticsearch .common .io .stream .BytesStreamOutput ;
22
+ import org .elasticsearch .geo .GeometryTestUtils ;
22
23
import org .elasticsearch .geometry .Geometry ;
23
24
import org .elasticsearch .geometry .Line ;
24
25
import org .elasticsearch .geometry .LinearRing ;
25
26
import org .elasticsearch .geometry .MultiPoint ;
26
27
import org .elasticsearch .geometry .Point ;
27
28
import org .elasticsearch .geometry .Polygon ;
28
29
import org .elasticsearch .geometry .Rectangle ;
30
+ import org .elasticsearch .index .mapper .GeoShapeIndexer ;
29
31
import org .elasticsearch .test .ESTestCase ;
30
32
31
33
import java .io .IOException ;
32
34
import java .util .Arrays ;
33
35
import java .util .Collections ;
34
36
import java .util .List ;
37
+ import java .util .function .Function ;
35
38
39
+ import static org .elasticsearch .geo .GeometryTestUtils .fold ;
40
+ import static org .elasticsearch .geo .GeometryTestUtils .randomPoint ;
36
41
import static org .hamcrest .Matchers .equalTo ;
37
42
38
43
public class GeometryTreeTests extends ESTestCase {
@@ -56,8 +61,8 @@ public void testRectangleShape() throws IOException {
56
61
57
62
assertThat (Extent .fromPoints (minX , minY , maxX , maxY ), equalTo (reader .getExtent ()));
58
63
// encoder loses precision when casting to integer, so centroid is calculated using integer division here
59
- assertThat (reader .getCentroidX (), equalTo ((double ) ((minX + maxX )/ 2 )));
60
- assertThat (reader .getCentroidY (), equalTo ((double ) ((minY + maxY )/ 2 )));
64
+ assertThat (reader .getCentroidX (), equalTo ((double ) ((minX + maxX ) / 2 )));
65
+ assertThat (reader .getCentroidY (), equalTo ((double ) ((minY + maxY ) / 2 )));
61
66
62
67
// box-query touches bottom-left corner
63
68
assertTrue (reader .intersects (Extent .fromPoints (minX - randomIntBetween (1 , 10 ), minY - randomIntBetween (1 , 10 ), minX , minY )));
@@ -117,8 +122,8 @@ public void testPacManPolygon() throws Exception {
117
122
118
123
// adapted from org.apache.lucene.geo.TestPolygon2D#testMultiPolygon
119
124
public void testPolygonWithHole () throws Exception {
120
- Polygon polyWithHole = new Polygon (new LinearRing (new double [] { -50 , 50 , 50 , -50 , -50 }, new double [] { -50 , -50 , 50 , 50 , -50 }),
121
- Collections .singletonList (new LinearRing (new double [] { -10 , 10 , 10 , -10 , -10 }, new double [] { -10 , -10 , 10 , 10 , -10 })));
125
+ Polygon polyWithHole = new Polygon (new LinearRing (new double []{ -50 , 50 , 50 , -50 , -50 }, new double []{ -50 , -50 , 50 , 50 , -50 }),
126
+ Collections .singletonList (new LinearRing (new double []{ -10 , 10 , 10 , -10 , -10 }, new double []{ -10 , -10 , 10 , 10 , -10 })));
122
127
123
128
GeometryTreeWriter writer = new GeometryTreeWriter (polyWithHole , TestCoordinateEncoder .INSTANCE );
124
129
BytesStreamOutput output = new BytesStreamOutput ();
@@ -135,13 +140,13 @@ public void testPolygonWithHole() throws Exception {
135
140
}
136
141
137
142
public void testCombPolygon () throws Exception {
138
- double [] px = {0 , 10 , 10 , 20 , 20 , 30 , 30 , 40 , 40 , 50 , 50 , 0 , 0 };
139
- double [] py = {0 , 0 , 20 , 20 , 0 , 0 , 20 , 20 , 0 , 0 , 30 , 30 , 0 };
143
+ double [] px = {0 , 10 , 10 , 20 , 20 , 30 , 30 , 40 , 40 , 50 , 50 , 0 , 0 };
144
+ double [] py = {0 , 0 , 20 , 20 , 0 , 0 , 20 , 20 , 0 , 0 , 30 , 30 , 0 };
140
145
141
146
double [] hx = {21 , 21 , 29 , 29 , 21 };
142
147
double [] hy = {1 , 20 , 20 , 1 , 1 };
143
148
144
- Polygon polyWithHole = new Polygon (new LinearRing (px , py ), Collections .singletonList (new LinearRing (hx , hy )));
149
+ Polygon polyWithHole = new Polygon (new LinearRing (px , py ), Collections .singletonList (new LinearRing (hx , hy )));
145
150
// test cell crossing poly
146
151
GeometryTreeWriter writer = new GeometryTreeWriter (polyWithHole , TestCoordinateEncoder .INSTANCE );
147
152
BytesStreamOutput output = new BytesStreamOutput ();
@@ -217,4 +222,53 @@ public void testPacManPoints() throws Exception {
217
222
GeometryTreeReader reader = new GeometryTreeReader (output .bytes ().toBytesRef (), TestCoordinateEncoder .INSTANCE );
218
223
assertTrue (reader .intersects (Extent .fromPoints (xMin , yMin , xMax , yMax )));
219
224
}
225
+
226
+ @ AwaitsFix (bugUrl = "https://github.com/elastic/elasticsearch/issues/37206" )
227
+ public void testRandomGeometryIntersection () throws IOException {
228
+ int testPointCount = randomIntBetween (100 , 200 );
229
+ Point [] testPoints = new Point [testPointCount ];
230
+ double extentSize = randomDoubleBetween (1 , 10 , true );
231
+ boolean [] intersects = new boolean [testPointCount ];
232
+ for (int i = 0 ; i < testPoints .length ; i ++) {
233
+ testPoints [i ] = randomPoint (false );
234
+ }
235
+
236
+ Geometry geometry = randomGeometryTreeGeometry ();
237
+ GeoShapeIndexer indexer = new GeoShapeIndexer (true , "test" );
238
+ geometry = indexer .prepareForIndexing (geometry );
239
+
240
+ for (int i = 0 ; i < testPointCount ; i ++) {
241
+ int cur = i ;
242
+ intersects [cur ] = fold (geometry , false , (g , s ) -> s || intersects (g , testPoints [cur ], extentSize ));
243
+ }
244
+
245
+ for (int i = 0 ; i < testPointCount ; i ++) {
246
+ assertEquals (intersects [i ], intersects (geometry , testPoints [i ], extentSize ));
247
+ }
248
+ }
249
+
250
+ private boolean intersects (Geometry g , Point p , double extentSize ) throws IOException {
251
+ // TODO: Make this independent from GeometryTree
252
+ GeometryTreeWriter writer = new GeometryTreeWriter (g , GeoShapeCoordinateEncoder .INSTANCE );
253
+ BytesStreamOutput output = new BytesStreamOutput ();
254
+ writer .writeTo (output );
255
+ output .close ();
256
+ int xMin = GeoShapeCoordinateEncoder .INSTANCE .encodeX (Math .max (p .getX () - extentSize , -180.0 ));
257
+ int xMax = GeoShapeCoordinateEncoder .INSTANCE .encodeX (Math .min (p .getX () + extentSize , 180.0 ));
258
+ int yMin = GeoShapeCoordinateEncoder .INSTANCE .encodeY (Math .max (p .getY () - extentSize , -90 ));
259
+ int yMax = GeoShapeCoordinateEncoder .INSTANCE .encodeY (Math .min (p .getY () + extentSize , 90 ));
260
+ GeometryTreeReader reader = new GeometryTreeReader (output .bytes ().toBytesRef (), GeoShapeCoordinateEncoder .INSTANCE );
261
+ return reader .intersects (Extent .fromPoints (xMin , yMin , xMax , yMax ));
262
+ }
263
+
264
+ private static Geometry randomGeometryTreeGeometry () {
265
+ @ SuppressWarnings ("unchecked" ) Function <Boolean , Geometry > geometry = ESTestCase .randomFrom (
266
+ GeometryTestUtils ::randomLine ,
267
+ GeometryTestUtils ::randomPoint ,
268
+ GeometryTestUtils ::randomPolygon ,
269
+ GeometryTestUtils ::randomMultiLine ,
270
+ GeometryTestUtils ::randomMultiPoint
271
+ );
272
+ return geometry .apply (false );
273
+ }
220
274
}
0 commit comments