Làm thế nào để lặp đệ quy qua các đa giác cha mẹ để có được đa giác nhỏ nhất (con) không có chồng chéo?


11

Tôi đang vật lộn với một vấn đề trong vài ngày và nhận ra nhiều người cũng gặp khó khăn khi chủ đề là giao điểm trong PostGIS (v2,5). Đó là lý do tại sao tôi quyết định hỏi một câu hỏi phổ biến và chi tiết hơn.

Tôi có bảng sau:

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 );

Nó trông như thế này:

khởi đầu

Tôi muốn có được tất cả các đa giác con dựa trên giao điểm của đa giác cha. Đối với kết quả, nó sẽ được mong đợi:

  • Các đa giác con không có sự chồng chéo giữa chúng.
  • Một cột chứa tổng giá trị của đa giác cha của chúng,
  • Một cột chứa số lượng đa giác cha của một loại
  • Một cột chứa số lượng của một loại khác
  • Một cột chứa danh mục của đa giác con, dựa trên quy tắc sau: -Nếu TẤT CẢ các đa giác cha là từ một lớp, đa giác con cũng có lớp này. Khác, thể loại của đa giác con là một thể loại thứ ba.

Vì vậy, nó trông giống như nó:

đầu ra

Vì vậy, cuối cùng, bảng sản lượng tạo ra (ví dụ này) sẽ có 7 hàng (tất cả 7, không chồng chéo, đa giác con), chứa các cột category, sum_value, ct_overlap_cat1,ct_overlap_cat2

Đoạn mã sau tôi đã bắt đầu, cung cấp cho tôi các giao điểm riêng lẻ, so sánh cha mẹ này với cha mẹ khác.

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);

Làm thế nào để tôi lặp lại đệ quy thông qua kết quả của mã được đề cập này, rằng, độc lập với số lượng đa giác chồng lấp, tôi luôn nhận được đa giác 'nhỏ nhất' (con) của nó (Hình 2)?

Câu trả lời:


8

Thử cái này xem sao:

Tải xuống các Addon PostGIS từ liên kết này: https://github.com/pedrogit/postgisaddons

Cài đặt bằng cách chạy tệp postgis_addons.sql để lấy hàm ST_SplitAgg ().

Kiểm tra bằng cách chạy tệp postgis_addons_test.sql.

Đây là truy vấn của bạn:

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

Tôi đã xem addons git repo của bạn trước đây. Công cụ truyền cảm hứng.
John Powell

Wow giải pháp tuyệt vời. Bạn cũng đã làm một công việc khá tuyệt vời để tạo ra các addon này. Trước khi tôi nhấp để trao giải cho câu trả lời này, tôi chỉ cần một để chắc chắn về một điều khiến tôi bận tâm. Chạy mã bạn cung cấp, 'đa giác 5' (của hình thứ hai của câu hỏi) dường như không nhận ra sự trùng lặp với một đa giác khác ('ct_overlap_cat2 = 1'; 'ct_overlap_cat2 = 0'). Do đó, đa giác này kết thúc được phân loại là 'cat1' và 'sum = 2', thay vì 'cat3' và 'sum = 7'. Tôi đang đối mặt với một chút khó khăn để gỡ lỗi vấn đề nhỏ này. Bạn có thể giúp tôi?
Matt_Geo

1
Vấn đề duy nhất với giải pháp này là các báo cáo trường hợp được mã hóa cứng. Về nguyên tắc, nó có thể có thể xử lý một số lượng các danh mục tùy ý.
John Powell

@Matt_Geo Tôi nhận được 6 đa giác trong bảng kết quả. Đa giác tam giác được chia thành ba. Một với tổng = 2, một với tổng = 7 và một với tổng = 8 như trong hình mong muốn của bạn.
Pierre Racine

1
Nếu bạn thay thế ST_Centroid (geom) bằng ST_Area (geom) thì sao?
Pierre Racine

1

Tôi cho rằng nếu bạn sử dụng loại hình học đa giác thay vì MultiPolygon, mọi thứ sẽ rơi vào vị trí:

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 );

Kết quả là 9 mục tương ứng với các tùy chọn giao nhau khác nhau trong ví dụ do bạn cung cấp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.