This is an automated email from the ASF dual-hosted git repository. jiayu pushed a commit to branch SEDONA-578 in repository https://gitbox.apache.org/repos/asf/sedona.git
commit 19e2e55e319e42fb91b22c96c9cc7d7e9eff4594 Author: Pranav Toggi <[email protected]> AuthorDate: Mon Apr 8 19:16:01 2024 -0400 [TASK-4] Add ST_Points (#157) * init * init 2 * add flink test * add scala, python, snowflake tests * add docs * Fix scala implementation * Fix test * Add ST_LineFromWKB * fix typo * Fix scala implementation * add scala dataframeapi test * Add flink tests * Add python dataframeapi test * Fix test * Fix doc * Fix test * Add tests * Fix test * Fix typo * Init * Implement for common and flink * Implement for scala; add tests * Fix typo * Implement for python, snowflake * Update docs * Fix tests * Fix tests * Fix test * Remove show() --- .../java/org/apache/sedona/common/Functions.java | 19 ++++++++++++++++ .../org/apache/sedona/common/FunctionsTest.java | 26 ++++++++++++++++++++++ docs/api/flink/Function.md | 20 +++++++++++++++++ docs/api/snowflake/vector-data/Function.md | 18 +++++++++++++++ docs/api/sql/Function.md | 20 +++++++++++++++++ .../main/java/org/apache/sedona/flink/Catalog.java | 1 + .../apache/sedona/flink/expressions/Functions.java | 8 +++++++ .../java/org/apache/sedona/flink/FunctionTest.java | 8 +++++++ python/sedona/sql/st_functions.py | 11 +++++++++ python/tests/sql/test_dataframe_api.py | 1 + python/tests/sql/test_function.py | 20 +++++++++++++++++ .../sedona/snowflake/snowsql/TestFunctions.java | 11 +++++++++ .../sedona/snowflake/snowsql/TestFunctionsV2.java | 9 ++++++++ .../org/apache/sedona/snowflake/snowsql/UDFs.java | 9 ++++++++ .../apache/sedona/snowflake/snowsql/UDFsV2.java | 9 ++++++++ .../scala/org/apache/sedona/sql/UDF/Catalog.scala | 1 + .../sql/sedona_sql/expressions/Functions.scala | 8 +++++++ .../sql/sedona_sql/expressions/st_functions.scala | 3 +++ .../apache/sedona/sql/dataFrameAPITestScala.scala | 9 ++++++++ .../org/apache/sedona/sql/functionTestScala.scala | 12 ++++++++++ 20 files changed, 223 insertions(+) diff --git a/common/src/main/java/org/apache/sedona/common/Functions.java b/common/src/main/java/org/apache/sedona/common/Functions.java index 774a2bfe3..d6dceb1f5 100644 --- a/common/src/main/java/org/apache/sedona/common/Functions.java +++ b/common/src/main/java/org/apache/sedona/common/Functions.java @@ -1728,4 +1728,23 @@ public class Functions { return GEOMETRY_FACTORY.createGeometryCollection(null); } } + + /** + * Creates a MultiPoint containing all coordinates of the given geometry. + * Duplicates, M and Z coordinates are preserved. + * + * @param geometry The input geometry + * @return A MultiPoint geometry + */ + public static Geometry points(Geometry geometry) { + if (geometry == null) { + return null; + } + + // Extracting all coordinates from the geometry + Coordinate[] coordinates = geometry.getCoordinates(); + + // Creating a MultiPoint from the extracted coordinates + return GEOMETRY_FACTORY.createMultiPointFromCoords(coordinates); + } } diff --git a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java index 4fe7d1578..9f233f71b 100644 --- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java +++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java @@ -2438,4 +2438,30 @@ public class FunctionsTest extends TestBase { String invalidReasonESRI = Functions.isValidReason(invalidGeom, ESRI_VALIDITY); assertEquals("Self-intersection at or near point (10.0, 20.0, NaN)", invalidReasonESRI); } + + @Test + public void points() throws ParseException { + Geometry polygon = Constructors.geomFromEWKT("POLYGON ((0 0, 1 1, 5 1, 5 0, 1 0, 0 0))"); + Geometry lineString = Constructors.geomFromEWKT("LINESTRING (0 0, 1 1, 2 2)"); + Geometry point = Constructors.geomFromEWKT("POINT (0 0)"); + Geometry multiPoint = Constructors.geomFromEWKT("MULTIPOINT ((0 0), (1 1), (2 2))"); + Geometry multiLineString = Constructors.geomFromEWKT("MULTILINESTRING ((0 0, 1 1), (2 2, 3 3))"); + Geometry multiPolygon = Constructors.geomFromEWKT("MULTIPOLYGON (((0 0, 1 1, 1 0, 0 0)), ((2 2, 3 3, 3 2, 2 2)))"); + Geometry geometry3D = Constructors.geomFromEWKT("POLYGON Z ((0 0 1, 1 1 2, 2 2 3, 0 0 1))"); + + String result = Functions.asEWKT(Functions.points(polygon)); + assertEquals("MULTIPOINT ((0 0), (1 1), (5 1), (5 0), (1 0), (0 0))", result); + result = Functions.asEWKT(Functions.points(lineString)); + assertEquals("MULTIPOINT ((0 0), (1 1), (2 2))", result); + result = Functions.asEWKT(Functions.points(point)); + assertEquals("MULTIPOINT ((0 0))", result); + result = Functions.asEWKT(Functions.points(multiPoint)); + assertEquals("MULTIPOINT ((0 0), (1 1), (2 2))", result); + result = Functions.asEWKT(Functions.points(multiLineString)); + assertEquals("MULTIPOINT ((0 0), (1 1), (2 2), (3 3))", result); + result = Functions.asEWKT(Functions.points(multiPolygon)); + assertEquals("MULTIPOINT ((0 0), (1 1), (1 0), (0 0), (2 2), (3 3), (3 2), (2 2))", result); + String result1 = Functions.asEWKT(Functions.points(geometry3D)); + assertEquals("MULTIPOINT Z((0 0 1), (1 1 2), (2 2 3), (0 0 1))", result1); + } } diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md index 28726f8b6..6b48f3278 100644 --- a/docs/api/flink/Function.md +++ b/docs/api/flink/Function.md @@ -2514,6 +2514,26 @@ FROM df Output: `POINT Z(0 0 1)` +## ST_Points + +Introduction: Returns a MultiPoint geometry consisting of all the coordinates of the input geometry. It preserves duplicate points as well as M and Z coordinates. + +Format: `ST_Points(geom: Geometry)` + +Since: `vTBD` + +SQL Example + +```sql +SELECT ST_AsText(ST_Points(ST_GeomFromEWKT('LINESTRING (2 4, 3 3, 4 2, 7 3)'))); +``` + +Output: + +``` +MULTIPOINT ((2 4), (3 3), (4 2), (7,3)) +``` + ## ST_Polygon Introduction: Function to create a polygon built from the given LineString and sets the spatial reference system from the srid diff --git a/docs/api/snowflake/vector-data/Function.md b/docs/api/snowflake/vector-data/Function.md index 54afc40d6..61325853c 100644 --- a/docs/api/snowflake/vector-data/Function.md +++ b/docs/api/snowflake/vector-data/Function.md @@ -1891,6 +1891,24 @@ SELECT ST_AsText(ST_PointOnSurface(ST_GeomFromText('LINESTRING(0 5 1, 0 0 1, 0 1 ``` +## ST_Points + +Introduction: Returns a MultiPoint geometry consisting of all the coordinates of the input geometry. It preserves duplicate points as well as M and Z coordinates. + +Format: `ST_Points(geom: Geometry)` + +SQL Example + +```sql +SELECT ST_AsText(ST_Points(ST_GeomFromEWKT('LINESTRING (2 4, 3 3, 4 2, 7 3)'))); +``` + +Output: + +``` +MULTIPOINT ((2 4), (3 3), (4 2), (7,3)) +``` + ## ST_Polygon Introduction: Function to create a polygon built from the given LineString and sets the spatial reference system from the srid diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md index a09573fa3..5dc6f3e67 100644 --- a/docs/api/sql/Function.md +++ b/docs/api/sql/Function.md @@ -2523,6 +2523,26 @@ SELECT ST_AsText(ST_PointOnSurface(ST_GeomFromText('LINESTRING(0 5 1, 0 0 1, 0 1 ``` +## ST_Points + +Introduction: Returns a MultiPoint geometry consisting of all the coordinates of the input geometry. It preserves duplicate points as well as M and Z coordinates. + +Format: `ST_Points(geom: Geometry)` + +Since: `vTBD` + +SQL Example + +```sql +SELECT ST_AsText(ST_Points(ST_GeomFromEWKT('LINESTRING (2 4, 3 3, 4 2, 7 3)'))); +``` + +Output: + +``` +MULTIPOINT ((2 4), (3 3), (4 2), (7,3)) +``` + ## ST_Polygon Introduction: Function to create a polygon built from the given LineString and sets the spatial reference system from the srid diff --git a/flink/src/main/java/org/apache/sedona/flink/Catalog.java b/flink/src/main/java/org/apache/sedona/flink/Catalog.java index 234e58b59..b1dd1692f 100644 --- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java +++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java @@ -133,6 +133,7 @@ public class Catalog { new Functions.ST_MMin(), new Functions.ST_MMax(), new Functions.ST_MakeLine(), + new Functions.ST_Points(), new Functions.ST_Polygon(), new Functions.ST_Polygonize(), new Functions.ST_MakePolygon(), diff --git a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java index 7397087c5..56b8b1a44 100644 --- a/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java +++ b/flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java @@ -813,6 +813,14 @@ public class Functions { } } + public static class ST_Points extends ScalarFunction { + @DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) + public Geometry eval(@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) Object o1) { + Geometry geom = (Geometry) o1; + return org.apache.sedona.common.Functions.points(geom); + } + } + public static class ST_Polygon extends ScalarFunction { @DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) public Geometry eval(@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) Object o1, diff --git a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java index 9d4d6bb79..b12c37cba 100644 --- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java +++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java @@ -969,6 +969,14 @@ public class FunctionTest extends TestBase{ assertEquals("LINESTRING (2 2, 3 3)", result.toString()); } + @Test + public void testPoints() { + Table table = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('POLYGON ((0 0, 1 1, 5 1, 5 0, 1 0, 0 0))') AS polygon"); + table = table.select(call(Functions.ST_Points.class.getSimpleName(), $("polygon"))); + Geometry result = (Geometry) first(table).getField(0); + assertEquals("MULTIPOINT ((0 0), (1 1), (5 1), (5 0), (1 0), (0 0))", result.toString()); + } + @Test public void testPolygon() { Table table = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('LINESTRING (0 0, 1 0, 1 1, 0 0)') AS line"); diff --git a/python/sedona/sql/st_functions.py b/python/sedona/sql/st_functions.py index 07814947a..bd222d86a 100644 --- a/python/sedona/sql/st_functions.py +++ b/python/sedona/sql/st_functions.py @@ -917,6 +917,17 @@ def ST_MakeLine(geom1: ColumnOrName, geom2: Optional[ColumnOrName] = None) -> Co args = (geom1,) if geom2 is None else (geom1, geom2) return _call_st_function("ST_MakeLine", args) +@validate_argument_types +def ST_Points(geometry: ColumnOrName) -> Column: + """Creates a MultiPoint geometry consisting of all the coordinates of the input geometry + + :param geometry: input geometry. + :type geometry: ColumnOrName + :return: Multipoint geometry + :rtype: Column + """ + return _call_st_function("ST_Points", (geometry)) + @validate_argument_types def ST_Polygon(line_string: ColumnOrName, srid: ColumnOrNameOrNumber) -> Column: """Create a polygon built from the given LineString and sets the spatial reference system from the srid. diff --git a/python/tests/sql/test_dataframe_api.py b/python/tests/sql/test_dataframe_api.py index 420a26ed1..045fae719 100644 --- a/python/tests/sql/test_dataframe_api.py +++ b/python/tests/sql/test_dataframe_api.py @@ -154,6 +154,7 @@ test_configurations = [ (stf.ST_MMax, ("line",), "4D_line", "", 3.0), (stf.ST_MakeValid, ("geom",), "invalid_geom", "", "MULTIPOLYGON (((1 5, 3 3, 1 1, 1 5)), ((5 3, 7 5, 7 1, 5 3)))"), (stf.ST_MakeLine, ("line1", "line2"), "two_lines", "", "LINESTRING (0 0, 1 1, 0 0, 3 2)"), + (stf.ST_Points, ("line",), "linestring_geom", "ST_Normalize(geom)", "MULTIPOINT (0 0, 1 0, 2 0, 3 0, 4 0, 5 0)"), (stf.ST_Polygon, ("geom", 4236), "closed_linestring_geom", "", "POLYGON ((0 0, 1 0, 1 1, 0 0))"), (stf.ST_Polygonize, ("geom",), "noded_linework", "ST_Normalize(geom)", "GEOMETRYCOLLECTION (POLYGON ((0 2, 1 3, 2 4, 2 3, 2 2, 1 2, 0 2)), POLYGON ((2 2, 2 3, 2 4, 3 3, 4 2, 3 2, 2 2)))"), (stf.ST_MakePolygon, ("geom",), "closed_linestring_geom", "", "POLYGON ((0 0, 1 0, 1 1, 0 0))"), diff --git a/python/tests/sql/test_function.py b/python/tests/sql/test_function.py index 1df5e8508..eba49e795 100644 --- a/python/tests/sql/test_function.py +++ b/python/tests/sql/test_function.py @@ -998,6 +998,26 @@ class TestPredicateJoin(TestBase): for actual, expected in result: assert actual == expected + def test_st_points(self): + # Given + geometry_df = self.spark.createDataFrame( + [ + # Adding only the input that will result in a non-null polygon + ["MULTILINESTRING ((0 0, 1 1), (2 2, 3 3))", "MULTIPOINT ((0 0), (1 1), (2 2), (3 3))"] + ] + ).selectExpr("ST_GeomFromText(_1) AS geom", "_2 AS expected") + + # When calling st_points + geom_poly = geometry_df.withColumn("actual", expr("st_normalize(st_points(geom))")) + + result = geom_poly.filter("actual IS NOT NULL").selectExpr("ST_AsText(actual)", "expected"). \ + collect() + + assert result.__len__() == 1 + + for actual, expected in result: + assert actual == expected + def test_st_polygon(self): # Given geometry_df = self.spark.createDataFrame( diff --git a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java index a83645497..7ccd6184b 100644 --- a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java +++ b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctions.java @@ -720,6 +720,17 @@ public class TestFunctions extends TestBase { "POINT (2.5 2.5)" ); } + + @Test + public void test_ST_Points() { + registerUDF("ST_Points", byte[].class); + registerUDF("ST_AsEWKT", byte[].class); + verifySqlSingleRes( + "select sedona.ST_AsEWKT(sedona.ST_Points(sedona.ST_GeomFromText('LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)')))", + "MULTIPOINT ((0 0), (0 1), (0 2), (0 3), (0 4))" + ); + } + @Test public void test_ST_Polygon() { registerUDF("ST_Polygon", byte[].class, int.class); diff --git a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java index 299cbcdc9..58f36de43 100644 --- a/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java +++ b/snowflake-tester/src/test/java/org/apache/sedona/snowflake/snowsql/TestFunctionsV2.java @@ -668,6 +668,15 @@ public class TestFunctionsV2 ); } + @Test + public void test_ST_Points() { + registerUDFV2("ST_Points", String.class); + verifySqlSingleRes( + "select ST_AsEWKT(sedona.ST_Points(ST_GeometryFromWKT('LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)')))", + "SRID=0;MULTIPOINT((0 0),(0 1),(0 2),(0 3),(0 4))" + ); + } + @Test public void test_ST_Polygon() { registerUDFV2("ST_Polygon", String.class, int.class); diff --git a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java index a4ed232b6..4c4b8a534 100644 --- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java +++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java @@ -992,6 +992,15 @@ public class UDFs { ); } + @UDFAnnotations.ParamMeta(argNames = {"geometry"}) + public static byte[] ST_Points(byte[] geometry) { + return GeometrySerde.serialize( + Functions.points( + GeometrySerde.deserialize(geometry) + ) + ); + } + @UDFAnnotations.ParamMeta(argNames = {"geometry", "srid"}) public static byte[] ST_Polygon(byte[] geometry, int srid) { return GeometrySerde.serialize( diff --git a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java index 08bad21ec..583693c23 100644 --- a/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java +++ b/snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java @@ -808,6 +808,15 @@ public class UDFsV2 ); } + @UDFAnnotations.ParamMeta(argNames = {"geometry"}, argTypes = {"Geometry"}, returnTypes = "Geometry") + public static String ST_Points(String geometry) { + return GeometrySerde.serGeoJson( + Functions.points( + GeometrySerde.deserGeoJson(geometry) + ) + ); + } + @UDFAnnotations.ParamMeta(argNames = {"geometry", "srid"}, argTypes = {"Geometry", "int"}, returnTypes = "Geometry") public static String ST_Polygon(String geometry, int srid) { return GeometrySerde.serGeoJson( diff --git a/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala b/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala index a411f67b7..eacd30c0e 100644 --- a/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala +++ b/spark/common/src/main/scala/org/apache/sedona/sql/UDF/Catalog.scala @@ -54,6 +54,7 @@ object Catalog { function[ST_GeomFromKML](), function[ST_CoordDim](), function[ST_Point](), + function[ST_Points](), function[ST_MakePoint](null, null), function[ST_PointZ](0), function[ST_PointM](0), diff --git a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala index 21613b37c..e52b89809 100644 --- a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala +++ b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala @@ -786,6 +786,14 @@ case class ST_MakeLine(inputExpressions: Seq[Expression]) } } +case class ST_Points(inputExpressions: Seq[Expression]) + extends InferredExpression(Functions.points _) { + + protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = { + copy(inputExpressions = newChildren) + } +} + case class ST_Polygon(inputExpressions: Seq[Expression]) extends InferredExpression(Functions.makepolygonWithSRID _) { diff --git a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala index 65cec5a29..601f33f73 100644 --- a/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala +++ b/spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/st_functions.scala @@ -229,6 +229,9 @@ object st_functions extends DataFrameAPI { def ST_MakeLine(geom1: Column, geom2: Column): Column = wrapExpression[ST_MakeLine](geom1, geom2) def ST_MakeLine(geom1: String, geom2: String): Column = wrapExpression[ST_MakeLine](geom1, geom2) + def ST_Points(geom: Column): Column = wrapExpression[ST_Points](geom) + def ST_Points(geom: String): Column = wrapExpression[ST_Points](geom) + def ST_Polygon(lineString: Column, srid: Column): Column = wrapExpression[ST_Polygon](lineString, srid) def ST_Polygon(lineString: String, srid: Integer): Column = wrapExpression[ST_Polygon](lineString, srid) diff --git a/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala b/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala index 70e7201dd..1d37d89c0 100644 --- a/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala +++ b/spark/common/src/test/scala/org/apache/sedona/sql/dataFrameAPITestScala.scala @@ -514,6 +514,15 @@ class dataFrameAPITestScala extends TestBaseScala { assert(actualResult == expectedResult) } + it("Passed ST_Points") { + val invalidDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON ((0 0, 1 1, 5 1, 5 0, 1 0, 0 0))') AS geom") + val df = invalidDf.select(ST_Normalize(ST_Points("geom"))) + val actualResult = df.take(1)(0).get(0).asInstanceOf[Geometry] + actualResult.normalize() + val expectedResult = "MULTIPOINT ((0 0), (0 0), (1 0), (1 1), (5 0), (5 1))" + assert(actualResult.toText() == expectedResult) + } + it("Passed ST_Polygon") { val invalidDf = sparkSession.sql("SELECT ST_GeomFromWKT('LINESTRING (0 0, 1 0, 1 1, 0 0)') AS geom") val df = invalidDf.select(ST_Polygon("geom", 4236)) diff --git a/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala b/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala index 98f4975ea..9eb8d5704 100644 --- a/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala +++ b/spark/common/src/test/scala/org/apache/sedona/sql/functionTestScala.scala @@ -431,6 +431,18 @@ class functionTestScala extends TestBaseScala with Matchers with GeometrySample assert(row.get(1).asInstanceOf[Geometry].toText.equals("LINESTRING (5 6, 7 8, 9 10)")) } + it("Passed ST_Points") { + + val testtable = sparkSession.sql( + "SELECT ST_Points(ST_GeomFromText('MULTIPOLYGON (((0 0, 1 1, 1 0, 0 0)), ((2 2, 3 3, 3 2, 2 2)))'))" + ) + + val result = testtable.take(1)(0).get(0).asInstanceOf[Geometry] + + result.normalize() + assert(result.toText() == "MULTIPOINT ((0 0), (0 0), (1 0), (1 1), (2 2), (2 2), (3 2), (3 3))") + } + it("Passed ST_Polygon") { var testtable = sparkSession.sql(
