Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,10 @@ public static int nPoints(Geometry geometry) {
public static int nDims(Geometry geometry) {
int count_dimension = 0;
Coordinate geom = geometry.getCoordinate();
if (geom == null) {
// Empty geometries have no coordinate to inspect; report them as 2D like PostGIS does.
return 2;
}
Double x_cord = geom.getX();
Double y_cord = geom.getY();
Double z_cord = geom.getZ();
Expand Down Expand Up @@ -1300,6 +1304,10 @@ public static Geometry delaunayTriangle(Geometry geometry, double tolerance, int

public static int zmFlag(Geometry geom) {
Coordinate coords = geom.getCoordinate();
if (coords == null) {
// Empty geometries have no coordinate to inspect; report them as 2D like PostGIS does.
return 0;
}
boolean hasZ = !Double.isNaN(coords.getZ());
boolean hasM = !Double.isNaN(coords.getM());
if (hasM && hasZ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2819,6 +2819,34 @@ public void simplifyPolygonHull() throws ParseException {
});
}

@Test
public void nDims() throws ParseException {
assertEquals(2, Functions.nDims(Constructors.geomFromWKT("POINT (1 2)", 0)));
assertEquals(3, Functions.nDims(Constructors.geomFromWKT("LINESTRING (1 2 3, 4 5 6)", 0)));
assertEquals(
3,
Functions.nDims(Constructors.geomFromWKT("POLYGON M ((1 2 3, 3 4 3, 5 6 3, 1 2 3))", 0)));
assertEquals(4, Functions.nDims(Constructors.geomFromWKT("POINT ZM (1 2 3 4)", 0)));
}

@Test
public void nDimsEmptyGeometries() throws ParseException {
String[] emptyWkts = {
"POINT EMPTY",
"LINESTRING EMPTY",
"POLYGON EMPTY",
"MULTIPOINT EMPTY",
"MULTILINESTRING EMPTY",
"MULTIPOLYGON EMPTY",
"GEOMETRYCOLLECTION EMPTY"
};
for (String wkt : emptyWkts) {
assertEquals(wkt, 2, Functions.nDims(Constructors.geomFromWKT(wkt, 0)));
}
assertEquals(2, Functions.nDims(GEOMETRY_FACTORY.createPoint()));
assertEquals(2, Functions.nDims(GEOMETRY_FACTORY.createGeometryCollection()));
}

@Test
public void force3DObject2D() {
int expectedDims = 3;
Expand Down Expand Up @@ -4852,6 +4880,24 @@ public void testZmFlag() throws ParseException {
assertEquals(_4D, Functions.zmFlag(geom));
}

@Test
public void testZmFlagEmptyGeometries() throws ParseException {
String[] emptyWkts = {
"POINT EMPTY",
"LINESTRING EMPTY",
"POLYGON EMPTY",
"MULTIPOINT EMPTY",
"MULTILINESTRING EMPTY",
"MULTIPOLYGON EMPTY",
"GEOMETRYCOLLECTION EMPTY"
};
for (String wkt : emptyWkts) {
assertEquals(wkt, 0, Functions.zmFlag(Constructors.geomFromWKT(wkt, 0)));
}
assertEquals(0, Functions.zmFlag(GEOMETRY_FACTORY.createPoint()));
assertEquals(0, Functions.zmFlag(GEOMETRY_FACTORY.createGeometryCollection()));
}

@Test
public void hausdorffDistanceDefaultGeom2D() throws Exception {
Polygon polygon1 =
Expand Down
14 changes: 13 additions & 1 deletion docs/api/sql/Geometry-Accessors/ST_CoordDim.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

# ST_CoordDim

Introduction: Returns the coordinate dimensions of the geometry. It is an alias of `ST_NDims`.
Introduction: Returns the coordinate dimensions of the geometry. It is an alias of `ST_NDims`. Empty geometries return 2.

![ST_CoordDim](../../../image/ST_CoordDim/ST_CoordDim.svg "ST_CoordDim")

Expand Down Expand Up @@ -52,3 +52,15 @@ Output:
```
2
```

Spark SQL Example with an empty geometry:

```sql
SELECT ST_CoordDim(ST_GeomFromWKT('LINESTRING EMPTY'))
```

Output:

```
2
```
14 changes: 13 additions & 1 deletion docs/api/sql/Geometry-Accessors/ST_NDims.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

# ST_NDims

Introduction: Returns the coordinate dimension of the geometry.
Introduction: Returns the coordinate dimension of the geometry. Empty geometries return 2.

![ST_NDims](../../../image/ST_NDims/ST_NDims.svg "ST_NDims")

Expand Down Expand Up @@ -52,3 +52,15 @@ Output:
```
2
```

Spark SQL example with an empty geometry:

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

Output:

```
2
```
16 changes: 15 additions & 1 deletion docs/api/sql/Geometry-Accessors/ST_Zmflag.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

Introduction: Returns a code indicating the Z and M coordinate dimensions present in the input geometry.

Values are: 0 = 2D, 1 = 3D-M, 2 = 3D-Z, 3 = 4D.
Values are: 0 = 2D, 1 = 3D-M, 2 = 3D-Z, 3 = 4D. Empty geometries return 0.

![ST_Zmflag](../../../image/ST_Zmflag/ST_Zmflag.svg "ST_Zmflag")

Expand Down Expand Up @@ -58,3 +58,17 @@ Output:
```
3
```

SQL Example

```sql
SELECT ST_Zmflag(
ST_GeomFromWKT('POLYGON EMPTY')
)
```

Output:

```
0
```
4 changes: 4 additions & 0 deletions docs/setup/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@

### Bug Fixes

#### Sedona SQL

* [<a href='https://github.com/apache/sedona/issues/3359'>GH-3359</a>] - Return 2D results from `ST_NDims`, `ST_CoordDim` and `ST_Zmflag` for empty geometries instead of throwing

#### GeoPandas API

* [<a href='https://github.com/apache/sedona/issues/3269'>GH-3269</a>] - Warn when `geom_equals` or `geom_equals_exact` compares geometry operands with mismatched CRSs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,16 @@ class functionTestScala
assert(test.take(1)(0).get(0).asInstanceOf[Int] == 4)
}

it("Passed ST_NDims and ST_CoordDim with empty geometries") {
Seq("POINT EMPTY", "LINESTRING EMPTY", "POLYGON EMPTY", "GEOMETRYCOLLECTION EMPTY")
.foreach { wkt =>
val test = sparkSession.sql(
s"SELECT ST_NDims(ST_GeomFromWKT('$wkt')), ST_CoordDim(ST_GeomFromWKT('$wkt'))")
assert(test.first().getInt(0) == 2)
assert(test.first().getInt(1) == 2)
}
}

it("Passed ST_GeometryType") {
var test = sparkSession.sql(
"SELECT ST_GeometryType(ST_GeomFromText('LINESTRING(77.29 29.07,77.42 29.26,77.27 29.31,77.29 29.07)'))")
Expand Down Expand Up @@ -1506,6 +1516,15 @@ class functionTestScala
assert(actual == 3)
}

it("Passed ST_Zmflag with empty geometries") {
Seq("POINT EMPTY", "LINESTRING EMPTY", "POLYGON EMPTY", "GEOMETRYCOLLECTION EMPTY")
.foreach { wkt =>
val actual =
sparkSession.sql(s"SELECT ST_Zmflag(ST_GeomFromWKT('$wkt'))").first().get(0)
assert(actual == 0)
}
}

it("Should pass ST_StartPoint function") {
Given("Polygon Data Frame, Point DataFrame, LineString Data Frame")

Expand Down
Loading