부모 다각형 교차점을 반복적으로 반복하여 중첩없이 가장 작은 (자식) 다각형을 얻는 방법은 무엇입니까?


11

나는 며칠 동안 문제로 어려움을 겪고 있으며 PostGIS (v2.5)의 주제가 교차 할 때 많은 사람들이 붙어 있다는 것을 깨달았습니다. 그래서 더 상세하고 일반적인 질문을하기로 결정했습니다.

다음 테이블이 있습니다.

DROP TABLE IF EXISTS tbl_foo;
CREATE TABLE tbl_foo (
    id bigint NOT NULL,
    geom public.geometry(MultiPolygon, 4326),
    att_category character varying(15),
    att_value integer
);
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (1, ST_SetSRID('MULTIPOLYGON (((0 6, 0 12, 8 9, 0 6)))'::geometry,4326) , 'cat1', 2 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (2, ST_SetSRID('MULTIPOLYGON (((5 0, 5 12, 9 12, 9 0, 5 0)))'::geometry,4326), 'cat1', 1 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (3, ST_SetSRID('MULTIPOLYGON (((4 4, 3 8, 4 12, 7 14,10 12, 11 8, 10 4, 4 4)))'::geometry,4326) , 'cat2', 5 );

다음과 같이 보입니다 :

스타트

부모 다각형의 교차점을 기준으로 모든 자식 다각형을 가져오고 싶습니다. 결과적으로 다음과 같이 예상됩니다.

  • 하위 다각형은 서로 겹치지 않습니다.
  • 부모 폴리곤 값의 합계를 포함하는 열
  • 한 범주의 부모 다각형 수를 포함하는 열
  • 다른 범주의 개수를 포함하는 열
  • 다음 규칙에 따라 자식 다각형의 범주를 포함하는 열입니다.-모든 부모 다각형이 하나의 클래스에서 온 경우 자식 다각형에도이 클래스가 있습니다. 그렇지 않으면 자식 다각형의 범주는 세 번째 범주입니다.

따라서 다음과 같이 보입니다.

산출

따라서, 단부 (이 예) 생성 된 출력 테이블의 열을 포함하는 7 행 (모두 7 겹치지 자식 다각형) 것 category, sum_value, ct_overlap_cat1,ct_overlap_cat2

내가 시작한 다음 코드는 한 부모를 다른 부모와 비교하여 개별 교차점을 제공합니다.

SELECT
(ST_Dump(
    ST_SymDifference(a.geom, b.geom) 
)).geom
FROM tbl_foo a, tbl_foo b
WHERE a.ID < b.ID AND ST_INTERSECTS(a.geom, b.geom)
UNION ALL
SELECT
ST_Intersection(a.geom, b.geom) as geom
FROM tbl_foo a, tbl_foo b
WHERE a.ID < b.ID AND ST_INTERSECTS(a.geom, b.geom);

중복 된 다각형의 수에 관계없이 항상 '가장 작은'(자식) 다각형을 얻는다는 언급 된 코드의 결과를 재귀 적으로 반복하는 방법은 무엇입니까 (그림 2)?

답변:


8

이 시도:

이 링크에서 PostGIS 애드온을 다운로드하십시오 : https://github.com/pedrogit/postgisaddons

postgis_addons.sql 파일을 실행하여 ST_SplitAgg () 함수를 가져와 설치하십시오.

postgis_addons_test.sql 파일을 실행하여 테스트하십시오.

검색어는 다음과 같습니다.

WITH  result_table AS (
    WITH  parts AS (
      SELECT a.att_value val,
             CASE WHEN a.att_category = 'cat1' THEN 1 ELSE 0 END cat1,
             CASE WHEN a.att_category = 'cat2' THEN 1 ELSE 0 END cat2,
             unnest(ST_SplitAgg(a.geom, b.geom, 0.00001)) geom
      FROM tbl_foo a,
           tbl_foo b
      WHERE ST_Equals(a.geom, b.geom) OR
            ST_Contains(a.geom, b.geom) OR
            ST_Contains(b.geom, a.geom) OR
            ST_Overlaps(a.geom, b.geom)
      GROUP BY a.id, a.att_category , ST_AsEWKB(a.geom), val
    )
    SELECT CASE WHEN sum(cat2) = 0 THEN 'cat1'
                WHEN sum(cat1) = 0 THEN 'cat2'
                ELSE 'cat3'
           END category, 
           sum(val*1.0) sum_value, 
           sum(cat1) ct_overlap_cat1, 
           sum(cat2) ct_overlap_cat2, 
           ST_Union(geom) geom
    FROM parts
    GROUP BY ST_Area(geom)
)
SELECT category, sum_value, ct_overlap_cat1, ct_overlap_cat2,
(ST_Dump(result_table.geom)).geom as geom
FROM result_table

전에 애드온 git repo를 살펴 보았습니다. Inspirstionsl 물건.
John Powell

와우 훌륭한 솔루션. 이 애드온을 만드는데도 놀라운 일을했습니다. 이 답변에 클릭하여이 답변을 수여하기 전에 한 가지만 확인하면됩니다. 제공 한 코드를 실행하면 '질문의 두 번째 그림 중'폴리곤 5 '가 다른 다각형과의 겹침을 인식하지 못하는 것 같습니다 ('ct_overlap_cat2 = 1 ';'ct_overlap_cat2 = 0 '). 따라서이 다각형은 'cat3'과 'sum = 7'대신 'cat1'과 'sum = 2'로 분류됩니다. 이 작은 문제를 디버깅하는 데 약간의 어려움이 있습니다. 당신이 나를 도울 수?
Matt_Geo

1
이 솔루션의 유일한 문제점은 케이스 문이 하드 코딩되어 있다는 것입니다. 원칙적으로 임의의 수의 범주를 처리 할 수 ​​있어야합니다.
John Powell

@Matt_Geo 결과 테이블에 6 개의 다각형이 있습니다. 삼각형 폴리곤은 3 개로 나뉩니다. 하나는 sum = 2이고 다른 하나는 sum = 7이고 다른 하나는 sum = 8입니다.
Pierre Racine

1
ST_Centroid (geom)을 ST_Area (geom)으로 바꾸면 어떻게됩니까?
Pierre Racine

1

MultiPolygon 대신 폴리곤 지오메트리 유형을 사용하면 모든 것이 제 위치에 있다고 가정합니다.

DROP TABLE IF EXISTS tbl_foo;
CREATE TABLE tbl_foo (
    id bigint NOT NULL,
    geom public.geometry(Polygon, 4326),
    att_category character varying(15),
    att_value integer
);

INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (1, ST_SetSRID('POLYGON ((0 6, 0 12, 8 9, 0 6))'::geometry,4326) , 'cat1', 2 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (2, ST_SetSRID('POLYGON ((5 0, 5 12, 9 12, 9 0, 5 0))'::geometry,4326), 'cat1', 1 );
INSERT INTO tbl_foo (id, geom, att_category, att_value) VALUES 
    (3, ST_SetSRID('POLYGON ((4 4, 3 8, 4 12, 7 14,10 12, 11 8, 10 4, 4 4))'::geometry,4326) , 'cat2', 5 );

결과는 사용자가 제시 한 예에서 다른 교차 옵션에 해당하는 9 개의 항목입니다.

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