CREATEOR REPLACE FUNCTION ST_RemoveIntersection(line GEOMETRY) RETURNS GEOMETRY AS $$ DECLARE result GEOMETRY; BEGIN -- 存储线串所有的点和线段 CREATE TEMPORARY TABLE points ( index INTEGER, -- 点的索引,也是线段的索引 point GEOMETRY, -- 点 segment GEOMETRY, -- 线段 PRIMARY KEY (index) ) ONCOMMITDROP;
-- 创建索引加快长线串的处理速度 CREATE INDEX points_segment_gist ON points USING GIST(segment);
-- 将线串拆分为点和线段,最后一个点没有与之匹配的线段 INSERT INTO points(index, point, segment) SELECT t.path[1] AS index, t.geom AS point, ST_MakeLine(t.geom, LEAD(t.geom, 1) OVER()) AS segment FROM ST_DumpPoints(line) AS t;
WITH remove_indexs AS ( -- 找出相交的线段的索引,也是要删除的点的索引 SELECT a.index AS start_index, b.index AS end_index FROM points AS a LEFTJOIN points AS b -- 两条线段之间至少隔了一条线段,即相邻线段不算相交 ON b.index >= a.index +2 WHERE a.segment ISNOT NULL AND b.segment ISNOT NULL -- 判断线段是否相交 AND ST_Intersects(a.segment, b.segment) ) -- 剩下的点构成新的线串 SELECT ST_MakeLine(p.point) INTOresult FROM points as p WHERENOTEXISTS( -- 删除相交的线段,也是要删除的点 SELECT1FROM remove_indexs AS r WHERE r.start_index < p.index AND p.index <= r.end_index );