diff --git a/python/sedona/sql/st_functions.py b/python/sedona/sql/st_functions.py index 6b666630e2..6bea901716 100644 --- a/python/sedona/sql/st_functions.py +++ b/python/sedona/sql/st_functions.py @@ -796,6 +796,19 @@ def ST_IsValidDetail(geometry: ColumnOrName, flag: Optional[Union[ColumnOrName, args = (geometry,) if flag is None else (geometry, flag) return _call_st_function("ST_IsValidDetail", args) +@validate_argument_types +def ST_IsValidTrajectory(geometry: ColumnOrName) -> Column: + """ + Tests if a geometry encodes a valid trajectory. A valid trajectory is represented as a LINESTRING with measures + (M values). The measure values must increase from each vertex to the next. + + :param geometry: Geometry column to validate. + :type geometry: ColumnOrName + :return: True if the geometry is valid trajectory and False otherwise as a boolean column. + :rtype: Column + """ + return _call_st_function("ST_IsValidTrajectory", (geometry)) + @validate_argument_types def ST_IsValidReason(geometry: ColumnOrName, flag: 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 2300ada346..11d1444444 100644 --- a/python/tests/sql/test_dataframe_api.py +++ b/python/tests/sql/test_dataframe_api.py @@ -157,6 +157,7 @@ (stf.ST_IsPolygonCCW, ("geom",), "geom_with_hole", "", True), (stf.ST_IsRing, ("line",), "linestring_geom", "", False), (stf.ST_IsSimple, ("geom",), "triangle_geom", "", True), + (stf.ST_IsValidTrajectory, ("line",), "4D_line", "", False), (stf.ST_IsValid, ("geom",), "triangle_geom", "", True), (stf.ST_IsValid, ("geom", 1), "triangle_geom", "", True), (stf.ST_IsValid, ("geom", 0), "triangle_geom", "", True), @@ -364,6 +365,7 @@ (stf.ST_IsPolygonCCW, (None,)), (stf.ST_IsRing, (None,)), (stf.ST_IsSimple, (None,)), + (stf.ST_IsValidTrajectory, (None,)), (stf.ST_IsValidDetail, (None,)), (stf.ST_IsValid, (None,)), (stf.ST_IsValidReason, (None,)), diff --git a/python/tests/sql/test_function.py b/python/tests/sql/test_function.py index 1b36d34892..9b67c4f0f8 100644 --- a/python/tests/sql/test_function.py +++ b/python/tests/sql/test_function.py @@ -322,6 +322,14 @@ def test_st_is_valid_detail(self): self.spark.sql("SELECT ST_GeomFromText('POINT (1 1)')").first()[0]) assert expected == actual + def test_st_is_valid_trajectory(self): + baseDf = self.spark.sql("SELECT ST_GeomFromText('LINESTRING M (0 0 1, 0 1 2)') as geom1, ST_GeomFromText('LINESTRING M (0 0 1, 0 1 1)') as geom2") + actual = baseDf.selectExpr("ST_IsValidTrajectory(geom1)").first()[0] + assert actual + + actual = baseDf.selectExpr("ST_IsValidTrajectory(geom2)").first()[0] + assert not actual + def test_st_is_valid(self): test_table = self.spark.sql( "SELECT ST_IsValid(ST_GeomFromWKT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (15 15, 15 20, 20 20, 20 15, 15 15))')) AS a, " +