简体   繁体   中英

How to iterate over points to split linestring into portions in PgSQL?

Context : I'm working with a PostgreSQL (10.6) database and PostGIS 2.5.

I need help creating a function that'll split the linestring of each row from a table using points from another table, and insert the split portions into a new table. Each line has it's proper points and the points have a precise order.

I know how to split a linestring using ST_Line_Substring ( documentation here ), and I know how to do it using a point using ST_LineLocatePoint ( documentation here ).


I have 2 problems : I don't want to split the line at a point's location, but rather in between each point according to their position on the line as fraction. So if there is a point at 0% and the next one is at 20% of the line, the first portion would go from 0% to 10% of the original line. Here's a quick illustration (sorry if it looks childish) : 在此处输入图片说明

The black line represent the original linestring, the blue circles are the points, and the colored "lines" represent what kind of line_substring I want.

The solution I came up with this problem is just just adding the fraction of the previous point and current point on the line and dividing by 2 for the start of the portion, and same thing with the current point and the next one, for the end of the portion, as written below :

ST_Line_Substring(line.geom, (
    ((ST_LineLocatePoint(line.geom, previous_point.geom) + ST_LineLocatePoint(line.geom, current_point.geom)) / 2),
    ((ST_LineLocatePoint(line.geom, current_point.geom) + ST_LineLocatePoint(line.geom, next_point.geom)) / 2)
)

My 2nd problem, I have no idea how to access the previous and next point from the table containing the points. At first I wanted to use some kind of loop mechanism but I've seen a lot of answers from other topics saying this isn't something optimal and it's better to avoid them, and I've found nothing looking like an index in SQL to iterate over a result set or a table to easily access previous or next element.

So my main question is, how do I iterate over my points table, for each line, to access previous, current, and next point at the same time ?

I found a solution, I'm using a cursor and then the RELATIVE option, which allows me to access other indexes than the row I'm iterating over, here's what my function looks like :

CREATE OR REPLACE FUNCTION splitLine(
    id character varying,
    linestring geometry(POINT,4326)
    )
RETURNS VOID AS $$

DECLARE
prior_point RECORD;
current_point RECORD;
next_point RECORD;
cursor_point SCROLL CURSOR FOR  SELECT id, line_id, line_order, geom
                                  FROM points
                                  WHERE id LIKE line_id
                                  ORDER BY line_order;

BEGIN

    OPEN cursor_points;

    LOOP

        FETCH FROM cursor_point INTO prior_point;
        FETCH RELATIVE 1 FROM cursor_point INTO current_point;
        FETCH RELATIVE 2 FROM cursor_point INTO next_point;

        -- Operations on my points and line 

    END LOOP;

    CLOSE cursor_point;
END; $$

LANGUAGE plpgsql;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM