diff --git a/pom.xml b/pom.xml index 9c1e339a70b30..74bec04c28427 100644 --- a/pom.xml +++ b/pom.xml @@ -1254,7 +1254,7 @@ org.locationtech.jts jts-core - 1.15.0 + 1.16.1 diff --git a/presto-docs/src/main/sphinx/functions/geospatial.rst b/presto-docs/src/main/sphinx/functions/geospatial.rst index bb023d9fb5ddc..2ffaedd735d7a 100644 --- a/presto-docs/src/main/sphinx/functions/geospatial.rst +++ b/presto-docs/src/main/sphinx/functions/geospatial.rst @@ -395,6 +395,11 @@ Accessors Returns an array of geometries in the specified collection. Returns a one-element array if the input geometry is not a multi-geometry. Returns ``null`` if input geometry is empty. + For example, a MultiLineString will create an array of LineStrings. A GeometryCollection + will produce an un-flattened array of its constituents: + ``GEOMETRYCOLLECTION(MULTIPOINT(0 0, 1 1), GEOMETRYCOLLECTION(MULTILINESTRING((2 2, 3 3))))`` + would produce ``array[MULTIPOINT(0 0, 1 1), GEOMETRYCOLLECTION(MULTILINESTRING((2 2, 3 3)))]``. + .. function:: ST_NumPoints(Geometry) -> bigint Returns the number of points in a geometry. This is an extension to the SQL/MM diff --git a/presto-geospatial-toolkit/pom.xml b/presto-geospatial-toolkit/pom.xml index 4daf2c4f4b499..48c46a4ebc010 100644 --- a/presto-geospatial-toolkit/pom.xml +++ b/presto-geospatial-toolkit/pom.xml @@ -79,6 +79,11 @@ presto-array + + com.facebook.presto + presto-spi + + it.unimi.dsi fastutil diff --git a/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/GeometryUtils.java b/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/GeometryUtils.java index ab1bd4bb5ed65..eb4dae5abc9a9 100644 --- a/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/GeometryUtils.java +++ b/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/GeometryUtils.java @@ -23,14 +23,21 @@ import com.esri.core.geometry.ogc.OGCGeometry; import com.esri.core.geometry.ogc.OGCPoint; import com.esri.core.geometry.ogc.OGCPolygon; +import com.facebook.presto.spi.PrestoException; import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.CoordinateSequenceFactory; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.impl.PackedCoordinateSequenceFactory; +import org.locationtech.jts.io.ParseException; +import org.locationtech.jts.io.WKTReader; +import org.locationtech.jts.io.WKTWriter; import java.util.HashSet; import java.util.Set; +import static com.facebook.presto.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT; + public final class GeometryUtils { private static final CoordinateSequenceFactory COORDINATE_SEQUENCE_FACTORY = new PackedCoordinateSequenceFactory(); @@ -220,13 +227,53 @@ public static boolean isPointOrRectangle(OGCGeometry ogcGeometry, Envelope envel return true; } - public static org.locationtech.jts.geom.Point makeJtsEmptyPoint() + public static org.locationtech.jts.geom.Geometry jtsGeometryFromWkt(String wkt) + { + try { + return new WKTReader(GEOMETRY_FACTORY).read(wkt); + } + catch (ParseException | IllegalArgumentException e) { + throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Invalid WKT: " + e.getMessage(), e); + } + } + + public static String wktFromJtsGeometry(org.locationtech.jts.geom.Geometry geometry) + { + return new WKTWriter().write(geometry); + } + + public static org.locationtech.jts.geom.Point createJtsEmptyPoint() { return GEOMETRY_FACTORY.createPoint(); } - public static org.locationtech.jts.geom.Point makeJtsPoint(Coordinate coordinate) + public static org.locationtech.jts.geom.Point createJtsPoint(Coordinate coordinate) { return GEOMETRY_FACTORY.createPoint(coordinate); } + + public static org.locationtech.jts.geom.Point createJtsPoint(double x, double y) + { + return createJtsPoint(new Coordinate(x, y)); + } + + public static org.locationtech.jts.geom.MultiPoint createJtsMultiPoint(CoordinateSequence coordinates) + { + return GEOMETRY_FACTORY.createMultiPoint(coordinates); + } + + public static org.locationtech.jts.geom.Geometry createJtsEmptyLineString() + { + return GEOMETRY_FACTORY.createLineString(); + } + + public static org.locationtech.jts.geom.Geometry createJtsLineString(CoordinateSequence coordinates) + { + return GEOMETRY_FACTORY.createLineString(coordinates); + } + + public static org.locationtech.jts.geom.Geometry createJtsEmptyPolygon() + { + return GEOMETRY_FACTORY.createPolygon(); + } } diff --git a/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/GeometrySerde.java b/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/EsriGeometrySerde.java similarity index 99% rename from presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/GeometrySerde.java rename to presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/EsriGeometrySerde.java index c7988dbf6ff83..536c81089b0e2 100644 --- a/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/GeometrySerde.java +++ b/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/EsriGeometrySerde.java @@ -52,9 +52,9 @@ import static java.lang.Math.toIntExact; import static java.util.Objects.requireNonNull; -public class GeometrySerde +public class EsriGeometrySerde { - private GeometrySerde() {} + private EsriGeometrySerde() {} public static Slice serialize(OGCGeometry input) { diff --git a/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/JtsGeometrySerde.java b/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/JtsGeometrySerde.java index 7b2262491e9e5..420748c48d267 100644 --- a/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/JtsGeometrySerde.java +++ b/presto-geospatial-toolkit/src/main/java/com/facebook/presto/geospatial/serde/JtsGeometrySerde.java @@ -280,6 +280,8 @@ private static void writeGeometry(Geometry geometry, DynamicSliceOutput output) writeMultiPoint((MultiPoint) geometry, output); break; case "LineString": + case "LinearRing": + // LinearRings are a subclass of LineString writePolyline(geometry, output, false); break; case "MultiLineString": diff --git a/presto-geospatial-toolkit/src/test/java/com/facebook/presto/geospatial/serde/BenchmarkGeometrySerde.java b/presto-geospatial-toolkit/src/test/java/com/facebook/presto/geospatial/serde/BenchmarkGeometrySerde.java index a8f8e1432ffb8..0dd0ecb987ba6 100644 --- a/presto-geospatial-toolkit/src/test/java/com/facebook/presto/geospatial/serde/BenchmarkGeometrySerde.java +++ b/presto-geospatial-toolkit/src/test/java/com/facebook/presto/geospatial/serde/BenchmarkGeometrySerde.java @@ -40,9 +40,9 @@ import static com.facebook.presto.geospatial.serde.BenchmarkGeometrySerializationData.POINT; import static com.facebook.presto.geospatial.serde.BenchmarkGeometrySerializationData.POLYGON; import static com.facebook.presto.geospatial.serde.BenchmarkGeometrySerializationData.readResource; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserializeEnvelope; -import static com.facebook.presto.geospatial.serde.GeometrySerde.serialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserializeEnvelope; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.serialize; import static java.util.concurrent.TimeUnit.SECONDS; import static org.openjdk.jmh.annotations.Mode.Throughput; diff --git a/presto-geospatial-toolkit/src/test/java/com/facebook/presto/geospatial/serde/TestGeometrySerialization.java b/presto-geospatial-toolkit/src/test/java/com/facebook/presto/geospatial/serde/TestGeometrySerialization.java index 3cd5161226147..fe90756fe84dd 100644 --- a/presto-geospatial-toolkit/src/test/java/com/facebook/presto/geospatial/serde/TestGeometrySerialization.java +++ b/presto-geospatial-toolkit/src/test/java/com/facebook/presto/geospatial/serde/TestGeometrySerialization.java @@ -21,11 +21,11 @@ import org.locationtech.jts.io.WKTReader; import org.testng.annotations.Test; -import static com.facebook.presto.geospatial.serde.GeometrySerde.createFromEsriGeometry; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserializeEnvelope; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserializeType; -import static com.facebook.presto.geospatial.serde.GeometrySerde.serialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.createFromEsriGeometry; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserializeEnvelope; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserializeType; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.serialize; import static com.facebook.presto.geospatial.serde.GeometrySerializationType.ENVELOPE; import static com.facebook.presto.geospatial.serde.GeometrySerializationType.GEOMETRY_COLLECTION; import static com.facebook.presto.geospatial.serde.GeometrySerializationType.LINE_STRING; @@ -208,9 +208,9 @@ private static void testCrossSerialization(String wkt) OGCGeometry esriGeometry = OGCGeometry.fromText(wkt); Slice jtsSerialized = JtsGeometrySerde.serialize(jtsGeometry); - Slice esriSerialized = GeometrySerde.serialize(esriGeometry); + Slice esriSerialized = EsriGeometrySerde.serialize(esriGeometry); - OGCGeometry esriFromJts = GeometrySerde.deserialize(jtsSerialized); + OGCGeometry esriFromJts = EsriGeometrySerde.deserialize(jtsSerialized); Geometry jtsFromEsri = JtsGeometrySerde.deserialize(esriSerialized); assertGeometryEquals(esriFromJts, esriGeometry); assertGeometryEquals(jtsFromEsri, jtsGeometry); diff --git a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/BingTileFunctions.java b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/BingTileFunctions.java index f4366771b7836..ddbe94e9e7585 100644 --- a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/BingTileFunctions.java +++ b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/BingTileFunctions.java @@ -34,8 +34,8 @@ import static com.facebook.presto.geospatial.GeometryUtils.getEnvelope; import static com.facebook.presto.geospatial.GeometryUtils.getPointCount; import static com.facebook.presto.geospatial.GeometryUtils.isPointOrRectangle; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; -import static com.facebook.presto.geospatial.serde.GeometrySerde.serialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.serialize; import static com.facebook.presto.plugin.geospatial.BingTile.MAX_ZOOM_LEVEL; import static com.facebook.presto.plugin.geospatial.GeometryType.GEOMETRY_TYPE_NAME; import static com.facebook.presto.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT; diff --git a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/GeoFunctions.java b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/GeoFunctions.java index e6e7ba74ef1f9..0ee404f93c780 100644 --- a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/GeoFunctions.java +++ b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/GeoFunctions.java @@ -17,7 +17,6 @@ import com.esri.core.geometry.GeometryCursor; import com.esri.core.geometry.ListeningGeometryCursor; import com.esri.core.geometry.MultiPath; -import com.esri.core.geometry.MultiPoint; import com.esri.core.geometry.MultiVertexGeometry; import com.esri.core.geometry.NonSimpleResult; import com.esri.core.geometry.NonSimpleResult.Reason; @@ -30,14 +29,11 @@ import com.esri.core.geometry.ogc.OGCGeometry; import com.esri.core.geometry.ogc.OGCGeometryCollection; import com.esri.core.geometry.ogc.OGCLineString; -import com.esri.core.geometry.ogc.OGCPoint; -import com.esri.core.geometry.ogc.OGCPolygon; import com.facebook.presto.geospatial.GeometryType; import com.facebook.presto.geospatial.KdbTree; import com.facebook.presto.geospatial.Rectangle; -import com.facebook.presto.geospatial.serde.GeometrySerde; +import com.facebook.presto.geospatial.serde.EsriGeometrySerde; import com.facebook.presto.geospatial.serde.GeometrySerializationType; -import com.facebook.presto.geospatial.serde.JtsGeometrySerde; import com.facebook.presto.spi.PrestoException; import com.facebook.presto.spi.block.Block; import com.facebook.presto.spi.block.BlockBuilder; @@ -51,9 +47,14 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import io.airlift.slice.BasicSliceInput; import io.airlift.slice.Slice; +import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryCollection; import org.locationtech.jts.geom.LineString; +import org.locationtech.jts.geom.MultiLineString; +import org.locationtech.jts.geom.impl.PackedCoordinateSequenceFactory; import org.locationtech.jts.linearref.LengthIndexedLine; import java.util.ArrayDeque; @@ -82,13 +83,19 @@ import static com.facebook.presto.geospatial.GeometryType.MULTI_POLYGON; import static com.facebook.presto.geospatial.GeometryType.POINT; import static com.facebook.presto.geospatial.GeometryType.POLYGON; +import static com.facebook.presto.geospatial.GeometryUtils.createJtsEmptyLineString; +import static com.facebook.presto.geospatial.GeometryUtils.createJtsEmptyPoint; +import static com.facebook.presto.geospatial.GeometryUtils.createJtsEmptyPolygon; +import static com.facebook.presto.geospatial.GeometryUtils.createJtsLineString; +import static com.facebook.presto.geospatial.GeometryUtils.createJtsMultiPoint; +import static com.facebook.presto.geospatial.GeometryUtils.createJtsPoint; import static com.facebook.presto.geospatial.GeometryUtils.getPointCount; -import static com.facebook.presto.geospatial.GeometryUtils.makeJtsEmptyPoint; -import static com.facebook.presto.geospatial.GeometryUtils.makeJtsPoint; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserializeEnvelope; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserializeType; -import static com.facebook.presto.geospatial.serde.GeometrySerde.serialize; +import static com.facebook.presto.geospatial.GeometryUtils.jtsGeometryFromWkt; +import static com.facebook.presto.geospatial.GeometryUtils.wktFromJtsGeometry; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserializeEnvelope; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserializeType; +import static com.facebook.presto.geospatial.serde.JtsGeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.JtsGeometrySerde.serialize; import static com.facebook.presto.plugin.geospatial.GeometryType.GEOMETRY; import static com.facebook.presto.plugin.geospatial.GeometryType.GEOMETRY_TYPE_NAME; import static com.facebook.presto.plugin.geospatial.SphericalGeographyType.SPHERICAL_GEOGRAPHY_TYPE_NAME; @@ -121,8 +128,7 @@ public final class GeoFunctions { private static final Joiner OR_JOINER = Joiner.on(" or "); - private static final Slice EMPTY_POLYGON = serialize(new OGCPolygon(new Polygon(), null)); - private static final Slice EMPTY_MULTIPOINT = serialize(createFromEsriGeometry(new MultiPoint(), null, true)); + private static final Slice EMPTY_POLYGON = serialize(createJtsEmptyPolygon()); private static final double EARTH_RADIUS_KM = 6371.01; private static final double EARTH_RADIUS_M = EARTH_RADIUS_KM * 1000.0; private static final Map NON_SIMPLE_REASONS = ImmutableMap.builder() @@ -152,7 +158,7 @@ private GeoFunctions() {} @SqlType(GEOMETRY_TYPE_NAME) public static Slice parseLine(@SqlType(VARCHAR) Slice input) { - OGCGeometry geometry = geometryFromText(input); + Geometry geometry = jtsGeometryFromWkt(input.toStringUtf8()); validateType("ST_LineFromText", geometry, EnumSet.of(LINE_STRING)); return serialize(geometry); } @@ -162,39 +168,12 @@ public static Slice parseLine(@SqlType(VARCHAR) Slice input) @SqlType(GEOMETRY_TYPE_NAME) public static Slice stLineString(@SqlType("array(" + GEOMETRY_TYPE_NAME + ")") Block input) { - MultiPath multipath = new Polyline(); - OGCPoint previousPoint = null; - for (int i = 0; i < input.getPositionCount(); i++) { - Slice slice = GEOMETRY.getSlice(input, i); - - if (slice.getInput().available() == 0) { - throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid input to ST_LineString: null point at index %s", i + 1)); - } - - OGCGeometry geometry = deserialize(slice); - if (!(geometry instanceof OGCPoint)) { - throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("ST_LineString takes only an array of valid points, %s was passed", geometry.geometryType())); - } - OGCPoint point = (OGCPoint) geometry; - - if (point.isEmpty()) { - throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid input to ST_LineString: empty point at index %s", i + 1)); - } - - if (previousPoint == null) { - multipath.startPath(point.X(), point.Y()); - } - else { - if (point.Equals(previousPoint)) { - throw new PrestoException(INVALID_FUNCTION_ARGUMENT, - format("Invalid input to ST_LineString: consecutive duplicate points at index %s", i + 1)); - } - multipath.lineTo(point.X(), point.Y()); - } - previousPoint = point; + CoordinateSequence coordinates = readPointCoordinates(input, "ST_LineString", true); + if (coordinates.size() < 2) { + return serialize(createJtsEmptyLineString()); } - OGCLineString linestring = new OGCLineString(multipath, 0, null); - return serialize(linestring); + + return serialize(createJtsLineString(coordinates)); } @Description("Returns a Geometry type Point object with the given coordinate values") @@ -202,8 +181,7 @@ public static Slice stLineString(@SqlType("array(" + GEOMETRY_TYPE_NAME + ")") B @SqlType(GEOMETRY_TYPE_NAME) public static Slice stPoint(@SqlType(DOUBLE) double x, @SqlType(DOUBLE) double y) { - OGCGeometry geometry = createFromEsriGeometry(new Point(x, y), null); - return serialize(geometry); + return serialize(createJtsPoint(x, y)); } @SqlNullable @@ -212,28 +190,49 @@ public static Slice stPoint(@SqlType(DOUBLE) double x, @SqlType(DOUBLE) double y @SqlType(GEOMETRY_TYPE_NAME) public static Slice stMultiPoint(@SqlType("array(" + GEOMETRY_TYPE_NAME + ")") Block input) { - MultiPoint multipoint = new MultiPoint(); + CoordinateSequence coordinates = readPointCoordinates(input, "ST_MultiPoint", false); + if (coordinates.size() == 0) { + return null; + } + + return serialize(createJtsMultiPoint(coordinates)); + } + + private static CoordinateSequence readPointCoordinates(Block input, String functionName, boolean forbidDuplicates) + { + PackedCoordinateSequenceFactory coordinateSequenceFactory = new PackedCoordinateSequenceFactory(); + double[] coordinates = new double[2 * input.getPositionCount()]; + double lastX = Double.NaN; + double lastY = Double.NaN; for (int i = 0; i < input.getPositionCount(); i++) { if (input.isNull(i)) { - throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid input to ST_MultiPoint: null at index %s", i + 1)); + throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid input to %s: null at index %s", functionName, i + 1)); } - Slice slice = GEOMETRY.getSlice(input, i); - OGCGeometry geometry = deserialize(slice); - if (!(geometry instanceof OGCPoint)) { - throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid input to ST_MultiPoint: geometry is not a point: %s at index %s", geometry.geometryType(), i + 1)); + BasicSliceInput slice = new BasicSliceInput(GEOMETRY.getSlice(input, i)); + GeometrySerializationType type = GeometrySerializationType.getForCode(slice.readByte()); + if (type != GeometrySerializationType.POINT) { + throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid input to %s: geometry is not a point: %s at index %s", functionName, type.toString(), i + 1)); } - OGCPoint point = (OGCPoint) geometry; - if (point.isEmpty()) { - throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid input to ST_MultiPoint: empty point at index %s", i + 1)); + + double x = slice.readDouble(); + double y = slice.readDouble(); + + if (Double.isNaN(x) || Double.isNaN(x)) { + throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid input to %s: empty point at index %s", functionName, i + 1)); + } + if (forbidDuplicates && x == lastX && y == lastY) { + throw new PrestoException(INVALID_FUNCTION_ARGUMENT, + format("Invalid input to %s: consecutive duplicate points at index %s", functionName, i + 1)); } - multipoint.add(point.X(), point.Y()); + lastX = x; + lastY = y; + coordinates[2 * i] = x; + coordinates[2 * i + 1] = y; } - if (multipoint.getPointCount() == 0) { - return null; - } - return serialize(createFromEsriGeometry(multipoint, null, true)); + + return coordinateSequenceFactory.create(coordinates, 2); } @Description("Returns a Geometry type Polygon object from Well-Known Text representation (WKT)") @@ -241,7 +240,7 @@ public static Slice stMultiPoint(@SqlType("array(" + GEOMETRY_TYPE_NAME + ")") B @SqlType(GEOMETRY_TYPE_NAME) public static Slice stPolygon(@SqlType(VARCHAR) Slice input) { - OGCGeometry geometry = geometryFromText(input); + Geometry geometry = jtsGeometryFromWkt(input.toStringUtf8()); validateType("ST_Polygon", geometry, EnumSet.of(POLYGON)); return serialize(geometry); } @@ -251,24 +250,7 @@ public static Slice stPolygon(@SqlType(VARCHAR) Slice input) @SqlType(DOUBLE) public static double stArea(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); - - // The Esri geometry library does not support area for geometry collections. We compute the area - // of collections by summing the area of the individual components. - GeometryType type = GeometryType.getForEsriGeometryType(geometry.geometryType()); - if (type == GeometryType.GEOMETRY_COLLECTION) { - double area = 0.0; - GeometryCursor cursor = geometry.getEsriGeometryCursor(); - while (true) { - com.esri.core.geometry.Geometry esriGeometry = cursor.next(); - if (esriGeometry == null) { - return area; - } - - area += esriGeometry.calculateArea2D(); - } - } - return geometry.getEsriGeometry().calculateArea2D(); + return deserialize(input).getArea(); } @Description("Returns a Geometry type object from Well-Known Text representation (WKT)") @@ -276,7 +258,7 @@ public static double stArea(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(GEOMETRY_TYPE_NAME) public static Slice stGeometryFromText(@SqlType(VARCHAR) Slice input) { - return serialize(geometryFromText(input)); + return serialize(jtsGeometryFromWkt(input.toStringUtf8())); } @Description("Returns a Geometry type object from Well-Known Binary representation (WKB)") @@ -284,7 +266,7 @@ public static Slice stGeometryFromText(@SqlType(VARCHAR) Slice input) @SqlType(GEOMETRY_TYPE_NAME) public static Slice stGeomFromBinary(@SqlType(VARBINARY) Slice input) { - return serialize(geomFromBinary(input)); + return EsriGeometrySerde.serialize(geomFromBinary(input)); } @Description("Converts a Geometry object to a SphericalGeography object") @@ -300,7 +282,7 @@ public static Slice toSphericalGeography(@SqlType(GEOMETRY_TYPE_NAME) Slice inpu checkLongitude(envelope.getXMin()); checkLongitude(envelope.getXMax()); } - OGCGeometry geometry = deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); if (geometry.is3D()) { throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Cannot convert 3D geometry to a spherical geography"); } @@ -334,7 +316,7 @@ public static Slice toGeometry(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice inp @SqlType(VARCHAR) public static Slice stAsText(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - return utf8Slice(deserialize(input).asText()); + return utf8Slice(wktFromJtsGeometry(deserialize(input))); } @Description("Returns the Well-Known Binary (WKB) representation of the geometry") @@ -342,7 +324,7 @@ public static Slice stAsText(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(VARBINARY) public static Slice stAsBinary(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - return wrappedBuffer(deserialize(input).asBinary()); + return wrappedBuffer(EsriGeometrySerde.deserialize(input).asBinary()); } @SqlNullable @@ -363,11 +345,11 @@ public static Slice stBuffer(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @SqlType( return input; } - OGCGeometry geometry = deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); if (geometry.isEmpty()) { return null; } - return serialize(geometry.buffer(distance)); + return EsriGeometrySerde.serialize(geometry.buffer(distance)); } @Description("Returns the Point value that is the mathematical centroid of a Geometry") @@ -375,19 +357,17 @@ public static Slice stBuffer(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @SqlType( @SqlType(GEOMETRY_TYPE_NAME) public static Slice stCentroid(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_Centroid", geometry, EnumSet.of(POINT, MULTI_POINT, LINE_STRING, MULTI_LINE_STRING, POLYGON, MULTI_POLYGON)); - GeometryType geometryType = GeometryType.getForEsriGeometryType(geometry.geometryType()); + GeometryType geometryType = GeometryType.getForJtsGeometryType(geometry.getGeometryType()); if (geometryType == GeometryType.POINT) { return input; } - int pointCount = ((MultiVertexGeometry) geometry.getEsriGeometry()).getPointCount(); - if (pointCount == 0) { - return serialize(createFromEsriGeometry(new Point(), geometry.getEsriSpatialReference())); + if (geometry.getNumPoints() == 0) { + return serialize(createJtsEmptyPoint()); } - - return serialize(geometry.centroid()); + return serialize(geometry.getCentroid()); } @Description("Returns the minimum convex geometry that encloses all input geometries") @@ -395,14 +375,14 @@ public static Slice stCentroid(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(GEOMETRY_TYPE_NAME) public static Slice stConvexHull(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); if (geometry.isEmpty()) { return input; } if (GeometryType.getForEsriGeometryType(geometry.geometryType()) == POINT) { return input; } - return serialize(geometry.convexHull()); + return EsriGeometrySerde.serialize(geometry.convexHull()); } @Description("Return the coordinate dimension of the Geometry") @@ -410,7 +390,7 @@ public static Slice stConvexHull(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(TINYINT) public static long stCoordinateDimension(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - return deserialize(input).coordinateDimension(); + return EsriGeometrySerde.deserialize(input).coordinateDimension(); } @Description("Returns the inherent dimension of this Geometry object, which must be less than or equal to the coordinate dimension") @@ -418,7 +398,7 @@ public static long stCoordinateDimension(@SqlType(GEOMETRY_TYPE_NAME) Slice inpu @SqlType(TINYINT) public static long stDimension(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - return deserialize(input).dimension(); + return deserialize(input).getDimension(); } @SqlNullable @@ -427,18 +407,17 @@ public static long stDimension(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(BOOLEAN) public static Boolean stIsClosed(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_IsClosed", geometry, EnumSet.of(LINE_STRING, MULTI_LINE_STRING)); - MultiPath lines = (MultiPath) geometry.getEsriGeometry(); - int pathCount = lines.getPathCount(); - for (int i = 0; i < pathCount; i++) { - Point start = lines.getPoint(lines.getPathStart(i)); - Point end = lines.getPoint(lines.getPathEnd(i) - 1); - if (!end.equals(start)) { - return false; - } + if (geometry instanceof LineString) { + return ((LineString) geometry).isClosed(); + } + else if (geometry instanceof MultiLineString) { + return ((MultiLineString) geometry).isClosed(); } - return true; + + // This would be handled in validateType, but for completeness. + throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("Invalid type for isClosed: %s", geometry.getGeometryType())); } @SqlNullable @@ -455,7 +434,7 @@ public static Boolean stIsEmpty(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(BOOLEAN) public static boolean stIsSimple(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); return geometry.isEmpty() || geometry.isSimple(); } @@ -464,7 +443,7 @@ public static boolean stIsSimple(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(BOOLEAN) public static boolean stIsValid(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - GeometryCursor cursor = deserialize(input).getEsriGeometryCursor(); + GeometryCursor cursor = EsriGeometrySerde.deserialize(input).getEsriGeometryCursor(); while (true) { com.esri.core.geometry.Geometry geometry = cursor.next(); if (geometry == null) { @@ -483,7 +462,7 @@ public static boolean stIsValid(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlNullable public static Slice invalidReason(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - GeometryCursor cursor = deserialize(input).getEsriGeometryCursor(); + GeometryCursor cursor = EsriGeometrySerde.deserialize(input).getEsriGeometryCursor(); NonSimpleResult result = new NonSimpleResult(); while (true) { com.esri.core.geometry.Geometry geometry = cursor.next(); @@ -520,9 +499,9 @@ public static Slice invalidReason(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(DOUBLE) public static double stLength(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_Length", geometry, EnumSet.of(LINE_STRING, MULTI_LINE_STRING)); - return geometry.getEsriGeometry().calculateLength2D(); + return geometry.getLength(); } @SqlNullable @@ -531,8 +510,8 @@ public static double stLength(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(DOUBLE) public static Double lineLocatePoint(@SqlType(GEOMETRY_TYPE_NAME) Slice lineSlice, @SqlType(GEOMETRY_TYPE_NAME) Slice pointSlice) { - Geometry line = JtsGeometrySerde.deserialize(lineSlice); - Geometry point = JtsGeometrySerde.deserialize(pointSlice); + Geometry line = deserialize(lineSlice); + Geometry point = deserialize(pointSlice); if (line.isEmpty() || point.isEmpty()) { return null; @@ -560,16 +539,16 @@ public static Slice lineInterpolatePoint(@SqlType(GEOMETRY_TYPE_NAME) Slice line throw new PrestoException(INVALID_FUNCTION_ARGUMENT, format("line_interpolate_point: Fraction must be between 0 and 1, but is %s", fraction)); } - Geometry geometry = JtsGeometrySerde.deserialize(lineSlice); + Geometry geometry = deserialize(lineSlice); validateType("line_interpolate_point", geometry, ImmutableSet.of(LINE_STRING)); LineString line = (LineString) geometry; if (line.isEmpty()) { - return JtsGeometrySerde.serialize(makeJtsEmptyPoint()); + return serialize(createJtsEmptyPoint()); } org.locationtech.jts.geom.Coordinate coordinate = new LengthIndexedLine(line).extractPoint(fraction * line.getLength()); - return JtsGeometrySerde.serialize(makeJtsPoint(coordinate)); + return serialize(createJtsPoint(coordinate)); } @SqlNullable @@ -630,12 +609,12 @@ public static Double stYMin(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(BIGINT) public static Long stNumInteriorRings(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_NumInteriorRing", geometry, EnumSet.of(POLYGON)); if (geometry.isEmpty()) { return null; } - return Long.valueOf(((OGCPolygon) geometry).numInteriorRing()); + return Long.valueOf(((org.locationtech.jts.geom.Polygon) geometry).getNumInteriorRing()); } @SqlNullable @@ -644,16 +623,16 @@ public static Long stNumInteriorRings(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType("array(" + GEOMETRY_TYPE_NAME + ")") public static Block stInteriorRings(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_InteriorRings", geometry, EnumSet.of(POLYGON)); if (geometry.isEmpty()) { return null; } - OGCPolygon polygon = (OGCPolygon) geometry; - BlockBuilder blockBuilder = GEOMETRY.createBlockBuilder(null, polygon.numInteriorRing()); - for (int i = 0; i < polygon.numInteriorRing(); i++) { - GEOMETRY.writeSlice(blockBuilder, serialize(polygon.interiorRingN(i))); + org.locationtech.jts.geom.Polygon polygon = (org.locationtech.jts.geom.Polygon) geometry; + BlockBuilder blockBuilder = GEOMETRY.createBlockBuilder(null, polygon.getNumInteriorRing()); + for (int i = 0; i < polygon.getNumInteriorRing(); i++) { + GEOMETRY.writeSlice(blockBuilder, serialize((LineString) polygon.getInteriorRingN(i))); } return blockBuilder.build(); } @@ -663,15 +642,11 @@ public static Block stInteriorRings(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(INTEGER) public static long stNumGeometries(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); if (geometry.isEmpty()) { return 0; } - GeometryType type = GeometryType.getForEsriGeometryType(geometry.geometryType()); - if (!type.isMultitype()) { - return 1; - } - return ((OGCGeometryCollection) geometry).numGeometries(); + return geometry.getNumGeometries(); } @Description("Returns a geometry that represents the point set union of the input geometries.") @@ -715,7 +690,7 @@ private static Slice stUnion(Iterable slices) continue; } - for (OGCGeometry geometry : flattenCollection(deserialize(slice))) { + for (OGCGeometry geometry : flattenCollection(EsriGeometrySerde.deserialize(slice))) { int dimension = geometry.dimension(); cursorsByDimension[dimension].tick(geometry.getEsriGeometry()); operatorsByDimension[dimension].tock(); @@ -731,9 +706,9 @@ private static Slice stUnion(Iterable slices) } if (outputs.size() == 1) { - return serialize(outputs.get(0)); + return EsriGeometrySerde.serialize(outputs.get(0)); } - return serialize(new OGCConcreteGeometryCollection(outputs, null).flattenAndRemoveOverlaps().reduceFromMulti()); + return EsriGeometrySerde.serialize(new OGCConcreteGeometryCollection(outputs, null).flattenAndRemoveOverlaps().reduceFromMulti()); } @SqlNullable @@ -742,23 +717,22 @@ private static Slice stUnion(Iterable slices) @SqlType(GEOMETRY_TYPE_NAME) public static Slice stGeometryN(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @SqlType(INTEGER) long index) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); if (geometry.isEmpty()) { return null; } - GeometryType type = GeometryType.getForEsriGeometryType(geometry.geometryType()); + GeometryType type = GeometryType.getForJtsGeometryType(geometry.getGeometryType()); if (!type.isMultitype()) { if (index == 1) { return input; } return null; } - OGCGeometryCollection geometryCollection = ((OGCGeometryCollection) geometry); - if (index < 1 || index > geometryCollection.numGeometries()) { + GeometryCollection geometryCollection = ((GeometryCollection) geometry); + if (index < 1 || index > geometryCollection.getNumGeometries()) { return null; } - OGCGeometry ogcGeometry = geometryCollection.geometryN((int) index - 1); - return serialize(ogcGeometry); + return serialize(geometryCollection.getGeometryN((int) index - 1)); } @SqlNullable @@ -767,14 +741,14 @@ public static Slice stGeometryN(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @SqlTy @SqlType(GEOMETRY_TYPE_NAME) public static Slice stPointN(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @SqlType(INTEGER) long index) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_PointN", geometry, EnumSet.of(LINE_STRING)); - OGCLineString linestring = (OGCLineString) geometry; - if (index < 1 || index > linestring.numPoints()) { + LineString linestring = (LineString) geometry; + if (index < 1 || index > linestring.getNumPoints()) { return null; } - return serialize(linestring.pointN(toIntExact(index) - 1)); + return serialize(linestring.getPointN(toIntExact(index) - 1)); } @SqlNullable @@ -783,22 +757,22 @@ public static Slice stPointN(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @SqlType( @SqlType("array(" + GEOMETRY_TYPE_NAME + ")") public static Block stGeometries(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); if (geometry.isEmpty()) { return null; } - GeometryType type = GeometryType.getForEsriGeometryType(geometry.geometryType()); + GeometryType type = GeometryType.getForJtsGeometryType(geometry.getGeometryType()); if (!type.isMultitype()) { BlockBuilder blockBuilder = GEOMETRY.createBlockBuilder(null, 1); GEOMETRY.writeSlice(blockBuilder, serialize(geometry)); return blockBuilder.build(); } - OGCGeometryCollection collection = (OGCGeometryCollection) geometry; - BlockBuilder blockBuilder = GEOMETRY.createBlockBuilder(null, collection.numGeometries()); - for (int i = 0; i < collection.numGeometries(); i++) { - GEOMETRY.writeSlice(blockBuilder, serialize(collection.geometryN(i))); + GeometryCollection collection = (GeometryCollection) geometry; + BlockBuilder blockBuilder = GEOMETRY.createBlockBuilder(null, collection.getNumGeometries()); + for (int i = 0; i < collection.getNumGeometries(); i++) { + GEOMETRY.writeSlice(blockBuilder, serialize(collection.getGeometryN(i))); } return blockBuilder.build(); } @@ -809,14 +783,13 @@ public static Block stGeometries(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(GEOMETRY_TYPE_NAME) public static Slice stInteriorRingN(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @SqlType(INTEGER) long index) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_InteriorRingN", geometry, EnumSet.of(POLYGON)); - OGCPolygon polygon = (OGCPolygon) geometry; - if (index < 1 || index > polygon.numInteriorRing()) { + org.locationtech.jts.geom.Polygon polygon = (org.locationtech.jts.geom.Polygon) geometry; + if (index < 1 || index > polygon.getNumInteriorRing()) { return null; } - OGCGeometry interiorRing = polygon.interiorRingN(toIntExact(index) - 1); - return serialize(interiorRing); + return serialize(polygon.getInteriorRingN(toIntExact(index) - 1)); } @Description("Returns the number of points in a Geometry") @@ -824,7 +797,7 @@ public static Slice stInteriorRingN(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @S @SqlType(BIGINT) public static long stNumPoints(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - return getPointCount(deserialize(input)); + return getPointCount(EsriGeometrySerde.deserialize(input)); } @SqlNullable @@ -833,7 +806,7 @@ public static long stNumPoints(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(BOOLEAN) public static Boolean stIsRing(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); validateType("ST_IsRing", geometry, EnumSet.of(LINE_STRING)); OGCLineString line = (OGCLineString) geometry; return line.isClosed() && line.isSimple(); @@ -845,13 +818,12 @@ public static Boolean stIsRing(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(GEOMETRY_TYPE_NAME) public static Slice stStartPoint(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_StartPoint", geometry, EnumSet.of(LINE_STRING)); if (geometry.isEmpty()) { return null; } - MultiPath lines = (MultiPath) geometry.getEsriGeometry(); - return serialize(createFromEsriGeometry(lines.getPoint(0), null)); + return serialize(((LineString) geometry).getStartPoint()); } @Description("Returns a \"simplified\" version of the given geometry") @@ -871,7 +843,7 @@ public static Slice simplifyGeometry(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @ return input; } - return JtsGeometrySerde.serialize(simplify(JtsGeometrySerde.deserialize(input), distanceTolerance)); + return serialize(simplify(deserialize(input), distanceTolerance)); } @SqlNullable @@ -880,13 +852,12 @@ public static Slice simplifyGeometry(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @ @SqlType(GEOMETRY_TYPE_NAME) public static Slice stEndPoint(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_EndPoint", geometry, EnumSet.of(LINE_STRING)); if (geometry.isEmpty()) { return null; } - MultiPath lines = (MultiPath) geometry.getEsriGeometry(); - return serialize(createFromEsriGeometry(lines.getPoint(lines.getPointCount() - 1), null)); + return serialize(((LineString) geometry).getEndPoint()); } @SqlNullable @@ -895,15 +866,15 @@ public static Slice stEndPoint(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType("array(" + GEOMETRY_TYPE_NAME + ")") public static Block stPoints(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_Points", geometry, EnumSet.of(LINE_STRING)); if (geometry.isEmpty()) { return null; } - MultiPath lines = (MultiPath) geometry.getEsriGeometry(); - BlockBuilder blockBuilder = GEOMETRY.createBlockBuilder(null, lines.getPointCount()); - for (int i = 0; i < lines.getPointCount(); i++) { - GEOMETRY.writeSlice(blockBuilder, serialize(createFromEsriGeometry(lines.getPoint(i), null))); + LineString lineString = (LineString) geometry; + BlockBuilder blockBuilder = GEOMETRY.createBlockBuilder(null, lineString.getNumPoints()); + for (int i = 0; i < lineString.getNumPoints(); i++) { + GEOMETRY.writeSlice(blockBuilder, serialize(lineString.getPointN(i))); } return blockBuilder.build(); } @@ -914,12 +885,12 @@ public static Block stPoints(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(DOUBLE) public static Double stX(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_X", geometry, EnumSet.of(POINT)); if (geometry.isEmpty()) { return null; } - return ((OGCPoint) geometry).X(); + return ((org.locationtech.jts.geom.Point) geometry).getX(); } @SqlNullable @@ -928,12 +899,12 @@ public static Double stX(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(DOUBLE) public static Double stY(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_Y", geometry, EnumSet.of(POINT)); if (geometry.isEmpty()) { return null; } - return ((OGCPoint) geometry).Y(); + return ((org.locationtech.jts.geom.Point) geometry).getY(); } @Description("Returns the closure of the combinatorial boundary of this Geometry") @@ -941,12 +912,7 @@ public static Double stY(@SqlType(GEOMETRY_TYPE_NAME) Slice input) @SqlType(GEOMETRY_TYPE_NAME) public static Slice stBoundary(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); - if (geometry.isEmpty() && GeometryType.getForEsriGeometryType(geometry.geometryType()) == LINE_STRING) { - // OCGGeometry#boundary crashes with NPE for LINESTRING EMPTY - return EMPTY_MULTIPOINT; - } - return serialize(geometry.boundary()); + return serialize(deserialize(input).getBoundary()); } @Description("Returns the bounding rectangular polygon of a Geometry") @@ -958,7 +924,7 @@ public static Slice stEnvelope(@SqlType(GEOMETRY_TYPE_NAME) Slice input) if (envelope.isEmpty()) { return EMPTY_POLYGON; } - return serialize(envelope); + return EsriGeometrySerde.serialize(envelope); } @SqlNullable @@ -972,10 +938,10 @@ public static Block stEnvelopeAsPts(@SqlType(GEOMETRY_TYPE_NAME) Slice input) return null; } BlockBuilder blockBuilder = GEOMETRY.createBlockBuilder(null, 2); - Point lowerLeftCorner = new Point(envelope.getXMin(), envelope.getYMin()); - Point upperRightCorner = new Point(envelope.getXMax(), envelope.getYMax()); - GEOMETRY.writeSlice(blockBuilder, serialize(createFromEsriGeometry(lowerLeftCorner, null, false))); - GEOMETRY.writeSlice(blockBuilder, serialize(createFromEsriGeometry(upperRightCorner, null, false))); + org.locationtech.jts.geom.Point lowerLeftCorner = createJtsPoint(envelope.getXMin(), envelope.getYMin()); + org.locationtech.jts.geom.Point upperRightCorner = createJtsPoint(envelope.getXMax(), envelope.getYMax()); + GEOMETRY.writeSlice(blockBuilder, serialize(lowerLeftCorner)); + GEOMETRY.writeSlice(blockBuilder, serialize(upperRightCorner)); return blockBuilder.build(); } @@ -996,7 +962,7 @@ public static Slice expandEnvelope(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @Sq if (envelope.isEmpty()) { return EMPTY_POLYGON; } - return serialize(new Envelope( + return EsriGeometrySerde.serialize(new Envelope( envelope.getXMin() - distance, envelope.getYMin() - distance, envelope.getXMax() + distance, @@ -1008,10 +974,10 @@ public static Slice expandEnvelope(@SqlType(GEOMETRY_TYPE_NAME) Slice input, @Sq @SqlType(GEOMETRY_TYPE_NAME) public static Slice stDifference(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType(GEOMETRY_TYPE_NAME) Slice right) { - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); - return serialize(leftGeometry.difference(rightGeometry)); + return EsriGeometrySerde.serialize(leftGeometry.difference(rightGeometry)); } @SqlNullable @@ -1020,8 +986,8 @@ public static Slice stDifference(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTy @SqlType(DOUBLE) public static Double stDistance(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType(GEOMETRY_TYPE_NAME) Slice right) { - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.isEmpty() || rightGeometry.isEmpty() ? null : leftGeometry.distance(rightGeometry); } @@ -1032,12 +998,12 @@ public static Double stDistance(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTyp @SqlType(GEOMETRY_TYPE_NAME) public static Slice stExteriorRing(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + Geometry geometry = deserialize(input); validateType("ST_ExteriorRing", geometry, EnumSet.of(POLYGON)); if (geometry.isEmpty()) { return null; } - return serialize(((OGCPolygon) geometry).exteriorRing()); + return serialize(((org.locationtech.jts.geom.Polygon) geometry).getExteriorRing()); } @Description("Returns the Geometry value that represents the point set intersection of two Geometries") @@ -1057,22 +1023,22 @@ public static Slice stIntersection(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @Sql Envelope intersection = leftEnvelope; if (intersection.getXMin() == intersection.getXMax()) { if (intersection.getYMin() == intersection.getYMax()) { - return serialize(createFromEsriGeometry(new Point(intersection.getXMin(), intersection.getXMax()), null)); + return EsriGeometrySerde.serialize(createFromEsriGeometry(new Point(intersection.getXMin(), intersection.getXMax()), null)); } - return serialize(createFromEsriGeometry(new Polyline(new Point(intersection.getXMin(), intersection.getYMin()), new Point(intersection.getXMin(), intersection.getYMax())), null)); + return EsriGeometrySerde.serialize(createFromEsriGeometry(new Polyline(new Point(intersection.getXMin(), intersection.getYMin()), new Point(intersection.getXMin(), intersection.getYMax())), null)); } if (intersection.getYMin() == intersection.getYMax()) { - return serialize(createFromEsriGeometry(new Polyline(new Point(intersection.getXMin(), intersection.getYMin()), new Point(intersection.getXMax(), intersection.getYMin())), null)); + return EsriGeometrySerde.serialize(createFromEsriGeometry(new Polyline(new Point(intersection.getXMin(), intersection.getYMin()), new Point(intersection.getXMax(), intersection.getYMin())), null)); } - return serialize(intersection); + return EsriGeometrySerde.serialize(intersection); } - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); - return serialize(leftGeometry.intersection(rightGeometry)); + return EsriGeometrySerde.serialize(leftGeometry.intersection(rightGeometry)); } @Description("Returns the Geometry value that represents the point set symmetric difference of two Geometries") @@ -1080,10 +1046,10 @@ public static Slice stIntersection(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @Sql @SqlType(GEOMETRY_TYPE_NAME) public static Slice stSymmetricDifference(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType(GEOMETRY_TYPE_NAME) Slice right) { - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); - return serialize(leftGeometry.symDifference(rightGeometry)); + return EsriGeometrySerde.serialize(leftGeometry.symDifference(rightGeometry)); } @SqlNullable @@ -1095,8 +1061,8 @@ public static Boolean stContains(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTy if (!envelopes(left, right, Envelope::contains)) { return false; } - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.contains(rightGeometry); } @@ -1110,8 +1076,8 @@ public static Boolean stCrosses(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTyp if (!envelopes(left, right, Envelope::intersect)) { return false; } - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.crosses(rightGeometry); } @@ -1125,8 +1091,8 @@ public static Boolean stDisjoint(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTy if (!envelopes(left, right, Envelope::intersect)) { return true; } - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.disjoint(rightGeometry); } @@ -1137,10 +1103,10 @@ public static Boolean stDisjoint(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTy @SqlType(BOOLEAN) public static Boolean stEquals(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType(GEOMETRY_TYPE_NAME) Slice right) { - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); - return leftGeometry.equals(rightGeometry); + return leftGeometry.Equals(rightGeometry); } @SqlNullable @@ -1152,8 +1118,8 @@ public static Boolean stIntersects(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @Sql if (!envelopes(left, right, Envelope::intersect)) { return false; } - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.intersects(rightGeometry); } @@ -1167,8 +1133,8 @@ public static Boolean stOverlaps(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTy if (!envelopes(left, right, Envelope::intersect)) { return false; } - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.overlaps(rightGeometry); } @@ -1179,8 +1145,8 @@ public static Boolean stOverlaps(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTy @SqlType(BOOLEAN) public static Boolean stRelate(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType(GEOMETRY_TYPE_NAME) Slice right, @SqlType(VARCHAR) Slice relation) { - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.relate(rightGeometry, relation.toStringUtf8()); } @@ -1194,8 +1160,8 @@ public static Boolean stTouches(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlTyp if (!envelopes(left, right, Envelope::intersect)) { return false; } - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.touches(rightGeometry); } @@ -1209,8 +1175,8 @@ public static Boolean stWithin(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType if (!envelopes(right, left, Envelope::contains)) { return false; } - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); verifySameSpatialReference(leftGeometry, rightGeometry); return leftGeometry.within(rightGeometry); } @@ -1220,7 +1186,7 @@ public static Boolean stWithin(@SqlType(GEOMETRY_TYPE_NAME) Slice left, @SqlType @SqlType(VARCHAR) public static Slice stGeometryType(@SqlType(GEOMETRY_TYPE_NAME) Slice input) { - return GeometrySerde.getGeometryType(input).standardName(); + return EsriGeometrySerde.getGeometryType(input).standardName(); } @ScalarFunction @@ -1341,19 +1307,6 @@ private static void checkLongitude(double longitude) } } - private static OGCGeometry geometryFromText(Slice input) - { - OGCGeometry geometry; - try { - geometry = OGCGeometry.fromText(input.toStringUtf8()); - } - catch (IllegalArgumentException e) { - throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "Invalid WKT: " + input.toStringUtf8(), e); - } - geometry.setSpatialReference(null); - return geometry; - } - private static OGCGeometry geomFromBinary(Slice input) { requireNonNull(input, "input is null"); @@ -1410,8 +1363,8 @@ private interface EnvelopesPredicate @SqlType(DOUBLE) public static Double stSphericalDistance(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice left, @SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice right) { - OGCGeometry leftGeometry = deserialize(left); - OGCGeometry rightGeometry = deserialize(right); + OGCGeometry leftGeometry = EsriGeometrySerde.deserialize(left); + OGCGeometry rightGeometry = EsriGeometrySerde.deserialize(right); if (leftGeometry.isEmpty() || rightGeometry.isEmpty()) { return null; } @@ -1440,7 +1393,7 @@ private static void validateSphericalType(String function, OGCGeometry geometry, @SqlType(DOUBLE) public static Double stSphericalArea(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); if (geometry.isEmpty()) { return null; } @@ -1473,7 +1426,7 @@ public static Double stSphericalArea(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Sli @SqlType(DOUBLE) public static Double stSphericalLength(@SqlType(SPHERICAL_GEOGRAPHY_TYPE_NAME) Slice input) { - OGCGeometry geometry = deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); if (geometry.isEmpty()) { return null; } diff --git a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/GeometryType.java b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/GeometryType.java index 2b007eb380739..724f855382a02 100644 --- a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/GeometryType.java +++ b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/GeometryType.java @@ -20,7 +20,7 @@ import com.facebook.presto.spi.type.TypeSignature; import io.airlift.slice.Slice; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; public class GeometryType extends AbstractVariableWidthType diff --git a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/SpatialPartitioningInternalAggregateFunction.java b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/SpatialPartitioningInternalAggregateFunction.java index 81c671b81f8a9..58ab1e44b99a8 100644 --- a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/SpatialPartitioningInternalAggregateFunction.java +++ b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/SpatialPartitioningInternalAggregateFunction.java @@ -31,7 +31,7 @@ import java.util.concurrent.ThreadLocalRandom; import static com.facebook.presto.geospatial.KdbTree.buildKdbTree; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserializeEnvelope; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserializeEnvelope; import static com.facebook.presto.plugin.geospatial.GeometryType.GEOMETRY_TYPE_NAME; import static com.facebook.presto.plugin.geospatial.SpatialPartitioningAggregateFunction.NAME; import static com.facebook.presto.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT; diff --git a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/SphericalGeographyType.java b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/SphericalGeographyType.java index 1b6461f1ae52b..bf277b8b55acc 100644 --- a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/SphericalGeographyType.java +++ b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/SphericalGeographyType.java @@ -20,7 +20,7 @@ import com.facebook.presto.spi.type.TypeSignature; import io.airlift.slice.Slice; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; public class SphericalGeographyType extends AbstractVariableWidthType diff --git a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/ConvexHullAggregation.java b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/ConvexHullAggregation.java index 276f66b74dbe0..da3b23352d22c 100644 --- a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/ConvexHullAggregation.java +++ b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/ConvexHullAggregation.java @@ -15,7 +15,7 @@ import com.esri.core.geometry.ogc.OGCGeometry; import com.facebook.presto.geospatial.GeometryType; -import com.facebook.presto.geospatial.serde.GeometrySerde; +import com.facebook.presto.geospatial.serde.EsriGeometrySerde; import com.facebook.presto.spi.PrestoException; import com.facebook.presto.spi.block.BlockBuilder; import com.facebook.presto.spi.function.AggregationFunction; @@ -51,7 +51,7 @@ private ConvexHullAggregation() {} public static void input(@AggregationState GeometryState state, @SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = GeometrySerde.deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); if (state.getGeometry() == null) { state.setGeometry(geometry.convexHull(), 0); } @@ -81,7 +81,7 @@ public static void output(@AggregationState GeometryState state, BlockBuilder ou out.appendNull(); } else { - GEOMETRY.writeSlice(out, GeometrySerde.serialize(state.getGeometry())); + GEOMETRY.writeSlice(out, EsriGeometrySerde.serialize(state.getGeometry())); } } diff --git a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/GeometryStateSerializer.java b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/GeometryStateSerializer.java index 2654d9299fe7d..83649fda1fd31 100644 --- a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/GeometryStateSerializer.java +++ b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/GeometryStateSerializer.java @@ -13,7 +13,7 @@ */ package com.facebook.presto.plugin.geospatial.aggregation; -import com.facebook.presto.geospatial.serde.GeometrySerde; +import com.facebook.presto.geospatial.serde.EsriGeometrySerde; import com.facebook.presto.spi.block.Block; import com.facebook.presto.spi.block.BlockBuilder; import com.facebook.presto.spi.function.AccumulatorStateSerializer; @@ -37,7 +37,7 @@ public void serialize(GeometryState state, BlockBuilder out) out.appendNull(); } else { - GEOMETRY.writeSlice(out, GeometrySerde.serialize(state.getGeometry())); + GEOMETRY.writeSlice(out, EsriGeometrySerde.serialize(state.getGeometry())); } } @@ -45,6 +45,6 @@ public void serialize(GeometryState state, BlockBuilder out) public void deserialize(Block block, int index, GeometryState state) { long previousMemorySize = state.getGeometry() != null ? state.getGeometry().estimateMemorySize() : 0; - state.setGeometry(GeometrySerde.deserialize(GEOMETRY.getSlice(block, index)), previousMemorySize); + state.setGeometry(EsriGeometrySerde.deserialize(GEOMETRY.getSlice(block, index)), previousMemorySize); } } diff --git a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/GeometryUnionAgg.java b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/GeometryUnionAgg.java index 14c0f34fa2801..6991e416a6171 100644 --- a/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/GeometryUnionAgg.java +++ b/presto-geospatial/src/main/java/com/facebook/presto/plugin/geospatial/aggregation/GeometryUnionAgg.java @@ -14,7 +14,7 @@ package com.facebook.presto.plugin.geospatial.aggregation; import com.esri.core.geometry.ogc.OGCGeometry; -import com.facebook.presto.geospatial.serde.GeometrySerde; +import com.facebook.presto.geospatial.serde.EsriGeometrySerde; import com.facebook.presto.spi.block.BlockBuilder; import com.facebook.presto.spi.function.AggregationFunction; import com.facebook.presto.spi.function.AggregationState; @@ -41,7 +41,7 @@ private GeometryUnionAgg() {} @InputFunction public static void input(@AggregationState GeometryState state, @SqlType(GEOMETRY_TYPE_NAME) Slice input) { - OGCGeometry geometry = GeometrySerde.deserialize(input); + OGCGeometry geometry = EsriGeometrySerde.deserialize(input); if (state.getGeometry() == null) { state.setGeometry(geometry, 0); } @@ -70,7 +70,7 @@ public static void output(@AggregationState GeometryState state, BlockBuilder ou out.appendNull(); } else { - GEOMETRY.writeSlice(out, GeometrySerde.serialize(state.getGeometry())); + GEOMETRY.writeSlice(out, EsriGeometrySerde.serialize(state.getGeometry())); } } } diff --git a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkEnvelopeIntersection.java b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkEnvelopeIntersection.java index 99900b376ab6e..808e2130182a0 100644 --- a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkEnvelopeIntersection.java +++ b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkEnvelopeIntersection.java @@ -33,7 +33,7 @@ import java.util.concurrent.TimeUnit; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; import static com.facebook.presto.plugin.geospatial.GeoFunctions.stEnvelope; import static com.facebook.presto.plugin.geospatial.GeoFunctions.stGeometryFromText; import static com.facebook.presto.plugin.geospatial.GeoFunctions.stIntersection; diff --git a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkSTArea.java b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkSTArea.java index d888f80438825..a095c3935ce35 100644 --- a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkSTArea.java +++ b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkSTArea.java @@ -111,10 +111,10 @@ public static void verify() throws IOException data.setup(); BenchmarkSTArea benchmark = new BenchmarkSTArea(); - assertEquals(Math.round(1000 * (Double) benchmark.stSphericalArea(data) / 3.659E8), 1000); - assertEquals(Math.round(1000 * (Double) benchmark.stSphericalArea500k(data) / 38842273735.0), 1000); - assertEquals(benchmark.stArea(data), 0.05033099592771004); - assertEquals(Math.round(1000 * (Double) benchmark.stArea500k(data) / Math.PI), 1000); + assertEquals((Double) benchmark.stSphericalArea(data) / 3.659E8, 1.0, 1E-3); + assertEquals((Double) benchmark.stSphericalArea500k(data) / 38842273735.0, 1.0, 1E-3); + assertEquals((Double) benchmark.stArea(data) / 0.0503309959277, 1.0, 1E-3); + assertEquals((Double) benchmark.stArea500k(data) / Math.PI, 1.0, 1E-3); } private static String createPolygon(double numVertices) diff --git a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkSTContains.java b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkSTContains.java index 6eb1bda1f6668..89909dd232ab2 100644 --- a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkSTContains.java +++ b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/BenchmarkSTContains.java @@ -36,8 +36,8 @@ import java.io.IOException; import java.util.concurrent.TimeUnit; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserializeEnvelope; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserializeEnvelope; import static com.facebook.presto.plugin.geospatial.GeometryBenchmarkUtils.loadPolygon; @State(Scope.Thread) diff --git a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestBingTileFunctions.java b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestBingTileFunctions.java index 6f505cb5c15d8..e572b54f5942f 100644 --- a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestBingTileFunctions.java +++ b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestBingTileFunctions.java @@ -384,8 +384,8 @@ public void testBingTileZoomLevel() @Test public void testBingTilePolygon() { - assertFunction("ST_AsText(bing_tile_polygon(bing_tile('123030123010121')))", VARCHAR, "POLYGON ((59.996337890625 30.11662158281937, 60.00732421875 30.11662158281937, 60.00732421875 30.12612436422458, 59.996337890625 30.12612436422458, 59.996337890625 30.11662158281937))"); - assertFunction("ST_AsText(ST_Centroid(bing_tile_polygon(bing_tile('123030123010121'))))", VARCHAR, "POINT (60.0018310546875 30.121372973521975)"); + assertFunction("ST_AsText(bing_tile_polygon(bing_tile('123030123010121')))", VARCHAR, "POLYGON ((59.996337890625 30.11662158281937, 59.996337890625 30.12612436422458, 60.00732421875 30.12612436422458, 60.00732421875 30.11662158281937, 59.996337890625 30.11662158281937))"); + assertFunction("ST_AsText(ST_Centroid(bing_tile_polygon(bing_tile('123030123010121'))))", VARCHAR, "POINT (60.0018310546875 30.12137297352197)"); // Check bottom right corner of a stack of tiles at different zoom levels assertFunction("ST_AsText(apply(bing_tile_polygon(bing_tile(1, 1, 1)), g -> ST_Point(ST_XMax(g), ST_YMin(g))))", VARCHAR, "POINT (180 -85.05112877980659)"); diff --git a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestGeoFunctions.java b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestGeoFunctions.java index 51734c92450d5..0365132b11c2c 100644 --- a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestGeoFunctions.java +++ b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestGeoFunctions.java @@ -18,7 +18,7 @@ import com.esri.core.geometry.ogc.OGCPoint; import com.facebook.presto.geospatial.KdbTreeUtils; import com.facebook.presto.geospatial.Rectangle; -import com.facebook.presto.geospatial.serde.GeometrySerde; +import com.facebook.presto.geospatial.serde.EsriGeometrySerde; import com.facebook.presto.operator.scalar.AbstractTestFunctions; import com.facebook.presto.spi.block.Block; import com.facebook.presto.spi.block.BlockBuilder; @@ -135,14 +135,17 @@ public void testSTLineFromText() assertFunction("ST_AsText(ST_LineFromText('LINESTRING (1 1, 2 2, 1 3)'))", VARCHAR, "LINESTRING (1 1, 2 2, 1 3)"); assertInvalidFunction("ST_AsText(ST_LineFromText('MULTILINESTRING EMPTY'))", "ST_LineFromText only applies to LINE_STRING. Input type is: MULTI_LINE_STRING"); assertInvalidFunction("ST_AsText(ST_LineFromText('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'))", "ST_LineFromText only applies to LINE_STRING. Input type is: POLYGON"); + assertInvalidFunction("ST_LineFromText('LINESTRING (0 0)')", INVALID_FUNCTION_ARGUMENT, "Invalid WKT: Invalid number of points in LineString (found 1 - must be 0 or >= 2)"); + assertInvalidFunction("ST_LineFromText('LINESTRING (0 0, 1)')", INVALID_FUNCTION_ARGUMENT, "Invalid WKT: Expected number but found ')' (line 1)"); } @Test public void testSTPolygon() { assertFunction("ST_AsText(ST_Polygon('POLYGON EMPTY'))", VARCHAR, "POLYGON EMPTY"); - assertFunction("ST_AsText(ST_Polygon('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'))", VARCHAR, "POLYGON ((1 1, 4 1, 4 4, 1 4, 1 1))"); + assertFunction("ST_AsText(ST_Polygon('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'))", VARCHAR, "POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))"); assertInvalidFunction("ST_AsText(ST_Polygon('LINESTRING (1 1, 2 2, 1 3)'))", "ST_Polygon only applies to POLYGON. Input type is: LINE_STRING"); + assertInvalidFunction("ST_Polygon('POLYGON((-1 1, 1 -1))')", INVALID_FUNCTION_ARGUMENT, "Invalid WKT: Points of LinearRing do not form a closed linestring"); } @Test @@ -174,17 +177,17 @@ private void assertArea(String wkt, double expectedArea) @Test public void testSTBuffer() { - assertFunction("ST_AsText(ST_Buffer(ST_Point(0, 0), 0.5))", VARCHAR, "POLYGON ((0.5 0, 0.4989294616193014 0.03270156461507146, 0.49572243068690486 0.0652630961100257, 0.4903926402016149 0.09754516100806403, 0.4829629131445338 0.12940952255126026, 0.47346506474755257 0.16071973265158065, 0.46193976625564315 0.19134171618254472, 0.4484363707663439 0.22114434510950046, 0.43301270189221913 0.2499999999999998, 0.41573480615127245 0.2777851165098009, 0.39667667014561747 0.30438071450436016, 0.3759199037394886 0.32967290755003426, 0.3535533905932737 0.3535533905932736, 0.32967290755003437 0.3759199037394886, 0.3043807145043603 0.39667667014561747, 0.2777851165098011 0.4157348061512725, 0.24999999999999997 0.43301270189221924, 0.22114434510950062 0.4484363707663441, 0.19134171618254486 0.4619397662556433, 0.16071973265158077 0.4734650647475528, 0.12940952255126037 0.48296291314453416, 0.09754516100806412 0.4903926402016152, 0.06526309611002579 0.4957224306869052, 0.03270156461507153 0.49892946161930174, 0 0.5, -0.03270156461507146 0.4989294616193014, -0.0652630961100257 0.49572243068690486, -0.09754516100806403 0.4903926402016149, -0.12940952255126026 0.4829629131445338, -0.16071973265158065 0.47346506474755257, -0.19134171618254472 0.46193976625564315, -0.22114434510950046 0.4484363707663439, -0.2499999999999998 0.43301270189221913, -0.2777851165098009 0.41573480615127245, -0.30438071450436016 0.39667667014561747, -0.32967290755003426 0.3759199037394886, -0.3535533905932736 0.3535533905932737, -0.3759199037394886 0.32967290755003437, -0.39667667014561747 0.3043807145043603, -0.4157348061512725 0.2777851165098011, -0.43301270189221924 0.24999999999999997, -0.4484363707663441 0.22114434510950062, -0.4619397662556433 0.19134171618254486, -0.4734650647475528 0.16071973265158077, -0.48296291314453416 0.12940952255126037, -0.4903926402016152 0.09754516100806412, -0.4957224306869052 0.06526309611002579, -0.49892946161930174 0.03270156461507153, -0.5 0, -0.4989294616193014 -0.03270156461507146, -0.49572243068690486 -0.0652630961100257, -0.4903926402016149 -0.09754516100806403, -0.4829629131445338 -0.12940952255126026, -0.47346506474755257 -0.16071973265158065, -0.46193976625564315 -0.19134171618254472, -0.4484363707663439 -0.22114434510950046, -0.43301270189221913 -0.2499999999999998, -0.41573480615127245 -0.2777851165098009, -0.39667667014561747 -0.30438071450436016, -0.3759199037394886 -0.32967290755003426, -0.3535533905932737 -0.3535533905932736, -0.32967290755003437 -0.3759199037394886, -0.3043807145043603 -0.39667667014561747, -0.2777851165098011 -0.4157348061512725, -0.24999999999999997 -0.43301270189221924, -0.22114434510950062 -0.4484363707663441, -0.19134171618254486 -0.4619397662556433, -0.16071973265158077 -0.4734650647475528, -0.12940952255126037 -0.48296291314453416, -0.09754516100806412 -0.4903926402016152, -0.06526309611002579 -0.4957224306869052, -0.03270156461507153 -0.49892946161930174, 0 -0.5, 0.03270156461507146 -0.4989294616193014, 0.0652630961100257 -0.49572243068690486, 0.09754516100806403 -0.4903926402016149, 0.12940952255126026 -0.4829629131445338, 0.16071973265158065 -0.47346506474755257, 0.19134171618254472 -0.46193976625564315, 0.22114434510950046 -0.4484363707663439, 0.2499999999999998 -0.43301270189221913, 0.2777851165098009 -0.41573480615127245, 0.30438071450436016 -0.39667667014561747, 0.32967290755003426 -0.3759199037394886, 0.3535533905932736 -0.3535533905932737, 0.3759199037394886 -0.32967290755003437, 0.39667667014561747 -0.3043807145043603, 0.4157348061512725 -0.2777851165098011, 0.43301270189221924 -0.24999999999999997, 0.4484363707663441 -0.22114434510950062, 0.4619397662556433 -0.19134171618254486, 0.4734650647475528 -0.16071973265158077, 0.48296291314453416 -0.12940952255126037, 0.4903926402016152 -0.09754516100806412, 0.4957224306869052 -0.06526309611002579, 0.49892946161930174 -0.03270156461507153, 0.5 0))"); - assertFunction("ST_AsText(ST_Buffer(ST_LineFromText('LINESTRING (0 0, 1 1, 2 0.5)'), 0.2))", VARCHAR, "POLYGON ((0 -0.19999999999999996, 0.013080625846028537 -0.19957178464772052, 0.02610523844401036 -0.19828897227476194, 0.03901806440322564 -0.19615705608064593, 0.05176380902050415 -0.1931851652578136, 0.06428789306063232 -0.18938602589902098, 0.07653668647301792 -0.18477590650225728, 0.0884577380438003 -0.17937454830653754, 0.09999999999999987 -0.17320508075688767, 0.11111404660392044 -0.166293922460509, 0.12175228580174413 -0.15867066805824703, 0.13186916302001372 -0.15036796149579545, 0.14142135623730945 -0.14142135623730945, 1.0394906098164265 0.7566478973418078, 1.9105572809000084 0.32111456180001685, 1.9115422619561997 0.32062545169346235, 1.923463313526982 0.31522409349774266, 1.9357121069393677 0.3106139741009789, 1.9482361909794959 0.3068148347421863, 1.9609819355967744 0.3038429439193539, 1.9738947615559896 0.30171102772523795, 1.9869193741539715 0.30042821535227926, 2 0.3, 2.0130806258460288 0.3004282153522794, 2.02610523844401 0.30171102772523806, 2.0390180644032254 0.30384294391935407, 2.051763809020504 0.30681483474218646, 2.0642878930606323 0.31061397410097896, 2.076536686473018 0.3152240934977427, 2.0884577380438003 0.32062545169346246, 2.1 0.3267949192431123, 2.1111140466039204 0.333706077539491, 2.121752285801744 0.34132933194175297, 2.1318691630200135 0.34963203850420455, 2.1414213562373092 0.35857864376269055, 2.1503679614957956 0.3681308369799863, 2.158670668058247 0.37824771419825587, 2.166293922460509 0.38888595339607956, 2.1732050807568877 0.4, 2.1793745483065377 0.41154226195619975, 2.1847759065022574 0.4234633135269821, 2.189386025899021 0.4357121069393677, 2.193185165257814 0.44823619097949585, 2.1961570560806463 0.46098193559677436, 2.1982889722747623 0.4738947615559897, 2.1995717846477207 0.4869193741539714, 2.2 0.5, 2.1995717846477207 0.5130806258460285, 2.198288972274762 0.5261052384440102, 2.196157056080646 0.5390180644032256, 2.1931851652578134 0.5517638090205041, 2.189386025899021 0.5642878930606323, 2.1847759065022574 0.5765366864730179, 2.1793745483065377 0.5884577380438002, 2.1732050807568877 0.5999999999999999, 2.166293922460509 0.6111140466039204, 2.158670668058247 0.6217522858017441, 2.1503679614957956 0.6318691630200137, 2.1414213562373097 0.6414213562373094, 2.131869163020014 0.6503679614957955, 2.121752285801744 0.658670668058247, 2.1111140466039204 0.666293922460509, 2.1 0.6732050807568877, 2.0894427190999916 0.6788854381999831, 1.0894427190999916 1.1788854381999831, 1.0884577380438003 1.1793745483065377, 1.076536686473018 1.1847759065022574, 1.0642878930606323 1.189386025899021, 1.0517638090205041 1.1931851652578138, 1.0390180644032256 1.196157056080646, 1.0261052384440104 1.198288972274762, 1.0130806258460288 1.1995717846477207, 1 1.2, 0.9869193741539715 1.1995717846477205, 0.9738947615559896 1.1982889722747618, 0.9609819355967744 1.1961570560806458, 0.9482361909794959 1.1931851652578136, 0.9357121069393677 1.189386025899021, 0.9234633135269821 1.1847759065022574, 0.9115422619561997 1.1793745483065377, 0.9000000000000001 1.1732050807568877, 0.8888859533960796 1.166293922460509, 0.8782477141982559 1.158670668058247, 0.8681308369799863 1.1503679614957956, 0.8585786437626906 1.1414213562373094, -0.14142135623730967 0.1414213562373095, -0.15036796149579557 0.13186916302001372, -0.1586706680582468 0.12175228580174413, -0.1662939224605089 0.11111404660392044, -0.17320508075688767 0.09999999999999998, -0.17937454830653765 0.08845773804380025, -0.1847759065022574 0.07653668647301792, -0.18938602589902098 0.06428789306063232, -0.19318516525781382 0.05176380902050415, -0.19615705608064626 0.03901806440322564, -0.19828897227476228 0.026105238444010304, -0.19957178464772074 0.013080625846028593, -0.20000000000000018 0, -0.19957178464772074 -0.013080625846028537, -0.19828897227476183 -0.026105238444010248, -0.19615705608064582 -0.03901806440322564, -0.19318516525781337 -0.05176380902050415, -0.18938602589902098 -0.06428789306063232, -0.1847759065022574 -0.07653668647301792, -0.17937454830653765 -0.0884577380438002, -0.17320508075688767 -0.09999999999999987, -0.1662939224605089 -0.11111404660392044, -0.1586706680582468 -0.12175228580174413, -0.15036796149579557 -0.13186916302001372, -0.14142135623730967 -0.14142135623730945, -0.13186916302001395 -0.15036796149579545, -0.12175228580174391 -0.15867066805824703, -0.11111404660392044 -0.166293922460509, -0.10000000000000009 -0.17320508075688767, -0.0884577380438003 -0.17937454830653765, -0.07653668647301792 -0.1847759065022574, -0.06428789306063232 -0.1893860258990211, -0.05176380902050415 -0.1931851652578137, -0.03901806440322586 -0.19615705608064604, -0.026105238444010137 -0.19828897227476205, -0.01308062584602876 -0.19957178464772074, 0 -0.19999999999999996))"); - assertFunction("ST_AsText(ST_Buffer(ST_GeometryFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))'), 1.2))", VARCHAR, "POLYGON ((-1.2 0, -1.1974307078863233 -0.0784837550761715, -1.1897338336485717 -0.15663143066406168, -1.1769423364838756 -0.23410838641935366, -1.1591109915468811 -0.3105828541230246, -1.1363161553941261 -0.38572735836379357, -1.1086554390135435 -0.4592201188381073, -1.0762472898392252 -0.530746428262801, -1.0392304845413258 -0.5999999999999995, -0.9977635347630538 -0.6666842796235222, -0.9520240083494819 -0.7305137148104643, -0.9022077689747725 -0.7912149781200822, -0.8485281374238568 -0.8485281374238567, -0.7912149781200825 -0.9022077689747725, -0.7305137148104647 -0.9520240083494819, -0.6666842796235226 -0.997763534763054, -0.5999999999999999 -1.039230484541326, -0.5307464282628015 -1.0762472898392257, -0.45922011883810765 -1.108655439013544, -0.38572735836379385 -1.1363161553941266, -0.3105828541230249 -1.159110991546882, -0.2341083864193539 -1.1769423364838765, -0.15663143066406188 -1.1897338336485723, -0.07848375507617167 -1.1974307078863242, 0 -1.2, 5 -1.2, 5.078483755076172 -1.1974307078863233, 5.156631430664062 -1.1897338336485717, 5.234108386419353 -1.1769423364838756, 5.310582854123025 -1.1591109915468811, 5.385727358363794 -1.1363161553941261, 5.4592201188381075 -1.1086554390135435, 5.530746428262801 -1.0762472898392252, 5.6 -1.0392304845413258, 5.666684279623523 -0.9977635347630538, 5.730513714810464 -0.9520240083494819, 5.791214978120082 -0.9022077689747725, 5.848528137423857 -0.8485281374238568, 5.9022077689747725 -0.7912149781200825, 5.952024008349482 -0.7305137148104647, 5.997763534763054 -0.6666842796235226, 6.039230484541326 -0.5999999999999999, 6.076247289839226 -0.5307464282628015, 6.108655439013544 -0.45922011883810765, 6.136316155394127 -0.38572735836379385, 6.159110991546882 -0.3105828541230249, 6.176942336483877 -0.2341083864193539, 6.189733833648573 -0.15663143066406188, 6.197430707886324 -0.07848375507617167, 6.2 0, 6.2 5, 6.1974307078863236 5.078483755076172, 6.189733833648572 5.156631430664062, 6.176942336483876 5.234108386419353, 6.159110991546881 5.310582854123025, 6.136316155394126 5.385727358363794, 6.1086554390135435 5.4592201188381075, 6.076247289839225 5.530746428262801, 6.039230484541326 5.6, 5.997763534763054 5.666684279623523, 5.952024008349482 5.730513714810464, 5.9022077689747725 5.791214978120082, 5.848528137423857 5.848528137423857, 5.791214978120083 5.9022077689747725, 5.730513714810464 5.952024008349482, 5.666684279623523 5.997763534763054, 5.6 6.039230484541326, 5.530746428262802 6.076247289839226, 5.4592201188381075 6.108655439013544, 5.385727358363794 6.136316155394127, 5.310582854123025 6.159110991546882, 5.234108386419354 6.176942336483877, 5.156631430664062 6.189733833648573, 5.078483755076172 6.197430707886324, 5 6.2, 0 6.2, -0.0784837550761715 6.1974307078863236, -0.15663143066406168 6.189733833648572, -0.23410838641935366 6.176942336483876, -0.3105828541230246 6.159110991546881, -0.38572735836379357 6.136316155394126, -0.4592201188381073 6.1086554390135435, -0.530746428262801 6.076247289839225, -0.5999999999999995 6.039230484541326, -0.6666842796235222 5.997763534763054, -0.7305137148104643 5.952024008349482, -0.7912149781200822 5.9022077689747725, -0.8485281374238567 5.848528137423857, -0.9022077689747725 5.791214978120083, -0.9520240083494819 5.730513714810464, -0.997763534763054 5.666684279623523, -1.039230484541326 5.6, -1.0762472898392257 5.530746428262802, -1.108655439013544 5.4592201188381075, -1.1363161553941266 5.385727358363794, -1.159110991546882 5.310582854123025, -1.1769423364838765 5.234108386419354, -1.1897338336485723 5.156631430664062, -1.1974307078863242 5.078483755076172, -1.2 5, -1.2 0))"); + assertFunction("ST_AsText(ST_Buffer(ST_Point(0, 0), 0.5))", VARCHAR, "POLYGON ((0.5 0, 0.4989294616193017 -0.0327015646150715, 0.4957224306869052 -0.0652630961100258, 0.4903926402016152 -0.0975451610080641, 0.4829629131445342 -0.1294095225512604, 0.4734650647475528 -0.1607197326515808, 0.4619397662556433 -0.1913417161825449, 0.4484363707663441 -0.2211443451095006, 0.4330127018922192 -0.25, 0.4157348061512725 -0.2777851165098011, 0.3966766701456175 -0.3043807145043603, 0.3759199037394886 -0.3296729075500344, 0.3535533905932736 -0.3535533905932737, 0.3296729075500343 -0.3759199037394886, 0.3043807145043602 -0.3966766701456175, 0.2777851165098009 -0.4157348061512725, 0.2499999999999998 -0.4330127018922191, 0.2211443451095005 -0.4484363707663439, 0.1913417161825447 -0.4619397662556431, 0.1607197326515807 -0.4734650647475526, 0.1294095225512603 -0.4829629131445338, 0.097545161008064 -0.4903926402016149, 0.0652630961100257 -0.4957224306869049, 0.0327015646150715 -0.4989294616193014, 0 -0.5, -0.0327015646150715 -0.4989294616193017, -0.0652630961100258 -0.4957224306869052, -0.0975451610080641 -0.4903926402016152, -0.1294095225512604 -0.4829629131445342, -0.1607197326515808 -0.4734650647475528, -0.1913417161825449 -0.4619397662556433, -0.2211443451095006 -0.4484363707663441, -0.25 -0.4330127018922192, -0.2777851165098011 -0.4157348061512725, -0.3043807145043603 -0.3966766701456175, -0.3296729075500344 -0.3759199037394886, -0.3535533905932737 -0.3535533905932736, -0.3759199037394886 -0.3296729075500343, -0.3966766701456175 -0.3043807145043602, -0.4157348061512725 -0.2777851165098009, -0.4330127018922191 -0.2499999999999998, -0.4484363707663439 -0.2211443451095005, -0.4619397662556431 -0.1913417161825447, -0.4734650647475526 -0.1607197326515807, -0.4829629131445338 -0.1294095225512603, -0.4903926402016149 -0.097545161008064, -0.4957224306869049 -0.0652630961100257, -0.4989294616193014 -0.0327015646150715, -0.5 0, -0.4989294616193017 0.0327015646150715, -0.4957224306869052 0.0652630961100258, -0.4903926402016152 0.0975451610080641, -0.4829629131445342 0.1294095225512604, -0.4734650647475528 0.1607197326515808, -0.4619397662556433 0.1913417161825449, -0.4484363707663441 0.2211443451095006, -0.4330127018922192 0.25, -0.4157348061512725 0.2777851165098011, -0.3966766701456175 0.3043807145043603, -0.3759199037394886 0.3296729075500344, -0.3535533905932736 0.3535533905932737, -0.3296729075500343 0.3759199037394886, -0.3043807145043602 0.3966766701456175, -0.2777851165098009 0.4157348061512725, -0.2499999999999998 0.4330127018922191, -0.2211443451095005 0.4484363707663439, -0.1913417161825447 0.4619397662556431, -0.1607197326515807 0.4734650647475526, -0.1294095225512603 0.4829629131445338, -0.097545161008064 0.4903926402016149, -0.0652630961100257 0.4957224306869049, -0.0327015646150715 0.4989294616193014, 0 0.5, 0.0327015646150715 0.4989294616193017, 0.0652630961100258 0.4957224306869052, 0.0975451610080641 0.4903926402016152, 0.1294095225512604 0.4829629131445342, 0.1607197326515808 0.4734650647475528, 0.1913417161825449 0.4619397662556433, 0.2211443451095006 0.4484363707663441, 0.25 0.4330127018922192, 0.2777851165098011 0.4157348061512725, 0.3043807145043603 0.3966766701456175, 0.3296729075500344 0.3759199037394886, 0.3535533905932737 0.3535533905932736, 0.3759199037394886 0.3296729075500343, 0.3966766701456175 0.3043807145043602, 0.4157348061512725 0.2777851165098009, 0.4330127018922191 0.2499999999999998, 0.4484363707663439 0.2211443451095005, 0.4619397662556431 0.1913417161825447, 0.4734650647475526 0.1607197326515807, 0.4829629131445338 0.1294095225512603, 0.4903926402016149 0.097545161008064, 0.4957224306869049 0.0652630961100257, 0.4989294616193014 0.0327015646150715, 0.5 0))"); + assertFunction("ST_AsText(ST_Buffer(ST_LineFromText('LINESTRING (0 0, 1 1, 2 0.5)'), 0.2))", VARCHAR, "POLYGON ((0 -0.2, -0.0130806258460288 -0.1995717846477207, -0.0261052384440101 -0.1982889722747621, -0.0390180644032259 -0.196157056080646, -0.0517638090205041 -0.1931851652578137, -0.0642878930606323 -0.1893860258990211, -0.0765366864730179 -0.1847759065022574, -0.0884577380438003 -0.1793745483065377, -0.1000000000000001 -0.1732050807568877, -0.1111140466039204 -0.166293922460509, -0.1217522858017439 -0.158670668058247, -0.1318691630200139 -0.1503679614957955, -0.1414213562373097 -0.1414213562373094, -0.1503679614957956 -0.1318691630200137, -0.1586706680582468 -0.1217522858017441, -0.1662939224605089 -0.1111140466039204, -0.1732050807568877 -0.0999999999999999, -0.1793745483065377 -0.0884577380438002, -0.1847759065022574 -0.0765366864730179, -0.189386025899021 -0.0642878930606323, -0.1931851652578134 -0.0517638090205041, -0.1961570560806458 -0.0390180644032256, -0.1982889722747618 -0.0261052384440102, -0.1995717846477207 -0.0130806258460285, -0.2000000000000002 0, -0.1995717846477207 0.0130806258460286, -0.1982889722747623 0.0261052384440103, -0.1961570560806463 0.0390180644032256, -0.1931851652578138 0.0517638090205041, -0.189386025899021 0.0642878930606323, -0.1847759065022574 0.0765366864730179, -0.1793745483065377 0.0884577380438002, -0.1732050807568877 0.1, -0.1662939224605089 0.1111140466039204, -0.1586706680582468 0.1217522858017441, -0.1503679614957956 0.1318691630200137, -0.1414213562373097 0.1414213562373095, 0.8585786437626906 1.1414213562373094, 0.8681308369799863 1.1503679614957956, 0.8782477141982559 1.158670668058247, 0.8888859533960796 1.166293922460509, 0.9000000000000001 1.1732050807568877, 0.9115422619561997 1.1793745483065377, 0.9234633135269821 1.1847759065022574, 0.9357121069393677 1.189386025899021, 0.9482361909794959 1.1931851652578136, 0.9609819355967744 1.1961570560806458, 0.9738947615559896 1.1982889722747618, 0.9869193741539715 1.1995717846477205, 1 1.2, 1.0130806258460288 1.1995717846477207, 1.0261052384440104 1.198288972274762, 1.0390180644032256 1.196157056080646, 1.0517638090205041 1.1931851652578138, 1.0642878930606323 1.189386025899021, 1.076536686473018 1.1847759065022574, 1.0884577380438003 1.1793745483065377, 1.0894427190999916 1.1788854381999831, 2.0894427190999916 0.6788854381999831, 2.1 0.6732050807568877, 2.1111140466039204 0.666293922460509, 2.121752285801744 0.658670668058247, 2.131869163020014 0.6503679614957955, 2.1414213562373097 0.6414213562373094, 2.1503679614957956 0.6318691630200137, 2.158670668058247 0.6217522858017441, 2.166293922460509 0.6111140466039204, 2.1732050807568877 0.5999999999999999, 2.1793745483065377 0.5884577380438002, 2.1847759065022574 0.5765366864730179, 2.189386025899021 0.5642878930606323, 2.1931851652578134 0.5517638090205041, 2.196157056080646 0.5390180644032256, 2.198288972274762 0.5261052384440102, 2.1995717846477207 0.5130806258460285, 2.2 0.5, 2.1995717846477207 0.4869193741539714, 2.1982889722747623 0.4738947615559897, 2.1961570560806463 0.4609819355967744, 2.193185165257814 0.4482361909794959, 2.189386025899021 0.4357121069393677, 2.1847759065022574 0.4234633135269821, 2.1793745483065377 0.4115422619561998, 2.1732050807568877 0.4, 2.166293922460509 0.3888859533960796, 2.158670668058247 0.3782477141982559, 2.1503679614957956 0.3681308369799863, 2.1414213562373092 0.3585786437626906, 2.1318691630200135 0.3496320385042045, 2.121752285801744 0.341329331941753, 2.1111140466039204 0.333706077539491, 2.1 0.3267949192431123, 2.0884577380438003 0.3206254516934625, 2.076536686473018 0.3152240934977427, 2.0642878930606323 0.310613974100979, 2.051763809020504 0.3068148347421865, 2.0390180644032254 0.3038429439193541, 2.02610523844401 0.3017110277252381, 2.0130806258460288 0.3004282153522794, 2 0.3, 1.9869193741539715 0.3004282153522793, 1.9738947615559896 0.3017110277252379, 1.9609819355967744 0.3038429439193539, 1.9482361909794959 0.3068148347421863, 1.9357121069393677 0.3106139741009789, 1.923463313526982 0.3152240934977427, 1.9115422619561997 0.3206254516934623, 1.9105572809000084 0.3211145618000169, 1.0394906098164265 0.7566478973418078, 0.1414213562373094 -0.1414213562373094, 0.1318691630200137 -0.1503679614957955, 0.1217522858017441 -0.158670668058247, 0.1111140466039204 -0.166293922460509, 0.0999999999999999 -0.1732050807568877, 0.0884577380438003 -0.1793745483065375, 0.0765366864730179 -0.1847759065022573, 0.0642878930606323 -0.189386025899021, 0.0517638090205041 -0.1931851652578136, 0.0390180644032256 -0.1961570560806459, 0.0261052384440104 -0.1982889722747619, 0.0130806258460285 -0.1995717846477205, 0 -0.2))"); + assertFunction("ST_AsText(ST_Buffer(ST_GeometryFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))'), 1.2))", VARCHAR, "POLYGON ((-1.2 0, -1.2 5, -1.1974307078863242 5.078483755076172, -1.1897338336485723 5.156631430664062, -1.1769423364838765 5.234108386419354, -1.159110991546882 5.310582854123025, -1.1363161553941266 5.385727358363794, -1.108655439013544 5.4592201188381075, -1.0762472898392257 5.530746428262802, -1.039230484541326 5.6, -0.997763534763054 5.666684279623523, -0.9520240083494819 5.730513714810464, -0.9022077689747725 5.791214978120083, -0.8485281374238567 5.848528137423857, -0.7912149781200822 5.9022077689747725, -0.7305137148104643 5.952024008349482, -0.6666842796235222 5.997763534763054, -0.5999999999999995 6.039230484541326, -0.530746428262801 6.076247289839225, -0.4592201188381073 6.1086554390135435, -0.3857273583637936 6.136316155394126, -0.3105828541230246 6.159110991546881, -0.2341083864193537 6.176942336483876, -0.1566314306640617 6.189733833648572, -0.0784837550761715 6.1974307078863236, 0 6.2, 5 6.2, 5.078483755076172 6.197430707886324, 5.156631430664062 6.189733833648573, 5.234108386419354 6.176942336483877, 5.310582854123025 6.159110991546882, 5.385727358363794 6.136316155394127, 5.4592201188381075 6.108655439013544, 5.530746428262802 6.076247289839226, 5.6 6.039230484541326, 5.666684279623523 5.997763534763054, 5.730513714810464 5.952024008349482, 5.791214978120083 5.9022077689747725, 5.848528137423857 5.848528137423857, 5.9022077689747725 5.791214978120082, 5.952024008349482 5.730513714810464, 5.997763534763054 5.666684279623523, 6.039230484541326 5.6, 6.076247289839225 5.530746428262801, 6.1086554390135435 5.4592201188381075, 6.136316155394126 5.385727358363794, 6.159110991546881 5.310582854123025, 6.176942336483876 5.234108386419353, 6.189733833648572 5.156631430664062, 6.1974307078863236 5.078483755076172, 6.2 5, 6.2 0, 6.197430707886324 -0.0784837550761717, 6.189733833648573 -0.1566314306640619, 6.176942336483877 -0.2341083864193539, 6.159110991546882 -0.3105828541230249, 6.136316155394127 -0.3857273583637938, 6.108655439013544 -0.4592201188381076, 6.076247289839226 -0.5307464282628015, 6.039230484541326 -0.5999999999999999, 5.997763534763054 -0.6666842796235226, 5.952024008349482 -0.7305137148104647, 5.9022077689747725 -0.7912149781200825, 5.848528137423857 -0.8485281374238568, 5.791214978120082 -0.9022077689747725, 5.730513714810464 -0.9520240083494819, 5.666684279623523 -0.9977635347630538, 5.6 -1.0392304845413258, 5.530746428262801 -1.0762472898392252, 5.4592201188381075 -1.1086554390135435, 5.385727358363794 -1.1363161553941261, 5.310582854123025 -1.1591109915468811, 5.234108386419353 -1.1769423364838756, 5.156631430664062 -1.1897338336485717, 5.078483755076172 -1.1974307078863233, 5 -1.2, 0 -1.2, -0.0784837550761717 -1.1974307078863242, -0.1566314306640619 -1.1897338336485723, -0.2341083864193539 -1.1769423364838765, -0.3105828541230249 -1.159110991546882, -0.3857273583637938 -1.1363161553941266, -0.4592201188381076 -1.108655439013544, -0.5307464282628015 -1.0762472898392257, -0.5999999999999999 -1.039230484541326, -0.6666842796235226 -0.997763534763054, -0.7305137148104647 -0.9520240083494819, -0.7912149781200825 -0.9022077689747725, -0.8485281374238568 -0.8485281374238567, -0.9022077689747725 -0.7912149781200822, -0.9520240083494819 -0.7305137148104643, -0.9977635347630538 -0.6666842796235222, -1.0392304845413258 -0.5999999999999995, -1.0762472898392252 -0.530746428262801, -1.1086554390135435 -0.4592201188381073, -1.1363161553941261 -0.3857273583637936, -1.1591109915468811 -0.3105828541230246, -1.1769423364838756 -0.2341083864193537, -1.1897338336485717 -0.1566314306640617, -1.1974307078863233 -0.0784837550761715, -1.2 0))"); // zero distance assertFunction("ST_AsText(ST_Buffer(ST_Point(0, 0), 0))", VARCHAR, "POINT (0 0)"); assertFunction("ST_AsText(ST_Buffer(ST_LineFromText('LINESTRING (0 0, 1 1, 2 0.5)'), 0))", VARCHAR, "LINESTRING (0 0, 1 1, 2 0.5)"); - assertFunction("ST_AsText(ST_Buffer(ST_GeometryFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))'), 0))", VARCHAR, "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); + assertFunction("ST_AsText(ST_Buffer(ST_GeometryFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))'), 0))", VARCHAR, "POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))"); // geometry collection - assertFunction("ST_AsText(ST_Buffer(ST_Intersection(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))'), ST_GeometryFromText('MULTILINESTRING ((3 4, 6 4), (5 0, 5 4))')), 0.2))", VARCHAR, "MULTIPOLYGON (((5 0.8, 5.013080625846029 0.8004282153522794, 5.026105238444011 0.801711027725238, 5.039018064403225 0.803842943919354, 5.051763809020504 0.8068148347421864, 5.064287893060633 0.8106139741009789, 5.076536686473018 0.8152240934977427, 5.0884577380438 0.8206254516934623, 5.1 0.8267949192431123, 5.11111404660392 0.833706077539491, 5.121752285801744 0.841329331941753, 5.1318691630200135 0.8496320385042045, 5.141421356237309 0.8585786437626906, 5.150367961495795 0.8681308369799863, 5.158670668058247 0.8782477141982559, 5.166293922460509 0.8888859533960796, 5.173205080756888 0.9, 5.179374548306538 0.9115422619561997, 5.184775906502257 0.9234633135269821, 5.189386025899021 0.9357121069393677, 5.193185165257813 0.9482361909794959, 5.196157056080646 0.9609819355967744, 5.198288972274762 0.9738947615559896, 5.199571784647721 0.9869193741539714, 5.2 1, 5.199571784647721 1.0130806258460288, 5.198288972274762 1.0261052384440104, 5.196157056080646 1.0390180644032256, 5.193185165257813 1.0517638090205041, 5.189386025899021 1.0642878930606323, 5.184775906502257 1.076536686473018, 5.179374548306537 1.0884577380438003, 5.173205080756888 1.1, 5.166293922460509 1.1111140466039204, 5.158670668058247 1.1217522858017441, 5.150367961495795 1.1318691630200137, 5.141421356237309 1.1414213562373094, 5.1318691630200135 1.1503679614957956, 5.121752285801744 1.158670668058247, 5.11111404660392 1.1662939224605091, 5.1 1.1732050807568877, 5.0884577380438 1.1793745483065377, 5.076536686473018 1.1847759065022574, 5.064287893060632 1.1893860258990212, 5.051763809020504 1.1931851652578138, 5.039018064403225 1.196157056080646, 5.026105238444011 1.198288972274762, 5.013080625846029 1.1995717846477207, 5 1.2, 4.986919374153971 1.1995717846477207, 4.973894761555989 1.198288972274762, 4.960981935596775 1.196157056080646, 4.948236190979496 1.1931851652578136, 4.935712106939367 1.189386025899021, 4.923463313526982 1.1847759065022574, 4.9115422619562 1.1793745483065377, 4.9 1.1732050807568877, 4.88888595339608 1.166293922460509, 4.878247714198256 1.158670668058247, 4.8681308369799865 1.1503679614957956, 4.858578643762691 1.1414213562373094, 4.849632038504205 1.1318691630200137, 4.841329331941753 1.1217522858017441, 4.833706077539491 1.1111140466039204, 4.826794919243112 1.1, 4.820625451693462 1.0884577380438003, 4.815224093497743 1.076536686473018, 4.810613974100979 1.0642878930606323, 4.806814834742187 1.0517638090205041, 4.803842943919354 1.0390180644032256, 4.801711027725238 1.0261052384440104, 4.800428215352279 1.0130806258460285, 4.8 1, 4.800428215352279 0.9869193741539714, 4.801711027725238 0.9738947615559896, 4.803842943919354 0.9609819355967743, 4.806814834742187 0.9482361909794959, 4.810613974100979 0.9357121069393677, 4.815224093497743 0.923463313526982, 4.820625451693463 0.9115422619561997, 4.826794919243112 0.8999999999999999, 4.833706077539491 0.8888859533960796, 4.841329331941753 0.8782477141982559, 4.849632038504205 0.8681308369799862, 4.858578643762691 0.8585786437626904, 4.8681308369799865 0.8496320385042044, 4.878247714198256 0.841329331941753, 4.88888595339608 0.8337060775394909, 4.9 0.8267949192431122, 4.9115422619562 0.8206254516934623, 4.923463313526982 0.8152240934977426, 4.935712106939368 0.8106139741009788, 4.948236190979496 0.8068148347421863, 4.960981935596775 0.8038429439193538, 4.973894761555989 0.801711027725238, 4.986919374153971 0.8004282153522793, 5 0.8)), ((3 3.8, 4 3.8, 4.013080625846029 3.8004282153522793, 4.026105238444011 3.801711027725238, 4.039018064403225 3.803842943919354, 4.051763809020504 3.8068148347421866, 4.064287893060632 3.810613974100979, 4.076536686473018 3.8152240934977426, 4.0884577380438 3.8206254516934623, 4.1 3.8267949192431123, 4.11111404660392 3.833706077539491, 4.121752285801744 3.841329331941753, 4.1318691630200135 3.8496320385042044, 4.141421356237309 3.8585786437626903, 4.150367961495795 3.868130836979986, 4.158670668058247 3.878247714198256, 4.166293922460509 3.8888859533960796, 4.173205080756888 3.9, 4.179374548306537 3.9115422619561997, 4.184775906502257 3.923463313526982, 4.189386025899021 3.9357121069393677, 4.193185165257813 3.948236190979496, 4.196157056080646 3.960981935596774, 4.198288972274762 3.97389476155599, 4.199571784647721 3.9869193741539712, 4.2 4, 4.199571784647721 4.013080625846029, 4.198288972274762 4.026105238444011, 4.196157056080646 4.039018064403225, 4.193185165257813 4.051763809020504, 4.189386025899021 4.064287893060632, 4.184775906502257 4.076536686473018, 4.179374548306537 4.0884577380438, 4.173205080756888 4.1, 4.166293922460509 4.11111404660392, 4.158670668058247 4.121752285801744, 4.150367961495795 4.1318691630200135, 4.141421356237309 4.141421356237309, 4.1318691630200135 4.150367961495795, 4.121752285801744 4.158670668058247, 4.11111404660392 4.166293922460509, 4.1 4.173205080756888, 4.0884577380438 4.179374548306537, 4.076536686473018 4.184775906502257, 4.064287893060632 4.189386025899021, 4.051763809020504 4.193185165257813, 4.039018064403225 4.196157056080646, 4.026105238444011 4.198288972274762, 4.013080625846029 4.199571784647721, 4 4.2, 3 4.2, 2.9869193741539712 4.199571784647721, 2.9738947615559894 4.198288972274762, 2.9609819355967746 4.196157056080646, 2.948236190979496 4.193185165257813, 2.9357121069393677 4.189386025899021, 2.923463313526982 4.184775906502257, 2.9115422619561997 4.179374548306537, 2.9000000000000004 4.173205080756888, 2.8888859533960796 4.166293922460509, 2.878247714198256 4.158670668058247, 2.8681308369799865 4.150367961495795, 2.8585786437626908 4.141421356237309, 2.8496320385042044 4.1318691630200135, 2.841329331941753 4.121752285801744, 2.833706077539491 4.11111404660392, 2.8267949192431123 4.1, 2.8206254516934623 4.0884577380438, 2.8152240934977426 4.076536686473018, 2.8106139741009786 4.064287893060632, 2.8068148347421866 4.051763809020504, 2.8038429439193537 4.039018064403225, 2.801711027725238 4.026105238444011, 2.8004282153522793 4.013080625846029, 2.8 4, 2.8004282153522793 3.9869193741539712, 2.801711027725238 3.97389476155599, 2.8038429439193537 3.9609819355967746, 2.8068148347421866 3.948236190979496, 2.810613974100979 3.9357121069393677, 2.8152240934977426 3.923463313526982, 2.8206254516934623 3.9115422619561997, 2.8267949192431123 3.9, 2.833706077539491 3.8888859533960796, 2.841329331941753 3.878247714198256, 2.8496320385042044 3.8681308369799865, 2.8585786437626908 3.8585786437626908, 2.8681308369799865 3.8496320385042044, 2.878247714198256 3.841329331941753, 2.8888859533960796 3.833706077539491, 2.9 3.8267949192431123, 2.9115422619561997 3.8206254516934623, 2.923463313526982 3.8152240934977426, 2.9357121069393677 3.810613974100979, 2.948236190979496 3.806814834742186, 2.9609819355967746 3.8038429439193537, 2.9738947615559894 3.8017110277252377, 2.9869193741539712 3.8004282153522793, 3 3.8)))"); + assertFunction("ST_AsText(ST_Buffer(ST_Intersection(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))'), ST_GeometryFromText('MULTILINESTRING ((3 4, 6 4), (5 0, 5 4))')), 0.2))", VARCHAR, "MULTIPOLYGON (((5 0.8, 4.986919374153971 0.8004282153522793, 4.973894761555989 0.801711027725238, 4.960981935596775 0.8038429439193538, 4.948236190979496 0.8068148347421863, 4.935712106939368 0.8106139741009788, 4.923463313526982 0.8152240934977426, 4.9115422619562 0.8206254516934623, 4.9 0.8267949192431122, 4.88888595339608 0.8337060775394909, 4.878247714198256 0.841329331941753, 4.8681308369799865 0.8496320385042044, 4.858578643762691 0.8585786437626904, 4.849632038504205 0.8681308369799862, 4.841329331941753 0.8782477141982559, 4.833706077539491 0.8888859533960796, 4.826794919243112 0.8999999999999999, 4.820625451693463 0.9115422619561997, 4.815224093497743 0.923463313526982, 4.810613974100979 0.9357121069393677, 4.806814834742187 0.9482361909794959, 4.803842943919354 0.9609819355967743, 4.801711027725238 0.9738947615559896, 4.800428215352279 0.9869193741539714, 4.8 1, 4.800428215352279 1.0130806258460285, 4.801711027725238 1.0261052384440104, 4.803842943919354 1.0390180644032256, 4.806814834742187 1.0517638090205041, 4.810613974100979 1.0642878930606323, 4.815224093497743 1.076536686473018, 4.820625451693462 1.0884577380438003, 4.826794919243112 1.1, 4.833706077539491 1.1111140466039204, 4.841329331941753 1.1217522858017441, 4.849632038504205 1.1318691630200137, 4.858578643762691 1.1414213562373094, 4.8681308369799865 1.1503679614957956, 4.878247714198256 1.158670668058247, 4.88888595339608 1.166293922460509, 4.9 1.1732050807568877, 4.9115422619562 1.1793745483065377, 4.923463313526982 1.1847759065022574, 4.935712106939367 1.189386025899021, 4.948236190979496 1.1931851652578136, 4.960981935596775 1.196157056080646, 4.973894761555989 1.198288972274762, 4.986919374153971 1.1995717846477207, 5 1.2, 5.013080625846029 1.1995717846477207, 5.026105238444011 1.198288972274762, 5.039018064403225 1.196157056080646, 5.051763809020504 1.1931851652578138, 5.064287893060632 1.1893860258990212, 5.076536686473018 1.1847759065022574, 5.0884577380438 1.1793745483065377, 5.1 1.1732050807568877, 5.11111404660392 1.1662939224605091, 5.121752285801744 1.158670668058247, 5.1318691630200135 1.1503679614957956, 5.141421356237309 1.1414213562373094, 5.150367961495795 1.1318691630200137, 5.158670668058247 1.1217522858017441, 5.166293922460509 1.1111140466039204, 5.173205080756888 1.1, 5.179374548306537 1.0884577380438003, 5.184775906502257 1.076536686473018, 5.189386025899021 1.0642878930606323, 5.193185165257813 1.0517638090205041, 5.196157056080646 1.0390180644032256, 5.198288972274762 1.0261052384440104, 5.199571784647721 1.0130806258460288, 5.2 1, 5.199571784647721 0.9869193741539714, 5.198288972274762 0.9738947615559896, 5.196157056080646 0.9609819355967744, 5.193185165257813 0.9482361909794959, 5.189386025899021 0.9357121069393677, 5.184775906502257 0.9234633135269821, 5.179374548306538 0.9115422619561997, 5.173205080756888 0.9, 5.166293922460509 0.8888859533960796, 5.158670668058247 0.8782477141982559, 5.150367961495795 0.8681308369799863, 5.141421356237309 0.8585786437626906, 5.1318691630200135 0.8496320385042045, 5.121752285801744 0.841329331941753, 5.11111404660392 0.833706077539491, 5.1 0.8267949192431123, 5.0884577380438 0.8206254516934623, 5.076536686473018 0.8152240934977427, 5.064287893060633 0.8106139741009789, 5.051763809020504 0.8068148347421864, 5.039018064403225 0.803842943919354, 5.026105238444011 0.801711027725238, 5.013080625846029 0.8004282153522794, 5 0.8)), ((3 3.8, 2.9869193741539712 3.8004282153522793, 2.9738947615559894 3.8017110277252377, 2.9609819355967746 3.8038429439193537, 2.948236190979496 3.806814834742186, 2.9357121069393677 3.810613974100979, 2.923463313526982 3.8152240934977426, 2.9115422619561997 3.8206254516934623, 2.9 3.8267949192431123, 2.8888859533960796 3.833706077539491, 2.878247714198256 3.841329331941753, 2.8681308369799865 3.8496320385042044, 2.8585786437626908 3.8585786437626908, 2.8496320385042044 3.8681308369799865, 2.841329331941753 3.878247714198256, 2.833706077539491 3.8888859533960796, 2.8267949192431123 3.9, 2.8206254516934623 3.9115422619561997, 2.8152240934977426 3.923463313526982, 2.810613974100979 3.9357121069393677, 2.8068148347421866 3.948236190979496, 2.8038429439193537 3.9609819355967746, 2.801711027725238 3.97389476155599, 2.8004282153522793 3.9869193741539712, 2.8 4, 2.8004282153522793 4.013080625846029, 2.801711027725238 4.026105238444011, 2.8038429439193537 4.039018064403225, 2.8068148347421866 4.051763809020504, 2.8106139741009786 4.064287893060632, 2.8152240934977426 4.076536686473018, 2.8206254516934623 4.0884577380438, 2.8267949192431123 4.1, 2.833706077539491 4.11111404660392, 2.841329331941753 4.121752285801744, 2.8496320385042044 4.1318691630200135, 2.8585786437626908 4.141421356237309, 2.8681308369799865 4.150367961495795, 2.878247714198256 4.158670668058247, 2.8888859533960796 4.166293922460509, 2.9000000000000004 4.173205080756888, 2.9115422619561997 4.179374548306537, 2.923463313526982 4.184775906502257, 2.9357121069393677 4.189386025899021, 2.948236190979496 4.193185165257813, 2.9609819355967746 4.196157056080646, 2.9738947615559894 4.198288972274762, 2.9869193741539712 4.199571784647721, 3 4.2, 4 4.2, 4.013080625846029 4.199571784647721, 4.026105238444011 4.198288972274762, 4.039018064403225 4.196157056080646, 4.051763809020504 4.193185165257813, 4.064287893060632 4.189386025899021, 4.076536686473018 4.184775906502257, 4.0884577380438 4.179374548306537, 4.1 4.173205080756888, 4.11111404660392 4.166293922460509, 4.121752285801744 4.158670668058247, 4.1318691630200135 4.150367961495795, 4.141421356237309 4.141421356237309, 4.150367961495795 4.1318691630200135, 4.158670668058247 4.121752285801744, 4.166293922460509 4.11111404660392, 4.173205080756888 4.1, 4.179374548306537 4.0884577380438, 4.184775906502257 4.076536686473018, 4.189386025899021 4.064287893060632, 4.193185165257813 4.051763809020504, 4.196157056080646 4.039018064403225, 4.198288972274762 4.026105238444011, 4.199571784647721 4.013080625846029, 4.2 4, 4.199571784647721 3.9869193741539712, 4.198288972274762 3.97389476155599, 4.196157056080646 3.960981935596774, 4.193185165257813 3.948236190979496, 4.189386025899021 3.9357121069393677, 4.184775906502257 3.923463313526982, 4.179374548306537 3.9115422619561997, 4.173205080756888 3.9, 4.166293922460509 3.8888859533960796, 4.158670668058247 3.878247714198256, 4.150367961495795 3.868130836979986, 4.141421356237309 3.8585786437626903, 4.1318691630200135 3.8496320385042044, 4.121752285801744 3.841329331941753, 4.11111404660392 3.833706077539491, 4.1 3.8267949192431123, 4.0884577380438 3.8206254516934623, 4.076536686473018 3.8152240934977426, 4.064287893060632 3.810613974100979, 4.051763809020504 3.8068148347421866, 4.039018064403225 3.803842943919354, 4.026105238444011 3.801711027725238, 4.013080625846029 3.8004282153522793, 4 3.8, 3 3.8)))"); // empty geometry assertFunction("ST_Buffer(ST_GeometryFromText('POINT EMPTY'), 1)", GEOMETRY, null); @@ -249,8 +252,8 @@ private void assertCentroid(String wkt, Point centroid) private void assertApproximateCentroid(String wkt, Point expectedCentroid, double epsilon) { - OGCPoint actualCentroid = (OGCPoint) GeometrySerde.deserialize( - stCentroid(GeometrySerde.serialize(OGCGeometry.fromText(wkt)))); + OGCPoint actualCentroid = (OGCPoint) EsriGeometrySerde.deserialize( + stCentroid(EsriGeometrySerde.serialize(OGCGeometry.fromText(wkt)))); assertEquals(actualCentroid.X(), expectedCentroid.getX(), epsilon); assertEquals(actualCentroid.Y(), expectedCentroid.getY(), epsilon); } @@ -267,19 +270,19 @@ public void testSTConvexHull() assertConvexHull("MULTIPOLYGON EMPTY", "MULTIPOLYGON EMPTY"); assertConvexHull("GEOMETRYCOLLECTION EMPTY", "GEOMETRYCOLLECTION EMPTY"); assertConvexHull("GEOMETRYCOLLECTION (POINT (1 1), POINT EMPTY)", "POINT (1 1)"); - assertConvexHull("GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (1 1), GEOMETRYCOLLECTION (POINT (1 5), POINT (4 5), GEOMETRYCOLLECTION (POINT (3 4), POINT EMPTY))))", "POLYGON ((1 1, 4 5, 1 5, 1 1))"); + assertConvexHull("GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (1 1), GEOMETRYCOLLECTION (POINT (1 5), POINT (4 5), GEOMETRYCOLLECTION (POINT (3 4), POINT EMPTY))))", "POLYGON ((1 1, 1 5, 4 5, 1 1))"); // test single geometry assertConvexHull("POINT (1 1)", "POINT (1 1)"); - assertConvexHull("LINESTRING (1 1, 1 9, 2 2)", "POLYGON ((1 1, 2 2, 1 9, 1 1))"); + assertConvexHull("LINESTRING (1 1, 1 9, 2 2)", "POLYGON ((1 1, 1 9, 2 2, 1 1))"); // convex single geometry - assertConvexHull("LINESTRING (1 1, 1 9, 2 2, 1 1)", "POLYGON ((1 1, 2 2, 1 9, 1 1))"); - assertConvexHull("POLYGON ((0 0, 0 3, 2 4, 4 2, 3 0, 0 0))", "POLYGON ((0 0, 3 0, 4 2, 2 4, 0 3, 0 0))"); + assertConvexHull("LINESTRING (1 1, 1 9, 2 2, 1 1)", "POLYGON ((1 1, 1 9, 2 2, 1 1))"); + assertConvexHull("POLYGON ((0 0, 0 3, 2 4, 4 2, 3 0, 0 0))", "POLYGON ((0 0, 0 3, 2 4, 4 2, 3 0, 0 0))"); // non-convex geometry - assertConvexHull("LINESTRING (1 1, 1 9, 2 2, 1 1, 4 0)", "POLYGON ((1 1, 4 0, 1 9, 1 1))"); - assertConvexHull("POLYGON ((0 0, 0 3, 4 4, 1 1, 3 0, 0 0))", "POLYGON ((0 0, 3 0, 4 4, 0 3, 0 0))"); + assertConvexHull("LINESTRING (1 1, 1 9, 2 2, 1 1, 4 0)", "POLYGON ((1 1, 1 9, 4 0, 1 1))"); + assertConvexHull("POLYGON ((0 0, 0 3, 4 4, 1 1, 3 0, 0 0))", "POLYGON ((0 0, 0 3, 4 4, 3 0, 0 0))"); // all points are on the same line assertConvexHull("LINESTRING (20 20, 30 30)", "LINESTRING (20 20, 30 30)"); @@ -289,23 +292,23 @@ public void testSTConvexHull() assertConvexHull("GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (2 2), POINT (1 1)), POINT (3 3))", "LINESTRING (3 3, 1 1)"); // not all points are on the same line - assertConvexHull("MULTILINESTRING ((1 1, 5 1, 6 6), (2 4, 4 0), (2 -4, 4 4), (3 -2, 4 -3))", "POLYGON ((1 1, 2 -4, 4 -3, 5 1, 6 6, 2 4, 1 1))"); - assertConvexHull("MULTIPOINT (0 2, 1 0, 3 0, 4 0, 4 2, 2 2, 2 4)", "POLYGON ((0 2, 1 0, 4 0, 4 2, 2 4, 0 2))"); - assertConvexHull("MULTIPOLYGON (((0 3, 2 0, 3 6, 0 3), (2 1, 2 3, 5 3, 5 1, 2 1), (1 7, 2 4, 4 2, 5 6, 3 8, 1 7)))", "POLYGON ((0 3, 2 0, 5 1, 5 6, 3 8, 1 7, 0 3))"); - assertConvexHull("GEOMETRYCOLLECTION (POINT (2 3), LINESTRING (2 8, 7 10), POINT (8 10), POLYGON ((4 4, 4 8, 9 8, 6 6, 6 4, 8 3, 6 1, 4 4)), POINT (4 2), LINESTRING (3 6, 5 5), POLYGON ((7 5, 7 6, 8 6, 8 5, 7 5)))", "POLYGON ((2 3, 6 1, 8 3, 9 8, 8 10, 7 10, 2 8, 2 3))"); - assertConvexHull("GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (2 3), LINESTRING (2 8, 7 10), GEOMETRYCOLLECTION (POINT (8 10))), POLYGON ((4 4, 4 8, 9 8, 6 6, 6 4, 8 3, 6 1, 4 4)), POINT (4 2), LINESTRING (3 6, 5 5), POLYGON ((7 5, 7 6, 8 6, 8 5, 7 5)))", "POLYGON ((2 3, 6 1, 8 3, 9 8, 8 10, 7 10, 2 8, 2 3))"); + assertConvexHull("MULTILINESTRING ((1 1, 5 1, 6 6), (2 4, 4 0), (2 -4, 4 4), (3 -2, 4 -3))", "POLYGON ((1 1, 2 4, 6 6, 5 1, 4 -3, 2 -4, 1 1))"); + assertConvexHull("MULTIPOINT (0 2, 1 0, 3 0, 4 0, 4 2, 2 2, 2 4)", "POLYGON ((0 2, 2 4, 4 2, 4 0, 1 0, 0 2))"); + assertConvexHull("MULTIPOLYGON (((0 3, 2 0, 3 6, 0 3), (2 1, 2 3, 5 3, 5 1, 2 1), (1 7, 2 4, 4 2, 5 6, 3 8, 1 7)))", "POLYGON ((0 3, 1 7, 3 8, 5 6, 5 1, 2 0, 0 3))"); + assertConvexHull("GEOMETRYCOLLECTION (POINT (2 3), LINESTRING (2 8, 7 10), POINT (8 10), POLYGON ((4 4, 4 8, 9 8, 6 6, 6 4, 8 3, 6 1, 4 4)), POINT (4 2), LINESTRING (3 6, 5 5), POLYGON ((7 5, 7 6, 8 6, 8 5, 7 5)))", "POLYGON ((2 3, 2 8, 7 10, 8 10, 9 8, 8 3, 6 1, 2 3))"); + assertConvexHull("GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (2 3), LINESTRING (2 8, 7 10), GEOMETRYCOLLECTION (POINT (8 10))), POLYGON ((4 4, 4 8, 9 8, 6 6, 6 4, 8 3, 6 1, 4 4)), POINT (4 2), LINESTRING (3 6, 5 5), POLYGON ((7 5, 7 6, 8 6, 8 5, 7 5)))", "POLYGON ((2 3, 2 8, 7 10, 8 10, 9 8, 8 3, 6 1, 2 3))"); // single-element multi-geometries and geometry collections - assertConvexHull("MULTILINESTRING ((1 1, 5 1, 6 6))", "POLYGON ((1 1, 5 1, 6 6, 1 1))"); - assertConvexHull("MULTILINESTRING ((1 1, 5 1, 1 4, 5 4))", "POLYGON ((1 1, 5 1, 5 4, 1 4, 1 1))"); + assertConvexHull("MULTILINESTRING ((1 1, 5 1, 6 6))", "POLYGON ((1 1, 6 6, 5 1, 1 1))"); + assertConvexHull("MULTILINESTRING ((1 1, 5 1, 1 4, 5 4))", "POLYGON ((1 1, 1 4, 5 4, 5 1, 1 1))"); assertConvexHull("MULTIPOINT (0 2)", "POINT (0 2)"); - assertConvexHull("MULTIPOLYGON (((0 3, 2 0, 3 6, 0 3)))", "POLYGON ((0 3, 2 0, 3 6, 0 3))"); - assertConvexHull("MULTIPOLYGON (((0 0, 4 0, 4 4, 0 4, 2 2, 0 0)))", "POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))"); + assertConvexHull("MULTIPOLYGON (((0 3, 3 6, 2 0, 0 3)))", "POLYGON ((0 3, 3 6, 2 0, 0 3))"); + assertConvexHull("MULTIPOLYGON (((0 0, 4 0, 4 4, 0 4, 2 2, 0 0)))", "POLYGON ((0 0, 0 4, 4 4, 4 0, 0 0))"); assertConvexHull("GEOMETRYCOLLECTION (POINT (2 3))", "POINT (2 3)"); - assertConvexHull("GEOMETRYCOLLECTION (LINESTRING (1 1, 5 1, 6 6))", "POLYGON ((1 1, 5 1, 6 6, 1 1))"); - assertConvexHull("GEOMETRYCOLLECTION (LINESTRING (1 1, 5 1, 1 4, 5 4))", "POLYGON ((1 1, 5 1, 5 4, 1 4, 1 1))"); - assertConvexHull("GEOMETRYCOLLECTION (POLYGON ((0 3, 2 0, 3 6, 0 3)))", "POLYGON ((0 3, 2 0, 3 6, 0 3))"); - assertConvexHull("GEOMETRYCOLLECTION (POLYGON ((0 0, 4 0, 4 4, 0 4, 2 2, 0 0)))", "POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))"); + assertConvexHull("GEOMETRYCOLLECTION (LINESTRING (1 1, 5 1, 6 6))", "POLYGON ((1 1, 6 6, 5 1, 1 1))"); + assertConvexHull("GEOMETRYCOLLECTION (LINESTRING (1 1, 5 1, 1 4, 5 4))", "POLYGON ((1 1, 1 4, 5 4, 5 1, 1 1))"); + assertConvexHull("GEOMETRYCOLLECTION (POLYGON ((0 3, 3 6, 2 0, 0 3)))", "POLYGON ((0 3, 3 6, 2 0, 0 3))"); + assertConvexHull("GEOMETRYCOLLECTION (POLYGON ((0 0, 4 0, 4 4, 0 4, 2 2, 0 0)))", "POLYGON ((0 0, 0 4, 4 4, 4 0, 0 0))"); } private void assertConvexHull(String inputWKT, String expectWKT) @@ -336,6 +339,8 @@ public void testSTIsClosed() { assertFunction("ST_IsClosed(ST_GeometryFromText('LINESTRING (1 1, 2 2, 1 3, 1 1)'))", BOOLEAN, true); assertFunction("ST_IsClosed(ST_GeometryFromText('LINESTRING (1 1, 2 2, 1 3)'))", BOOLEAN, false); + assertFunction("ST_IsClosed(ST_GeometryFromText('MULTILINESTRING ((1 1, 2 2, 1 3, 1 1), (4 4, 5 5))'))", BOOLEAN, false); + assertFunction("ST_IsClosed(ST_GeometryFromText('MULTILINESTRING ((1 1, 2 2, 1 3, 1 1), (4 4, 5 4, 5 5, 4 5, 4 4))'))", BOOLEAN, true); assertInvalidFunction("ST_IsClosed(ST_GeometryFromText('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'))", "ST_IsClosed only applies to LINE_STRING or MULTI_LINE_STRING. Input type is: POLYGON"); } @@ -376,11 +381,11 @@ public void testSTIsSimple() public void testSimplifyGeometry() { // Eliminate unnecessary points on the same line. - assertFunction("ST_AsText(simplify_geometry(ST_GeometryFromText('POLYGON ((1 0, 2 1, 3 1, 3 1, 4 1, 1 0))'), 1.5))", VARCHAR, "POLYGON ((1 0, 4 1, 2 1, 1 0))"); + assertFunction("ST_AsText(simplify_geometry(ST_GeometryFromText('POLYGON ((1 0, 2 1, 3 1, 3 1, 4 1, 1 0))'), 1.5))", VARCHAR, "POLYGON ((1 0, 2 1, 4 1, 1 0))"); // Use distanceTolerance to control fidelity. - assertFunction("ST_AsText(simplify_geometry(ST_GeometryFromText('POLYGON ((1 0, 1 1, 2 1, 2 3, 3 3, 3 1, 4 1, 4 0, 1 0))'), 1.0))", VARCHAR, "POLYGON ((1 0, 4 0, 3 3, 2 3, 1 0))"); - assertFunction("ST_AsText(simplify_geometry(ST_GeometryFromText('POLYGON ((1 0, 1 1, 2 1, 2 3, 3 3, 3 1, 4 1, 4 0, 1 0))'), 0.5))", VARCHAR, "POLYGON ((1 0, 4 0, 4 1, 3 1, 3 3, 2 3, 2 1, 1 1, 1 0))"); + assertFunction("ST_AsText(simplify_geometry(ST_GeometryFromText('POLYGON ((1 0, 1 1, 2 1, 2 3, 3 3, 3 1, 4 1, 4 0, 1 0))'), 1.0))", VARCHAR, "POLYGON ((1 0, 2 3, 3 3, 4 0, 1 0))"); + assertFunction("ST_AsText(simplify_geometry(ST_GeometryFromText('POLYGON ((1 0, 1 1, 2 1, 2 3, 3 3, 3 1, 4 1, 4 0, 1 0))'), 0.5))", VARCHAR, "POLYGON ((1 0, 1 1, 2 1, 2 3, 3 3, 3 1, 4 1, 4 0, 1 0))"); // Negative distance tolerance is invalid. assertInvalidFunction("ST_AsText(simplify_geometry(ST_GeometryFromText('" + "POLYGON ((1 0, 1 1, 2 1, 2 3, 3 3, 3 1, 4 1, 4 0, 1 0))" + "'), -0.5))", "distanceTolerance is negative"); @@ -618,27 +623,27 @@ public void testSTXY() @Test public void testSTBoundary() { - assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('POINT (1 2)')))", VARCHAR, "MULTIPOINT EMPTY"); - assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('MULTIPOINT (1 2, 2 4, 3 6, 4 8)')))", VARCHAR, "MULTIPOINT EMPTY"); + assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('POINT (1 2)')))", VARCHAR, "GEOMETRYCOLLECTION EMPTY"); + assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('MULTIPOINT (1 2, 2 4, 3 6, 4 8)')))", VARCHAR, "GEOMETRYCOLLECTION EMPTY"); assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('LINESTRING EMPTY')))", VARCHAR, "MULTIPOINT EMPTY"); assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('LINESTRING (8 4, 5 7)')))", VARCHAR, "MULTIPOINT ((8 4), (5 7))"); assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('LINESTRING (100 150,50 60, 70 80, 160 170)')))", VARCHAR, "MULTIPOINT ((100 150), (160 170))"); - assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))')))", VARCHAR, "MULTIPOINT ((1 1), (5 1), (2 4), (4 4))"); - assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('POLYGON ((1 1, 4 1, 1 4, 1 1))')))", VARCHAR, "MULTILINESTRING ((1 1, 4 1, 1 4, 1 1))"); - assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((0 0, 0 2, 2 2, 2 0, 0 0)))')))", VARCHAR, "MULTILINESTRING ((1 1, 3 1, 3 3, 1 3, 1 1), (0 0, 2 0, 2 2, 0 2, 0 0))"); + assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))')))", VARCHAR, "MULTIPOINT ((1 1), (2 4), (4 4), (5 1))"); + assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('POLYGON ((1 1, 4 1, 1 4, 1 1))')))", VARCHAR, "LINESTRING (1 1, 1 4, 4 1, 1 1)"); + assertFunction("ST_AsText(ST_Boundary(ST_GeometryFromText('MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((0 0, 0 2, 2 2, 2 0, 0 0)))')))", VARCHAR, "MULTILINESTRING ((1 1, 1 3, 3 3, 3 1, 1 1), (0 0, 0 2, 2 2, 2 0, 0 0))"); } @Test public void testSTEnvelope() { - assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('MULTIPOINT (1 2, 2 4, 3 6, 4 8)')))", VARCHAR, "POLYGON ((1 2, 4 2, 4 8, 1 8, 1 2))"); + assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('MULTIPOINT (1 2, 2 4, 3 6, 4 8)')))", VARCHAR, "POLYGON ((1 2, 1 8, 4 8, 4 2, 1 2))"); assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('LINESTRING EMPTY')))", VARCHAR, "POLYGON EMPTY"); - assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('LINESTRING (1 1, 2 2, 1 3)')))", VARCHAR, "POLYGON ((1 1, 2 1, 2 3, 1 3, 1 1))"); - assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('LINESTRING (8 4, 5 7)')))", VARCHAR, "POLYGON ((5 4, 8 4, 8 7, 5 7, 5 4))"); - assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))')))", VARCHAR, "POLYGON ((1 1, 5 1, 5 4, 1 4, 1 1))"); - assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('POLYGON ((1 1, 4 1, 1 4, 1 1))')))", VARCHAR, "POLYGON ((1 1, 4 1, 4 4, 1 4, 1 1))"); - assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((0 0, 0 2, 2 2, 2 0, 0 0)))')))", VARCHAR, "POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0))"); - assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('GEOMETRYCOLLECTION (POINT (5 1), LINESTRING (3 4, 4 4))')))", VARCHAR, "POLYGON ((3 1, 5 1, 5 4, 3 4, 3 1))"); + assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('LINESTRING (1 1, 2 2, 1 3)')))", VARCHAR, "POLYGON ((1 1, 1 3, 2 3, 2 1, 1 1))"); + assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('LINESTRING (8 4, 5 7)')))", VARCHAR, "POLYGON ((5 4, 5 7, 8 7, 8 4, 5 4))"); + assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))')))", VARCHAR, "POLYGON ((1 1, 1 4, 5 4, 5 1, 1 1))"); + assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('POLYGON ((1 1, 4 1, 1 4, 1 1))')))", VARCHAR, "POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))"); + assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((0 0, 0 2, 2 2, 2 0, 0 0)))')))", VARCHAR, "POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0))"); + assertFunction("ST_AsText(ST_Envelope(ST_GeometryFromText('GEOMETRYCOLLECTION (POINT (5 1), LINESTRING (3 4, 4 4))')))", VARCHAR, "POLYGON ((3 1, 3 4, 5 4, 5 1, 3 1))"); } @Test @@ -665,10 +670,10 @@ public void testExpandEnvelope() { assertFunction("ST_IsEmpty(expand_envelope(ST_GeometryFromText('POINT EMPTY'), 1))", BOOLEAN, true); assertFunction("ST_IsEmpty(expand_envelope(ST_GeometryFromText('POLYGON EMPTY'), 1))", BOOLEAN, true); - assertFunction("ST_AsText(expand_envelope(ST_Envelope(ST_Point(1, 10)), 3))", VARCHAR, "POLYGON ((-2 7, 4 7, 4 13, -2 13, -2 7))"); - assertFunction("ST_AsText(expand_envelope(ST_Point(1, 10), 3))", VARCHAR, "POLYGON ((-2 7, 4 7, 4 13, -2 13, -2 7))"); - assertFunction("ST_AsText(expand_envelope(ST_GeometryFromText('LINESTRING (1 10, 3 15)'), 2))", VARCHAR, "POLYGON ((-1 8, 5 8, 5 17, -1 17, -1 8))"); - assertFunction("ST_AsText(expand_envelope(ST_GeometryFromText('GEOMETRYCOLLECTION (POINT (5 1), LINESTRING (3 4, 4 4))'), 1))", VARCHAR, "POLYGON ((2 0, 6 0, 6 5, 2 5, 2 0))"); + assertFunction("ST_AsText(expand_envelope(ST_Envelope(ST_Point(1, 10)), 3))", VARCHAR, "POLYGON ((-2 7, -2 13, 4 13, 4 7, -2 7))"); + assertFunction("ST_AsText(expand_envelope(ST_Point(1, 10), 3))", VARCHAR, "POLYGON ((-2 7, -2 13, 4 13, 4 7, -2 7))"); + assertFunction("ST_AsText(expand_envelope(ST_GeometryFromText('LINESTRING (1 10, 3 15)'), 2))", VARCHAR, "POLYGON ((-1 8, -1 17, 5 17, 5 8, -1 8))"); + assertFunction("ST_AsText(expand_envelope(ST_GeometryFromText('GEOMETRYCOLLECTION (POINT (5 1), LINESTRING (3 4, 4 4))'), 1))", VARCHAR, "POLYGON ((2 0, 2 5, 6 5, 6 0, 2 0))"); // JTS has an envelope expanded by infinity to be empty, which is weird. // PostGIS returns an infinite envelope, which is a tricky concept. // We'll leave it like this until it becomes a problem. @@ -685,8 +690,8 @@ public void testSTDifference() assertFunction("ST_AsText(ST_Difference(ST_GeometryFromText('MULTIPOINT (50 100, 50 200)'), ST_GeometryFromText('POINT (50 100)')))", VARCHAR, "POINT (50 200)"); assertFunction("ST_AsText(ST_Difference(ST_GeometryFromText('LINESTRING (50 100, 50 200)'), ST_GeometryFromText('LINESTRING (50 50, 50 150)')))", VARCHAR, "LINESTRING (50 150, 50 200)"); assertFunction("ST_AsText(ST_Difference(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))'), ST_GeometryFromText('MULTILINESTRING ((2 1, 4 1), (3 3, 7 3))')))", VARCHAR, "MULTILINESTRING ((1 1, 2 1), (4 1, 5 1), (2 4, 4 4))"); - assertFunction("ST_AsText(ST_Difference(ST_GeometryFromText('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'), ST_GeometryFromText('POLYGON ((2 2, 2 5, 5 5, 5 2, 2 2))')))", VARCHAR, "POLYGON ((1 1, 4 1, 4 2, 2 2, 2 4, 1 4, 1 1))"); - assertFunction("ST_AsText(ST_Difference(ST_GeometryFromText('MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((0 0, 0 2, 2 2, 2 0, 0 0)))'), ST_GeometryFromText('POLYGON ((0 1, 3 1, 3 3, 0 3, 0 1))')))", VARCHAR, "POLYGON ((1 1, 0 1, 0 0, 2 0, 2 1, 1 1))"); + assertFunction("ST_AsText(ST_Difference(ST_GeometryFromText('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'), ST_GeometryFromText('POLYGON ((2 2, 2 5, 5 5, 5 2, 2 2))')))", VARCHAR, "POLYGON ((1 1, 1 4, 2 4, 2 2, 4 2, 4 1, 1 1))"); + assertFunction("ST_AsText(ST_Difference(ST_GeometryFromText('MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((0 0, 0 2, 2 2, 2 0, 0 0)))'), ST_GeometryFromText('POLYGON ((0 1, 3 1, 3 3, 0 3, 0 1))')))", VARCHAR, "POLYGON ((1 1, 2 1, 2 0, 0 0, 0 1, 1 1))"); } @Test @@ -715,8 +720,8 @@ public void testSTDistance() public void testSTExteriorRing() { assertFunction("ST_AsText(ST_ExteriorRing(ST_GeometryFromText('POLYGON EMPTY')))", VARCHAR, null); - assertFunction("ST_AsText(ST_ExteriorRing(ST_GeometryFromText('POLYGON ((1 1, 1 4, 4 1, 1 1))')))", VARCHAR, "LINESTRING (1 1, 4 1, 1 4, 1 1)"); - assertFunction("ST_AsText(ST_ExteriorRing(ST_GeometryFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))')))", VARCHAR, "LINESTRING (0 0, 5 0, 5 5, 0 5, 0 0)"); + assertFunction("ST_AsText(ST_ExteriorRing(ST_GeometryFromText('POLYGON ((1 1, 1 4, 4 1, 1 1))')))", VARCHAR, "LINESTRING (1 1, 1 4, 4 1, 1 1)"); + assertFunction("ST_AsText(ST_ExteriorRing(ST_GeometryFromText('POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))')))", VARCHAR, "LINESTRING (0 0, 0 5, 5 5, 5 0, 0 0)"); assertInvalidFunction("ST_AsText(ST_ExteriorRing(ST_GeometryFromText('LINESTRING (1 1, 2 2, 1 3)')))", "ST_ExteriorRing only applies to POLYGON. Input type is: LINE_STRING"); assertInvalidFunction("ST_AsText(ST_ExteriorRing(ST_GeometryFromText('MULTIPOLYGON (((1 1, 2 2, 1 3, 1 1)), ((4 4, 5 5, 4 6, 4 4)))')))", "ST_ExteriorRing only applies to POLYGON. Input type is: MULTI_POLYGON"); } @@ -729,19 +734,19 @@ public void testSTIntersection() assertFunction("ST_AsText(ST_Intersection(ST_GeometryFromText('LINESTRING (50 100, 50 200)'), ST_GeometryFromText('LINESTRING (20 150, 100 150)')))", VARCHAR, "POINT (50 150)"); assertFunction("ST_AsText(ST_Intersection(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))'), ST_GeometryFromText('MULTILINESTRING ((3 4, 6 4), (5 0, 5 4))')))", VARCHAR, "GEOMETRYCOLLECTION (POINT (5 1), LINESTRING (3 4, 4 4))"); assertFunction("ST_AsText(ST_Intersection(ST_GeometryFromText('POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))'), ST_GeometryFromText('POLYGON ((4 4, 4 5, 5 5, 5 4, 4 4))')))", VARCHAR, "MULTIPOLYGON EMPTY"); - assertFunction("ST_AsText(ST_Intersection(ST_GeometryFromText('MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((0 0, 0 2, 2 2, 2 0, 0 0)))'), ST_GeometryFromText('POLYGON ((0 1, 3 1, 3 3, 0 3, 0 1))')))", VARCHAR, "GEOMETRYCOLLECTION (LINESTRING (1 1, 2 1), MULTIPOLYGON (((0 1, 1 1, 1 2, 0 2, 0 1)), ((2 1, 3 1, 3 3, 1 3, 1 2, 2 2, 2 1))))"); + assertFunction("ST_AsText(ST_Intersection(ST_GeometryFromText('MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((0 0, 0 2, 2 2, 2 0, 0 0)))'), ST_GeometryFromText('POLYGON ((0 1, 3 1, 3 3, 0 3, 0 1))')))", VARCHAR, "GEOMETRYCOLLECTION (LINESTRING (1 1, 2 1), MULTIPOLYGON (((0 1, 0 2, 1 2, 1 1, 0 1)), ((2 1, 2 2, 1 2, 1 3, 3 3, 3 1, 2 1))))"); assertFunction("ST_AsText(ST_Intersection(ST_GeometryFromText('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'), ST_GeometryFromText('LINESTRING (2 0, 2 3)')))", VARCHAR, "LINESTRING (2 1, 2 3)"); assertFunction("ST_AsText(ST_Intersection(ST_GeometryFromText('POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))'), ST_GeometryFromText('LINESTRING (0 0, 1 -1, 1 2)')))", VARCHAR, "GEOMETRYCOLLECTION (POINT (0 0), LINESTRING (1 0, 1 1))"); // test intersection of envelopes - assertEnvelopeIntersection("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))"); - assertEnvelopeIntersection("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((-1 4, 1 4, 1 6, -1 6, -1 4))", "POLYGON ((0 4, 1 4, 1 5, 0 5, 0 4))"); - assertEnvelopeIntersection("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((1 4, 2 4, 2 6, 1 6, 1 4))", "POLYGON ((1 4, 2 4, 2 5, 1 5, 1 4))"); - assertEnvelopeIntersection("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((4 4, 6 4, 6 6, 4 6, 4 4))", "POLYGON ((4 4, 5 4, 5 5, 4 5, 4 4))"); - assertEnvelopeIntersection("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((10 10, 11 10, 11 11, 10 11, 10 10))", "POLYGON EMPTY"); - assertEnvelopeIntersection("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((-1 -1, 0 -1, 0 1, -1 1, -1 -1))", "LINESTRING (0 0, 0 1)"); - assertEnvelopeIntersection("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((1 -1, 2 -1, 2 0, 1 0, 1 -1))", "LINESTRING (1 0, 2 0)"); - assertEnvelopeIntersection("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))", "POLYGON ((-1 -1, 0 -1, 0 0, -1 0, -1 -1))", "POINT (0 0)"); + assertEnvelopeIntersection("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))"); + assertEnvelopeIntersection("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((-1 4, 1 4, 1 6, -1 6, -1 4))", "POLYGON ((0 4, 0 5, 1 5, 1 4, 0 4))"); + assertEnvelopeIntersection("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((1 4, 2 4, 2 6, 1 6, 1 4))", "POLYGON ((1 4, 1 5, 2 5, 2 4, 1 4))"); + assertEnvelopeIntersection("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((4 4, 6 4, 6 6, 4 6, 4 4))", "POLYGON ((4 4, 4 5, 5 5, 5 4, 4 4))"); + assertEnvelopeIntersection("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((10 10, 11 10, 11 11, 10 11, 10 10))", "POLYGON EMPTY"); + assertEnvelopeIntersection("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((-1 -1, 0 -1, 0 1, -1 1, -1 -1))", "LINESTRING (0 0, 0 1)"); + assertEnvelopeIntersection("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((1 -1, 2 -1, 2 0, 1 0, 1 -1))", "LINESTRING (1 0, 2 0)"); + assertEnvelopeIntersection("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((-1 -1, 0 -1, 0 0, -1 0, -1 -1))", "POINT (0 0)"); } private void assertEnvelopeIntersection(String envelope, String otherEnvelope, String intersection) @@ -756,16 +761,8 @@ public void testSTSymmetricDifference() assertFunction("ST_AsText(ST_SymDifference(ST_GeometryFromText('MULTIPOINT (50 100, 60 200)'), ST_GeometryFromText('MULTIPOINT (60 200, 70 150)')))", VARCHAR, "MULTIPOINT ((50 100), (70 150))"); assertFunction("ST_AsText(ST_SymDifference(ST_GeometryFromText('LINESTRING (50 100, 50 200)'), ST_GeometryFromText('LINESTRING (50 50, 50 150)')))", VARCHAR, "MULTILINESTRING ((50 50, 50 100), (50 150, 50 200))"); assertFunction("ST_AsText(ST_SymDifference(ST_GeometryFromText('MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))'), ST_GeometryFromText('MULTILINESTRING ((3 4, 6 4), (5 0, 5 4))')))", VARCHAR, "MULTILINESTRING ((5 0, 5 1), (1 1, 5 1), (5 1, 5 4), (2 4, 3 4), (4 4, 5 4), (5 4, 6 4))"); - assertFunction("ST_AsText(ST_SymDifference(ST_GeometryFromText('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'), ST_GeometryFromText('POLYGON ((2 2, 2 5, 5 5, 5 2, 2 2))')))", VARCHAR, "MULTIPOLYGON (((1 1, 4 1, 4 2, 2 2, 2 4, 1 4, 1 1)), ((4 2, 5 2, 5 5, 2 5, 2 4, 4 4, 4 2)))"); - assertFunction("ST_AsText(ST_SymDifference(ST_GeometryFromText('MULTIPOLYGON (((0 0, 0 2, 2 2, 2 0, 0 0)), ((2 2, 2 4, 4 4, 4 2, 2 2)))'), ST_GeometryFromText('POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0))')))", VARCHAR, "MULTIPOLYGON (((2 0, 3 0, 3 2, 2 2, 2 0)), ((0 2, 2 2, 2 3, 0 3, 0 2)), ((3 2, 4 2, 4 4, 2 4, 2 3, 3 3, 3 2)))"); - } - - @Test - public void testInvalidWKT() - { - assertInvalidFunction("ST_LineFromText('LINESTRING (0 0, 1)')", INVALID_FUNCTION_ARGUMENT, "Invalid WKT: LINESTRING (0 0, 1)"); - assertInvalidFunction("ST_GeometryFromText('POLYGON(0 0)')", INVALID_FUNCTION_ARGUMENT, "Invalid WKT: POLYGON(0 0)"); - assertInvalidFunction("ST_Polygon('POLYGON(-1 1, 1 -1)')", INVALID_FUNCTION_ARGUMENT, "Invalid WKT: POLYGON(-1 1, 1 -1)"); + assertFunction("ST_AsText(ST_SymDifference(ST_GeometryFromText('POLYGON ((1 1, 1 4, 4 4, 4 1, 1 1))'), ST_GeometryFromText('POLYGON ((2 2, 2 5, 5 5, 5 2, 2 2))')))", VARCHAR, "MULTIPOLYGON (((1 1, 1 4, 2 4, 2 2, 4 2, 4 1, 1 1)), ((4 2, 4 4, 2 4, 2 5, 5 5, 5 2, 4 2)))"); + assertFunction("ST_AsText(ST_SymDifference(ST_GeometryFromText('MULTIPOLYGON (((0 0, 0 2, 2 2, 2 0, 0 0)), ((2 2, 2 4, 4 4, 4 2, 2 2)))'), ST_GeometryFromText('POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0))')))", VARCHAR, "MULTIPOLYGON (((2 0, 2 2, 3 2, 3 0, 2 0)), ((0 2, 0 3, 2 3, 2 2, 0 2)), ((3 2, 3 3, 2 3, 2 4, 4 4, 4 2, 3 2)))"); } @Test @@ -802,10 +799,10 @@ public void testSTInteriorRings() assertInvalidInteriorRings("GEOMETRYCOLLECTION (POINT (1 1), POINT (2 3), LINESTRING (5 8, 13 21))", "GEOMETRY_COLLECTION"); assertFunction("ST_InteriorRings(ST_GeometryFromText('POLYGON EMPTY'))", new ArrayType(GEOMETRY), null); - assertInteriorRings("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))"); - assertInteriorRings("POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))", "LINESTRING (1 1, 1 2, 2 2, 2 1, 1 1)"); - assertInteriorRings("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (3 3, 3 4, 4 4, 4 3, 3 3))", - "LINESTRING (1 1, 1 2, 2 2, 2 1, 1 1)", "LINESTRING (3 3, 3 4, 4 4, 4 3, 3 3)"); + assertInteriorRings("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))"); + assertInteriorRings("POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))", "LINESTRING (1 1, 2 1, 2 2, 1 2, 1 1)"); + assertInteriorRings("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1), (3 3, 4 3, 4 4, 3 4, 3 3))", + "LINESTRING (1 1, 2 1, 2 2, 1 2, 1 1)", "LINESTRING (3 3, 4 3, 4 4, 3 4, 3 3)"); } private void assertInteriorRings(String wkt, String... expected) @@ -860,9 +857,9 @@ public void testSTUnion() "MULTIPOINT ((1 2), (3 4))", "LINESTRING (0 0, 2 2, 4 4)", "MULTILINESTRING ((0 0, 2 2, 4 4), (5 5, 7 7, 9 9))", - "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", - "MULTIPOLYGON (((1 1, 3 1, 3 3, 1 3, 1 1)), ((2 4, 6 4, 6 6, 2 6, 2 4)))", - "GEOMETRYCOLLECTION (LINESTRING (0 5, 5 5), POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1)))"); + "POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", + "MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((2 4, 2 6, 6 6, 6 4, 2 4)))", + "GEOMETRYCOLLECTION (LINESTRING (0 5, 5 5), POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1)))"); // empty geometry for (String emptyWkt : emptyWkts) { @@ -881,24 +878,24 @@ public void testSTUnion() assertUnion("MULTIPOINT ((1 2))", "MULTIPOINT ((1 2), (3 4))", "MULTIPOINT ((1 2), (3 4))"); assertUnion("LINESTRING (0 1, 1 2)", "LINESTRING (1 2, 3 4)", "LINESTRING (0 1, 1 2, 3 4)"); assertUnion("MULTILINESTRING ((0 0, 2 2, 4 4), (5 5, 7 7, 9 9))", "MULTILINESTRING ((5 5, 7 7, 9 9), (11 11, 13 13, 15 15))", "MULTILINESTRING ((0 0, 2 2, 4 4), (5 5, 7 7, 9 9), (11 11, 13 13, 15 15))"); - assertUnion("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", "POLYGON ((1 0, 2 0, 2 1, 1 1, 1 0))", "POLYGON ((0 0, 1 0, 2 0, 2 1, 1 1, 0 1, 0 0))"); - assertUnion("MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)))", "MULTIPOLYGON (((1 0, 2 0, 2 1, 1 1, 1 0)))", "POLYGON ((0 0, 1 0, 2 0, 2 1, 1 1, 0 1, 0 0))"); - assertUnion("GEOMETRYCOLLECTION (POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)), POINT (1 2))", "GEOMETRYCOLLECTION (POLYGON ((1 0, 2 0, 2 1, 1 1, 1 0)), MULTIPOINT ((1 2), (3 4)))", "GEOMETRYCOLLECTION (MULTIPOINT ((1 2), (3 4)), POLYGON ((0 0, 1 0, 2 0, 2 1, 1 1, 0 1, 0 0)))"); + assertUnion("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", "POLYGON ((1 0, 2 0, 2 1, 1 1, 1 0))", "POLYGON ((0 0, 0 1, 1 1, 2 1, 2 0, 1 0, 0 0))"); + assertUnion("MULTIPOLYGON (((0 0, 0 1, 1 1, 1 0, 0 0)))", "MULTIPOLYGON (((1 0, 2 0, 2 1, 1 1, 1 0)))", "POLYGON ((0 0, 0 1, 1 1, 2 1, 2 0, 1 0, 0 0))"); + assertUnion("GEOMETRYCOLLECTION (POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)), POINT (1 2))", "GEOMETRYCOLLECTION (POLYGON ((1 0, 2 0, 2 1, 1 1, 1 0)), MULTIPOINT ((1 2), (3 4)))", "GEOMETRYCOLLECTION (MULTIPOINT ((1 2), (3 4)), POLYGON ((0 0, 0 1, 1 1, 2 1, 2 0, 1 0, 0 0)))"); // within union assertUnion("MULTIPOINT ((20 20), (25 25))", "POINT (25 25)", "MULTIPOINT ((20 20), (25 25))"); assertUnion("LINESTRING (20 20, 30 30)", "POINT (25 25)", "LINESTRING (20 20, 25 25, 30 30)"); assertUnion("LINESTRING (20 20, 30 30)", "LINESTRING (25 25, 27 27)", "LINESTRING (20 20, 25 25, 27 27, 30 30)"); - assertUnion("POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))", "POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))", "POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0))"); - assertUnion("MULTIPOLYGON (((0 0, 0 2, 2 2, 2 0, 0 0)), ((2 2, 2 4, 4 4, 4 2, 2 2)))", "POLYGON ((2 2, 2 3, 3 3, 3 2, 2 2))", "MULTIPOLYGON (((2 2, 3 2, 4 2, 4 4, 2 4, 2 3, 2 2)), ((0 0, 2 0, 2 2, 0 2, 0 0)))"); - assertUnion("GEOMETRYCOLLECTION (POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0)), MULTIPOINT ((20 20), (25 25)))", "GEOMETRYCOLLECTION (POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1)), POINT (25 25))", "GEOMETRYCOLLECTION (MULTIPOINT ((20 20), (25 25)), POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0)))"); + assertUnion("POLYGON ((0 0, 0 4, 4 4, 4 0, 0 0))", "POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))", "POLYGON ((0 0, 0 4, 4 4, 4 0, 0 0))"); + assertUnion("MULTIPOLYGON (((0 0, 0 2, 2 2, 2 0, 0 0)), ((2 2, 2 4, 4 4, 4 2, 2 2)))", "POLYGON ((2 2, 2 3, 3 3, 3 2, 2 2))", "MULTIPOLYGON (((2 2, 2 3, 2 4, 4 4, 4 2, 3 2, 2 2)), ((0 0, 0 2, 2 2, 2 0, 0 0)))"); + assertUnion("GEOMETRYCOLLECTION (POLYGON ((0 0, 0 4, 4 4, 4 0, 0 0)), MULTIPOINT ((20 20), (25 25)))", "GEOMETRYCOLLECTION (POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1)), POINT (25 25))", "GEOMETRYCOLLECTION (MULTIPOINT ((20 20), (25 25)), POLYGON ((0 0, 0 4, 4 4, 4 0, 0 0)))"); // overlap union assertUnion("LINESTRING (1 1, 3 1)", "LINESTRING (2 1, 4 1)", "LINESTRING (1 1, 2 1, 3 1, 4 1)"); assertUnion("MULTILINESTRING ((1 1, 3 1))", "MULTILINESTRING ((2 1, 4 1))", "LINESTRING (1 1, 2 1, 3 1, 4 1)"); - assertUnion("POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))", "POLYGON ((2 2, 4 2, 4 4, 2 4, 2 2))", "POLYGON ((1 1, 3 1, 3 2, 4 2, 4 4, 2 4, 2 3, 1 3, 1 1))"); - assertUnion("MULTIPOLYGON (((1 1, 3 1, 3 3, 1 3, 1 1)))", "MULTIPOLYGON (((2 2, 4 2, 4 4, 2 4, 2 2)))", "POLYGON ((1 1, 3 1, 3 2, 4 2, 4 4, 2 4, 2 3, 1 3, 1 1))"); - assertUnion("GEOMETRYCOLLECTION (POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1)), LINESTRING (1 1, 3 1))", "GEOMETRYCOLLECTION (POLYGON ((2 2, 4 2, 4 4, 2 4, 2 2)), LINESTRING (2 1, 4 1))", "GEOMETRYCOLLECTION (LINESTRING (3 1, 4 1), POLYGON ((1 1, 2 1, 3 1, 3 2, 4 2, 4 4, 2 4, 2 3, 1 3, 1 1)))"); + assertUnion("POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))", "POLYGON ((2 2, 4 2, 4 4, 2 4, 2 2))", "POLYGON ((1 1, 1 3, 2 3, 2 4, 4 4, 4 2, 3 2, 3 1, 1 1))"); + assertUnion("MULTIPOLYGON (((1 1, 3 1, 3 3, 1 3, 1 1)))", "MULTIPOLYGON (((2 2, 4 2, 4 4, 2 4, 2 2)))", "POLYGON ((1 1, 1 3, 2 3, 2 4, 4 4, 4 2, 3 2, 3 1, 1 1))"); + assertUnion("GEOMETRYCOLLECTION (POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1)), LINESTRING (1 1, 3 1))", "GEOMETRYCOLLECTION (POLYGON ((2 2, 4 2, 4 4, 2 4, 2 2)), LINESTRING (2 1, 4 1))", "GEOMETRYCOLLECTION (LINESTRING (3 1, 4 1), POLYGON ((1 1, 1 3, 2 3, 2 4, 4 4, 4 2, 3 2, 3 1, 2 1, 1 1)))"); } private void assertUnion(String leftWkt, String rightWkt, String expectWkt) @@ -934,9 +931,9 @@ public void testSTGeometryN() assertSTGeometryN("LINESTRING(77.29 29.07, 77.42 29.26, 77.27 29.31, 77.29 29.07)", 1, "LINESTRING (77.29 29.07, 77.42 29.26, 77.27 29.31, 77.29 29.07)"); assertSTGeometryN("LINESTRING(77.29 29.07, 77.42 29.26, 77.27 29.31, 77.29 29.07)", 2, null); assertSTGeometryN("LINESTRING(77.29 29.07, 77.42 29.26, 77.27 29.31, 77.29 29.07)", -1, null); - assertSTGeometryN("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", 1, "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))"); - assertSTGeometryN("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", 2, null); - assertSTGeometryN("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", -1, null); + assertSTGeometryN("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", 1, "POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))"); + assertSTGeometryN("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", 2, null); + assertSTGeometryN("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", -1, null); assertSTGeometryN("MULTIPOINT (1 2, 2 4, 3 6, 4 8)", 1, "POINT (1 2)"); assertSTGeometryN("MULTIPOINT (1 2, 2 4, 3 6, 4 8)", 2, "POINT (2 4)"); assertSTGeometryN("MULTIPOINT (1 2, 2 4, 3 6, 4 8)", 0, null); @@ -947,8 +944,8 @@ public void testSTGeometryN() assertSTGeometryN("MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))", 0, null); assertSTGeometryN("MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))", 3, null); assertSTGeometryN("MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))", -1, null); - assertSTGeometryN("MULTIPOLYGON (((1 1, 3 1, 3 3, 1 3, 1 1)), ((2 4, 6 4, 6 6, 2 6, 2 4)))", 1, "POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))"); - assertSTGeometryN("MULTIPOLYGON (((1 1, 3 1, 3 3, 1 3, 1 1)), ((2 4, 6 4, 6 6, 2 6, 2 4)))", 2, "POLYGON ((2 4, 6 4, 6 6, 2 6, 2 4))"); + assertSTGeometryN("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((2 4, 2 6, 6 6, 6 4, 2 4)))", 1, "POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))"); + assertSTGeometryN("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((2 4, 2 6, 6 6, 6 4, 2 4)))", 2, "POLYGON ((2 4, 2 6, 6 6, 6 4, 2 4))"); assertSTGeometryN("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((2 4, 2 6, 6 6, 6 4, 2 4)))", 0, null); assertSTGeometryN("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((2 4, 2 6, 6 6, 6 4, 2 4)))", 3, null); assertSTGeometryN("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((2 4, 2 6, 6 6, 6 4, 2 4)))", -1, null); @@ -986,13 +983,13 @@ public void testSTLineString() assertFunction("ST_LineString(array[])", GEOMETRY, "LINESTRING EMPTY"); // Only points can be passed - assertInvalidFunction("ST_LineString(array[ST_Point(7,8), ST_GeometryFromText('LINESTRING (1 2, 3 4)')])", INVALID_FUNCTION_ARGUMENT, "ST_LineString takes only an array of valid points, LineString was passed"); + assertInvalidFunction("ST_LineString(array[ST_Point(7,8), ST_GeometryFromText('LINESTRING (1 2, 3 4)')])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: geometry is not a point: LINE_STRING at index 2"); // Nulls points are invalid - assertInvalidFunction("ST_LineString(array[NULL])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: null point at index 1"); - assertInvalidFunction("ST_LineString(array[ST_Point(1,2), NULL])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: null point at index 2"); - assertInvalidFunction("ST_LineString(array[ST_Point(1, 2), NULL, ST_Point(3, 4)])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: null point at index 2"); - assertInvalidFunction("ST_LineString(array[ST_Point(1, 2), NULL, ST_Point(3, 4), NULL])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: null point at index 2"); + assertInvalidFunction("ST_LineString(array[NULL])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: null at index 1"); + assertInvalidFunction("ST_LineString(array[ST_Point(1,2), NULL])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: null at index 2"); + assertInvalidFunction("ST_LineString(array[ST_Point(1, 2), NULL, ST_Point(3, 4)])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: null at index 2"); + assertInvalidFunction("ST_LineString(array[ST_Point(1, 2), NULL, ST_Point(3, 4), NULL])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: null at index 2"); // Empty points are invalid assertInvalidFunction("ST_LineString(array[ST_GeometryFromText('POINT EMPTY')])", INVALID_FUNCTION_ARGUMENT, "Invalid input to ST_LineString: empty point at index 1"); @@ -1020,7 +1017,7 @@ public void testMultiPoint() assertFunction("ST_MultiPoint(array[])", GEOMETRY, null); // Only points can be passed - assertInvalidMultiPoint("geometry is not a point: LineString at index 2", "POINT (7 8)", "LINESTRING (1 2, 3 4)"); + assertInvalidMultiPoint("geometry is not a point: LINE_STRING at index 2", "POINT (7 8)", "LINESTRING (1 2, 3 4)"); // Null point raises exception assertInvalidFunction("ST_MultiPoint(array[null])", "Invalid input to ST_MultiPoint: null at index 1"); @@ -1069,7 +1066,7 @@ public void testSTPointN() assertInvalidPointN("POINT (1 2)", "POINT"); assertInvalidPointN("MULTIPOINT (1 1, 2 2)", "MULTI_POINT"); assertInvalidPointN("MULTILINESTRING ((1 1, 2 2), (3 3, 4 4))", "MULTI_LINE_STRING"); - assertInvalidPointN("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", "POLYGON"); + assertInvalidPointN("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", "POLYGON"); assertInvalidPointN("MULTIPOLYGON (((1 1, 1 4, 4 4, 4 1, 1 1)), ((1 1, 1 4, 4 4, 4 1, 1 1)))", "MULTI_POLYGON"); assertInvalidPointN("GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6, 7 10))", "GEOMETRY_COLLECTION"); } @@ -1091,12 +1088,14 @@ public void testSTGeometries() assertFunction("ST_Geometries(ST_GeometryFromText('POINT EMPTY'))", new ArrayType(GEOMETRY), null); assertSTGeometries("POINT (1 5)", "POINT (1 5)"); assertSTGeometries("LINESTRING (77.29 29.07, 77.42 29.26, 77.27 29.31, 77.29 29.07)", "LINESTRING (77.29 29.07, 77.42 29.26, 77.27 29.31, 77.29 29.07)"); - assertSTGeometries("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))"); + assertSTGeometries("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", "POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))"); assertSTGeometries("MULTIPOINT (1 2, 4 8, 16 32)", "POINT (1 2)", "POINT (4 8)", "POINT (16 32)"); assertSTGeometries("MULTILINESTRING ((1 1, 2 2))", "LINESTRING (1 1, 2 2)"); - assertSTGeometries("MULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)), ((1 1, 3 1, 3 3, 1 3, 1 1)))", - "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", "POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))"); + assertSTGeometries("MULTIPOLYGON (((0 0, 0 1, 1 1, 1 0, 0 0)), ((1 1, 3 1, 3 3, 1 3, 1 1)))", + "POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", "POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))"); assertSTGeometries("GEOMETRYCOLLECTION (POINT (2 3), LINESTRING (2 3, 3 4))", "POINT (2 3)", "LINESTRING (2 3, 3 4)"); + assertSTGeometries("GEOMETRYCOLLECTION(MULTIPOINT(0 0, 1 1), GEOMETRYCOLLECTION(MULTILINESTRING((2 2, 3 3))))", + "MULTIPOINT ((0 0), (1 1))", "GEOMETRYCOLLECTION (MULTILINESTRING ((2 2, 3 3)))"); } private void assertSTGeometries(String wkt, String... expected) @@ -1114,12 +1113,12 @@ public void testSTInteriorRingN() assertInvalidInteriorRingN("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((2 4, 2 6, 6 6, 6 4, 2 4)))", 2, "MULTI_POLYGON"); assertInvalidInteriorRingN("GEOMETRYCOLLECTION (POINT (2 2), POINT (10 20))", 1, "GEOMETRY_COLLECTION"); - assertInteriorRingN("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", 1, null); - assertInteriorRingN("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", 2, null); - assertInteriorRingN("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", -1, null); - assertInteriorRingN("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", 0, null); - assertInteriorRingN("POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))", 1, "LINESTRING (1 1, 1 2, 2 2, 2 1, 1 1)"); - assertInteriorRingN("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (3 3, 3 4, 4 4, 4 3, 3 3))", 2, "LINESTRING (3 3, 3 4, 4 4, 4 3, 3 3)"); + assertInteriorRingN("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", 1, null); + assertInteriorRingN("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", 2, null); + assertInteriorRingN("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", -1, null); + assertInteriorRingN("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", 0, null); + assertInteriorRingN("POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))", 1, "LINESTRING (1 1, 2 1, 2 2, 1 2, 1 1)"); + assertInteriorRingN("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1), (3 3, 4 3, 4 4, 3 4, 3 3))", 2, "LINESTRING (3 3, 4 3, 4 4, 3 4, 3 3)"); } private void assertInteriorRingN(String wkt, int index, String expected) @@ -1145,6 +1144,17 @@ public void testSTGeometryType() assertFunction("ST_GeometryType(ST_Envelope(ST_GeometryFromText('LINESTRING (1 1, 2 2)')))", VARCHAR, "ST_Polygon"); } + @Test + public void testSTGeometryFromText() + { + assertInvalidFunction("ST_GeometryFromText('xyz')", "Invalid WKT: Unknown geometry type: XYZ (line 1)"); + assertInvalidFunction("ST_GeometryFromText('LINESTRING (-71.3839245 42.3128124)')", "Invalid WKT: Invalid number of points in LineString (found 1 - must be 0 or >= 2)"); + assertInvalidFunction("ST_GeometryFromText('POLYGON ((-13.719076 9.508430, -13.723493 9.510049, -13.719076 9.508430))')", "Invalid WKT: Invalid number of points in LinearRing (found 3 - must be 0 or >= 4)"); + assertInvalidFunction("ST_GeometryFromText('POLYGON ((-13.637339 9.617113, -13.637339 9.617113))')", "Invalid WKT: Invalid number of points in LinearRing (found 2 - must be 0 or >= 4)"); + assertInvalidFunction("ST_GeometryFromText('POLYGON(0 0)')", INVALID_FUNCTION_ARGUMENT, "Invalid WKT: Expected EMPTY or ( but found '0' (line 1)"); + assertInvalidFunction("ST_GeometryFromText('POLYGON((0 0))')", INVALID_FUNCTION_ARGUMENT, "Invalid WKT: Invalid number of points in LineString (found 1 - must be 0 or >= 2)"); + } + @Test public void testSTGeometryFromBinary() { @@ -1164,10 +1174,10 @@ public void testSTGeometryFromBinary() assertGeomFromBinary("MULTIPOINT ((1 2), (3 4))"); assertGeomFromBinary("LINESTRING (0 0, 1 2, 3 4)"); assertGeomFromBinary("MULTILINESTRING ((1 1, 5 1), (2 4, 4 4))"); - assertGeomFromBinary("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))"); - assertGeomFromBinary("POLYGON ((0 0, 3 0, 3 3, 0 3, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))"); - assertGeomFromBinary("MULTIPOLYGON (((1 1, 3 1, 3 3, 1 3, 1 1)), ((2 4, 6 4, 6 6, 2 6, 2 4)))"); - assertGeomFromBinary("GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 0, 1 2, 3 4), POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)))"); + assertGeomFromBinary("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))"); + assertGeomFromBinary("POLYGON ((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))"); + assertGeomFromBinary("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)), ((2 4, 2 6, 6 6, 6 4, 2 4)))"); + assertGeomFromBinary("GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (0 0, 1 2, 3 4), POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)))"); // array of geometries assertFunction("transform(array[ST_AsBinary(ST_Point(1, 2)), ST_AsBinary(ST_Point(3, 4))], wkb -> ST_AsText(ST_GeomFromBinary(wkb)))", new ArrayType(VARCHAR), ImmutableList.of("POINT (1 2)", "POINT (3 4)")); diff --git a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestSpatialPartitioningInternalAggregation.java b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestSpatialPartitioningInternalAggregation.java index c4bcdd3241251..468d10d2921c7 100644 --- a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestSpatialPartitioningInternalAggregation.java +++ b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestSpatialPartitioningInternalAggregation.java @@ -40,7 +40,7 @@ import java.util.Optional; import static com.facebook.presto.geospatial.KdbTree.buildKdbTree; -import static com.facebook.presto.geospatial.serde.GeometrySerde.serialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.serialize; import static com.facebook.presto.operator.aggregation.AggregationTestUtils.createGroupByIdBlock; import static com.facebook.presto.operator.aggregation.AggregationTestUtils.getFinalBlock; import static com.facebook.presto.operator.aggregation.AggregationTestUtils.getGroupValue; diff --git a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestSphericalGeoFunctions.java b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestSphericalGeoFunctions.java index e7fe523582f8c..491057508a207 100644 --- a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestSphericalGeoFunctions.java +++ b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/TestSphericalGeoFunctions.java @@ -97,13 +97,13 @@ public void testToAndFromSphericalGeography() assertToAndFromSphericalGeography("MULTIPOINT ((-40.2 28.9), (-40.2 31.9))"); assertToAndFromSphericalGeography("LINESTRING (-40.2 28.9, -40.2 31.9, -37.2 31.9)"); assertToAndFromSphericalGeography("MULTILINESTRING ((-40.2 28.9, -40.2 31.9), (-40.2 31.9, -37.2 31.9))"); - assertToAndFromSphericalGeography("POLYGON ((-40.2 28.9, -37.2 28.9, -37.2 31.9, -40.2 31.9, -40.2 28.9))"); - assertToAndFromSphericalGeography("POLYGON ((-40.2 28.9, -37.2 28.9, -37.2 31.9, -40.2 31.9, -40.2 28.9), " + - "(-39.2 29.9, -39.2 30.9, -38.2 30.9, -38.2 29.9, -39.2 29.9))"); - assertToAndFromSphericalGeography("MULTIPOLYGON (((-40.2 28.9, -37.2 28.9, -37.2 31.9, -40.2 31.9, -40.2 28.9)), " + - "((-39.2 29.9, -38.2 29.9, -38.2 30.9, -39.2 30.9, -39.2 29.9)))"); + assertToAndFromSphericalGeography("POLYGON ((-40.2 28.9, -40.2 31.9, -37.2 31.9, -37.2 28.9, -40.2 28.9))"); + assertToAndFromSphericalGeography("POLYGON ((-40.2 28.9, -40.2 31.9, -37.2 31.9, -37.2 28.9, -40.2 28.9), " + + "(-39.2 29.9, -38.2 29.9, -38.2 30.9, -39.2 30.9, -39.2 29.9))"); + assertToAndFromSphericalGeography("MULTIPOLYGON (((-40.2 28.9, -40.2 31.9, -37.2 31.9, -37.2 28.9, -40.2 28.9)), " + + "((-39.2 29.9, -39.2 30.9, -38.2 30.9, -38.2 29.9, -39.2 29.9)))"); assertToAndFromSphericalGeography("GEOMETRYCOLLECTION (POINT (-40.2 28.9), LINESTRING (-40.2 28.9, -40.2 31.9, -37.2 31.9), " + - "POLYGON ((-40.2 28.9, -37.2 28.9, -37.2 31.9, -40.2 31.9, -40.2 28.9)))"); + "POLYGON ((-40.2 28.9, -40.2 31.9, -37.2 31.9, -37.2 28.9, -40.2 28.9)))"); // geometries containing invalid latitude or longitude values assertInvalidLongitude("POINT (-340.2 28.9)"); @@ -111,7 +111,7 @@ public void testToAndFromSphericalGeography() assertInvalidLongitude("LINESTRING (-40.2 28.9, -40.2 31.9, 237.2 31.9)"); assertInvalidLatitude("MULTILINESTRING ((-40.2 28.9, -40.2 31.9), (-40.2 131.9, -37.2 31.9))"); assertInvalidLongitude("POLYGON ((-40.2 28.9, -40.2 31.9, 237.2 31.9, -37.2 28.9, -40.2 28.9))"); - assertInvalidLatitude("POLYGON ((-40.2 28.9, -40.2 31.9, -37.2 131.9, -37.2 28.9, -40.2 28.9), (-39.2 29.9, -39.2 30.9, -38.2 30.9, -38.2 29.9, -39.2 29.9))"); + assertInvalidLatitude("POLYGON ((-40.2 28.9, -40.2 31.9, -37.2 131.9, -37.2 28.9, -40.2 28.9), (-39.2 29.9, -38.2 29.9, -38.2 30.9, -39.2 30.9, -39.2 29.9))"); assertInvalidLongitude("MULTIPOLYGON (((-40.2 28.9, -40.2 31.9, -37.2 31.9, -37.2 28.9, -40.2 28.9)), " + "((-39.2 29.9, -39.2 30.9, 238.2 30.9, -38.2 29.9, -39.2 29.9)))"); assertInvalidLatitude("GEOMETRYCOLLECTION (POINT (-40.2 28.9), LINESTRING (-40.2 28.9, -40.2 131.9, -37.2 31.9), " + @@ -158,9 +158,6 @@ public void testArea() // Empty polygon assertFunction("ST_Area(to_spherical_geography(ST_GeometryFromText('POLYGON EMPTY')))", DOUBLE, null); - // Invalid polygon (too few vertices) - assertInvalidFunction("ST_Area(to_spherical_geography(ST_GeometryFromText('POLYGON((90 0, 0 0))')))", "Polygon is not valid: a loop contains less then 3 vertices."); - // Invalid data type (point) assertInvalidFunction("ST_Area(to_spherical_geography(ST_GeometryFromText('POINT (0 1)')))", "When applied to SphericalGeography inputs, ST_Area only supports POLYGON or MULTI_POLYGON. Input type is: POINT"); @@ -210,12 +207,6 @@ public void testLength() // Empty linestring returns null assertLength("LINESTRING EMPTY", null); - // Linestring with one point has length 0 - assertLength("LINESTRING (0 0)", 0.0); - - // Linestring with only one distinct point has length 0 - assertLength("LINESTRING (0 0, 0 0, 0 0)", 0.0); - double length = 4350866.6362; // ST_Length is equivalent to sums of ST_DISTANCE between points in the LineString diff --git a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/aggregation/AbstractTestGeoAggregationFunctions.java b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/aggregation/AbstractTestGeoAggregationFunctions.java index cb870e03ffc73..782ec2c337a1e 100644 --- a/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/aggregation/AbstractTestGeoAggregationFunctions.java +++ b/presto-geospatial/src/test/java/com/facebook/presto/plugin/geospatial/aggregation/AbstractTestGeoAggregationFunctions.java @@ -15,7 +15,7 @@ import com.esri.core.geometry.ogc.OGCGeometry; import com.facebook.presto.block.BlockAssertions; -import com.facebook.presto.geospatial.serde.GeometrySerde; +import com.facebook.presto.geospatial.serde.EsriGeometrySerde; import com.facebook.presto.metadata.FunctionManager; import com.facebook.presto.operator.aggregation.InternalAggregationFunction; import com.facebook.presto.operator.scalar.AbstractTestFunctions; @@ -58,7 +58,7 @@ protected void assertAggregatedGeometries(String testDescription, String expecte { List geometrySlices = Arrays.stream(wkts) .map(text -> text == null ? null : OGCGeometry.fromText(text)) - .map(input -> input == null ? null : GeometrySerde.serialize(input)) + .map(input -> input == null ? null : EsriGeometrySerde.serialize(input)) .collect(Collectors.toList()); // Add a custom equality assertion because the resulting geometry may have diff --git a/presto-main/src/main/java/com/facebook/presto/operator/PagesRTreeIndex.java b/presto-main/src/main/java/com/facebook/presto/operator/PagesRTreeIndex.java index 412388356efb4..a765c7a9c9af4 100644 --- a/presto-main/src/main/java/com/facebook/presto/operator/PagesRTreeIndex.java +++ b/presto-main/src/main/java/com/facebook/presto/operator/PagesRTreeIndex.java @@ -37,7 +37,7 @@ import java.util.OptionalDouble; import static com.facebook.presto.geospatial.GeometryUtils.getExtent; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; import static com.facebook.presto.operator.JoinUtils.channelsToPages; import static com.facebook.presto.operator.SyntheticAddress.decodePosition; import static com.facebook.presto.operator.SyntheticAddress.decodeSliceIndex; diff --git a/presto-main/src/main/java/com/facebook/presto/operator/PagesSpatialIndexSupplier.java b/presto-main/src/main/java/com/facebook/presto/operator/PagesSpatialIndexSupplier.java index 5812eb2cb5160..381727006acad 100644 --- a/presto-main/src/main/java/com/facebook/presto/operator/PagesSpatialIndexSupplier.java +++ b/presto-main/src/main/java/com/facebook/presto/operator/PagesSpatialIndexSupplier.java @@ -38,7 +38,7 @@ import java.util.Optional; import java.util.function.Supplier; -import static com.facebook.presto.geospatial.serde.GeometrySerde.deserialize; +import static com.facebook.presto.geospatial.serde.EsriGeometrySerde.deserialize; import static com.facebook.presto.operator.PagesSpatialIndex.EMPTY_INDEX; import static com.facebook.presto.operator.SyntheticAddress.decodePosition; import static com.facebook.presto.operator.SyntheticAddress.decodeSliceIndex;