ST_Difference를 사용하여 겹치는 기능을 제거 하시겠습니까?


11

ST_Difference를 사용하여 PostGis 2.1 (및 Postgres SQL 9.3)을 사용하여 다른 다각형 세트 (test.single_geometry_1)로 커버되는 영역을 포함하지 않는 다각형 세트 (processing.trimmedparcelsnew)를 만들려고합니다. 내 쿼리는 다음과 같습니다.

CREATE TABLE processing.trimmedparcelsnew AS
SELECT
    orig.id, ST_Difference(orig.geom, cont.geom) AS difference
FROM 
    test.single_geometry_1 cont,
    test.multi_geometry_1 orig;

그러나 결과로 생성 된 다각형은 다듬어지지 않았으며 다른 레이어와 교차하는 지점에서 분할 된 것으로 보입니다. 결과를 테이블에 넣지 않고 다른 것을 생각하지 않고 select를 실행하려고 시도했지만이 기능을 작동시킬 수없는 것 같습니다.

결과의 그림을 첨부했습니다

여기에 이미지 설명을 입력하십시오


의견을 말한 후 WHERE 절을 추가하려고했습니다. 교차점이없는 소포를 원하고 다른 소포의 교차 영역이 제거되었습니다 (층 test.single_geometry는 필자가 소포에서 제거한 오염을 나타냅니다). 나는 교차를 시도했지만 물론 비 교차를 원하므로 이제는 분리를 시도하고 있습니다. 나는 또한 내 테이블에 orig를 추가하려고 시도했지만 ST_Difference ( http://postgis.net/docs/ST_Difference.html )에 대한 문서는 필요한 정확한 형상 (지오메트리 A의 해당 부분을 나타내는 형상)을 반환한다고 말합니다. 지오메트리 B)와 교차하지 않으므로 대신 테이블의 원래 다각형을 원할 이유가 혼란 스럽습니다. 어쨌든, 여기 수정 된 코드가 있습니다.

CREATE TABLE processing.trimmedparcelsnew AS
SELECT
    orig.id, ST_Difference(orig.geom, cont.geom) AS difference, orig.geom AS geom
FROM 
    test.single_geometry_1 cont,
    test.multi_geometry_1 orig
WHERE ST_Disjoint(orig.geom, cont.geom);

dbaston의 답변에 따라 이제 시도했습니다.

CREATE TABLE processing.parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.single_geometry_1 b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;

그 결과는 test.multi_geometry_1의 사본 일뿐입니다. 이제 분할이 더 이상 발생하지 않습니다.

이전 버전을 시도했지만 다시 test.multi_geometry_1의 사본을 얻습니다.

CREATE TABLE processing.parcels_trimmed_no_coalesce AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.single_geometry_1 b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.multi_geometry_1 a;

내가 잘못하고있는 것이 있는지 궁금해하고 있습니다. 진행 진술은 다음과 같습니다

DROP TABLE IF EXISTS processing.parcels_trimmed_no_coalesce;

그리고 PostgreSQL SQL 쿼리 창과 Openjump에서 쿼리를 실행하고 있습니다.

표를 보는 데 사용하는 진술은 다음과 같습니다.

SELECT * FROM processing.parcels_trimmed_no_coalesce;

단순화를 위해이 쿼리를 다음과 같이 줄였습니다.

SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM test.geometriestocutagainst b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM test.geometriestocut a;

원하는 결과가 test.geometriestocutagainst에 대해 트리밍 된 원본 일 때 여전히 원래 다각형 (test.geometriestocut)이됩니다.


WHERE절을 지정하지 않았 으므로 결과 테이블에 다항식 확장이있을 수 있습니다. 행이 몇 개 trimmedparcelsnew입니까?
Vince

교차점의 차이 만 원한다면 WHERE ST_Intersects (orig.geom, cont.geom)를 추가해보십시오. 그렇지 않으면 교차하지 않는 두 다각형의 차이는 원래 다각형입니다.
John Powell

잘린 소포에는 24 개의 행이 있으며, 교차하지 않아도 차이를 원하므로 차이가 아닌 테이블에서 orig.geom을 사용해야한다고 수정합니까?
Mart

각 기능 - 끊긴 테스트는 다항식 확장을 생산해야 계속을 모든 기능에 대해 한 번 표시 오리지널 겹치지 않는, 그 차이는 것입니다 결코 입력 형상 변경하지
빈스

설명에 감사드립니다. 그러나 여전히 원래 코드가 작동하지 않는 이유는 확실하지 않습니다. ST_Difference (orig.geom, cont.geom)이 b와 교차하지 않는 a의 도형을 반환하면 왜 b와 교차하지 않는 a의 도형이 아닌 분할 형상이 테이블에 포함됩니까?
Mart

답변:


14

자체 조인을 사용하면 두 기능 간의 관계를 조작 할 수 있습니다. 그러나 나는 당신이 쌍에 관심이 있다고 생각하지 않습니다. 각 기능에 대해 해당 기능과 데이터 세트의 다른 모든 기능 간의 관계를 운영하고 싶습니다 . 서브 쿼리 표현식으로이를 수행 할 수 있습니다.

CREATE TABLE parcels_trimmed AS
SELECT id, ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                FROM parcels b
                                WHERE ST_Intersects(a.geom, b.geom)
                                  AND a.id != b.id))
FROM parcels a;

그러나 결과에 이상한 것이있을 수 있습니다. 겹치지 않는 소포는 완전히 삭제됩니다! 즉 때문이다 ST_Union빈 레코드에 대한 집계가 될 것입니다 NULL, 그리고 ST_Difference(geom, NULL)이다 NULL. 이를 원활하게하려면 다음과 같이 ST_Difference통화 를 감싸 야합니다 COALESCE.

CREATE TABLE parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Union(b.geom) 
                                         FROM parcels b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         AND a.id != b.id)), a.geom)
FROM parcels a;

의 결과가 경우에 것을이 수단 ST_Difference이다 NULL의 합체 표현이 원래의 형상으로 평가합니다.

위의 쿼리는 도메인에서 겹치는 영역을 완전히 제거합니다. 대신 승자를 선택하려면 대신 a.id < b.id또는 대신 다른 기준을 사용할 수 a.id != b.id있습니다.


응답 주셔서 감사합니다, 불행히도이 작업을 수행하는 데 문제가 있습니다. 대신 원래 다각형으로 끝납니다 (a). 추가 정보로 질문을 편집하겠습니다. 다시 감사합니다.
Mart

2

나는 너와 같은 문제가 있었다. 귀하의 문제에 대한 해결책을 이미 찾았는지 모르겠지만 위의 답변을 수정하여 원하는 것을 얻었습니다.

CREATE TABLE parcels_trimmed AS
SELECT id, COALESCE(ST_Difference(geom, (SELECT ST_Collect(b.geom) 
                                         FROM parcels b
                                         WHERE ST_Intersects(a.geom, b.geom)
                                         )), a.geom)
FROM parcels a;

1

PostGIS Addons 에서 ST_DifferenceAgg ()를 사용 합니다 . 두 테이블을 함께 병합하고 기하학 열에 고유 식별자와 색인이 있어야합니다. 다음은 간단한 예입니다.

WITH overlappingtable AS (
  SELECT 1 id, ST_GeomFromText('POLYGON((0 1, 3 2, 3 0, 0 1), (1.5 1.333, 2 1.333, 2 0.666, 1.5 0.666, 1.5 1.333))') geom
  UNION ALL
  SELECT 2 id, ST_GeomFromText('POLYGON((1 1, 3.8 2, 4 0, 1 1))')
  UNION ALL
  SELECT 3 id, ST_GeomFromText('POLYGON((2 1, 4.6 2, 5 0, 2 1))')
  UNION ALL
  SELECT 4 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))')
  UNION ALL
  SELECT 5 id, ST_GeomFromText('POLYGON((3 1, 5.4 2, 6 0, 3 1))')
)
SELECT a.id, ST_DifferenceAgg(a.geom, b.geom) geom
FROM overlappingtable a,
     overlappingtable b
WHERE a.id = b.id OR -- Make sure to pass at least once the polygon with itself
      ((ST_Contains(a.geom, b.geom) OR -- Select all the containing, contained and overlapping polygons
        ST_Contains(b.geom, a.geom) OR
        ST_Overlaps(a.geom, b.geom)) AND
       (ST_Area(a.geom) < ST_Area(b.geom) OR -- Make sure bigger polygons are removed from smaller ones
        (ST_Area(a.geom) = ST_Area(b.geom) AND -- If areas are equal, arbitrarily remove one from the other but in a determined order so it's not done twice.
         a.id < b.id)))
GROUP BY a.id
HAVING ST_Area(ST_DifferenceAgg(a.geom, b.geom)) > 0 AND NOT ST_IsEmpty(ST_DifferenceAgg(a.geom, b.geom));

겹치는 부분을 가장 큰 겹치는 다각형과 병합합니다. 겹치는 부분을 분리하여 유지하려면 ST_splitAgg () 예제를보십시오.

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