PostGIS에서 라인의 시작 및 끝 노드를 다른 라인으로 스냅


9

선을 점에 맞추는 방법을 보여주는 많은 예제가 있지만 줄 문자열의 시작 및 끝 노드를 다른 줄의 노드에 스냅하는 방법을 찾을 수 없었습니다.

본질적으로 postgis (2.0)에서 레이어를 "청소"하고 거의 비슷한 점을 함께 이동하며 줄 사이에 작은 구멍을 꿰매고 싶습니다.

다른 노드를 추가하든, 한 줄의 첫 번째 / 마지막 노드를 이동하든, 또는 두 지점을 가운데로 이동하든 상관 없습니다.

두 가지 옵션을 찾았지만 그중 하나를 시작하는 방법을 모르겠습니다.

두 번째 옵션은 가능하지만이 방법을 따르는 방법에 대한 도움을 주시면 감사하겠습니다.

답변:


6

언급 된 GRASS 도구 또는 토폴로지 기능을 사용하지 않고도이 문제를 해결할 수있었습니다.

기본적으로 나는 모든 시작 및 끝 노드를 가져 와서 새로운 임시 테이블에 넣고 주위에 버퍼를 놓고 버퍼 객체를 통합하고 각 버퍼에서 찾은 모든 노드를 버퍼의 중심으로 옮깁니다.

완료되면 원래 시작점과 끝점을 새 위치로 옮깁니다.

예상보다 쉽고 여전히 빠르지 만 PostGIS는이를 위해 몇 가지 내장 기능을 가질 것으로 예상했습니다.

편집 : 커뮤니티에 환원하기 위해, 이것은 현재 내 (아주 거친) 코드입니다.

drop table if exists nodes;
drop table if exists nodes2;
drop table if exists buffers;

-- Get Start and End nodes
select ST_StartPoint(wkb_geometry) startnode,  ST_EndPoint(wkb_geometry) endnode,    ogc_fid into nodes  from sourceTable;
-- Combine all nodes into one table for easier queries
select startnode node, ogc_fid into nodes2 from nodes;
insert into nodes2 select endnode node, ogc_fid from nodes;

-- Some indexes to speed everything up
CREATE INDEX nodesstart_idx ON nodes USING gist  (startnode);
CREATE INDEX nodesend_idx ON nodes USING gist  (endnode);
CREATE INDEX nodes2_idx ON nodes2 USING gist  (node);
CREATE INDEX nodes_ogcfid_idx ON nodes USING btree (ogc_fid ASC NULLS LAST);

-- Create buffers, combine them, split combined objects again
select (ST_Dump(ST_Union(ST_Buffer(node, 1)))).geom geom into buffers from nodes2;
CREATE INDEX buffers_idx ON buffers USING gist  (geom);

-- Update start/end nodes table
UPDATE nodes SET startnode = ST_Centroid((select geom from buffers WHERE geom && startnode));
UPDATE nodes SET endnode = ST_Centroid((select geom from buffers WHERE geom && endnode));
-- Update original points
update sourceTable set wkb_geometry = ST_SetPoint(
ST_SetPoint(wkb_geometry, 0, (select startnode from nodes where ogc_fid=sourceTable.ogc_fid)), 
ST_NumPoints(wkb_geometry) - 1, (select endnode from nodes where ogc_fid=sourceTable.ogc_fid));

DROP TABLE nodes;
DROP TABLE nodes2;
DROP TABLE buffers;

이 대답은 내 대답의 "비 토폴로지 적"제안과 매우 비슷합니다. 공감대를 주거나 답변을 선택하면 친절합니다. 이것이 커뮤니티를 여기에 공급하는 것입니다 :)
katahdin

네가 옳아. 귀하의 답변을 상향 조정했으며 코드를 포함하도록 응답을 편집하겠습니다.
Jelmer Baas

4

세 가지 옵션이 있습니다. 잘하면 도움이 될 것입니다.

청소

QGIS에서 GRASS 도구를 사용하면 공간 객체의 토폴로지를 정리할 수 있습니다. @RK 사용자 는 다른 질문대한 답변으로 이를 수행하는 방법에 대한 유용한 지침을 제공합니다 . GRASS가 제공하는 장점은 shapefile의 토폴로지를 유추한다는 것입니다. 상황에 대한 단점은 데이터가 쉐이프 파일에 있지 않다는 것입니다. 물론 "PostGIS Layer 추가"도구를 사용하여 Postgres의 데이터를 shapefile로 내보낼 수 있지만 추가 단계입니다.

비 토폴로지 PostGIS 기능

PostGIS에서는 ST_EndPointST_StartPoint 함수를 사용하여 선 스트링의 끝과 시작 지점을 얻을 수 있습니다. 그런 다음 ST_DWithi n과 ST_Distance 의 조합을 사용하여 가까운 지오메트리에서 가장 가까운 시작점 또는 끝점을 찾을 수 있습니다. 포인트가 많으면 인덱스가 있다고 가정하면 ST_DWithin이 쿼리 속도를 크게 향상시킵니다. 거기에서 수정 될 지점과 수정 될 지점을 정의하는 규칙을 설정해야합니다.

여기서 장점은 청소를 위해 데이터를 GRASS로 보낼 필요는 없지만주의해야 할 함정이 있다는 것입니다.

토폴로지 PostGIS 기능

이 질문은 PostGIS 위상 기능을 언급했습니다. 이것들은 훌륭하지만 위키가 설명 하듯 이 모서리, 노드 및면을 명시 적으로 정의해야합니다. 토폴로지에 알려진 문제가 있으므로 데이터 세트에 문제가 될 것입니다.


1

PostGIS에는 스냅 기능이 있습니다. 아마도 도움이 될까요?

ST_Snap: 입력 형상의 세그먼트와 정점을 참조 형상의 정점에 스냅합니다.

ST_SnapToGrid: 입력 형상의 모든 점을 일반 그리드에 스냅합니다.


1
고마워, 나는이 기능을 알고있다. ST_Snap은 모든 노드를 스냅 합니다. 시작 및 종료 노드 만 원합니다. ST_SnapToGrid는 기존의 모든 지오메트리를 수정하고 다른 세그먼트에 간신히 접근하기 때문에 더 가까운 노드를 이동할 가능성이 있기 때문에 실제로 적합하지 않습니다.
Jelmer Baas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.