Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SEDONA-300] Add ST_HausdorffDistance #868

Merged
merged 46 commits into from
Jun 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
85ae113
Remove prebuild_index config from search plugin
iGN5117 Jun 6, 2023
8e829fe
Update compile the code documentation for sedona
iGN5117 Jun 6, 2023
4bcf99c
approximate float comparisons in python test cases
iGN5117 Jun 6, 2023
c7f6236
Update compile the code documentation for sedona
iGN5117 Jun 6, 2023
ceed7a4
Remove prebuild_index config from search plugin
iGN5117 Jun 6, 2023
15c6255
Revert "Update compile the code documentation for sedona"
iGN5117 Jun 7, 2023
471e281
Revert "Remove prebuild_index config from search plugin"
iGN5117 Jun 7, 2023
2a5a6d8
FIxed incorrect indentation
iGN5117 Jun 7, 2023
6e9883d
Addressed PR comments for documentation changes
iGN5117 Jun 7, 2023
e66895e
Merge branch 'master' of https://github.com/iGN5117/sedona into docum…
iGN5117 Jun 7, 2023
cf7e78d
Add ST_NumPoints
iGN5117 Jun 8, 2023
fc23fc9
Update available version to 1.4.1 in documentation
iGN5117 Jun 8, 2023
fea1daa
Merge branch 'apache:master' into develop_Nilesh_1.4.0
iGN5117 Jun 8, 2023
816e4ed
Fix failing scala test case
iGN5117 Jun 8, 2023
472c383
Merge branch 'develop_Nilesh_1.4.0' of https://github.com/iGN5117/sed…
iGN5117 Jun 8, 2023
471a87e
Updated documentation to include negative flow.
iGN5117 Jun 8, 2023
b33499d
Removed Spark SQL from flink documentation
iGN5117 Jun 8, 2023
0d68337
Add ST_Force3D to sedona
iGN5117 Jun 9, 2023
d1e4365
Merge branch 'sedona-master' into develop_Nilesh_1.4.0
iGN5117 Jun 9, 2023
da0314a
Updated force3D logic to handle empty geometries
iGN5117 Jun 9, 2023
020e9b9
Updated force3D dataframe test
iGN5117 Jun 10, 2023
86de054
fix error in test case
iGN5117 Jun 10, 2023
307c060
Updated documentation for Force3D to include Z format WKT in the outp…
iGN5117 Jun 11, 2023
dbab04c
Added default zValue test case in sedona flink
iGN5117 Jun 11, 2023
c0eb8bc
Added default zValue dataframe test case
iGN5117 Jun 11, 2023
479b264
Added default zValue scala test case
iGN5117 Jun 11, 2023
641d2d9
fix dataframe testcase
iGN5117 Jun 11, 2023
c2e27d8
Addressed PR comments
iGN5117 Jun 12, 2023
4fa254d
Merge branch 'develop_Nilesh_1.4.0' into documentation_update_Nilesh
iGN5117 Jun 12, 2023
9815161
Update community/develop to include steps to run python test cases.
iGN5117 Jun 12, 2023
5bdf476
Merge branch 'apache:master' into documentation_update_Nilesh
iGN5117 Jun 12, 2023
b5cf30c
Add ST_NRings
iGN5117 Jun 13, 2023
b89cec1
Add ST_Translate
iGN5117 Jun 13, 2023
b49d789
Merge branch 'develop_Nilesh_1.4.1_Translate' of https://github.com/i…
iGN5117 Jun 13, 2023
ece4802
Updated GeomUtils to remove redundant geom return type
iGN5117 Jun 14, 2023
78be0f1
Simplified ST_Translate implementation, updated test cases and docs
iGN5117 Jun 14, 2023
cd12ce2
Updated tests for Translate
iGN5117 Jun 15, 2023
19016ae
temp affine commit
iGN5117 Jun 19, 2023
959b35c
core logic implementation of BoundingDiagonal (without fits parameter)
iGN5117 Jun 19, 2023
00d0e48
Revert "temp affine commit"
iGN5117 Jun 20, 2023
0e23430
Implement BoundingDiagonal
iGN5117 Jun 20, 2023
e04f668
Merge branch 'sedona-master' into develop_Nilesh_1.4.1_BoundingDiagonal
iGN5117 Jun 20, 2023
f18099e
Add flink test case
iGN5117 Jun 20, 2023
ea6ea55
Reduce loops in ST_BoundingDiagonal
iGN5117 Jun 20, 2023
73e28c0
Add ST_HausdorffDistance
iGN5117 Jun 22, 2023
170a5d3
Merge branch 'master' into develop_Nilesh_1.4.1_HausdorffDistance
iGN5117 Jun 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add ST_NRings
  • Loading branch information
iGN5117 committed Jun 13, 2023
commit b5cf30cb9f5f475d685473465c237134a65be4e0
20 changes: 20 additions & 0 deletions common/src/main/java/org/apache/sedona/common/Functions.java
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,26 @@ public static Geometry force3D(Geometry geometry) {
return GeomUtils.get3DGeom(geometry, 0.0);
}

public static Integer nRings(Geometry geometry) throws Exception {
String geometryType = geometry.getGeometryType();
if (!(geometry instanceof Polygon || geometry instanceof MultiPolygon)) {
throw new IllegalArgumentException("Unsupported geometry type: " + geometryType + ", only Polygon or MultiPolygon geometries are supported.");
}
int numRings = 0;
if (geometry instanceof Polygon) {
Polygon polygon = (Polygon) geometry;
numRings = GeomUtils.getPolygonNumRings(polygon);
}else {
MultiPolygon multiPolygon = (MultiPolygon) geometry;
int numPolygons = multiPolygon.getNumGeometries();
for (int i = 0; i < numPolygons; i++) {
Polygon polygon = (Polygon) multiPolygon.getGeometryN(i);
numRings += GeomUtils.getPolygonNumRings(polygon);
}
}
return numRings;
}

public static Geometry geometricMedian(Geometry geometry, double tolerance, int maxIter, boolean failIfNotConverged) throws Exception {
String geometryType = geometry.getGeometryType();
if(!(Geometry.TYPENAME_POINT.equals(geometryType) || Geometry.TYPENAME_MULTIPOINT.equals(geometryType))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,4 +433,13 @@ public static Geometry get3DGeom(Geometry geometry, double zValue) {
geometry.geometryChanged();
return geometry;
}

public static int getPolygonNumRings(Polygon polygon) {
LinearRing shell = polygon.getExteriorRing();
if (shell == null || shell.isEmpty()) {
return 0;
}else {
return 1 + polygon.getNumInteriorRing();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;

import javax.sound.sampled.Line;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
Expand Down Expand Up @@ -648,4 +649,86 @@ public void force3DEmptyObjectDefaultValue() {
assertEquals(emptyLine.isEmpty(), forcedEmptyLine.isEmpty());
}

@Test
public void nRingsPolygonOnlyExternal() throws Exception {
Polygon polygon = GEOMETRY_FACTORY.createPolygon(coordArray(1, 0, 1, 1, 2, 1, 2, 0, 1, 0));
Integer expected = 1;
Integer actual = Functions.nRings(polygon);
assertEquals(expected, actual);
}

@Test
public void nRingsPolygonWithHoles() throws Exception {
LinearRing shell = GEOMETRY_FACTORY.createLinearRing(coordArray(1, 0, 1, 6, 6, 6, 6, 0, 1, 0));
LinearRing[] holes = new LinearRing[] {GEOMETRY_FACTORY.createLinearRing(coordArray(2, 1, 2, 2, 3, 2, 3, 1, 2, 1)),
GEOMETRY_FACTORY.createLinearRing(coordArray(4, 1, 4, 2, 5, 2, 5, 1, 4, 1))};
Polygon polygonWithHoles = GEOMETRY_FACTORY.createPolygon(shell, holes);
Integer expected = 3;
Integer actual = Functions.nRings(polygonWithHoles);
assertEquals(expected, actual);
}

@Test public void nRingsPolygonEmpty() throws Exception {
Polygon emptyPolygon = GEOMETRY_FACTORY.createPolygon();
Integer expected = 0;
Integer actual = Functions.nRings(emptyPolygon);
assertEquals(expected, actual);
}

@Test
public void nRingsMultiPolygonOnlyExternal() throws Exception {
MultiPolygon multiPolygon = GEOMETRY_FACTORY.createMultiPolygon(new Polygon[] {GEOMETRY_FACTORY.createPolygon(coordArray(1, 0, 1, 1, 2, 1, 2, 0, 1, 0)),
GEOMETRY_FACTORY.createPolygon(coordArray(5, 0, 5, 1, 7, 1, 7, 0, 5, 0))});
Integer expected = 2;
Integer actual = Functions.nRings(multiPolygon);
assertEquals(expected, actual);
}

@Test
public void nRingsMultiPolygonOnlyWithHoles() throws Exception {
LinearRing shell1 = GEOMETRY_FACTORY.createLinearRing(coordArray(1, 0, 1, 6, 6, 6, 6, 0, 1, 0));
LinearRing[] holes1 = new LinearRing[] {GEOMETRY_FACTORY.createLinearRing(coordArray(2, 1, 2, 2, 3, 2, 3, 1, 2, 1)),
GEOMETRY_FACTORY.createLinearRing(coordArray(4, 1, 4, 2, 5, 2, 5, 1, 4, 1))};
Polygon polygonWithHoles1 = GEOMETRY_FACTORY.createPolygon(shell1, holes1);
LinearRing shell2 = GEOMETRY_FACTORY.createLinearRing(coordArray(10, 0, 10, 6, 16, 6, 16, 0, 10, 0));
LinearRing[] holes2 = new LinearRing[] {GEOMETRY_FACTORY.createLinearRing(coordArray(12, 1, 12, 2, 13, 2, 13, 1, 12, 1)),
GEOMETRY_FACTORY.createLinearRing(coordArray(14, 1, 14, 2, 15, 2, 15, 1, 14, 1))};
Polygon polygonWithHoles2 = GEOMETRY_FACTORY.createPolygon(shell2, holes2);
MultiPolygon multiPolygon = GEOMETRY_FACTORY.createMultiPolygon(new Polygon[]{polygonWithHoles1, polygonWithHoles2});
Integer expected = 6;
Integer actual = Functions.nRings(multiPolygon);
assertEquals(expected, actual);
}

@Test
public void nRingsMultiPolygonEmpty() throws Exception {
MultiPolygon multiPolygon = GEOMETRY_FACTORY.createMultiPolygon(new Polygon[] {GEOMETRY_FACTORY.createPolygon(),
GEOMETRY_FACTORY.createPolygon()});
Integer expected = 0;
Integer actual = Functions.nRings(multiPolygon);
assertEquals(expected, actual);
}

@Test
public void nRingsMultiPolygonMixed() throws Exception {
Polygon polygon = GEOMETRY_FACTORY.createPolygon(coordArray(1, 0, 1, 1, 2, 1, 2, 0, 1, 0));
LinearRing shell = GEOMETRY_FACTORY.createLinearRing(coordArray(1, 0, 1, 6, 6, 6, 6, 0, 1, 0));
LinearRing[] holes = new LinearRing[] {GEOMETRY_FACTORY.createLinearRing(coordArray(2, 1, 2, 2, 3, 2, 3, 1, 2, 1)),
GEOMETRY_FACTORY.createLinearRing(coordArray(4, 1, 4, 2, 5, 2, 5, 1, 4, 1))};
Polygon polygonWithHoles = GEOMETRY_FACTORY.createPolygon(shell, holes);
Polygon emptyPolygon = GEOMETRY_FACTORY.createPolygon();
MultiPolygon multiPolygon = GEOMETRY_FACTORY.createMultiPolygon(new Polygon[] {polygon, polygonWithHoles, emptyPolygon});
Integer expected = 4;
Integer actual = Functions.nRings(multiPolygon);
assertEquals(expected, actual);
}

@Test
public void nRingsUnsupported() {
LineString lineString = GEOMETRY_FACTORY.createLineString(coordArray3d(0, 1, 1, 1, 2, 1, 1, 2, 2));
String expected = "Unsupported geometry type: " + "LineString" + ", only Polygon or MultiPolygon geometries are supported.";
Exception e = assertThrows(IllegalArgumentException.class, () -> Functions.nRings(lineString));
assertEquals(expected, e.getMessage());
}

}
39 changes: 36 additions & 3 deletions docs/api/flink/Function.md
Original file line number Diff line number Diff line change
Expand Up @@ -703,14 +703,47 @@ SELECT ST_NDims(ST_GeomFromEWKT('POINT(1 1 2)'))

Output: `3`

Spark SQL example with x,y coordinate:
Example with x,y coordinate:

```sql
SELECT ST_NDims(ST_GeomFromText('POINT(1 1)'))
```

Output: `2`

## ST_NRings

Introduction: Returns the number of rings in a Polygon or MultiPolygon. Contrary to ST_NumInteriorRings,
this function also takes into account the number of exterior rings.

This function returns 0 for an empty Polygon or MultiPolygon.
If the geometry is not a Polygon or MultiPolygon, an IllegalArgument Exception is thrown.

Format: `ST_NRings(geom: geometry)`

Since: `1.4.1`


Examples:

Input: `POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))`

Output: `1`

Input: `'MULTIPOLYGON (((1 0, 1 6, 6 6, 6 0, 1 0), (2 1, 2 2, 3 2, 3 1, 2 1)), ((10 0, 10 6, 16 6, 16 0, 10 0), (12 1, 12 2, 13 2, 13 1, 12 1)))'`

Output: `4`

Input: `'POLYGON EMPTY'`

Output: `0`

Input: `'LINESTRING (1 0, 1 1, 2 1)'`

Output: `Unsupported geometry type: LineString, only Polygon or MultiPolygon geometries are supported.`



## ST_NumGeometries

Introduction: Returns the number of Geometries. If geometry is a GEOMETRYCOLLECTION (or MULTI*) return the number of geometries, for single geometries will return 1.
Expand Down Expand Up @@ -945,13 +978,13 @@ Format: `ST_Transform (A:geometry, SourceCRS:string, TargetCRS:string ,[Optional

Since: `v1.2.0`

Spark SQL example (simple):
Example (simple):
```sql
SELECT ST_Transform(polygondf.countyshape, 'epsg:4326','epsg:3857')
FROM polygondf
```

Spark SQL example (with optional parameters):
Example (with optional parameters):
```sql
SELECT ST_Transform(polygondf.countyshape, 'epsg:4326','epsg:3857', false)
FROM polygondf
Expand Down
31 changes: 31 additions & 0 deletions docs/api/sql/Function.md
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,37 @@ SELECT ST_NPoints(polygondf.countyshape)
FROM polygondf
```

## ST_NRings

Introduction: Returns the number of rings in a Polygon or MultiPolygon. Contrary to ST_NumInteriorRings,
this function also takes into account the number of exterior rings.

This function returns 0 for an empty Polygon or MultiPolygon.
If the geometry is not a Polygon or MultiPolygon, an IllegalArgument Exception is thrown.

Format: `ST_NRings(geom: geometry)`

Since: `1.4.1`


Examples:

Input: `POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))`

Output: `1`

Input: `'MULTIPOLYGON (((1 0, 1 6, 6 6, 6 0, 1 0), (2 1, 2 2, 3 2, 3 1, 2 1)), ((10 0, 10 6, 16 6, 16 0, 10 0), (12 1, 12 2, 13 2, 13 1, 12 1)))'`

Output: `4`

Input: `'POLYGON EMPTY'`

Output: `0`

Input: `'LINESTRING (1 0, 1 1, 2 1)'`

Output: `Unsupported geometry type: LineString, only Polygon or MultiPolygon geometries are supported.`

## ST_NumGeometries

Introduction: Returns the number of Geometries. If geometry is a GEOMETRYCOLLECTION (or MULTI*) return the number of geometries, for single geometries will return 1.
Expand Down
3 changes: 2 additions & 1 deletion flink/src/main/java/org/apache/sedona/flink/Catalog.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ public static UserDefinedFunction[] getFuncs() {
new Functions.ST_S2CellIDs(),
new Functions.ST_GeometricMedian(),
new Functions.ST_NumPoints(),
new Functions.ST_Force3D()
new Functions.ST_Force3D(),
new Functions.ST_NRings()
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -599,4 +599,12 @@ public Geometry eval(@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.j
}
}

public static class ST_NRings extends ScalarFunction {
@DataTypeHint(value = "Integer")
public int eval(@DataTypeHint(value = "RAW", bridgedTo = org.locationtech.jts.geom.Geometry.class) Object o) throws Exception {
Geometry geom = (Geometry) o;
return org.apache.sedona.common.Functions.nRings(geom);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -719,4 +719,12 @@ public void testForce3DDefaultValue() {
assertEquals(expectedDims, actual);
}

@Test
public void testNRings() {
Integer expected = 1;
Table pointTable = tableEnv.sqlQuery("SELECT ST_NRings(ST_GeomFromWKT('POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))'))");
Integer actual = (Integer) first(pointTable).getField(0);
assertEquals(expected, actual);
}

}
11 changes: 10 additions & 1 deletion python/sedona/sql/st_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@
"ST_ZMax",
"ST_ZMin",
"ST_NumPoints",
"ST_Force3D"
"ST_Force3D",
"ST_NRings"
]


Expand Down Expand Up @@ -1253,3 +1254,11 @@ def ST_Force3D(geometry: ColumnOrName, zValue: Optional[Union[ColumnOrName, floa
"""
args = (geometry, zValue)
return _call_st_function("ST_Force3D", args)

def ST_NRings(geometry: ColumnOrName) -> Column:
"""
Returns the total number of rings in a Polygon or MultiPolygon. Compared to ST_NumInteriorRings, ST_NRings takes exterior rings into account as well.
:param geometry: Geometry column to calculate rings for
:return: Number of exterior rings + interior rings (if any) for the given Polygon or MultiPolygon
"""
return _call_st_function("ST_NRings", geometry)
4 changes: 3 additions & 1 deletion python/tests/sql/test_dataframe_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
(stf.ST_Multi, ("point",), "point_geom", "", "MULTIPOINT (0 1)"),
(stf.ST_Normalize, ("geom",), "triangle_geom", "", "POLYGON ((0 0, 1 1, 1 0, 0 0))"),
(stf.ST_NPoints, ("line",), "linestring_geom", "", 6),
(stf.ST_NRings, ("geom",), "square_geom", "", 1),
(stf.ST_NumGeometries, ("geom",), "multipoint", "", 2),
(stf.ST_NumInteriorRings, ("geom",), "geom_with_hole", "", 1),
(stf.ST_NumPoints, ("line",), "linestring_geom", "", 6),
Expand Down Expand Up @@ -137,7 +138,6 @@
(stf.ST_YMax, ("geom",), "triangle_geom", "", 1.0),
(stf.ST_YMin, ("geom",), "triangle_geom", "", 0.0),
(stf.ST_Z, ("b",), "two_points", "", 4.0),
(stf.ST_NumPoints, ("line",), "linestring_geom", "", 6),

# predicates
(stp.ST_Contains, ("geom", lambda: f.expr("ST_Point(0.5, 0.25)")), "triangle_geom", "", True),
Expand Down Expand Up @@ -387,6 +387,8 @@ def base_df(self, request):
return TestDataFrameAPI.spark.sql("SELECT ST_GeomFromWKT('POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))') AS a, ST_GeomFromWKT('POLYGON ((1 0, 2 0, 2 1, 1 1, 1 0))') AS b")
elif request.param == "line_crossing_poly":
return TestDataFrameAPI.spark.sql("SELECT ST_GeomFromWKT('LINESTRING (0 0, 2 1)') AS line, ST_GeomFromWKT('POLYGON ((1 0, 2 0, 2 2, 1 2, 1 0))') AS poly")
elif request.param == "square_geom":
return TestDataFrameAPI.spark.sql("SELECT ST_GeomFromWKT('POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))') AS geom")
raise ValueError(f"Invalid base_df name passed: {request.param}")

def _id_test_configuration(val):
Expand Down
6 changes: 6 additions & 0 deletions python/tests/sql/test_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -1086,3 +1086,9 @@ def test_force3D(self):
actual = actualDf.selectExpr("ST_NDims(geom)").take(1)[0][0]
assert expected == actual

def test_nRings(self):
expected = 1
actualDf = self.spark.sql("SELECT ST_GeomFromText('POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))') AS geom")
actual = actualDf.selectExpr("ST_NRings(geom)").take(1)[0][0]
assert expected == actual

Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ object Catalog {
function[ST_LengthSpheroid](),
function[ST_NumPoints](),
function[ST_Force3D](0.0),
function[ST_NRings](),
// Expression for rasters
function[RS_NormalizedDifference](),
function[RS_Mean](),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -996,3 +996,10 @@ case class ST_Force3D(inputExpressions: Seq[Expression])
}
}

case class ST_NRings(inputExpressions: Seq[Expression])
extends InferredUnaryExpression(Functions.nRings) with FoldableExpression {
protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = {
copy(inputExpressions = newChildren)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -313,4 +313,8 @@ object st_functions extends DataFrameAPI {
def ST_Force3D(geometry: Column, zValue: Column): Column = wrapExpression[ST_Force3D](geometry, zValue)

def ST_Force3D(geometry: String, zValue: Double): Column = wrapExpression[ST_Force3D](geometry, zValue)

def ST_NRings(geometry: Column): Column = wrapExpression[ST_NRings](geometry)

def ST_NRings(geometry: String): Column = wrapExpression[ST_NRings](geometry)
}
Original file line number Diff line number Diff line change
Expand Up @@ -970,5 +970,13 @@ class dataFrameAPITestScala extends TestBaseScala {
val actualGeomDefaultValue = lineDfDefaultValue.select(ST_Force3D("geom")).take(1)(0).get(0).asInstanceOf[Geometry]
assertEquals(expectedGeomDefaultValue, wktWriter.write(actualGeomDefaultValue))
}

it("Passed ST_NRings") {
val polyDf = sparkSession.sql("SELECT ST_GeomFromWKT('POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))') AS geom")
val expected = 1
val df = polyDf.select(ST_NRings("geom"))
val actual = df.take(1)(0).getInt(0)
assert(expected == actual)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1940,4 +1940,18 @@ class functionTestScala extends TestBaseScala with Matchers with GeometrySample
assertEquals(expectedDefaultValue, actualDefaultValue);
}
}

it("should pass ST_NRings") {
val geomTestCases = Map(
("'POLYGON ((1 0, 1 1, 2 1, 2 0, 1 0))'") -> 1,
("'MULTIPOLYGON (((1 0, 1 6, 6 6, 6 0, 1 0), (2 1, 2 2, 3 2, 3 1, 2 1)), ((10 0, 10 6, 16 6, 16 0, 10 0), (12 1, 12 2, 13 2, 13 1, 12 1)))'") -> 4,
("'POLYGON EMPTY'") -> 0
)
for (((geom), expectedResult) <- geomTestCases) {
val df = sparkSession.sql(s"SELECT ST_NRings(ST_GeomFromWKT($geom)), " + s"$expectedResult")
val actual = df.take(1)(0).get(0).asInstanceOf[Int]
val expected = df.take(1)(0).get(1).asInstanceOf[java.lang.Integer].intValue()
assertEquals(expected, actual)
}
}
}