From 9338fc853636078005faf63151495c8369796c17 Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Mon, 22 Jul 2019 08:51:03 -0400 Subject: [PATCH] GEO: Switch to using GeoTestUtil to generate random geo shapes (#44635) Switches to more robust way of generating random test geometries by reusing lucene's GeoTestUtil. Removes duplicate random geometry generators by moving them to the test framework. Closes #37278 --- .../geo/geometry/BaseGeometryTestCase.java | 122 ------------ .../geo/geometry/GeometryCollectionTests.java | 3 +- .../elasticsearch/geo/geometry/LineTests.java | 3 +- .../geo/geometry/MultiLineTests.java | 3 +- .../geo/geometry/MultiPointTests.java | 3 +- .../geo/geometry/MultiPolygonTests.java | 3 +- .../geo/geometry/PointTests.java | 3 +- .../geo/geometry/PolygonTests.java | 3 +- .../geo/geometry/RectangleTests.java | 3 +- .../common/geo/GeoJsonSerializationTests.java | 164 ++-------------- .../elasticsearch/geo/GeometryTestUtils.java | 179 ++++++++++++++++++ 11 files changed, 206 insertions(+), 283 deletions(-) create mode 100644 test/framework/src/main/java/org/elasticsearch/geo/GeometryTestUtils.java diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/BaseGeometryTestCase.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/BaseGeometryTestCase.java index 073bff4cb75..841983da8da 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/BaseGeometryTestCase.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/BaseGeometryTestCase.java @@ -28,10 +28,7 @@ import org.elasticsearch.test.AbstractWireTestCase; import java.io.IOException; import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; abstract class BaseGeometryTestCase extends AbstractWireTestCase { @@ -131,123 +128,4 @@ abstract class BaseGeometryTestCase extends AbstractWireTest assertEquals("result", result); } - public static double randomLat() { - return randomDoubleBetween(-90, 90, true); - } - - public static double randomLon() { - return randomDoubleBetween(-180, 180, true); - } - - public static Circle randomCircle(boolean hasAlt) { - if (hasAlt) { - return new Circle(randomDoubleBetween(-90, 90, true), randomDoubleBetween(-180, 180, true), randomDouble(), - randomDoubleBetween(0, 100, false)); - } else { - return new Circle(randomDoubleBetween(-90, 90, true), randomDoubleBetween(-180, 180, true), randomDoubleBetween(0, 100, false)); - } - } - - public static Line randomLine() { - return randomLine(randomBoolean()); - } - - public static Line randomLine(boolean hasAlts) { - int size = randomIntBetween(2, 10); - double[] lats = new double[size]; - double[] lons = new double[size]; - double[] alts = hasAlts ? new double[size] : null; - for (int i = 0; i < size; i++) { - lats[i] = randomLat(); - lons[i] = randomLon(); - if (hasAlts) { - alts[i] = randomDouble(); - } - } - if (hasAlts) { - return new Line(lats, lons, alts); - } - return new Line(lats, lons); - } - - public static Point randomPoint() { - return randomPoint(randomBoolean()); - } - - public static Point randomPoint(boolean hasAlt) { - if (hasAlt) { - return new Point(randomLat(), randomLon(), randomDouble()); - } else { - return new Point(randomLat(), randomLon()); - } - } - - public static LinearRing randomLinearRing(boolean hasAlt) { - int size = randomIntBetween(3, 10); - double[] lats = new double[size + 1]; - double[] lons = new double[size + 1]; - double[] alts; - if (hasAlt) { - alts = new double[size + 1]; - } else { - alts = null; - } - for (int i = 0; i < size; i++) { - lats[i] = randomLat(); - lons[i] = randomLon(); - if (hasAlt) { - alts[i] = randomDouble(); - } - } - lats[size] = lats[0]; - lons[size] = lons[0]; - if (hasAlt) { - alts[size] = alts[0]; - return new LinearRing(lats, lons, alts); - } else { - return new LinearRing(lats, lons); - } - } - - public static Polygon randomPolygon(boolean hasAlt) { - int size = randomIntBetween(0, 10); - List holes = new ArrayList<>(); - for (int i = 0; i < size; i++) { - holes.add(randomLinearRing(hasAlt)); - } - if (holes.size() > 0) { - return new Polygon(randomLinearRing(hasAlt), holes); - } else { - return new Polygon(randomLinearRing(hasAlt)); - } - } - - public static Rectangle randomRectangle() { - double lat1 = randomLat(); - double lat2 = randomLat(); - double minLon = randomLon(); - double maxLon = randomLon(); - return new Rectangle(Math.min(lat1, lat2), Math.max(lat1, lat2), minLon, maxLon); - } - - public static GeometryCollection randomGeometryCollection(boolean hasAlt) { - return randomGeometryCollection(0, hasAlt); - } - - private static GeometryCollection randomGeometryCollection(int level, boolean hasAlt) { - int size = randomIntBetween(1, 10); - List shapes = new ArrayList<>(); - for (int i = 0; i < size; i++) { - @SuppressWarnings("unchecked") Function geometry = randomFrom( - BaseGeometryTestCase::randomCircle, - BaseGeometryTestCase::randomLine, - BaseGeometryTestCase::randomPoint, - BaseGeometryTestCase::randomPolygon, - hasAlt ? BaseGeometryTestCase::randomPoint : (b) -> randomRectangle(), - level < 3 ? (b) -> randomGeometryCollection(level + 1, b) : BaseGeometryTestCase::randomPoint // don't build too deep - ); - shapes.add(geometry.apply(hasAlt)); - } - return new GeometryCollection<>(shapes); - } } diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/GeometryCollectionTests.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/GeometryCollectionTests.java index 7d2b155c671..06f778aedaf 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/GeometryCollectionTests.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/GeometryCollectionTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.geo.geometry; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.geo.utils.StandardValidator; import org.elasticsearch.geo.utils.WellKnownText; @@ -31,7 +32,7 @@ import java.util.Collections; public class GeometryCollectionTests extends BaseGeometryTestCase> { @Override protected GeometryCollection createTestInstance(boolean hasAlt) { - return randomGeometryCollection(hasAlt); + return GeometryTestUtils.randomGeometryCollection(hasAlt); } diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/LineTests.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/LineTests.java index 1b447bad74c..ff18dcf9270 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/LineTests.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/LineTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.geo.geometry; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.geo.utils.GeometryValidator; import org.elasticsearch.geo.utils.StandardValidator; @@ -30,7 +31,7 @@ import java.text.ParseException; public class LineTests extends BaseGeometryTestCase { @Override protected Line createTestInstance(boolean hasAlt) { - return randomLine(hasAlt); + return GeometryTestUtils.randomLine(hasAlt); } public void testBasicSerialization() throws IOException, ParseException { diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiLineTests.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiLineTests.java index c406f4b485b..2b230dbbe52 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiLineTests.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiLineTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.geo.geometry; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.geo.utils.StandardValidator; import org.elasticsearch.geo.utils.WellKnownText; @@ -36,7 +37,7 @@ public class MultiLineTests extends BaseGeometryTestCase { int size = randomIntBetween(1, 10); List arr = new ArrayList(); for (int i = 0; i < size; i++) { - arr.add(randomLine(hasAlt)); + arr.add(GeometryTestUtils.randomLine(hasAlt)); } return new MultiLine(arr); } diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiPointTests.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiPointTests.java index 1d13693288b..ae0e0579289 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiPointTests.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiPointTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.geo.geometry; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.geo.utils.StandardValidator; import org.elasticsearch.geo.utils.WellKnownText; @@ -37,7 +38,7 @@ public class MultiPointTests extends BaseGeometryTestCase { int size = randomIntBetween(1, 10); List arr = new ArrayList<>(); for (int i = 0; i < size; i++) { - arr.add(randomPoint(hasAlt)); + arr.add(GeometryTestUtils.randomPoint(hasAlt)); } return new MultiPoint(arr); } diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiPolygonTests.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiPolygonTests.java index 77389dccaeb..45e05c93d13 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiPolygonTests.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/MultiPolygonTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.geo.geometry; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.geo.utils.StandardValidator; import org.elasticsearch.geo.utils.WellKnownText; @@ -36,7 +37,7 @@ public class MultiPolygonTests extends BaseGeometryTestCase { int size = randomIntBetween(1, 10); List arr = new ArrayList<>(); for (int i = 0; i < size; i++) { - arr.add(randomPolygon(hasAlt)); + arr.add(GeometryTestUtils.randomPolygon(hasAlt)); } return new MultiPolygon(arr); } diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/PointTests.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/PointTests.java index 888a0f97809..1adb3705f13 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/PointTests.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/PointTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.geo.geometry; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.geo.utils.GeometryValidator; import org.elasticsearch.geo.utils.StandardValidator; @@ -30,7 +31,7 @@ import java.text.ParseException; public class PointTests extends BaseGeometryTestCase { @Override protected Point createTestInstance(boolean hasAlt) { - return randomPoint(hasAlt); + return GeometryTestUtils.randomPoint(hasAlt); } public void testBasicSerialization() throws IOException, ParseException { diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/PolygonTests.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/PolygonTests.java index 11cbae50f46..c4a5ae5dd5a 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/PolygonTests.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/PolygonTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.geo.geometry; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.geo.utils.StandardValidator; import org.elasticsearch.geo.utils.WellKnownText; @@ -30,7 +31,7 @@ import java.util.Collections; public class PolygonTests extends BaseGeometryTestCase { @Override protected Polygon createTestInstance(boolean hasAlt) { - return randomPolygon(hasAlt); + return GeometryTestUtils.randomPolygon(hasAlt); } public void testBasicSerialization() throws IOException, ParseException { diff --git a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/RectangleTests.java b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/RectangleTests.java index ce80611cb60..a5f3e4d4686 100644 --- a/libs/geo/src/test/java/org/elasticsearch/geo/geometry/RectangleTests.java +++ b/libs/geo/src/test/java/org/elasticsearch/geo/geometry/RectangleTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.geo.geometry; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.geo.utils.GeometryValidator; import org.elasticsearch.geo.utils.StandardValidator; @@ -31,7 +32,7 @@ public class RectangleTests extends BaseGeometryTestCase { @Override protected Rectangle createTestInstance(boolean hasAlt) { assumeFalse("3rd dimension is not supported yet", hasAlt); - return randomRectangle(); + return GeometryTestUtils.randomRectangle(); } public void testBasicSerialization() throws IOException, ParseException { diff --git a/server/src/test/java/org/elasticsearch/common/geo/GeoJsonSerializationTests.java b/server/src/test/java/org/elasticsearch/common/geo/GeoJsonSerializationTests.java index 46766b4e11f..b113c8046e0 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/GeoJsonSerializationTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/GeoJsonSerializationTests.java @@ -23,28 +23,25 @@ import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.geo.geometry.Circle; +import org.elasticsearch.geo.GeometryTestUtils; import org.elasticsearch.geo.geometry.Geometry; -import org.elasticsearch.geo.geometry.GeometryCollection; -import org.elasticsearch.geo.geometry.Line; -import org.elasticsearch.geo.geometry.LinearRing; -import org.elasticsearch.geo.geometry.MultiLine; -import org.elasticsearch.geo.geometry.MultiPoint; -import org.elasticsearch.geo.geometry.MultiPolygon; -import org.elasticsearch.geo.geometry.Point; -import org.elasticsearch.geo.geometry.Polygon; -import org.elasticsearch.geo.geometry.Rectangle; import org.elasticsearch.geo.utils.GeographyValidator; import org.elasticsearch.test.AbstractXContentTestCase; import org.elasticsearch.test.ESTestCase; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; -import java.util.function.Function; import java.util.function.Supplier; +import static org.elasticsearch.geo.GeometryTestUtils.randomCircle; +import static org.elasticsearch.geo.GeometryTestUtils.randomGeometryCollection; +import static org.elasticsearch.geo.GeometryTestUtils.randomLine; +import static org.elasticsearch.geo.GeometryTestUtils.randomMultiLine; +import static org.elasticsearch.geo.GeometryTestUtils.randomMultiPoint; +import static org.elasticsearch.geo.GeometryTestUtils.randomMultiPolygon; +import static org.elasticsearch.geo.GeometryTestUtils.randomPoint; +import static org.elasticsearch.geo.GeometryTestUtils.randomPolygon; + public class GeoJsonSerializationTests extends ESTestCase { private static class GeometryWrapper implements ToXContentObject { @@ -119,7 +116,7 @@ public class GeoJsonSerializationTests extends ESTestCase { } public void testEnvelope() throws IOException { - xContentTest(GeoJsonSerializationTests::randomRectangle); + xContentTest(GeometryTestUtils::randomRectangle); } public void testGeometryCollection() throws IOException { @@ -129,143 +126,4 @@ public class GeoJsonSerializationTests extends ESTestCase { public void testCircle() throws IOException { xContentTest(() -> randomCircle(randomBoolean())); } - - public static double randomLat() { - return randomDoubleBetween(-90, 90, true); - } - - public static double randomLon() { - return randomDoubleBetween(-180, 180, true); - } - - public static Circle randomCircle(boolean hasAlt) { - if (hasAlt) { - return new Circle(randomDoubleBetween(-90, 90, true), randomDoubleBetween(-180, 180, true), randomDouble(), - randomDoubleBetween(0, 100, false)); - } else { - return new Circle(randomDoubleBetween(-90, 90, true), randomDoubleBetween(-180, 180, true), randomDoubleBetween(0, 100, false)); - } - } - - public static Line randomLine(boolean hasAlts) { - int size = randomIntBetween(2, 10); - double[] lats = new double[size]; - double[] lons = new double[size]; - double[] alts = hasAlts ? new double[size] : null; - for (int i = 0; i < size; i++) { - lats[i] = randomLat(); - lons[i] = randomLon(); - if (hasAlts) { - alts[i] = randomDouble(); - } - } - if (hasAlts) { - return new Line(lats, lons, alts); - } - return new Line(lats, lons); - } - - public static Point randomPoint(boolean hasAlt) { - if (hasAlt) { - return new Point(randomLat(), randomLon(), randomDouble()); - } else { - return new Point(randomLat(), randomLon()); - } - } - - public static MultiPoint randomMultiPoint(boolean hasAlt) { - int size = randomIntBetween(3, 10); - List points = new ArrayList<>(); - for (int i = 0; i < size; i++) { - points.add(randomPoint(hasAlt)); - } - return new MultiPoint(points); - } - - public static MultiLine randomMultiLine(boolean hasAlt) { - int size = randomIntBetween(3, 10); - List lines = new ArrayList<>(); - for (int i = 0; i < size; i++) { - lines.add(randomLine(hasAlt)); - } - return new MultiLine(lines); - } - - public static MultiPolygon randomMultiPolygon(boolean hasAlt) { - int size = randomIntBetween(3, 10); - List polygons = new ArrayList<>(); - for (int i = 0; i < size; i++) { - polygons.add(randomPolygon(hasAlt)); - } - return new MultiPolygon(polygons); - } - - public static LinearRing randomLinearRing(boolean hasAlt) { - int size = randomIntBetween(3, 10); - double[] lats = new double[size + 1]; - double[] lons = new double[size + 1]; - double[] alts; - if (hasAlt) { - alts = new double[size + 1]; - } else { - alts = null; - } - for (int i = 0; i < size; i++) { - lats[i] = randomLat(); - lons[i] = randomLon(); - if (hasAlt) { - alts[i] = randomDouble(); - } - } - lats[size] = lats[0]; - lons[size] = lons[0]; - if (hasAlt) { - alts[size] = alts[0]; - return new LinearRing(lats, lons, alts); - } else { - return new LinearRing(lats, lons); - } - } - - public static Polygon randomPolygon(boolean hasAlt) { - int size = randomIntBetween(0, 10); - List holes = new ArrayList<>(); - for (int i = 0; i < size; i++) { - holes.add(randomLinearRing(hasAlt)); - } - if (holes.size() > 0) { - return new Polygon(randomLinearRing(hasAlt), holes); - } else { - return new Polygon(randomLinearRing(hasAlt)); - } - } - - public static Rectangle randomRectangle() { - double lat1 = randomLat(); - double lat2 = randomLat(); - double minLon = randomLon(); - double maxLon = randomLon(); - return new Rectangle(Math.min(lat1, lat2), Math.max(lat1, lat2), minLon, maxLon); - } - - public static GeometryCollection randomGeometryCollection(boolean hasAlt) { - return randomGeometryCollection(0, hasAlt); - } - - private static GeometryCollection randomGeometryCollection(int level, boolean hasAlt) { - int size = randomIntBetween(1, 10); - List shapes = new ArrayList<>(); - for (int i = 0; i < size; i++) { - @SuppressWarnings("unchecked") Function geometry = randomFrom( - GeoJsonSerializationTests::randomCircle, - GeoJsonSerializationTests::randomLine, - GeoJsonSerializationTests::randomPoint, - GeoJsonSerializationTests::randomPolygon, - hasAlt ? GeoJsonSerializationTests::randomPoint : (b) -> randomRectangle(), - level < 3 ? (b) -> randomGeometryCollection(level + 1, b) : GeoJsonSerializationTests::randomPoint // don't build too deep - ); - shapes.add(geometry.apply(hasAlt)); - } - return new GeometryCollection<>(shapes); - } } diff --git a/test/framework/src/main/java/org/elasticsearch/geo/GeometryTestUtils.java b/test/framework/src/main/java/org/elasticsearch/geo/GeometryTestUtils.java new file mode 100644 index 00000000000..626f9b618d7 --- /dev/null +++ b/test/framework/src/main/java/org/elasticsearch/geo/GeometryTestUtils.java @@ -0,0 +1,179 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.geo; + +import org.apache.lucene.geo.GeoTestUtil; +import org.elasticsearch.geo.geometry.Circle; +import org.elasticsearch.geo.geometry.Geometry; +import org.elasticsearch.geo.geometry.GeometryCollection; +import org.elasticsearch.geo.geometry.Line; +import org.elasticsearch.geo.geometry.LinearRing; +import org.elasticsearch.geo.geometry.MultiLine; +import org.elasticsearch.geo.geometry.MultiPoint; +import org.elasticsearch.geo.geometry.MultiPolygon; +import org.elasticsearch.geo.geometry.Point; +import org.elasticsearch.geo.geometry.Polygon; +import org.elasticsearch.geo.geometry.Rectangle; +import org.elasticsearch.test.ESTestCase; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +public class GeometryTestUtils { + + public static double randomLat() { + return GeoTestUtil.nextLatitude(); + } + + public static double randomLon() { + return GeoTestUtil.nextLongitude(); + } + + public static double randomAlt() { + return ESTestCase.randomDouble(); + } + + public static Circle randomCircle(boolean hasAlt) { + if (hasAlt) { + return new Circle(randomLat(), randomLon(), ESTestCase.randomDouble(), + ESTestCase.randomDoubleBetween(0, 100, false)); + } else { + return new Circle(randomLat(), randomLon(), ESTestCase.randomDoubleBetween(0, 100, false)); + } + } + + public static Line randomLine(boolean hasAlts) { + int size = ESTestCase.randomIntBetween(2, 10); + double[] lats = new double[size]; + double[] lons = new double[size]; + double[] alts = hasAlts ? new double[size] : null; + for (int i = 0; i < size; i++) { + lats[i] = randomLat(); + lons[i] = randomLon(); + if (hasAlts) { + alts[i] = randomAlt(); + } + } + if (hasAlts) { + return new Line(lats, lons, alts); + } + return new Line(lats, lons); + } + + public static Point randomPoint() { + return randomPoint(ESTestCase.randomBoolean()); + } + + public static Point randomPoint(boolean hasAlt) { + if (hasAlt) { + return new Point(randomLat(), randomLon(), randomAlt()); + } else { + return new Point(randomLat(), randomLon()); + } + } + + public static Polygon randomPolygon(boolean hasAlt) { + org.apache.lucene.geo.Polygon lucenePolygon = GeoTestUtil.nextPolygon(); + if (lucenePolygon.numHoles() > 0) { + org.apache.lucene.geo.Polygon[] luceneHoles = lucenePolygon.getHoles(); + List holes = new ArrayList<>(); + for (int i = 0; i < lucenePolygon.numHoles(); i++) { + holes.add(linearRing(luceneHoles[i], hasAlt)); + } + return new Polygon(linearRing(lucenePolygon, hasAlt), holes); + } + return new Polygon(linearRing(lucenePolygon, hasAlt)); + } + + + private static double[] randomAltRing(int size) { + double[] alts = new double[size]; + for (int i = 0; i < size - 1; i++) { + alts[i] = randomAlt(); + } + alts[size - 1] = alts[0]; + return alts; + } + + private static LinearRing linearRing(org.apache.lucene.geo.Polygon polygon, boolean generateAlts) { + if (generateAlts) { + return new LinearRing(polygon.getPolyLats(), polygon.getPolyLons(), randomAltRing(polygon.numPoints())); + } else { + return new LinearRing(polygon.getPolyLats(), polygon.getPolyLons()); + } + } + + public static Rectangle randomRectangle() { + org.apache.lucene.geo.Rectangle rectangle = GeoTestUtil.nextBox(); + return new Rectangle(rectangle.minLat, rectangle.maxLat, rectangle.minLon, rectangle.maxLon); + } + + public static MultiPoint randomMultiPoint(boolean hasAlt) { + int size = ESTestCase.randomIntBetween(3, 10); + List points = new ArrayList<>(); + for (int i = 0; i < size; i++) { + points.add(randomPoint(hasAlt)); + } + return new MultiPoint(points); + } + + public static MultiLine randomMultiLine(boolean hasAlt) { + int size = ESTestCase.randomIntBetween(3, 10); + List lines = new ArrayList<>(); + for (int i = 0; i < size; i++) { + lines.add(randomLine(hasAlt)); + } + return new MultiLine(lines); + } + + public static MultiPolygon randomMultiPolygon(boolean hasAlt) { + int size = ESTestCase.randomIntBetween(3, 10); + List polygons = new ArrayList<>(); + for (int i = 0; i < size; i++) { + polygons.add(randomPolygon(hasAlt)); + } + return new MultiPolygon(polygons); + } + + public static GeometryCollection randomGeometryCollection(boolean hasAlt) { + return randomGeometryCollection(0, hasAlt); + } + + private static GeometryCollection randomGeometryCollection(int level, boolean hasAlt) { + int size = ESTestCase.randomIntBetween(1, 10); + List shapes = new ArrayList<>(); + for (int i = 0; i < size; i++) { + @SuppressWarnings("unchecked") Function geometry = ESTestCase.randomFrom( + GeometryTestUtils::randomCircle, + GeometryTestUtils::randomLine, + GeometryTestUtils::randomPoint, + GeometryTestUtils::randomPolygon, + GeometryTestUtils::randomMultiLine, + GeometryTestUtils::randomMultiPoint, + GeometryTestUtils::randomMultiPolygon, + hasAlt ? GeometryTestUtils::randomPoint : (b) -> randomRectangle(), + level < 3 ? (b) -> randomGeometryCollection(level + 1, b) : GeometryTestUtils::randomPoint // don't build too deep + ); + shapes.add(geometry.apply(hasAlt)); + } + return new GeometryCollection<>(shapes); + } +}