This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sedona.git
The following commit(s) were added to refs/heads/master by this push:
new 974350c2c [SEDONA-604] Add ST_AddMeasure (#1472)
974350c2c is described below
commit 974350c2c31a90c3fc2814ad1c15791f0aa69a21
Author: Jia Yu <[email protected]>
AuthorDate: Fri Jun 7 15:14:18 2024 -0700
[SEDONA-604] Add ST_AddMeasure (#1472)
* [TASK-92] Add ST_AddMeasure (#207)
* feat: add implementation
* feat: port to flink and spark
* feat: add another declaration to spark DataframeAPI
* Update versions
---------
Co-authored-by: Furqaan Khan <[email protected]>
---
.../java/org/apache/sedona/common/Functions.java | 4 ++
.../org/apache/sedona/common/utils/GeomUtils.java | 70 ++++++++++++++++++++++
.../org/apache/sedona/common/FunctionsTest.java | 18 ++++++
docs/api/flink/Function.md | 22 +++++++
docs/api/sql/Function.md | 22 +++++++
.../main/java/org/apache/sedona/flink/Catalog.java | 1 +
.../apache/sedona/flink/expressions/Functions.java | 9 +++
.../java/org/apache/sedona/flink/FunctionTest.java | 15 +++++
python/sedona/sql/st_functions.py | 14 +++++
python/tests/sql/test_dataframe_api.py | 3 +
python/tests/sql/test_function.py | 10 ++++
.../scala/org/apache/sedona/sql/UDF/Catalog.scala | 1 +
.../sql/sedona_sql/expressions/Functions.scala | 8 +++
.../sql/sedona_sql/expressions/st_functions.scala | 4 ++
.../apache/sedona/sql/dataFrameAPITestScala.scala | 16 +++++
.../org/apache/sedona/sql/functionTestScala.scala | 11 ++++
16 files changed, 228 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 33dd033c1..e9a37958e 100644
--- a/common/src/main/java/org/apache/sedona/common/Functions.java
+++ b/common/src/main/java/org/apache/sedona/common/Functions.java
@@ -1092,6 +1092,10 @@ public class Functions {
return isExteriorRingCCW && isInteriorRingCCW;
}
+ public static Geometry addMeasure(Geometry geom, double measure_start,
double measure_end) {
+ return GeomUtils.addMeasure(geom, measure_start, measure_end);
+ }
+
public static double maxDistance(Geometry geom1, Geometry geom2) {
return longestLine(geom1, geom2).getLength();
}
diff --git a/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
b/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
index fc36e79e5..a51f6ccc6 100644
--- a/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
+++ b/common/src/main/java/org/apache/sedona/common/utils/GeomUtils.java
@@ -530,6 +530,76 @@ public class GeomUtils {
return hausdorffDistanceObj.distance();
}
+ public static Geometry addMeasure(Geometry geom, double measure_start,
double measure_end) {
+ if (!(geom instanceof LineString) && !(geom instanceof
MultiLineString)) {
+ throw new IllegalArgumentException("Geometry must be a LineString
or MultiLineString.");
+ }
+
+ if (geom instanceof LineString) {
+ return addMeasure((LineString) geom, measure_start, measure_end);
+ } else { // MultiLineString
+ return addMeasure((MultiLineString) geom, measure_start,
measure_end);
+ }
+ }
+
+ private static Geometry addMeasure(LineString geom, double measureStart,
double measureEnd) {
+ Coordinate[] coordinates = geom.getCoordinates();
+ double totalLength = geom.getLength();
+ CoordinateList newCoordinates = new CoordinateList();
+
+ Coordinate c1 = coordinates[0];
+ double measure,
+ measureRange = measureEnd - measureStart;
+ int numCoordinates = coordinates.length;
+
+ for (int i = 0; i < numCoordinates; i++) {
+ Coordinate c2 = coordinates[i];
+ double length = c1.distance(c2);
+
+ if (totalLength > 0.0) {
+ measure = measureStart + measureRange * (length / totalLength);
+ } else if (totalLength == 0.0 && numCoordinates > 1) { // valid
zero length LineStrings
+ measure = measureStart + measureRange * i / (numCoordinates -
1);
+ } else {
+ measure = 0.0;
+ }
+
+ CoordinateXYZM newCoordinate = new CoordinateXYZM(c2.getX(),
c2.getY(), c2.getZ(), measure);
+ newCoordinates.add(newCoordinate);
+ }
+
+ return
geom.getFactory().createLineString(newCoordinates.toCoordinateArray());
+ }
+
+ private static Geometry addMeasure(MultiLineString geom, double
measureStart, double measureEnd) {
+ double totalLength = 0,
+ measureRange = measureEnd - measureStart;
+ for (int i = 0; i < geom.getNumGeometries(); i++) {
+ LineString linestring = (LineString) geom.getGeometryN(i);
+ if (linestring.getCoordinates().length > 1)
+ totalLength += linestring.getLength();
+ }
+ LineString[] newLineStrings = new LineString[geom.getNumGeometries()];
+ double length= 0;
+ for (int i = 0; i < geom.getNumGeometries(); i++) {
+ double subMeasureStart,
+ subMeasureEnd,
+ subLength = 0;
+ LineString lineString = (LineString) geom.getGeometryN(i);
+ if (lineString.getCoordinates().length > 1)
+ subLength = lineString.getCoordinates().length;
+
+ subMeasureStart = measureStart + measureRange * length /
totalLength;
+ subMeasureEnd = measureStart + measureRange * (length + subLength)
/ totalLength;
+
+ newLineStrings[i] = (LineString) addMeasure(lineString,
subMeasureStart, subMeasureEnd);
+
+ length += subLength;
+ }
+
+ return geom.getFactory().createMultiLineString(newLineStrings);
+ }
+
public static Boolean isMeasuredGeometry(Geometry geom) {
Coordinate coordinate = geom.getCoordinate();
return !Double.isNaN(coordinate.getM());
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 7c90ae320..8d2553350 100644
--- a/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
+++ b/common/src/test/java/org/apache/sedona/common/FunctionsTest.java
@@ -2760,6 +2760,24 @@ public class FunctionsTest extends TestBase {
}
+ @Test
+ public void testAddMeasure() throws ParseException {
+ Geometry geom = Constructors.geomFromEWKT("LINESTRING (1 1, 2 2, 2 2,
3 3)");
+ String actual = Functions.asWKT(Functions.addMeasure(geom, 1, 70));
+ String expected = "LINESTRING M(1 1 1, 2 2 35.5, 2 2 35.5, 3 3 70)";
+ assertEquals(expected, actual);
+
+ actual = Functions.asWKT(Functions.addMeasure(geom, 1, 2));
+ expected = "LINESTRING M(1 1 1, 2 2 1.5, 2 2 1.5, 3 3 2)";
+ assertEquals(expected, actual);
+
+ geom = Constructors.geomFromEWKT("MULTILINESTRING M((1 0 4, 2 0 4, 4 0
4),(1 0 4, 2 0 4, 4 0 4))");
+ actual = Functions.asWKT(Functions.addMeasure(geom, 1, 70));
+ expected = "MULTILINESTRING M((1 0 1, 2 0 12.5, 4 0 35.5), (1 0 35.5,
2 0 47, 4 0 70))";
+ assertEquals(expected, actual);
+
+ }
+
@Test
public void voronoiPolygons() {
MultiPoint multiPoint =
GEOMETRY_FACTORY.createMultiPointFromCoords(coordArray(0, 0, 2, 2));
diff --git a/docs/api/flink/Function.md b/docs/api/flink/Function.md
index 3cc6d415c..44acffffc 100644
--- a/docs/api/flink/Function.md
+++ b/docs/api/flink/Function.md
@@ -53,6 +53,28 @@ Output:
1.7320508075688772
```
+## ST_AddMeasure
+
+Introduction: Computes a new geometry with measure (M) values linearly
interpolated between start and end points. For geometries lacking M dimensions,
M values are added. Existing M values are overwritten by the new values.
Applies only to LineString and MultiLineString inputs.
+
+Format: `ST_AddMeasure(geom: Geometry, measureStart: Double, measureEnd:
Double)`
+
+Since: `v1.6.1`
+
+SQL Example:
+
+```sql
+SELECT ST_AsText(ST_AddMeasure(
+ ST_GeomFromWKT('LINESTRING (0 0, 1 0, 2 0, 3 0, 4 0, 5 0)')
+))
+```
+
+Output:
+
+```
+LINESTRING M(0 0 10, 1 0 16, 2 0 22, 3 0 28, 4 0 34, 5 0 40)
+```
+
## ST_AddPoint
Introduction: Return Linestring with additional point at the given index, if
position is not available the point will be added at the end of line.
diff --git a/docs/api/sql/Function.md b/docs/api/sql/Function.md
index c9beecc14..eb2485278 100644
--- a/docs/api/sql/Function.md
+++ b/docs/api/sql/Function.md
@@ -53,6 +53,28 @@ Output:
1.7320508075688772
```
+## ST_AddMeasure
+
+Introduction: Computes a new geometry with measure (M) values linearly
interpolated between start and end points. For geometries lacking M dimensions,
M values are added. Existing M values are overwritten by the new values.
Applies only to LineString and MultiLineString inputs.
+
+Format: `ST_AddMeasure(geom: Geometry, measureStart: Double, measureEnd:
Double)`
+
+Since: `v1.6.1`
+
+SQL Example:
+
+```sql
+SELECT ST_AsText(ST_AddMeasure(
+ ST_GeomFromWKT('LINESTRING (0 0, 1 0, 2 0, 3 0, 4 0, 5 0)')
+))
+```
+
+Output:
+
+```
+LINESTRING M(0 0 10, 1 0 16, 2 0 22, 3 0 28, 4 0 34, 5 0 40)
+```
+
## ST_AddPoint
Introduction: RETURN Linestring with additional point at the given index, if
position is not available the point will be added at the end of line.
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 c744a1655..e421669d6 100644
--- a/flink/src/main/java/org/apache/sedona/flink/Catalog.java
+++ b/flink/src/main/java/org/apache/sedona/flink/Catalog.java
@@ -132,6 +132,7 @@ public class Catalog {
new Functions.ST_IsSimple(),
new Functions.ST_IsValid(),
new Functions.ST_Normalize(),
+ new Functions.ST_AddMeasure(),
new Functions.ST_AddPoint(),
new Functions.ST_RemovePoint(),
new Functions.ST_SetPoint(),
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 5082c4c90..4c254fcb1 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
@@ -722,6 +722,15 @@ public class Functions {
}
}
+ public static class ST_AddMeasure 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,
+ @DataTypeHint(value = "Double") Double
measureStart, @DataTypeHint(value = "Double") Double measureEnd) {
+ Geometry geom = (Geometry) o1;
+ return org.apache.sedona.common.Functions.addMeasure(geom,
measureStart, measureEnd);
+ }
+ }
+
public static class ST_AddPoint 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 045a96c99..e237584d9 100644
--- a/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
+++ b/flink/src/test/java/org/apache/sedona/flink/FunctionTest.java
@@ -962,6 +962,21 @@ public class FunctionTest extends TestBase{
assertEquals("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))", result.toString());
}
+ @Test
+ public void testAddMeasure() {
+ Table baseTable = tableEnv.sqlQuery("SELECT ST_GeomFromWKT('LINESTRING
(1 1, 2 2, 2 2, 3 3)') as line, " +
+ "ST_GeomFromWKT('MULTILINESTRING M((1 0 4, 2 0 4, 4 0 4),(1 0
4, 2 0 4, 4 0 4))') as mline");
+ String actual = (String)
first(baseTable.select(call(Functions.ST_AddMeasure.class.getSimpleName(),
$("line"),
+ 1.0,
70.0)).as("geom").select(call(Functions.ST_AsText.class.getSimpleName(),
$("geom")))).getField(0);
+ String expected = "LINESTRING M(1 1 1, 2 2 35.5, 2 2 35.5, 3 3 70)";
+ assertEquals(expected, actual);
+
+ actual = (String)
first(baseTable.select(call(Functions.ST_AddMeasure.class.getSimpleName(),
$("mline"),
+ 10.0,
70.0)).as("geom").select(call(Functions.ST_AsText.class.getSimpleName(),
$("geom")))).getField(0);
+ expected = "MULTILINESTRING M((1 0 10, 2 0 20, 4 0 40), (1 0 40, 2 0
50, 4 0 70))";
+ assertEquals(expected, actual);
+ }
+
@Test
public void testAddPoint() {
Table pointTable = tableEnv.sqlQuery("SELECT
ST_AddPoint(ST_GeomFromWKT('LINESTRING (0 0, 1 1)'), ST_GeomFromWKT('POINT (2
2)'))");
diff --git a/python/sedona/sql/st_functions.py
b/python/sedona/sql/st_functions.py
index 4b1829c72..b1120a2ba 100644
--- a/python/sedona/sql/st_functions.py
+++ b/python/sedona/sql/st_functions.py
@@ -57,6 +57,20 @@ def ST_3DDistance(a: ColumnOrName, b: ColumnOrName) ->
Column:
"""
return _call_st_function("ST_3DDistance", (a, b))
+@validate_argument_types
+def ST_AddMeasure(geom: ColumnOrName, measureStart: Union[ColumnOrName,
float], measureEnd: Union[ColumnOrName, float]) -> Column:
+ """Interpolate measure values with the provided start and end points and
return the result geometry.
+
+ :param geom: Geometry column to use in the calculation.
+ :type geom: ColumnOrName
+ :param measureStart: Start point for the measure.
+ :type measureStart: ColumnOrName
+ :param measureEnd: End point for the measure.
+ :type measureEnd: ColumnOrName
+ :return: Result geometry column.
+ :rtype: Column
+ """
+ return _call_st_function("ST_AddMeasure", (geom, measureStart, measureEnd))
@validate_argument_types
def ST_AddPoint(line_string: ColumnOrName, point: ColumnOrName, index:
Optional[Union[ColumnOrName, int]] = None) -> Column:
diff --git a/python/tests/sql/test_dataframe_api.py
b/python/tests/sql/test_dataframe_api.py
index d57c3b466..ac8f8f7fa 100644
--- a/python/tests/sql/test_dataframe_api.py
+++ b/python/tests/sql/test_dataframe_api.py
@@ -78,6 +78,7 @@ test_configurations = [
(stf.ST_3DDistance, ("a", "b"), "two_points", "", 5.0),
(stf.ST_Affine, ("geom", 1.0, 2.0, 1.0, 2.0, 1.0, 2.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0), "square_geom", "", "POLYGON ((2 3, 4 5, 5 6, 3 4, 2 3))"),
(stf.ST_Affine, ("geom", 1.0, 2.0, 1.0, 2.0, 1.0, 2.0,), "square_geom",
"", "POLYGON ((2 3, 4 5, 5 6, 3 4, 2 3))"),
+ (stf.ST_AddMeasure, ("line", 10.0, 40.0), "linestring_geom",
"ST_AsText(geom)", "LINESTRING M(0 0 10, 1 0 16, 2 0 22, 3 0 28, 4 0 34, 5 0
40)"),
(stf.ST_AddPoint, ("line", lambda: f.expr("ST_Point(1.0, 1.0)")),
"linestring_geom", "", "LINESTRING (0 0, 1 0, 2 0, 3 0, 4 0, 5 0, 1 1)"),
(stf.ST_AddPoint, ("line", lambda: f.expr("ST_Point(1.0, 1.0)"), 1),
"linestring_geom", "", "LINESTRING (0 0, 1 1, 1 0, 2 0, 3 0, 4 0, 5 0)"),
(stf.ST_Angle, ("p1", "p2", "p3", "p4", ), "four_points", "",
0.4048917862850834),
@@ -291,6 +292,8 @@ wrong_type_configurations = [
# functions
(stf.ST_3DDistance, (None, "")),
(stf.ST_3DDistance, ("", None)),
+ (stf.ST_AddMeasure, (None, None, None)),
+ (stf.ST_AddMeasure, ("", None, "")),
(stf.ST_AddPoint, (None, "")),
(stf.ST_AddPoint, ("", None)),
(stf.ST_Area, (None,)),
diff --git a/python/tests/sql/test_function.py
b/python/tests/sql/test_function.py
index 3a8b00f58..de1b2e715 100644
--- a/python/tests/sql/test_function.py
+++ b/python/tests/sql/test_function.py
@@ -871,6 +871,16 @@ class TestPredicateJoin(TestBase):
collected_interior_rings = [[*row] for row in
number_of_interior_rings.filter("num is not null").collect()]
assert (collected_interior_rings == [[2, 0], [11, 1]])
+ def test_st_add_measure(self):
+ baseDf = self.spark.sql("SELECT ST_GeomFromWKT('LINESTRING (1 1, 2 2,
2 2, 3 3)') as line, ST_GeomFromWKT('MULTILINESTRING M((1 0 4, 2 0 4, 4 0 4),(1
0 4, 2 0 4, 4 0 4))') as mline")
+ actual = baseDf.selectExpr("ST_AsText(ST_AddMeasure(line, 1,
70))").first()[0]
+ expected = "LINESTRING M(1 1 1, 2 2 35.5, 2 2 35.5, 3 3 70)"
+ assert expected == actual
+
+ actual = baseDf.selectExpr("ST_AsText(ST_AddMeasure(mline, 10,
70))").first()[0]
+ expected = "MULTILINESTRING M((1 0 10, 2 0 20, 4 0 40), (1 0 40, 2 0
50, 4 0 70))"
+ assert expected == actual
+
def test_st_add_point(self):
geometry = [
("Point(21 52)", "Point(21 52)"),
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 364919521..7b0b4ebc9 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
@@ -148,6 +148,7 @@ object Catalog {
function[ST_IsCollection](),
function[ST_NumInteriorRings](),
function[ST_NumInteriorRing](),
+ function[ST_AddMeasure](),
function[ST_AddPoint](-1),
function[ST_RemovePoint](-1),
function[ST_SetPoint](),
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 697bf6128..4af8325a3 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
@@ -728,6 +728,14 @@ case class ST_NumInteriorRing(inputExpressions:
Seq[Expression])
}
}
+case class ST_AddMeasure(inputExpressions: Seq[Expression])
+ extends InferredExpression(inferrableFunction3(Functions.addMeasure)) {
+
+ protected def withNewChildrenInternal(newChildren: IndexedSeq[Expression]) =
{
+ copy(inputExpressions = newChildren)
+ }
+}
+
case class ST_AddPoint(inputExpressions: Seq[Expression])
extends InferredExpression(inferrableFunction3(Functions.addPoint)) {
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 77fd8fa4e..a6449d521 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
@@ -29,6 +29,10 @@ object st_functions extends DataFrameAPI {
def ST_3DDistance(a: Column, b: Column): Column =
wrapExpression[ST_3DDistance](a, b)
def ST_3DDistance(a: String, b: String): Column =
wrapExpression[ST_3DDistance](a, b)
+ def ST_AddMeasure(geom: Column, measureStart: Column, measureEnd: Column):
Column = wrapExpression[ST_AddMeasure](geom, measureStart, measureEnd)
+ def ST_AddMeasure(geom: String, measureStart: Double, measureEnd: Double):
Column = wrapExpression[ST_AddMeasure](geom, measureStart, measureEnd)
+ def ST_AddMeasure(geom: String, measureStart: String, measureEnd: String):
Column = wrapExpression[ST_AddMeasure](geom, measureStart, measureEnd)
+
def ST_AddPoint(lineString: Column, point: Column): Column =
wrapExpression[ST_AddPoint](lineString, point, -1)
def ST_AddPoint(lineString: String, point: String): Column =
wrapExpression[ST_AddPoint](lineString, point, -1)
def ST_AddPoint(lineString: Column, point: Column, index: Column): Column =
wrapExpression[ST_AddPoint](lineString, point, index)
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 e22f3727b..a11901447 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
@@ -926,6 +926,22 @@ class dataFrameAPITestScala extends TestBaseScala {
assert(actualResult == expectedResult)
}
+ it("Passed ST_AddMeasure") {
+ var baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('LINESTRING (1 1, 2
2, 2 2, 3 3)') as line, ST_GeomFromWKT('MULTILINESTRING M((1 0 4, 2 0 4, 4 0
4),(1 0 4, 2 0 4, 4 0 4))') as mline")
+ var actual = baseDf.select(ST_AsText(ST_AddMeasure("line", 1,
70))).first().get(0)
+ var expected = "LINESTRING M(1 1 1, 2 2 35.5, 2 2 35.5, 3 3 70)"
+ assertEquals(expected, actual)
+
+ actual = baseDf.select(ST_AsText(ST_AddMeasure("mline", 10,
70))).first().get(0)
+ expected = "MULTILINESTRING M((1 0 10, 2 0 20, 4 0 40), (1 0 40, 2 0 50,
4 0 70))"
+ assertEquals(expected, actual)
+
+ baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('MULTILINESTRING M((1 0
4, 2 0 4, 4 0 4),(1 0 4, 2 0 4, 4 0 4))') as mline, 10.0 as measureRangeStart,
70.0 as measureRangeEnd")
+ actual = baseDf.select(ST_AsText(ST_AddMeasure("mline",
"measureRangeEnd", "measureRangeStart"))).first().get(0)
+ expected = "MULTILINESTRING M((1 0 70, 2 0 60, 4 0 40), (1 0 40, 2 0 30,
4 0 10))"
+ assertEquals(expected, actual)
+ }
+
it("Passed ST_AddPoint without index") {
val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('LINESTRING (0 0, 1
0)') AS line, ST_Point(1.0, 1.0) AS point")
val df = baseDf.select(ST_AddPoint("line", "point"))
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 ccec742fd..2ff20d06f 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
@@ -1345,6 +1345,17 @@ class functionTestScala extends TestBaseScala with
Matchers with GeometrySample
.collect().toList should contain theSameElementsAs List((2, 0), (11, 1))
}
+ it("Should pass ST_AddMeasure") {
+ val baseDf = sparkSession.sql("SELECT ST_GeomFromWKT('LINESTRING (1 1, 2
2, 2 2, 3 3)') as line, ST_GeomFromWKT('MULTILINESTRING M((1 0 4, 2 0 4, 4 0
4),(1 0 4, 2 0 4, 4 0 4))') as mline")
+ var actual = baseDf.selectExpr("ST_AsText(ST_AddMeasure(line, 1,
70))").first().get(0)
+ var expected = "LINESTRING M(1 1 1, 2 2 35.5, 2 2 35.5, 3 3 70)"
+ assertEquals(expected, actual)
+
+ actual = baseDf.selectExpr("ST_AsText(ST_AddMeasure(mline, 10,
70))").first().get(0)
+ expected = "MULTILINESTRING M((1 0 10, 2 0 20, 4 0 40), (1 0 40, 2 0 50, 4
0 70))"
+ assertEquals(expected, actual)
+ }
+
it("Should pass ST_AddPoint") {
Given("Geometry df")
val geometryDf = Seq(