포인트가있는 줄을 자르시겠습니까?


10

선 문자열을 포인트로 자르는 가장 좋은 방법을 확인하고있었습니다.

시나리오는 다음과 같습니다. 거리가 많고 교차점으로 잘라진 세그먼트가 필요합니다.

예

알았어

  • 선 스트링 (점으로 전체 자르지 않은 표) 테이블

  • st_intersection 포인트 테이블

교차점 테이블로 자른 독립 선 스트링 세그먼트를 가져와야합니다.

PostGIS 함수를 사용하고 있으며 몇 가지 접근 방식을 찾았지만 각 방법으로 문제가 발생했습니다.

다음은 이미 테스트 한 내용입니다.

1

라인 테이블 : 1 행, st_memunion 1200 라인 포인트 테이블 : 1700 행 (포인트)

나쁜 점 : 실제로 많은 시간과 메모리 플러시가 필요합니다. 동시에 여러 테이블을 만들 수 없으므로 메모리에서 처리 할 수 ​​없습니다. 그리고 결과는 더럽고 지저분합니다. 나에게 올바른 행 번호를 부여하는 대신 나중에 정리해야합니다 (자세한 점은 교차점 에서 분할 선 )

CREATE TABLE lines_with_messy_result AS (
SELECT
((ST_DUMP(ST_SPLIT(a.geom,b.ix))).geom) as geom
FROM st_union_lines a
INNER JOIN lots_of_points b
ON ST_INTERSECTS(a.geom, b.ix)
);

--then need to clean this up
create table lines_segments_cleaned as (
SELECT DISTINCT ON (ST_AsBinary(geom)) 
geom 
FROM 
lines_with_messy_result
);

이 방법 / 접근 출처 : /programming/25753348/how-do-i-divide-city-streets-by-intersection-using-postgis


2

동일한 라인 / 포인트 테이블. 여전히 지저분한 결과이며이를 정리해야합니다. 여전히 쿼리를 완료하는 데 많은 시간이 걸립니다.

--messy table    
Create table messy_lines_segments as 
Select 
row_number() over() as id,
(st_dump(st_split(input.geom, blade.ix))).geom as geom
from st_union_lines input
inner join lots_of_points blade on st_intersects(input.geom, blade.ix);

--then cleaning the messy table
delete from messy_lines_segments a
where exists 
(
select 1 from messy_lines_segments b where a.id != b.id and st_coveredby(b.geom,a.geom)
);

이 방법 / 접근 원 : 교차점에서 분할 선


나는 또한이 기능을 발견했다 : https://github.com/Remi-C/PPPP_utilities/blob/master/postgis/rc_Split_Line_By_Points.sql

그것은 messy_result를 남기지 않고 그것을 정리해야한다는 좋은 점이 있습니다. 그러나 양쪽에서 st_memunion이 필요합니다 (lines table 및 points table)

그것은 종류입니다 :

create table osm.calles_cortadas_03segmentos_sanluis as (
SELECT result.geom
FROM 
osm.calles_cortadas_01uniones_sanluis AS line, 
osm.calles_cortadas_00intersecciones_sanluis AS point,
rc_split_line_by_points(
input_line:=line.geom
,input_points:=point.ix
,tolerance:=4
) AS result
);

그러나 결과를 얻는 데 오랜 시간이 걸립니다. 그리고 더 긴 테이블 (10k 라인, 14k 포인트)로 시도했는데 메모리 부족 문제가 발생했습니다.

나는 또한 나쁜 결과로 Esri의 ArcGIS를 시도했습니다 ...

PostGIS 기하 함수를 사용하여이를 수행하는 가장 좋은 방법은 무엇입니까?

토폴로지에 들어 가지 않고 의미합니다.

또는 가장 권장되는 사항은 무엇입니까?


1
공차가 매우 작은 버퍼 포인트, 버퍼 내부의 폴리 라인을 지우고 새 끝점을 함께 스냅합니다. .
Michael Stimson

4
최종 업데이트는 질문에 대한 답변이므로 답변으로 작성해야합니다
raphael

자체 답변을하는 것이 좋으며이 사이트에서 추가 기능을 사용하는 것으로 명성을 얻을 수 있습니다.
PolyGeo

답변:


5

이게 방법이야!

좋아, Remi-C로부터 큰 피드백을 받았으며 이제는 매력처럼 작동합니다.

최고의 비 토폴로지 솔루션. 정말 빠르고 쉽게 작동합니다 (이 작업을 수행하는 많은 방법을 테스트했다고 믿습니다).

--please add this function:
https://github.com/Remi-C/PPPP_utilities/blob/master/postgis/rc_split_multi.sql

-- please create a universal sequence for unique id multipurpose
CREATE SEQUENCE select_id
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1
  CYCLE;



-- lines (non st_unioned linestrings, with gist index) : linetable
-- points (non st_unioned points, with gist index) : pointtable

-- first, lines with cuts (pointtable)
create table segment_lines_00 as (
WITH points_intersecting_lines AS( 
   SELECT lines.id AS lines_id, lines.geom AS line_geom,  ST_Collect(points.ix) AS blade
   FROM 
   linetable as lines, 
   pointtable as points
   WHERE st_dwithin(lines.geom, points.ix, 4) = true
   GROUP BY lines.id, lines.geom
)
SELECT lines_id, rc_Split_multi(line_geom, blade, 4)
FROM points_intersecting_lines
);
CREATE INDEX ON segment_lines_00 USING gist(rc_split_multi);


-- then, segments cutted by points
create table segment_lines_01 as (
select 
(ST_Dump(rc_split_multi)).geom as geom,  nextval('SELECT_id'::regclass) AS gid  from segment_lines_00
);
CREATE INDEX ON segment_lines_01 USING gist(geom);

그게 다야!.


1

또한 st_split ()을 사용하지 않고 자체 메서드를 추가합니다.

각 선에 대해 교차점이 있는지 확인합니다.

그렇다면 내 temptable은 다음과 같습니다.

[line_id, fraction]
[1      , 0       ]
[1      , 0.3     ]
[1      , 1       ]
[2      , 0       ]
[2      , 0.88    ]
[2      , 1       ]
...

점이 선과 교차하는 선 ID와 선 길이의 일부를 포함하는 테이블입니다.

그런 다음 분수를 쌍으로 결합하여 새로운 절단 선을 만듭니다.

요구 사항 :

  • "점"테이블에는 각 줄의 끝 점이 포함됩니다.
  • 점이 선을 완벽하게 교차합니다.

쿼리 :

DROP TABLE IF EXISTS temptable;

CREATE TABLE temptable as 
(
    SELECT ST_LineLocatePoint(a.geom,b.geom) as fraction,a.id, a.geom as shape
    FROM lines a, points b
    WHERE st_intersects(a.geom,b.geom)
    UNION
    SELECT 1 as fraction ,a.id, a.geom as shape -- It avoid to get an incomplete line when the original line is circular
    FROM lines a
    ORDER BY a.id, fraction -- important to keep the same order
);

ALTER TABLE temptable  ADD COLUMN gid SERIAL PRIMARY KEY;

DROP TABLE IF EXISTS LINE_SPLIT;
CREATE TABLE LINE_SPLIT AS
(
SELECT b.fend,a.*, ST_LineSubstring(a.shape,a.fstart,b.fend) as geom
FROM
    (
    SELECT *, fraction as fstart FROM temptable
    LIMIT (SELECT COUNT(*) FROM temptable)-1
    ) a,
    (
    SELECT fraction as fend,gid-1 as gid FROM temptable
    OFFSET 1
    ) b
WHERE a.gid = b.gid
AND a.fstart < b.fend
);

ALTER TABLE LINE_SPLIT DROP COLUMN IF EXISTS shape;
DROP TABLE IF EXISTS temptable;

좋은! txs! 이 중 하나를 확인하십시오
vlasvlasvlas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.