diff --git a/server/src/main/java/org/elasticsearch/common/geo/GeoUtils.java b/server/src/main/java/org/elasticsearch/common/geo/GeoUtils.java index 2f3443639cd..795cc235ce7 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/GeoUtils.java +++ b/server/src/main/java/org/elasticsearch/common/geo/GeoUtils.java @@ -233,7 +233,11 @@ public class GeoUtils { * @return The normalized longitude. */ public static double normalizeLon(double lon) { - return centeredModulus(lon, 360); + if (lon > 180d || lon <= -180d) { + lon = centeredModulus(lon, 360); + } + // avoid -0.0 + return lon + 0d; } /** @@ -250,13 +254,16 @@ public class GeoUtils { * @see #normalizePoint(GeoPoint) */ public static double normalizeLat(double lat) { - lat = centeredModulus(lat, 360); - if (lat < -90) { - lat = -180 - lat; - } else if (lat > 90) { - lat = 180 - lat; + if (lat > 90d || lat < -90d) { + lat = centeredModulus(lat, 360); + if (lat < -90) { + lat = -180 - lat; + } else if (lat > 90) { + lat = 180 - lat; + } } - return lat; + // avoid -0.0 + return lat + 0d; } /** diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java index c6a0743980f..5e2b6cc1c44 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/CircleBuilder.java @@ -159,10 +159,15 @@ public class CircleBuilder extends ShapeBuilder { } @Override - public Circle build() { + public Circle buildS4J() { return SPATIAL_CONTEXT.makeCircle(center.x, center.y, 360 * radius / unit.getEarthCircumference()); } + @Override + public Object buildLucene() { + throw new UnsupportedOperationException("CIRCLE geometry is not supported"); + } + @Override public GeoShapeType type() { return TYPE; diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/EnvelopeBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/EnvelopeBuilder.java index a878a7c6d86..5f69f4ad44d 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/EnvelopeBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/EnvelopeBuilder.java @@ -108,10 +108,15 @@ public class EnvelopeBuilder extends ShapeBuilder { } @Override - public Rectangle build() { + public Rectangle buildS4J() { return SPATIAL_CONTEXT.makeRectangle(topLeft.x, bottomRight.x, bottomRight.y, topLeft.y); } + @Override + public org.apache.lucene.geo.Rectangle buildLucene() { + return new org.apache.lucene.geo.Rectangle(bottomRight.y, topLeft.y, topLeft.x, bottomRight.x); + } + @Override public GeoShapeType type() { return TYPE; diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java index d2ff86ea63c..b6e94c012c6 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java @@ -31,6 +31,7 @@ import org.locationtech.spatial4j.shape.Shape; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -168,12 +169,12 @@ public class GeometryCollectionBuilder extends ShapeBuilder shapes = new ArrayList<>(this.shapes.size()); for (ShapeBuilder shape : this.shapes) { - shapes.add(shape.build()); + shapes.add(shape.buildS4J()); } if (shapes.size() == 1) @@ -183,6 +184,25 @@ public class GeometryCollectionBuilder extends ShapeBuilder shapes = new ArrayList<>(this.shapes.size()); + + for (ShapeBuilder shape : this.shapes) { + Object o = shape.buildLucene(); + if (o.getClass().isArray()) { + shapes.addAll(Arrays.asList((Object[])o)); + } else { + shapes.add(o); + } + } + + if (shapes.size() == 1) { + return shapes.get(0); + } + return shapes.toArray(new Object[shapes.size()]); + } + @Override public int hashCode() { return Objects.hash(shapes); diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java index 035c4566a57..07edb241cd7 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java @@ -19,6 +19,7 @@ package org.elasticsearch.common.geo.builders; +import org.apache.lucene.geo.Line; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; @@ -35,6 +36,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import static org.elasticsearch.common.geo.GeoUtils.normalizeLat; +import static org.elasticsearch.common.geo.GeoUtils.normalizeLon; + public class LineStringBuilder extends ShapeBuilder { public static final GeoShapeType TYPE = GeoShapeType.LINESTRING; @@ -101,11 +105,11 @@ public class LineStringBuilder extends ShapeBuilder strings = decompose(FACTORY, coordinates, new ArrayList()); + ArrayList strings = decomposeS4J(FACTORY, coordinates, new ArrayList()); if(strings.size() == 1) { geometry = strings.get(0); @@ -120,7 +124,23 @@ public class LineStringBuilder extends ShapeBuilder decompose(GeometryFactory factory, Coordinate[] coordinates, ArrayList strings) { + @Override + public Object buildLucene() { + // decompose linestrings crossing dateline into array of Lines + Coordinate[] coordinates = this.coordinates.toArray(new Coordinate[this.coordinates.size()]); + if (wrapdateline) { + ArrayList linestrings = decomposeLucene(coordinates, new ArrayList<>()); + if (linestrings.size() == 1) { + return linestrings.get(0); + } else { + return linestrings.toArray(new Line[linestrings.size()]); + } + } + return new Line(Arrays.stream(coordinates).mapToDouble(i->normalizeLat(i.y)).toArray(), + Arrays.stream(coordinates).mapToDouble(i->normalizeLon(i.x)).toArray()); + } + + static ArrayList decomposeS4J(GeometryFactory factory, Coordinate[] coordinates, ArrayList strings) { for(Coordinate[] part : decompose(+DATELINE, coordinates)) { for(Coordinate[] line : decompose(-DATELINE, part)) { strings.add(factory.createLineString(line)); @@ -129,6 +149,16 @@ public class LineStringBuilder extends ShapeBuilder decomposeLucene(Coordinate[] coordinates, ArrayList lines) { + for (Coordinate[] part : decompose(+DATELINE, coordinates)) { + for (Coordinate[] line : decompose(-DATELINE, part)) { + lines.add(new Line(Arrays.stream(line).mapToDouble(i->normalizeLat(i.y)).toArray(), + Arrays.stream(line).mapToDouble(i->normalizeLon(i.x)).toArray())); + } + } + return lines; + } + /** * Decompose a linestring given as array of coordinates at a vertical line. * diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java index 68da45bbf0c..9902744fc3b 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java @@ -19,6 +19,7 @@ package org.elasticsearch.common.geo.builders; +import org.apache.lucene.geo.Line; import org.elasticsearch.common.geo.GeoShapeType; import org.elasticsearch.common.geo.parsers.GeoWKTParser; import org.elasticsearch.common.geo.parsers.ShapeParser; @@ -124,12 +125,12 @@ public class MultiLineStringBuilder extends ShapeBuilder parts = new ArrayList<>(); for (LineStringBuilder line : lines) { - LineStringBuilder.decompose(FACTORY, line.coordinates(false), parts); + LineStringBuilder.decomposeS4J(FACTORY, line.coordinates(false), parts); } if(parts.size() == 1) { geometry = parts.get(0); @@ -148,6 +149,27 @@ public class MultiLineStringBuilder extends ShapeBuilder parts = new ArrayList<>(); + for (LineStringBuilder line : lines) { + LineStringBuilder.decomposeLucene(line.coordinates(false), parts); + } + if (parts.size() == 1) { + return parts.get(0); + } + return parts.toArray(new Line[parts.size()]); + } + Line[] linestrings = new Line[lines.size()]; + for (int i = 0; i < lines.size(); ++i) { + LineStringBuilder lsb = lines.get(i); + linestrings[i] = new Line(lsb.coordinates.stream().mapToDouble(c->c.y).toArray(), + lsb.coordinates.stream().mapToDouble(c->c.x).toArray()); + } + return linestrings; + } + @Override public int hashCode() { return Objects.hash(lines); diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPointBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPointBuilder.java index c39cc397a34..b559bb58117 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPointBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPointBuilder.java @@ -61,7 +61,7 @@ public class MultiPointBuilder extends ShapeBuilder, Mul } @Override - public XShapeCollection build() { + public XShapeCollection buildS4J() { //Could wrap JtsGeometry but probably slower due to conversions to/from JTS in relate() //MultiPoint geometry = FACTORY.createMultiPoint(points.toArray(new Coordinate[points.size()])); List shapes = new ArrayList<>(coordinates.size()); @@ -73,6 +73,17 @@ public class MultiPointBuilder extends ShapeBuilder, Mul return multiPoints; } + @Override + public double[][] buildLucene() { + double[][] points = new double[coordinates.size()][]; + Coordinate coord; + for (int i = 0; i < coordinates.size(); ++i) { + coord = coordinates.get(i); + points[i] = new double[] {coord.x, coord.y}; + } + return points; + } + @Override public GeoShapeType type() { return TYPE; diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java index bac74c29dd8..95c2bbc6275 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java @@ -31,6 +31,7 @@ import org.locationtech.spatial4j.shape.Shape; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Objects; @@ -162,19 +163,19 @@ public class MultiPolygonBuilder extends ShapeBuilder shapes = new ArrayList<>(this.polygons.size()); if(wrapdateline) { for (PolygonBuilder polygon : this.polygons) { for(Coordinate[][] part : polygon.coordinates()) { - shapes.add(jtsGeometry(PolygonBuilder.polygon(FACTORY, part))); + shapes.add(jtsGeometry(PolygonBuilder.polygonS4J(FACTORY, part))); } } } else { for (PolygonBuilder polygon : this.polygons) { - shapes.add(jtsGeometry(polygon.toPolygon(FACTORY))); + shapes.add(jtsGeometry(polygon.toPolygonS4J(FACTORY))); } } if (shapes.size() == 1) @@ -184,6 +185,33 @@ public class MultiPolygonBuilder extends ShapeBuilder shapes = new ArrayList<>(this.polygons.size()); + Object poly; + if (wrapdateline) { + for (PolygonBuilder polygon : this.polygons) { + poly = polygon.buildLucene(); + if (poly instanceof org.apache.lucene.geo.Polygon[]) { + shapes.addAll(Arrays.asList((org.apache.lucene.geo.Polygon[])poly)); + } else { + shapes.add((org.apache.lucene.geo.Polygon)poly); + } + } + } else { + for (int i = 0; i < this.polygons.size(); ++i) { + PolygonBuilder pb = this.polygons.get(i); + poly = pb.buildLucene(); + if (poly instanceof org.apache.lucene.geo.Polygon[]) { + shapes.addAll(Arrays.asList((org.apache.lucene.geo.Polygon[])poly)); + } else { + shapes.add((org.apache.lucene.geo.Polygon)poly); + } + } + } + return shapes.stream().toArray(org.apache.lucene.geo.Polygon[]::new); + } + @Override public int hashCode() { return Objects.hash(polygons, orientation); diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/PointBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/PointBuilder.java index f8c18f317b6..c13eca936e4 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/PointBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/PointBuilder.java @@ -19,6 +19,7 @@ package org.elasticsearch.common.geo.builders; +import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.GeoShapeType; import org.elasticsearch.common.geo.parsers.ShapeParser; import org.locationtech.spatial4j.shape.Point; @@ -84,10 +85,15 @@ public class PointBuilder extends ShapeBuilder { } @Override - public Point build() { + public Point buildS4J() { return SPATIAL_CONTEXT.makePoint(coordinates.get(0).x, coordinates.get(0).y); } + @Override + public GeoPoint buildLucene() { + return new GeoPoint(coordinates.get(0).y, coordinates.get(0).x); + } + @Override public GeoShapeType type() { return TYPE; diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java index e4d48b8df45..8f7876d2ba9 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java @@ -46,6 +46,8 @@ import java.util.Locale; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; +import static org.elasticsearch.common.geo.GeoUtils.normalizeLat; +import static org.elasticsearch.common.geo.GeoUtils.normalizeLon; import static org.apache.lucene.geo.GeoUtils.orient; /** @@ -226,8 +228,19 @@ public class PolygonBuilder extends ShapeBuilder { } @Override - public JtsGeometry build() { - return jtsGeometry(buildGeometry(FACTORY, wrapdateline)); + public JtsGeometry buildS4J() { + return jtsGeometry(buildS4JGeometry(FACTORY, wrapdateline)); + } + + @Override + public Object buildLucene() { + if (wrapdateline) { + Coordinate[][][] polygons = coordinates(); + return polygons.length == 1 + ? polygonLucene(polygons[0]) + : multipolygonLucene(polygons); + } + return toPolygonLucene(); } protected XContentBuilder coordinatesArray(XContentBuilder builder, Params params) throws IOException { @@ -250,32 +263,46 @@ public class PolygonBuilder extends ShapeBuilder { return builder; } - public Geometry buildGeometry(GeometryFactory factory, boolean fixDateline) { + public Geometry buildS4JGeometry(GeometryFactory factory, boolean fixDateline) { if(fixDateline) { Coordinate[][][] polygons = coordinates(); return polygons.length == 1 - ? polygon(factory, polygons[0]) - : multipolygon(factory, polygons); + ? polygonS4J(factory, polygons[0]) + : multipolygonS4J(factory, polygons); } else { - return toPolygon(factory); + return toPolygonS4J(factory); } } - public Polygon toPolygon() { - return toPolygon(FACTORY); + public Polygon toPolygonS4J() { + return toPolygonS4J(FACTORY); } - protected Polygon toPolygon(GeometryFactory factory) { - final LinearRing shell = linearRing(factory, this.shell.coordinates); + protected Polygon toPolygonS4J(GeometryFactory factory) { + final LinearRing shell = linearRingS4J(factory, this.shell.coordinates); final LinearRing[] holes = new LinearRing[this.holes.size()]; Iterator iterator = this.holes.iterator(); for (int i = 0; iterator.hasNext(); i++) { - holes[i] = linearRing(factory, iterator.next().coordinates); + holes[i] = linearRingS4J(factory, iterator.next().coordinates); } return factory.createPolygon(shell, holes); } - protected static LinearRing linearRing(GeometryFactory factory, List coordinates) { + public Object toPolygonLucene() { + final org.apache.lucene.geo.Polygon[] holes = new org.apache.lucene.geo.Polygon[this.holes.size()]; + for (int i = 0; i < holes.length; ++i) { + holes[i] = linearRing(this.holes.get(i).coordinates); + } + return new org.apache.lucene.geo.Polygon(this.shell.coordinates.stream().mapToDouble(i -> normalizeLat(i.y)).toArray(), + this.shell.coordinates.stream().mapToDouble(i -> normalizeLon(i.x)).toArray(), holes); + } + + protected static org.apache.lucene.geo.Polygon linearRing(List coordinates) { + return new org.apache.lucene.geo.Polygon(coordinates.stream().mapToDouble(i -> normalizeLat(i.y)).toArray(), + coordinates.stream().mapToDouble(i -> normalizeLon(i.x)).toArray()); + } + + protected static LinearRing linearRingS4J(GeometryFactory factory, List coordinates) { return factory.createLinearRing(coordinates.toArray(new Coordinate[coordinates.size()])); } @@ -293,7 +320,7 @@ public class PolygonBuilder extends ShapeBuilder { return shell.numDimensions(); } - protected static Polygon polygon(GeometryFactory factory, Coordinate[][] polygon) { + protected static Polygon polygonS4J(GeometryFactory factory, Coordinate[][] polygon) { LinearRing shell = factory.createLinearRing(polygon[0]); LinearRing[] holes; @@ -308,6 +335,35 @@ public class PolygonBuilder extends ShapeBuilder { return factory.createPolygon(shell, holes); } + protected static org.apache.lucene.geo.Polygon polygonLucene(Coordinate[][] polygon) { + org.apache.lucene.geo.Polygon[] holes; + Coordinate[] shell = polygon[0]; + if (polygon.length > 1) { + holes = new org.apache.lucene.geo.Polygon[polygon.length - 1]; + for (int i = 0; i < holes.length; ++i) { + Coordinate[] coords = polygon[i+1]; + double[] x = new double[coords.length]; + double[] y = new double[coords.length]; + for (int c = 0; c < coords.length; ++c) { + x[c] = normalizeLon(coords[c].x); + y[c] = normalizeLat(coords[c].y); + } + holes[i] = new org.apache.lucene.geo.Polygon(y, x); + } + } else { + holes = new org.apache.lucene.geo.Polygon[0]; + } + + double[] x = new double[shell.length]; + double[] y = new double[shell.length]; + for (int i = 0; i < shell.length; ++i) { + x[i] = normalizeLon(shell[i].x); + y[i] = normalizeLat(shell[i].y); + } + + return new org.apache.lucene.geo.Polygon(y, x, holes); + } + /** * Create a Multipolygon from a set of coordinates. Each primary array contains a polygon which * in turn contains an array of linestrings. These line Strings are represented as an array of @@ -318,14 +374,22 @@ public class PolygonBuilder extends ShapeBuilder { * @param polygons definition of polygons * @return a new Multipolygon */ - protected static MultiPolygon multipolygon(GeometryFactory factory, Coordinate[][][] polygons) { + protected static MultiPolygon multipolygonS4J(GeometryFactory factory, Coordinate[][][] polygons) { Polygon[] polygonSet = new Polygon[polygons.length]; for (int i = 0; i < polygonSet.length; i++) { - polygonSet[i] = polygon(factory, polygons[i]); + polygonSet[i] = polygonS4J(factory, polygons[i]); } return factory.createMultiPolygon(polygonSet); } + protected static org.apache.lucene.geo.Polygon[] multipolygonLucene(Coordinate[][][] polygons) { + org.apache.lucene.geo.Polygon[] polygonSet = new org.apache.lucene.geo.Polygon[polygons.length]; + for (int i = 0; i < polygonSet.length; ++i) { + polygonSet[i] = polygonLucene(polygons[i]); + } + return polygonSet; + } + /** * This method sets the component id of all edges in a ring to a given id and shifts the * coordinates of this component according to the dateline diff --git a/server/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java b/server/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java index e90d7261c99..365dddb70ea 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java @@ -211,7 +211,14 @@ public abstract class ShapeBuilder> * the builder looses its validity. So this method should only be called once on a builder * @return new {@link Shape} defined by the builder */ - public abstract T build(); + public abstract T buildS4J(); + + /** + * build lucene geometry. + * + * @return GeoPoint, double[][], Line, Line[], Polygon, Polygon[], Rectangle, Object[] + */ + public abstract Object buildLucene(); protected static Coordinate shift(Coordinate coordinate, double dateline) { if (dateline == 0) { diff --git a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java index d2d081a63d0..7de40fe337d 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/GeoShapeFieldMapper.java @@ -496,7 +496,7 @@ public class GeoShapeFieldMapper extends FieldMapper { if (shapeBuilder == null) { return; } - shape = shapeBuilder.build(); + shape = shapeBuilder.buildS4J(); } if (fieldType().pointsOnly() == true) { // index configured for pointsOnly diff --git a/server/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java b/server/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java index d26973e390a..537127bc635 100644 --- a/server/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java +++ b/server/src/main/java/org/elasticsearch/index/query/GeoBoundingBoxQueryBuilder.java @@ -524,7 +524,7 @@ public class GeoBoundingBoxQueryBuilder extends AbstractQueryBuilderi.y).toArray(), + Arrays.stream(coordinates).mapToDouble(i->i.x).toArray()); + assertGeometryEquals(p, polygonGeoJson, false); } public void testInvalidDimensionalPolygon() throws IOException { @@ -464,9 +495,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertPolygon(shape); + try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 2: ccw poly crossing dateline @@ -485,9 +520,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertMultiPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertMultiPolygon(shape); + try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 3: cw poly not crossing dateline @@ -506,9 +545,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertPolygon(shape); + try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 4: cw poly crossing dateline @@ -527,9 +570,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertMultiPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertMultiPolygon(shape); + try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); } } @@ -556,9 +603,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertPolygon(shape); + try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 2: ccw poly crossing dateline @@ -583,9 +634,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertMultiPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertMultiPolygon(shape); + try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 3: cw poly not crossing dateline @@ -610,11 +665,14 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); - - ElasticsearchGeoAssertions.assertPolygon(shape); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertPolygon(shape, true); } + try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); + } // test 4: cw poly crossing dateline polygonGeoJson = Strings.toString(XContentFactory.jsonBuilder().startObject().field("type", "Polygon") @@ -638,9 +696,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertMultiPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertMultiPolygon(shape); + try (XContentParser parser = createParser(JsonXContent.jsonXContent, polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); } } @@ -785,12 +847,20 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { holeCoordinates.add(new Coordinate(100.2, 0.2)); LinearRing shell = GEOMETRY_FACTORY.createLinearRing( - shellCoordinates.toArray(new Coordinate[shellCoordinates.size()])); + shellCoordinates.toArray(new Coordinate[shellCoordinates.size()])); LinearRing[] holes = new LinearRing[1]; holes[0] = GEOMETRY_FACTORY.createLinearRing( - holeCoordinates.toArray(new Coordinate[holeCoordinates.size()])); + holeCoordinates.toArray(new Coordinate[holeCoordinates.size()])); Polygon expected = GEOMETRY_FACTORY.createPolygon(shell, holes); - assertGeometryEquals(jtsGeom(expected), polygonGeoJson); + assertGeometryEquals(jtsGeom(expected), polygonGeoJson, true); + + org.apache.lucene.geo.Polygon hole = + new org.apache.lucene.geo.Polygon( + new double[] {0.8d, 0.2d, 0.2d, 0.8d, 0.8d}, new double[] {100.8d, 100.8d, 100.2d, 100.2d, 100.8d}); + org.apache.lucene.geo.Polygon p = + new org.apache.lucene.geo.Polygon( + new double[] {0d, 0d, 1d, 1d, 0d}, new double[] {100d, 101d, 101d, 100d, 100d}, hole); + assertGeometryEquals(p, polygonGeoJson, false); } public void testParseSelfCrossingPolygon() throws IOException { @@ -828,9 +898,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { .endObject(); ShapeCollection expected = shapeCollection( - SPATIAL_CONTEXT.makePoint(100, 0), - SPATIAL_CONTEXT.makePoint(101, 1.0)); - assertGeometryEquals(expected, multiPointGeoJson); + SPATIAL_CONTEXT.makePoint(100, 0), + SPATIAL_CONTEXT.makePoint(101, 1.0)); + assertGeometryEquals(expected, multiPointGeoJson, true); + + assertGeometryEquals(new double[][]{ + new double[] {100d, 0d}, + new double[] {101d, 1d}}, multiPointGeoJson, false); } @Override @@ -900,7 +974,19 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { Shape expected = shapeCollection(withoutHoles, withHoles); - assertGeometryEquals(expected, multiPolygonGeoJson); + assertGeometryEquals(expected, multiPolygonGeoJson, true); + + org.apache.lucene.geo.Polygon hole = + new org.apache.lucene.geo.Polygon( + new double[] {0.8d, 0.2d, 0.2d, 0.8d, 0.8d}, new double[] {100.8d, 100.8d, 100.2d, 100.2d, 100.8d}); + + org.apache.lucene.geo.Polygon[] polygons = new org.apache.lucene.geo.Polygon[] { + new org.apache.lucene.geo.Polygon( + new double[] {2d, 3d, 3d, 2d, 2d}, new double[] {103d, 103d, 102d, 102d, 103d}), + new org.apache.lucene.geo.Polygon( + new double[] {0d, 1d, 1d, 0d, 0d}, new double[] {101d, 101d, 100d, 100d, 101d}, hole) + }; + assertGeometryEquals(polygons, multiPolygonGeoJson, false); // test #2: multipolygon; one polygon with one hole // this test converting the multipolygon from a ShapeCollection type @@ -947,7 +1033,17 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { holes[0] = GEOMETRY_FACTORY.createLinearRing(holeCoordinates.toArray(new Coordinate[holeCoordinates.size()])); withHoles = GEOMETRY_FACTORY.createPolygon(shell, holes); - assertGeometryEquals(jtsGeom(withHoles), multiPolygonGeoJson); + assertGeometryEquals(jtsGeom(withHoles), multiPolygonGeoJson, true); + + org.apache.lucene.geo.Polygon luceneHole = + new org.apache.lucene.geo.Polygon( + new double[] {0.8d, 0.2d, 0.2d, 0.8d, 0.8d}, new double[] {100.8d, 100.8d, 100.2d, 100.2d, 100.8d}); + + org.apache.lucene.geo.Polygon[] lucenePolygons = new org.apache.lucene.geo.Polygon[] { + new org.apache.lucene.geo.Polygon( + new double[] {0d, 0d, 1d, 1d, 0d}, new double[] {100d, 101d, 101d, 100d, 100d}, luceneHole) + }; + assertGeometryEquals(lucenePolygons, multiPolygonGeoJson, false); } @Override @@ -967,20 +1063,74 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { .field("type", "Point") .startArray("coordinates").value(102.0).value(2.0).endArray() .endObject() + .startObject() + .field("type", "Polygon") + .startArray("coordinates") + .startArray() + .startArray().value(-177.0).value(10.0).endArray() + .startArray().value(176.0).value(15.0).endArray() + .startArray().value(172.0).value(0.0).endArray() + .startArray().value(176.0).value(-15.0).endArray() + .startArray().value(-177.0).value(-10.0).endArray() + .startArray().value(-177.0).value(10.0).endArray() + .endArray() + .endArray() + .endObject() .endArray() .endObject(); - Shape[] expected = new Shape[2]; + ArrayList shellCoordinates1 = new ArrayList<>(); + shellCoordinates1.add(new Coordinate(180.0, -12.142857142857142)); + shellCoordinates1.add(new Coordinate(180.0, 12.142857142857142)); + shellCoordinates1.add(new Coordinate(176.0, 15.0)); + shellCoordinates1.add(new Coordinate(172.0, 0.0)); + shellCoordinates1.add(new Coordinate(176.0, -15)); + shellCoordinates1.add(new Coordinate(180.0, -12.142857142857142)); + + ArrayList shellCoordinates2 = new ArrayList<>(); + shellCoordinates2.add(new Coordinate(-180.0, 12.142857142857142)); + shellCoordinates2.add(new Coordinate(-180.0, -12.142857142857142)); + shellCoordinates2.add(new Coordinate(-177.0, -10.0)); + shellCoordinates2.add(new Coordinate(-177.0, 10.0)); + shellCoordinates2.add(new Coordinate(-180.0, 12.142857142857142)); + + Shape[] expected = new Shape[3]; LineString expectedLineString = GEOMETRY_FACTORY.createLineString(new Coordinate[]{ - new Coordinate(100, 0), - new Coordinate(101, 1), + new Coordinate(100, 0), + new Coordinate(101, 1), }); expected[0] = jtsGeom(expectedLineString); Point expectedPoint = GEOMETRY_FACTORY.createPoint(new Coordinate(102.0, 2.0)); expected[1] = new JtsPoint(expectedPoint, SPATIAL_CONTEXT); + LinearRing shell1 = GEOMETRY_FACTORY.createLinearRing( + shellCoordinates1.toArray(new Coordinate[shellCoordinates1.size()])); + LinearRing shell2 = GEOMETRY_FACTORY.createLinearRing( + shellCoordinates2.toArray(new Coordinate[shellCoordinates2.size()])); + MultiPolygon expectedMultiPoly = GEOMETRY_FACTORY.createMultiPolygon( + new Polygon[] { + GEOMETRY_FACTORY.createPolygon(shell1), + GEOMETRY_FACTORY.createPolygon(shell2) + } + ); + expected[2] = jtsGeom(expectedMultiPoly); + //equals returns true only if geometries are in the same order - assertGeometryEquals(shapeCollection(expected), geometryCollectionGeoJson); + assertGeometryEquals(shapeCollection(expected), geometryCollectionGeoJson, true); + + Object[] luceneExpected = new Object[] { + new Line(new double[] {0d, 1d}, new double[] {100d, 101d}), + new GeoPoint(2d, 102d), + new org.apache.lucene.geo.Polygon( + new double[] {-12.142857142857142d, 12.142857142857142d, 15d, 0d, -15d, -12.142857142857142d}, + new double[] {180d, 180d, 176d, 172d, 176d, 180d} + ), + new org.apache.lucene.geo.Polygon( + new double[] {12.142857142857142d, -12.142857142857142d, -10d, 10d, 12.142857142857142d}, + new double[] {180d, 180d, -177d, -177d, 180d} + ) + }; + assertGeometryEquals(luceneExpected, geometryCollectionGeoJson, false); } public void testThatParserExtractsCorrectTypeAndCoordinatesFromArbitraryJson() throws IOException { @@ -1000,8 +1150,11 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { .startObject("lala").field("type", "NotAPoint").endObject() .endObject(); - Point expected = GEOMETRY_FACTORY.createPoint(new Coordinate(100.0, 0.0)); - assertGeometryEquals(new JtsPoint(expected, SPATIAL_CONTEXT), pointGeoJson); + Point expected = GEOMETRY_FACTORY.createPoint(new Coordinate(100.0, 0.0)); + assertGeometryEquals(new JtsPoint(expected, SPATIAL_CONTEXT), pointGeoJson, true); + + GeoPoint expectedPt = new GeoPoint(0, 100); + assertGeometryEquals(expectedPt, pointGeoJson, false); } public void testParseOrientationOption() throws IOException { @@ -1030,9 +1183,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertPolygon(shape); + try (XContentParser parser = createParser(polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 2: valid ccw (right handed system) poly not crossing dateline (with 'ccw' field) @@ -1060,9 +1217,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertPolygon(shape); + try (XContentParser parser = createParser(polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 3: valid ccw (right handed system) poly not crossing dateline (with 'counterclockwise' field) @@ -1090,9 +1251,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertPolygon(shape); + try (XContentParser parser = createParser(polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 4: valid cw (left handed system) poly crossing dateline (with 'left' field) @@ -1120,9 +1285,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertMultiPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertMultiPolygon(shape); + try (XContentParser parser = createParser(polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 5: valid cw multipoly (left handed system) poly crossing dateline (with 'cw' field) @@ -1150,9 +1319,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertMultiPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertMultiPolygon(shape); + try (XContentParser parser = createParser(polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); } // test 6: valid cw multipoly (left handed system) poly crossing dateline (with 'clockwise' field) @@ -1180,9 +1353,13 @@ public class GeoJsonShapeParserTests extends BaseGeoParsingTestCase { try (XContentParser parser = createParser(polygonGeoJson)) { parser.nextToken(); - Shape shape = ShapeParser.parse(parser).build(); + Shape shape = ShapeParser.parse(parser).buildS4J(); + ElasticsearchGeoAssertions.assertMultiPolygon(shape, true); + } - ElasticsearchGeoAssertions.assertMultiPolygon(shape); + try (XContentParser parser = createParser(polygonGeoJson)) { + parser.nextToken(); + ElasticsearchGeoAssertions.assertMultiPolygon(ShapeParser.parse(parser).buildLucene(), false); } } diff --git a/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java b/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java index 965ca234ddd..1b4c0b9dce0 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/GeoWKTShapeParserTests.java @@ -19,6 +19,7 @@ package org.elasticsearch.common.geo; import org.apache.lucene.geo.GeoTestUtil; +import org.apache.lucene.geo.Line; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.Version; @@ -58,6 +59,7 @@ import org.locationtech.spatial4j.shape.jts.JtsPoint; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.elasticsearch.common.geo.builders.ShapeBuilder.SPATIAL_CONTEXT; @@ -84,9 +86,9 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { return XContentFactory.jsonBuilder().value(wkt); } - private void assertExpected(Shape expected, ShapeBuilder builder) throws IOException { + private void assertExpected(Object expected, ShapeBuilder builder, boolean useJTS) throws IOException { XContentBuilder xContentBuilder = toWKTContent(builder, false); - assertGeometryEquals(expected, xContentBuilder); + assertGeometryEquals(expected, xContentBuilder, useJTS); } private void assertMalformed(ShapeBuilder builder) throws IOException { @@ -99,7 +101,8 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { GeoPoint p = RandomShapeGenerator.randomPoint(random()); Coordinate c = new Coordinate(p.lon(), p.lat()); Point expected = GEOMETRY_FACTORY.createPoint(c); - assertExpected(new JtsPoint(expected, SPATIAL_CONTEXT), new PointBuilder().coordinate(c)); + assertExpected(new JtsPoint(expected, SPATIAL_CONTEXT), new PointBuilder().coordinate(c), true); + assertExpected(new GeoPoint(p.lat(), p.lon()), new PointBuilder().coordinate(c), false); assertMalformed(new PointBuilder().coordinate(c)); } @@ -107,15 +110,25 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { public void testParseMultiPoint() throws IOException { int numPoints = randomIntBetween(2, 100); List coordinates = new ArrayList<>(numPoints); - Shape[] shapes = new Shape[numPoints]; - GeoPoint p = new GeoPoint(); for (int i = 0; i < numPoints; ++i) { - p.reset(GeoTestUtil.nextLatitude(), GeoTestUtil.nextLongitude()); - coordinates.add(new Coordinate(p.lon(), p.lat())); - shapes[i] = SPATIAL_CONTEXT.makePoint(p.lon(), p.lat()); + coordinates.add(new Coordinate(GeoTestUtil.nextLongitude(), GeoTestUtil.nextLatitude())); + } + + Shape[] shapes = new Shape[numPoints]; + for (int i = 0; i < numPoints; ++i) { + Coordinate c = coordinates.get(i); + shapes[i] = SPATIAL_CONTEXT.makePoint(c.x, c.y); } ShapeCollection expected = shapeCollection(shapes); - assertExpected(expected, new MultiPointBuilder(coordinates)); + assertExpected(expected, new MultiPointBuilder(coordinates), true); + + double[][] luceneShapes = new double[numPoints][2]; + for (int i = 0; i < numPoints; ++i) { + Coordinate c = coordinates.get(i); + luceneShapes[i][0] = c.x; + luceneShapes[i][1] = c.y; + } + assertExpected(luceneShapes, new MultiPointBuilder(coordinates), false); assertMalformed(new MultiPointBuilder(coordinates)); } @@ -133,8 +146,17 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { @Override public void testParseLineString() throws IOException { List coordinates = randomLineStringCoords(); + LineString expected = GEOMETRY_FACTORY.createLineString(coordinates.toArray(new Coordinate[coordinates.size()])); - assertExpected(jtsGeom(expected), new LineStringBuilder(coordinates)); + assertExpected(jtsGeom(expected), new LineStringBuilder(coordinates), true); + + double[] lats = new double[coordinates.size()]; + double[] lons = new double[lats.length]; + for (int i = 0; i < lats.length; ++i) { + lats[i] = coordinates.get(i).y; + lons[i] = coordinates.get(i).x; + } + assertExpected(new Line(lats, lons), new LineStringBuilder(coordinates), false); } @Override @@ -148,9 +170,18 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { lineStrings.add(GEOMETRY_FACTORY.createLineString(coords)); builder.linestring(new LineStringBuilder(lsc)); } + MultiLineString expected = GEOMETRY_FACTORY.createMultiLineString( lineStrings.toArray(new LineString[lineStrings.size()])); - assertExpected(jtsGeom(expected), builder); + assertExpected(jtsGeom(expected), builder, true); + + Line[] lines = new Line[lineStrings.size()]; + for (int j = 0; j < lineStrings.size(); ++j) { + Coordinate[] c = lineStrings.get(j).getCoordinates(); + lines[j] = new Line(Arrays.stream(c).mapToDouble(i->i.y).toArray(), + Arrays.stream(c).mapToDouble(i->i.x).toArray()); + } + assertExpected(lines, builder, false); assertMalformed(builder); } @@ -159,9 +190,10 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { PolygonBuilder builder = PolygonBuilder.class.cast( RandomShapeGenerator.createShape(random(), RandomShapeGenerator.ShapeType.POLYGON)); Coordinate[] coords = builder.coordinates()[0][0]; + LinearRing shell = GEOMETRY_FACTORY.createLinearRing(coords); Polygon expected = GEOMETRY_FACTORY.createPolygon(shell, null); - assertExpected(jtsGeom(expected), builder); + assertExpected(jtsGeom(expected), builder, true); assertMalformed(builder); } @@ -180,8 +212,9 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { shell = GEOMETRY_FACTORY.createLinearRing(coordinates); shapes[i] = GEOMETRY_FACTORY.createPolygon(shell, null); } + Shape expected = shapeCollection(shapes); - assertExpected(expected, builder); + assertExpected(expected, builder, true); assertMalformed(builder); } @@ -210,8 +243,15 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { holes[0] = GEOMETRY_FACTORY.createLinearRing( holeCoordinates.toArray(new Coordinate[holeCoordinates.size()])); Polygon expected = GEOMETRY_FACTORY.createPolygon(shell, holes); + assertExpected(jtsGeom(expected), polygonWithHole, true); - assertExpected(jtsGeom(expected), polygonWithHole); + org.apache.lucene.geo.Polygon hole = + new org.apache.lucene.geo.Polygon( + new double[] {0.8d, 0.8d, 0.2d, 0.2d, 0.8d}, new double[] {100.2d, 100.8d, 100.8d, 100.2d, 100.2d}); + org.apache.lucene.geo.Polygon p = + new org.apache.lucene.geo.Polygon( + new double[] {0d, 1d, 1d, 0d, 0d}, new double[] {101d, 101d, 100d, 100d, 101d}, hole); + assertExpected(p, polygonWithHole, false); assertMalformed(polygonWithHole); } @@ -370,8 +410,10 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { public void testParseEnvelope() throws IOException { org.apache.lucene.geo.Rectangle r = GeoTestUtil.nextBox(); EnvelopeBuilder builder = new EnvelopeBuilder(new Coordinate(r.minLon, r.maxLat), new Coordinate(r.maxLon, r.minLat)); + Rectangle expected = SPATIAL_CONTEXT.makeRectangle(r.minLon, r.maxLon, r.minLat, r.maxLat); - assertExpected(expected, builder); + assertExpected(expected, builder, true); + assertExpected(r, builder, false); assertMalformed(builder); } @@ -386,10 +428,15 @@ public class GeoWKTShapeParserTests extends BaseGeoParsingTestCase { // assert empty shape collection GeometryCollectionBuilder builder = new GeometryCollectionBuilder(); Shape[] expected = new Shape[0]; - assertEquals(shapeCollection(expected).isEmpty(), builder.build().isEmpty()); + if (randomBoolean()) { + assertEquals(shapeCollection(expected).isEmpty(), builder.buildS4J().isEmpty()); + } else { + assertEquals(shapeCollection(expected).isEmpty(), ((Object[])builder.buildLucene()).length == 0); + } } else { GeometryCollectionBuilder gcb = RandomShapeGenerator.createGeometryCollection(random()); - assertExpected(gcb.build(), gcb); + assertExpected(gcb.buildS4J(), gcb, true); + assertExpected(gcb.buildLucene(), gcb, false); } } diff --git a/server/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java b/server/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java index 5dcc811b0c6..8b8bd2285ca 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java @@ -36,7 +36,6 @@ import org.locationtech.spatial4j.exception.InvalidShapeException; import org.locationtech.spatial4j.shape.Circle; import org.locationtech.spatial4j.shape.Point; import org.locationtech.spatial4j.shape.Rectangle; -import org.locationtech.spatial4j.shape.Shape; import org.locationtech.spatial4j.shape.impl.PointImpl; import static org.elasticsearch.test.hamcrest.ElasticsearchGeoAssertions.assertMultiLineString; @@ -49,65 +48,109 @@ import static org.hamcrest.Matchers.containsString; public class ShapeBuilderTests extends ESTestCase { public void testNewPoint() { - Point point = new PointBuilder().coordinate(-100, 45).build(); + PointBuilder pb = new PointBuilder().coordinate(-100, 45); + Point point = pb.buildS4J(); assertEquals(-100D, point.getX(), 0.0d); assertEquals(45D, point.getY(), 0.0d); + GeoPoint geoPoint = pb.buildLucene(); + assertEquals(-100D, geoPoint.getLon(), 0.0d); + assertEquals(45D, geoPoint.getLat(), 0.0d); } public void testNewRectangle() { - Rectangle rectangle = new EnvelopeBuilder(new Coordinate(-45, 30), new Coordinate(45, -30)).build(); + EnvelopeBuilder eb = new EnvelopeBuilder(new Coordinate(-45, 30), new Coordinate(45, -30)); + Rectangle rectangle = eb.buildS4J(); assertEquals(-45D, rectangle.getMinX(), 0.0d); assertEquals(-30D, rectangle.getMinY(), 0.0d); assertEquals(45D, rectangle.getMaxX(), 0.0d); assertEquals(30D, rectangle.getMaxY(), 0.0d); + + org.apache.lucene.geo.Rectangle luceneRectangle = eb.buildLucene(); + assertEquals(-45D, luceneRectangle.minLon, 0.0d); + assertEquals(-30D, luceneRectangle.minLat, 0.0d); + assertEquals(45D, luceneRectangle.maxLon, 0.0d); + assertEquals(30D, luceneRectangle.maxLat, 0.0d); } public void testNewPolygon() { - Polygon polygon = new PolygonBuilder(new CoordinatesBuilder() + PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder() .coordinate(-45, 30) .coordinate(45, 30) .coordinate(45, -30) .coordinate(-45, -30) - .coordinate(-45, 30)).toPolygon(); + .coordinate(-45, 30)); - LineString exterior = polygon.getExteriorRing(); + Polygon poly = pb.toPolygonS4J(); + LineString exterior = poly.getExteriorRing(); assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30)); assertEquals(exterior.getCoordinateN(1), new Coordinate(45, 30)); assertEquals(exterior.getCoordinateN(2), new Coordinate(45, -30)); assertEquals(exterior.getCoordinateN(3), new Coordinate(-45, -30)); + + org.apache.lucene.geo.Polygon lucenePoly = (org.apache.lucene.geo.Polygon)(pb.toPolygonLucene()); + assertEquals(lucenePoly.getPolyLat(0), 30, 0d); + assertEquals(lucenePoly.getPolyLon(0), -45, 0d); + assertEquals(lucenePoly.getPolyLat(1), 30, 0d); + assertEquals(lucenePoly.getPolyLon(1), 45, 0d); + assertEquals(lucenePoly.getPolyLat(2), -30, 0d); + assertEquals(lucenePoly.getPolyLon(2), 45, 0d); + assertEquals(lucenePoly.getPolyLat(3), -30, 0d); + assertEquals(lucenePoly.getPolyLon(3), -45, 0d); } public void testNewPolygon_coordinate() { - Polygon polygon = new PolygonBuilder(new CoordinatesBuilder() + PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder() .coordinate(new Coordinate(-45, 30)) .coordinate(new Coordinate(45, 30)) .coordinate(new Coordinate(45, -30)) .coordinate(new Coordinate(-45, -30)) - .coordinate(new Coordinate(-45, 30))).toPolygon(); + .coordinate(new Coordinate(-45, 30))); - LineString exterior = polygon.getExteriorRing(); + Polygon poly = pb.toPolygonS4J(); + LineString exterior = poly.getExteriorRing(); assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30)); assertEquals(exterior.getCoordinateN(1), new Coordinate(45, 30)); assertEquals(exterior.getCoordinateN(2), new Coordinate(45, -30)); assertEquals(exterior.getCoordinateN(3), new Coordinate(-45, -30)); + + org.apache.lucene.geo.Polygon lucenePoly = (org.apache.lucene.geo.Polygon)(pb.toPolygonLucene()); + assertEquals(lucenePoly.getPolyLat(0), 30, 0d); + assertEquals(lucenePoly.getPolyLon(0), -45, 0d); + assertEquals(lucenePoly.getPolyLat(1), 30, 0d); + assertEquals(lucenePoly.getPolyLon(1), 45, 0d); + assertEquals(lucenePoly.getPolyLat(2), -30, 0d); + assertEquals(lucenePoly.getPolyLon(2), 45, 0d); + assertEquals(lucenePoly.getPolyLat(3), -30, 0d); + assertEquals(lucenePoly.getPolyLon(3), -45, 0d); } public void testNewPolygon_coordinates() { - Polygon polygon = new PolygonBuilder(new CoordinatesBuilder() + PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder() .coordinates(new Coordinate(-45, 30), new Coordinate(45, 30), new Coordinate(45, -30), new Coordinate(-45, -30), new Coordinate(-45, 30)) - ).toPolygon(); + ); - LineString exterior = polygon.getExteriorRing(); + Polygon poly = pb.toPolygonS4J(); + LineString exterior = poly.getExteriorRing(); assertEquals(exterior.getCoordinateN(0), new Coordinate(-45, 30)); assertEquals(exterior.getCoordinateN(1), new Coordinate(45, 30)); assertEquals(exterior.getCoordinateN(2), new Coordinate(45, -30)); assertEquals(exterior.getCoordinateN(3), new Coordinate(-45, -30)); + + org.apache.lucene.geo.Polygon lucenePoly = (org.apache.lucene.geo.Polygon)(pb.toPolygonLucene()); + assertEquals(lucenePoly.getPolyLat(0), 30, 0d); + assertEquals(lucenePoly.getPolyLon(0), -45, 0d); + assertEquals(lucenePoly.getPolyLat(1), 30, 0d); + assertEquals(lucenePoly.getPolyLon(1), 45, 0d); + assertEquals(lucenePoly.getPolyLat(2), -30, 0d); + assertEquals(lucenePoly.getPolyLon(2), 45, 0d); + assertEquals(lucenePoly.getPolyLat(3), -30, 0d); + assertEquals(lucenePoly.getPolyLon(3), -45, 0d); } public void testLineStringBuilder() { // Building a simple LineString - new LineStringBuilder(new CoordinatesBuilder() + LineStringBuilder lsb = new LineStringBuilder(new CoordinatesBuilder() .coordinate(-130.0, 55.0) .coordinate(-130.0, -40.0) .coordinate(-15.0, -40.0) @@ -115,10 +158,13 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-45.0, 50.0) .coordinate(-45.0, -15.0) .coordinate(-110.0, -15.0) - .coordinate(-110.0, 55.0)).build(); + .coordinate(-110.0, 55.0)); + + lsb.buildS4J(); + lsb.buildLucene(); // Building a linestring that needs to be wrapped - new LineStringBuilder(new CoordinatesBuilder() + lsb = new LineStringBuilder(new CoordinatesBuilder() .coordinate(100.0, 50.0) .coordinate(110.0, -40.0) .coordinate(240.0, -40.0) @@ -126,31 +172,34 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(200.0, 60.0) .coordinate(200.0, -30.0) .coordinate(130.0, -30.0) - .coordinate(130.0, 60.0) - ) - .build(); + .coordinate(130.0, 60.0)); + + lsb.buildS4J(); + lsb.buildLucene(); // Building a lineString on the dateline - new LineStringBuilder(new CoordinatesBuilder() + lsb = new LineStringBuilder(new CoordinatesBuilder() .coordinate(-180.0, 80.0) .coordinate(-180.0, 40.0) .coordinate(-180.0, -40.0) - .coordinate(-180.0, -80.0) - ) - .build(); + .coordinate(-180.0, -80.0)); + + lsb.buildS4J(); + lsb.buildLucene(); // Building a lineString on the dateline - new LineStringBuilder(new CoordinatesBuilder() + lsb = new LineStringBuilder(new CoordinatesBuilder() .coordinate(180.0, 80.0) .coordinate(180.0, 40.0) .coordinate(180.0, -40.0) - .coordinate(180.0, -80.0) - ) - .build(); + .coordinate(180.0, -80.0)); + + lsb.buildS4J(); + lsb.buildLucene(); } public void testMultiLineString() { - new MultiLineStringBuilder() + MultiLineStringBuilder mlsb = new MultiLineStringBuilder() .linestring(new LineStringBuilder(new CoordinatesBuilder() .coordinate(-100.0, 50.0) .coordinate(50.0, 50.0) @@ -164,8 +213,9 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(50.0, 0.0) .coordinate(-100.0, 0.0) ) - ) - .build(); + ); + mlsb.buildS4J(); + mlsb.buildLucene(); // LineString that needs to be wrapped new MultiLineStringBuilder() @@ -182,8 +232,10 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(200.0, 0.0) .coordinate(150.0, 0.0) ) - ) - .build(); + ); + + mlsb.buildS4J(); + mlsb.buildLucene(); } public void testPolygonSelfIntersection() { @@ -192,58 +244,58 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(40.0, 50.0) .coordinate(-40.0, -50.0) .coordinate(40.0, -50.0).close()); - Exception e = expectThrows(InvalidShapeException.class, () -> newPolygon.build()); + Exception e = expectThrows(InvalidShapeException.class, () -> newPolygon.buildS4J()); assertThat(e.getMessage(), containsString("Self-intersection at or near point (0.0")); } + /** note: only supported by S4J at the moment */ public void testGeoCircle() { double earthCircumference = 40075016.69; - Circle circle = new CircleBuilder().center(0, 0).radius("100m").build(); + Circle circle = new CircleBuilder().center(0, 0).radius("100m").buildS4J(); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals(new PointImpl(0, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); - circle = new CircleBuilder().center(+180, 0).radius("100m").build(); + circle = new CircleBuilder().center(+180, 0).radius("100m").buildS4J(); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals(new PointImpl(180, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); - circle = new CircleBuilder().center(-180, 0).radius("100m").build(); + circle = new CircleBuilder().center(-180, 0).radius("100m").buildS4J(); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals(new PointImpl(-180, 0, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); - circle = new CircleBuilder().center(0, 90).radius("100m").build(); + circle = new CircleBuilder().center(0, 90).radius("100m").buildS4J(); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals(new PointImpl(0, 90, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); - circle = new CircleBuilder().center(0, -90).radius("100m").build(); + circle = new CircleBuilder().center(0, -90).radius("100m").buildS4J(); assertEquals((360 * 100) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals(new PointImpl(0, -90, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); double randomLat = (randomDouble() * 180) - 90; double randomLon = (randomDouble() * 360) - 180; double randomRadius = randomIntBetween(1, (int) earthCircumference / 4); - circle = new CircleBuilder().center(randomLon, randomLat).radius(randomRadius + "m").build(); + circle = new CircleBuilder().center(randomLon, randomLat).radius(randomRadius + "m").buildS4J(); assertEquals((360 * randomRadius) / earthCircumference, circle.getRadius(), 0.00000001); assertEquals(new PointImpl(randomLon, randomLat, ShapeBuilder.SPATIAL_CONTEXT), circle.getCenter()); } public void testPolygonWrapping() { - Shape shape = new PolygonBuilder(new CoordinatesBuilder() + PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder() .coordinate(-150.0, 65.0) .coordinate(-250.0, 65.0) .coordinate(-250.0, -65.0) .coordinate(-150.0, -65.0) - .close() - ) - .build(); + .close()); - assertMultiPolygon(shape); + assertMultiPolygon(pb.buildS4J(), true); + assertMultiPolygon(pb.buildLucene(), false); } public void testLineStringWrapping() { - Shape shape = new LineStringBuilder(new CoordinatesBuilder() + LineStringBuilder lsb = new LineStringBuilder(new CoordinatesBuilder() .coordinate(-150.0, 65.0) .coordinate(-250.0, 65.0) .coordinate(-250.0, -65.0) .coordinate(-150.0, -65.0) - .close() - ) - .build(); - assertMultiLineString(shape); + .close()); + + assertMultiLineString(lsb.buildS4J(), true); + assertMultiLineString(lsb.buildLucene(), false); } public void testDatelineOGC() { @@ -286,8 +338,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-179,1) )); - Shape shape = builder.close().build(); - assertMultiPolygon(shape); + assertMultiPolygon(builder.close().buildS4J(), true); + assertMultiPolygon(builder.close().buildLucene(), false); } public void testDateline() { @@ -330,8 +382,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-179,1) )); - Shape shape = builder.close().build(); - assertMultiPolygon(shape); + assertMultiPolygon(builder.close().buildS4J(), true); + assertMultiPolygon(builder.close().buildLucene(), false); } public void testComplexShapeWithHole() { @@ -405,9 +457,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-85.0000002,37.1317672) ) ); - - Shape shape = builder.close().build(); - assertPolygon(shape); + assertPolygon(builder.close().buildS4J(), true); + assertPolygon(builder.close().buildLucene(), false); } public void testShapeWithHoleAtEdgeEndPoints() { @@ -428,9 +479,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-4, 1) .coordinate(4, 1) )); - - Shape shape = builder.close().build(); - assertPolygon(shape); + assertPolygon(builder.close().buildS4J(), true); + assertPolygon(builder.close().buildLucene(), false); } public void testShapeWithPointOnDateline() { @@ -440,9 +490,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(176, -4) .coordinate(180, 0) ); - - Shape shape = builder.close().build(); - assertPolygon(shape); + assertPolygon(builder.close().buildS4J(), true); + assertPolygon(builder.close().buildLucene(), false); } public void testShapeWithEdgeAlongDateline() { @@ -454,8 +503,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(180, 0) ); - Shape shape = builder.close().build(); - assertPolygon(shape); + assertPolygon(builder.close().buildS4J(), true); + assertPolygon(builder.close().buildLucene(), false); // test case 2: test the negative side of the dateline builder = new PolygonBuilder(new CoordinatesBuilder() @@ -465,8 +514,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-176, 4) ); - shape = builder.close().build(); - assertPolygon(shape); + assertPolygon(builder.close().buildS4J(), true); + assertPolygon(builder.close().buildLucene(), false); } public void testShapeWithBoundaryHoles() { @@ -486,8 +535,9 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(176, -10) .coordinate(176, 10) )); - Shape shape = builder.close().build(); - assertMultiPolygon(shape); + + assertMultiPolygon(builder.close().buildS4J(), true); + assertMultiPolygon(builder.close().buildLucene(), false); // test case 2: test the negative side of the dateline builder = new PolygonBuilder( @@ -508,8 +558,9 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-176, 10) .close() )); - shape = builder.close().build(); - assertMultiPolygon(shape); + + assertMultiPolygon(builder.close().buildS4J(), true); + assertMultiPolygon(builder.close().buildLucene(), false); } public void testShapeWithTangentialHole() { @@ -529,8 +580,9 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-180, 5) .coordinate(-177, 10) )); - Shape shape = builder.close().build(); - assertMultiPolygon(shape); + + assertMultiPolygon(builder.close().buildS4J(), true); + assertMultiPolygon(builder.close().buildLucene(), false); } public void testShapeWithInvalidTangentialHole() { @@ -550,7 +602,11 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(179, -10) .coordinate(164, 0) )); - Exception e = expectThrows(InvalidShapeException.class, () -> builder.close().build()); + Exception e; + + e = expectThrows(InvalidShapeException.class, () -> builder.close().buildS4J()); + assertThat(e.getMessage(), containsString("interior cannot share more than one point with the exterior")); + e = expectThrows(InvalidShapeException.class, () -> builder.close().buildLucene()); assertThat(e.getMessage(), containsString("interior cannot share more than one point with the exterior")); } @@ -577,8 +633,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(176, -5) .coordinate(172, 0) )); - Shape shape = builder.close().build(); - assertMultiPolygon(shape); + assertMultiPolygon(builder.close().buildS4J(), true); + assertMultiPolygon(builder.close().buildLucene(), false); } public void testBoundaryShapeWithInvalidTangentialHole() { @@ -598,7 +654,10 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(176, -10) .coordinate(-177, 10) )); - Exception e = expectThrows(InvalidShapeException.class, () -> builder.close().build()); + Exception e; + e = expectThrows(InvalidShapeException.class, () -> builder.close().buildS4J()); + assertThat(e.getMessage(), containsString("interior cannot share more than one point with the exterior")); + e = expectThrows(InvalidShapeException.class, () -> builder.close().buildLucene()); assertThat(e.getMessage(), containsString("interior cannot share more than one point with the exterior")); } @@ -613,9 +672,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-180, 90) ); - Shape shape = builder.close().build(); - - assertPolygon(shape); + assertPolygon(builder.close().buildS4J(), true); + assertPolygon(builder.close().buildLucene(), false); } public void testShapeWithAlternateOrientation() { @@ -627,8 +685,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(180, 0) ); - Shape shape = builder.close().build(); - assertPolygon(shape); + assertPolygon(builder.close().buildS4J(), true); + assertPolygon(builder.close().buildLucene(), false); // cw: geo core will convert to ccw across the dateline builder = new PolygonBuilder(new CoordinatesBuilder() @@ -638,9 +696,8 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(180, 0) ); - shape = builder.close().build(); - - assertMultiPolygon(shape); + assertMultiPolygon(builder.close().buildS4J(), true); + assertMultiPolygon(builder.close().buildLucene(), false); } public void testInvalidShapeWithConsecutiveDuplicatePoints() { @@ -651,7 +708,10 @@ public class ShapeBuilderTests extends ESTestCase { .coordinate(-176, 4) .coordinate(180, 0) ); - Exception e = expectThrows(InvalidShapeException.class, () -> builder.close().build()); + + Exception e = expectThrows(InvalidShapeException.class, () -> builder.close().buildS4J()); + assertThat(e.getMessage(), containsString("duplicate consecutive coordinates at: (")); + e = expectThrows(InvalidShapeException.class, () -> builder.close().buildLucene()); assertThat(e.getMessage(), containsString("duplicate consecutive coordinates at: (")); } diff --git a/server/src/test/java/org/elasticsearch/common/geo/builders/PolygonBuilderTests.java b/server/src/test/java/org/elasticsearch/common/geo/builders/PolygonBuilderTests.java index 83bf2bae6a6..0d4f1427854 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/builders/PolygonBuilderTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/builders/PolygonBuilderTests.java @@ -128,7 +128,7 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase { PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder().coordinate(4, 3).coordinate(3, 2).coordinate(3, 3).close()); pb.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(4, 2).coordinate(3, 1).coordinate(4, 1).close())); - pb.build(); + pb.buildS4J(); }); assertEquals("Hole lies outside shell at or near point (4.0, 1.0, NaN)", e.getMessage()); @@ -138,7 +138,7 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase { PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder().coordinate(3, 2).coordinate(4, 1).coordinate(3, 1).close()); pb.hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(3, 3).coordinate(4, 2).coordinate(4, 3).close())); - pb.build(); + pb.buildS4J(); }); assertEquals("Hole lies outside shell at or near point (4.0, 3.0, NaN)", e.getMessage()); @@ -152,13 +152,13 @@ public class PolygonBuilderTests extends AbstractShapeBuilderTestCase polygonPoints = new ArrayList<>(); for (Coordinate coord : coordinates) { diff --git a/server/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java b/server/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java index ce6c00f359f..2f26e448273 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java @@ -123,7 +123,7 @@ public class GeoFilterIT extends ESIntegTestCase { .coordinate(-10, 10) .coordinate(10, -10) .close()) - .build(); + .buildS4J(); fail("Self intersection not detected"); } catch (InvalidShapeException e) { } @@ -132,14 +132,14 @@ public class GeoFilterIT extends ESIntegTestCase { new PolygonBuilder(new CoordinatesBuilder() .coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()) .hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close())) - .build(); + .buildS4J(); try { // polygon with overlapping hole new PolygonBuilder(new CoordinatesBuilder() .coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()) .hole(new LineStringBuilder(new CoordinatesBuilder() .coordinate(-5, -5).coordinate(-5, 11).coordinate(5, 11).coordinate(5, -5).close())) - .build(); + .buildS4J(); fail("Self intersection not detected"); } catch (InvalidShapeException e) { @@ -151,7 +151,7 @@ public class GeoFilterIT extends ESIntegTestCase { .coordinate(-10, -10).coordinate(-10, 10).coordinate(10, 10).coordinate(10, -10).close()) .hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -5).coordinate(-5, 5).coordinate(5, 5).coordinate(5, -5).close())) .hole(new LineStringBuilder(new CoordinatesBuilder().coordinate(-5, -6).coordinate(5, -6).coordinate(5, -4).coordinate(-5, -4).close())) - .build(); + .buildS4J(); fail("Intersection of holes not detected"); } catch (InvalidShapeException e) { } @@ -167,7 +167,7 @@ public class GeoFilterIT extends ESIntegTestCase { .coordinate(10, 20) .coordinate(10, -10) .close()) - .build(); + .buildS4J(); fail("Self intersection not detected"); } catch (InvalidShapeException e) { } @@ -190,7 +190,7 @@ public class GeoFilterIT extends ESIntegTestCase { .coordinate(-4, 4) .coordinate(4, 4) .coordinate(4, -4).close())) - .build(); + .buildS4J(); } public void testShapeRelations() throws Exception { 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 d0d05f6a369..9e0f51b9985 100644 --- a/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java +++ b/server/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java @@ -240,7 +240,7 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase { private void assertUnmodified(ShapeBuilder builder) throws IOException { String before = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); - builder.build(); + builder.buildS4J(); String after = Strings.toString(jsonBuilder().startObject().field("area", builder).endObject()); assertThat(before, equalTo(after)); } diff --git a/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java b/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java index e94d31b16a3..76d18a59f9f 100644 --- a/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java +++ b/server/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java @@ -32,7 +32,6 @@ import org.elasticsearch.common.geo.builders.MultiPointBuilder; import org.elasticsearch.common.geo.builders.PointBuilder; import org.elasticsearch.common.geo.builders.PolygonBuilder; import org.elasticsearch.common.geo.builders.ShapeBuilder; -import org.elasticsearch.search.geo.GeoShapeQueryTests; import org.junit.Assert; import org.locationtech.spatial4j.context.jts.JtsSpatialContext; import org.locationtech.spatial4j.distance.DistanceUtils; @@ -154,7 +153,6 @@ public class RandomShapeGenerator extends RandomGeoGenerator { /** * Creates a random shape useful for randomized testing, NOTE: exercise caution when using this to build random GeometryCollections * as creating a large random number of random shapes can result in massive resource consumption - * see: {@link GeoShapeQueryTests#testShapeFilterWithRandomGeoCollection} * * The following options are included * @param nearPoint Create a shape near a provided point @@ -206,7 +204,7 @@ public class RandomShapeGenerator extends RandomGeoGenerator { numPoints = RandomNumbers.randomIntBetween(r, 5, 25); Coordinate[] coordinates = new Coordinate[numPoints]; for (int i=0; i match) { @@ -257,11 +292,11 @@ public class ElasticsearchGeoAssertions { public static void assertValidException(XContentParser parser, Class expectedException) { try { - ShapeParser.parse(parser).build(); + ShapeParser.parse(parser).buildS4J(); Assert.fail("process completed successfully when " + expectedException.getName() + " expected"); } catch (Exception e) { - assert(e.getClass().equals(expectedException)): - "expected " + expectedException.getName() + " but found " + e.getClass().getName(); + assertTrue("expected " + expectedException.getName() + " but found " + e.getClass().getName(), + e.getClass().equals(expectedException)); } } }