Skip to content

Commit ee5c897

Browse files
authored
[GH-2720][GH-2721][GH-2722][GH-2723] Fix geometry function bugs (#2730)
1 parent 79b1512 commit ee5c897

11 files changed

Lines changed: 61 additions & 52 deletions

File tree

common/src/main/java/org/apache/sedona/common/Functions.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
import org.locationtech.jts.simplify.TopologyPreservingSimplifier;
7171
import org.locationtech.jts.simplify.VWSimplifier;
7272
import org.locationtech.jts.triangulate.DelaunayTriangulationBuilder;
73+
import org.locationtech.jts.triangulate.VoronoiDiagramBuilder;
7374
import org.locationtech.jts.triangulate.polygon.ConstrainedDelaunayTriangulator;
7475
import org.slf4j.Logger;
7576
import org.slf4j.LoggerFactory;
@@ -1153,6 +1154,23 @@ public static int zmFlag(Geometry geom) {
11531154
return 0;
11541155
}
11551156

1157+
public static Geometry voronoiPolygons(Geometry geom, double tolerance, Geometry extendTo) {
1158+
if (geom == null) {
1159+
return null;
1160+
}
1161+
VoronoiDiagramBuilder builder = new VoronoiDiagramBuilder();
1162+
builder.setSites(geom);
1163+
builder.setTolerance(tolerance);
1164+
if (extendTo != null) {
1165+
builder.setClipEnvelope(extendTo.getEnvelopeInternal());
1166+
} else {
1167+
Envelope e = geom.getEnvelopeInternal();
1168+
e.expandBy(Math.max(e.getWidth(), e.getHeight()));
1169+
builder.setClipEnvelope(e);
1170+
}
1171+
return builder.getDiagram(geom.getFactory());
1172+
}
1173+
11561174
public static Geometry concaveHull(Geometry geometry, double pctConvex, boolean allowHoles) {
11571175
ConcaveHull concave_hull = new ConcaveHull(geometry);
11581176
concave_hull.setMaximumEdgeLengthRatio(pctConvex);
@@ -2478,7 +2496,7 @@ public static Geometry geometricMedian(Geometry geometry) throws Exception {
24782496
return geometricMedian(geometry, DEFAULT_TOLERANCE, DEFAULT_MAX_ITER, false);
24792497
}
24802498

2481-
public static double frechetDistance(Geometry g1, Geometry g2) {
2499+
public static Double frechetDistance(Geometry g1, Geometry g2) {
24822500
return GeomUtils.getFrechetDistance(g1, g2);
24832501
}
24842502

common/src/main/java/org/apache/sedona/common/FunctionsGeoTools.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,9 @@
2929
import org.geotools.referencing.CRS;
3030
import org.geotools.referencing.ReferencingFactoryFinder;
3131
import org.geotools.util.factory.Hints;
32-
import org.locationtech.jts.geom.Envelope;
3332
import org.locationtech.jts.geom.Geometry;
3433
import org.locationtech.jts.operation.buffer.BufferOp;
3534
import org.locationtech.jts.operation.buffer.BufferParameters;
36-
import org.locationtech.jts.triangulate.VoronoiDiagramBuilder;
3735

3836
public class FunctionsGeoTools {
3937

@@ -174,23 +172,6 @@ private static CoordinateReferenceSystem parseCRSString(String CRSString)
174172
}
175173
}
176174

177-
public static Geometry voronoiPolygons(Geometry geom, double tolerance, Geometry extendTo) {
178-
if (geom == null) {
179-
return null;
180-
}
181-
VoronoiDiagramBuilder builder = new VoronoiDiagramBuilder();
182-
builder.setSites(geom);
183-
builder.setTolerance(tolerance);
184-
if (extendTo != null) {
185-
builder.setClipEnvelope(extendTo.getEnvelopeInternal());
186-
} else {
187-
Envelope e = geom.getEnvelopeInternal();
188-
e.expandBy(Math.max(e.getWidth(), e.getHeight()));
189-
builder.setClipEnvelope(e);
190-
}
191-
return builder.getDiagram(geom.getFactory());
192-
}
193-
194175
public static Geometry bufferSpheroid(Geometry geometry, double radius, BufferParameters params)
195176
throws IllegalArgumentException {
196177
// Determine the best SRID for spheroidal calculations

common/src/main/java/org/apache/sedona/common/Predicates.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static boolean touches(Geometry leftGeometry, Geometry rightGeometry) {
5656
}
5757

5858
public static boolean equals(Geometry leftGeometry, Geometry rightGeometry) {
59-
return leftGeometry.symDifference(rightGeometry).isEmpty();
59+
return leftGeometry.equalsTopo(rightGeometry);
6060
}
6161

6262
public static boolean disjoint(Geometry leftGeometry, Geometry rightGeometry) {

common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -542,13 +542,13 @@ public static void affineGeom(
542542
geometry.geometryChanged();
543543
}
544544

545-
public static double getFrechetDistance(Geometry g1, Geometry g2) {
546-
if (g1.isEmpty() || g2.isEmpty()) return 0.0;
545+
public static Double getFrechetDistance(Geometry g1, Geometry g2) {
546+
if (g1.isEmpty() || g2.isEmpty()) return null;
547547
return DiscreteFrechetDistance.distance(g1, g2);
548548
}
549549

550550
public static Double getHausdorffDistance(Geometry g1, Geometry g2, double densityFrac) {
551-
if (g1.isEmpty() || g2.isEmpty()) return 0.0;
551+
if (g1.isEmpty() || g2.isEmpty()) return null;
552552
DiscreteHausdorffDistance hausdorffDistanceObj = new DiscreteHausdorffDistance(g1, g2);
553553
if (densityFrac != -1) {
554554
hausdorffDistanceObj.setDensifyFraction(densityFrac);

common/src/test/java/org/apache/sedona/common/FunctionsTest.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3564,9 +3564,8 @@ public void testFrechetGeomCollection() {
35643564
public void testFrechetGeomEmpty() {
35653565
Polygon p1 = GEOMETRY_FACTORY.createPolygon(coordArray(1, 0, 1, 1, 2, 1, 2, 0, 1, 0));
35663566
LineString emptyPoint = GEOMETRY_FACTORY.createLineString();
3567-
double expected = 0.0;
3568-
double actual = Functions.frechetDistance(p1, emptyPoint);
3569-
assertEquals(expected, actual, 1e-9);
3567+
Double actual = Functions.frechetDistance(p1, emptyPoint);
3568+
assertNull(actual);
35703569
}
35713570

35723571
@Test
@@ -4278,18 +4277,16 @@ public void hausdorffDistanceGeomCollection() throws Exception {
42784277
public void hausdorffDistanceEmptyGeom() throws Exception {
42794278
Polygon polygon = GEOMETRY_FACTORY.createPolygon(coordArray(1, 2, 2, 1, 2, 0, 4, 1, 1, 2));
42804279
LineString emptyLineString = GEOMETRY_FACTORY.createLineString();
4281-
Double expected = 0.0;
42824280
Double actual = Functions.hausdorffDistance(polygon, emptyLineString, 0.00001);
4283-
assertEquals(expected, actual);
4281+
assertNull(actual);
42844282
}
42854283

42864284
@Test
42874285
public void hausdorffDistanceDefaultEmptyGeom() throws Exception {
42884286
Polygon polygon = GEOMETRY_FACTORY.createPolygon(coordArray(1, 2, 2, 1, 2, 0, 4, 1, 1, 2));
42894287
LineString emptyLineString = GEOMETRY_FACTORY.createLineString();
4290-
Double expected = 0.0;
42914288
Double actual = Functions.hausdorffDistance(polygon, emptyLineString);
4292-
assertEquals(expected, actual);
4289+
assertNull(actual);
42934290
}
42944291

42954292
@Test
@@ -4367,26 +4364,26 @@ public void testAddMeasure() throws ParseException {
43674364
@Test
43684365
public void voronoiPolygons() {
43694366
MultiPoint multiPoint = GEOMETRY_FACTORY.createMultiPointFromCoords(coordArray(0, 0, 2, 2));
4370-
Geometry actual1 = FunctionsGeoTools.voronoiPolygons(multiPoint, 0, null);
4367+
Geometry actual1 = Functions.voronoiPolygons(multiPoint, 0, null);
43714368
assertGeometryEquals(
43724369
"GEOMETRYCOLLECTION (POLYGON ((-2 -2, -2 4, 4 -2, -2 -2)), POLYGON ((-2 4, 4 4, 4 -2, -2 4)))",
43734370
actual1.toText());
43744371

4375-
Geometry actual2 = FunctionsGeoTools.voronoiPolygons(multiPoint, 30, null);
4372+
Geometry actual2 = Functions.voronoiPolygons(multiPoint, 30, null);
43764373
assertGeometryEquals(
43774374
"GEOMETRYCOLLECTION (POLYGON ((-2 -2, -2 4, 4 4, 4 -2, -2 -2)))", actual2.toText());
43784375

43794376
Geometry buf = Functions.buffer(GEOMETRY_FACTORY.createPoint(new Coordinate(1, 1)), 10);
4380-
Geometry actual3 = FunctionsGeoTools.voronoiPolygons(multiPoint, 0, buf);
4377+
Geometry actual3 = Functions.voronoiPolygons(multiPoint, 0, buf);
43814378
assertGeometryEquals(
43824379
"GEOMETRYCOLLECTION (POLYGON ((-9 -9, -9 11, 11 -9, -9 -9)), POLYGON ((-9 11, 11 11, 11 -9, -9 11)))",
43834380
actual3.toText());
43844381

4385-
Geometry actual4 = FunctionsGeoTools.voronoiPolygons(multiPoint, 30, buf);
4382+
Geometry actual4 = Functions.voronoiPolygons(multiPoint, 30, buf);
43864383
assertGeometryEquals(
43874384
"GEOMETRYCOLLECTION (POLYGON ((-9 -9, -9 11, 11 11, 11 -9, -9 -9)))", actual4.toText());
43884385

4389-
Geometry actual5 = FunctionsGeoTools.voronoiPolygons(null, 0, null);
4386+
Geometry actual5 = Functions.voronoiPolygons(null, 0, null);
43904387
assertEquals(null, actual5);
43914388
}
43924389

common/src/test/java/org/apache/sedona/common/PredicatesTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ public void testRelateString() throws ParseException {
9292
assertEquals("1010F0212", actual);
9393
}
9494

95+
@Test
96+
public void testEqualsGeometryCollection() throws ParseException {
97+
Geometry gc1 = geomFromEWKT("GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0, 1 1))");
98+
Geometry gc2 = geomFromEWKT("GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0, 1 1))");
99+
assertTrue(Predicates.equals(gc1, gc2));
100+
101+
Geometry gc3 = geomFromEWKT("GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0, 2 2))");
102+
assertFalse(Predicates.equals(gc1, gc3));
103+
}
104+
95105
@Test
96106
public void testRelateBoolean() throws ParseException {
97107
Geometry geom1 = geomFromEWKT("POINT(1 2)");

flink/src/main/java/org/apache/sedona/flink/expressions/Functions.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import org.apache.flink.table.annotation.DataTypeHint;
2424
import org.apache.flink.table.annotation.InputGroup;
2525
import org.apache.flink.table.functions.ScalarFunction;
26-
import org.apache.sedona.common.FunctionsGeoTools;
2726
import org.apache.sedona.flink.GeometryArrayTypeSerializer;
2827
import org.apache.sedona.flink.GeometryTypeSerializer;
2928
import org.geotools.api.referencing.FactoryException;
@@ -3039,7 +3038,7 @@ public Geometry eval(
30393038
Object extend) {
30403039
Geometry geom = (Geometry) o;
30413040
Geometry extendTo = (Geometry) extend;
3042-
return FunctionsGeoTools.voronoiPolygons(geom, tolerance, extendTo);
3041+
return org.apache.sedona.common.Functions.voronoiPolygons(geom, tolerance, extendTo);
30433042
}
30443043

30453044
@DataTypeHint(
@@ -3054,7 +3053,7 @@ public Geometry eval(
30543053
Object o,
30553054
@DataTypeHint("Double") Double tolerance) {
30563055
Geometry geom = (Geometry) o;
3057-
return FunctionsGeoTools.voronoiPolygons(geom, tolerance, null);
3056+
return org.apache.sedona.common.Functions.voronoiPolygons(geom, tolerance, null);
30583057
}
30593058

30603059
@DataTypeHint(
@@ -3068,7 +3067,7 @@ public Geometry eval(
30683067
bridgedTo = Geometry.class)
30693068
Object o) {
30703069
Geometry geom = (Geometry) o;
3071-
return FunctionsGeoTools.voronoiPolygons(geom, 0, null);
3070+
return org.apache.sedona.common.Functions.voronoiPolygons(geom, 0, null);
30723071
}
30733072
}
30743073

snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFs.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import javax.xml.parsers.ParserConfigurationException;
2323
import org.apache.sedona.common.Constructors;
2424
import org.apache.sedona.common.Functions;
25-
import org.apache.sedona.common.FunctionsGeoTools;
2625
import org.apache.sedona.common.FunctionsProj4;
2726
import org.apache.sedona.common.Predicates;
2827
import org.apache.sedona.common.enums.FileDataSplitter;
@@ -1171,19 +1170,19 @@ public static byte[] ST_UnaryUnion(byte[] geometry) {
11711170
@UDFAnnotations.ParamMeta(argNames = {"geometry"})
11721171
public static byte[] ST_VoronoiPolygons(byte[] geometry) {
11731172
return GeometrySerde.serialize(
1174-
FunctionsGeoTools.voronoiPolygons(GeometrySerde.deserialize(geometry), 0.0, null));
1173+
Functions.voronoiPolygons(GeometrySerde.deserialize(geometry), 0.0, null));
11751174
}
11761175

11771176
@UDFAnnotations.ParamMeta(argNames = {"geometry", "tolerance"})
11781177
public static byte[] ST_VoronoiPolygons(byte[] geometry, double tolerance) {
11791178
return GeometrySerde.serialize(
1180-
FunctionsGeoTools.voronoiPolygons(GeometrySerde.deserialize(geometry), tolerance, null));
1179+
Functions.voronoiPolygons(GeometrySerde.deserialize(geometry), tolerance, null));
11811180
}
11821181

11831182
@UDFAnnotations.ParamMeta(argNames = {"geometry", "tolerance", "extent"})
11841183
public static byte[] ST_VoronoiPolygons(byte[] geometry, double tolerance, byte[] extent) {
11851184
return GeometrySerde.serialize(
1186-
FunctionsGeoTools.voronoiPolygons(
1185+
Functions.voronoiPolygons(
11871186
GeometrySerde.deserialize(geometry), tolerance, GeometrySerde.deserialize(extent)));
11881187
}
11891188

@@ -1266,7 +1265,7 @@ public static boolean ST_DWithin(byte[] geomA, byte[] geomB, double distance) {
12661265
}
12671266

12681267
@UDFAnnotations.ParamMeta(argNames = {"geomA", "geomB"})
1269-
public static double ST_FrechetDistance(byte[] geomA, byte[] geomB) {
1268+
public static Double ST_FrechetDistance(byte[] geomA, byte[] geomB) {
12701269
return Functions.frechetDistance(
12711270
GeometrySerde.deserialize(geomA), GeometrySerde.deserialize(geomB));
12721271
}

snowflake/src/main/java/org/apache/sedona/snowflake/snowsql/UDFsV2.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import java.io.IOException;
2222
import org.apache.sedona.common.Functions;
23-
import org.apache.sedona.common.FunctionsGeoTools;
2423
import org.apache.sedona.common.FunctionsProj4;
2524
import org.apache.sedona.common.Predicates;
2625
import org.apache.sedona.common.sphere.Haversine;
@@ -1402,7 +1401,7 @@ public static String ST_UnaryUnion(String geometry) {
14021401
returnTypes = "Geometry")
14031402
public static String ST_VoronoiPolygons(String geometry) {
14041403
return GeometrySerde.serGeoJson(
1405-
FunctionsGeoTools.voronoiPolygons(GeometrySerde.deserGeoJson(geometry), 0.0, null));
1404+
Functions.voronoiPolygons(GeometrySerde.deserGeoJson(geometry), 0.0, null));
14061405
}
14071406

14081407
@UDFAnnotations.ParamMeta(
@@ -1411,7 +1410,7 @@ public static String ST_VoronoiPolygons(String geometry) {
14111410
returnTypes = "Geometry")
14121411
public static String ST_VoronoiPolygons(String geometry, double tolerance) {
14131412
return GeometrySerde.serGeoJson(
1414-
FunctionsGeoTools.voronoiPolygons(GeometrySerde.deserGeoJson(geometry), tolerance, null));
1413+
Functions.voronoiPolygons(GeometrySerde.deserGeoJson(geometry), tolerance, null));
14151414
}
14161415

14171416
@UDFAnnotations.ParamMeta(
@@ -1420,7 +1419,7 @@ public static String ST_VoronoiPolygons(String geometry, double tolerance) {
14201419
returnTypes = "Geometry")
14211420
public static String ST_VoronoiPolygons(String geometry, double tolerance, String extent) {
14221421
return GeometrySerde.serGeoJson(
1423-
FunctionsGeoTools.voronoiPolygons(
1422+
Functions.voronoiPolygons(
14241423
GeometrySerde.deserGeoJson(geometry), tolerance, GeometrySerde.deserGeoJson(extent)));
14251424
}
14261425

@@ -1535,7 +1534,7 @@ public static boolean ST_DWithin(String geomA, String geomB, double distance) {
15351534
@UDFAnnotations.ParamMeta(
15361535
argNames = {"geomA", "geomB"},
15371536
argTypes = {"Geometry", "Geometry"})
1538-
public static double ST_FrechetDistance(String geomA, String geomB) {
1537+
public static Double ST_FrechetDistance(String geomA, String geomB) {
15391538
return Functions.frechetDistance(
15401539
GeometrySerde.deserGeoJson(geomA), GeometrySerde.deserGeoJson(geomB));
15411540
}

spark/common/src/main/scala/org/apache/spark/sql/sedona_sql/expressions/Functions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1854,7 +1854,7 @@ private[apache] case class ST_TriangulatePolygon(inputExpressions: Seq[Expressio
18541854
}
18551855

18561856
private[apache] case class ST_VoronoiPolygons(inputExpressions: Seq[Expression])
1857-
extends InferredExpression(nullTolerantInferrableFunction3(FunctionsGeoTools.voronoiPolygons))
1857+
extends InferredExpression(nullTolerantInferrableFunction3(Functions.voronoiPolygons))
18581858
with FoldableExpression {
18591859
protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) = {
18601860
copy(inputExpressions = newChildren)

0 commit comments

Comments
 (0)