In PostGIS, I have a LINESTRING M and I want to remove a segment of the line that falls between two given M values. I tried the following:
SELECT
ST_AsText(line) as line,
ST_AsText(segment_to_delete) as segment_to_delete,
ST_AsText(ST_Difference(line, segment_to_delete)) as result
FROM
(
SELECT
line,
ST_FilterByM(t.line, 2, 4, TRUE) as segment_to_delete
FROM
(SELECT 'LINESTRING M(1 1 1, 2 2 2, 3 3 3, 4 4 4, 5 5 5)'::geometry as line) as t
) as t
;
line
and segment_to_delete
both have the expected points and M values (segment_to_delete
is LINESTRING M (2 2 2,3 3 3,4 4 4)
). However, the ST_Difference
drops the M value and result
is MULTILINESTRING((1 1,2 2),(4 4,5 5))
instead of the expected MULTILINESTRING((1 1 1,2 2 2),(4 4 4,5 5 5))
. I'm ignoring the question what exactly should happen to the boundary points.
How do I remove a section between two M values from a LINESTRING M and retain the remaining M values?
(EDIT: I should probably add that in reality I have more than one segment I want to remove. That is, not only a single LINESTRING that I obtained with ST_FilterByM, but multiple LINESTRINGS which I aggregated with ST_Collect into a MULTILINESTRING. Therefore, I cannot simply use two ST_FilterByM(line, start_m, x)
and ST_FilterByM(line, y, end_m)
because I don't know how I could combine the individual results into a MULTILINESTRING with the correct holes.)
Best Answer
Here's an example of how it could be done. This method allows you to keep M and Z values intact. It works by merging the substring of the route from the start point to the first measure with the substring of the route from the second measure to the end point. It only works with linestringm/zm:
Result: