2013-03-25 76 views
7

Tôi đang cố gắng thực hiện một giao thoa đệ quy giữa tất cả các đa giác trong một bảng không gian và thu được kết quả (đa) pololygons và thông tin về mọi giao lộ cho mỗi điểm.Giao tiếp đệ quy đệ quy giữa các đa giác

Một hình ảnh (không thực sự về quy mô) để giải thích nó: Example

Hãy nói rằng có A, B, C vuông trong một bảng. Tôi muốn có các đa giác A, B, C, A+B, A+C, B+C, A+B+C ở đầu ra và tôi cần biết rằng A+B là giao điểm của AB v.v.

Cho đến nay tôi có một truy vấn thực hiện giao lộ, nhưng nó không "cắt" phần được chia cắt của đa giác gốc. Ví dụ:

Polygon A should be  A - (A+B) - (A+C) - (A+B+C) 
Polygon A+C should be A+C - (A+B+C) 

Một hình ảnh của kết quả tôi nhận được ngay bây giờ cho các AA+C đa giác:

Current WRONG result

Dưới đây là một kịch bản kiểm tra, sử dụng các ô vuông trong hình ảnh dưới dạng dữ liệu. Nhìn vào cột area, rõ ràng là một số ST_Difference đệ quy bị thiếu, tôi không thể tìm ra cách. Bất kỳ ý tưởng được hoan nghênh.

-- Create a test table 
CREATE TABLE test (
    name text PRIMARY KEY, 
    geom geometry(POLYGON) 
); 

-- Insert test data 
INSERT INTO test (name, geom) VALUES 
    ('A', ST_GeomFromText('POLYGON((1 2, 1 6, 5 6, 5 2, 1 2))')), 
    ('B', ST_GeomFromText('POLYGON((0 0, 0 4, 4 4, 4 0, 0 0))')), 
    ('C', ST_GeomFromText('POLYGON((2 0, 2 4, 6 4, 6 0, 2 0))')); 


-- Query  
WITH RECURSIVE 
source (rownum, geom, ret) AS (
    SELECT row_number() OVER (ORDER BY name ASC), ST_Multi(geom), ARRAY[name] FROM test 
), 
r (rownum, geom, ret, incroci) AS (
    SELECT rownum, geom, ret, 0 FROM source 
    UNION ALL 
    SELECT s.rownum, ST_CollectionExtract(ST_Intersection(s.geom, r.geom), 3), (r.ret || s.ret), (r.incroci + 1) 
     FROM source AS s INNER JOIN r ON s.rownum > r.rownum AND ST_Intersects(s.geom, r.geom) AND ST_Area(ST_Intersection(s.geom, r.geom)) > 0.5 
), 
result (geom, ret) AS (
    SELECT ST_Union(geom) AS geom, ret FROM r GROUP BY ret 
) 
SELECT geom, ST_Area(geom) AS area, ret FROM result ORDER BY ret 

Chức năng cửa sổ không thực sự cần thiết trong ví dụ cụ thể này, nhưng mã này là phiên bản đơn giản của trường hợp thực của tôi, một vài thứ khác ở bên cạnh.

Tôi đang sử dụng PostgreSQL 9.2 và PostGIS 2.0

Trả lời

4

ST_DIFFRENCE không phải là đệ quy, bạn đã có tất cả các đa giác như vậy từ mỗi Geom bạn phải trừ sự kết hợp của geoms khác có chứa rằng ret nhưng không bằng với nó. Điều này hoạt động, do đó bạn nên làm như vậy:

WITH RECURSIVE 
source (rownum, geom, ret) AS (
    SELECT row_number() OVER (ORDER BY name ASC), ST_Multi(geom), ARRAY[name] FROM test 
), 
r (rownum, geom, ret, incroci) AS (
    SELECT rownum, geom, ret, 0 FROM source 
    UNION ALL 
    SELECT s.rownum, ST_CollectionExtract(ST_Intersection(s.geom, r.geom), 3), (r.ret || s.ret), (r.incroci + 1) 
     FROM source AS s INNER JOIN r ON s.rownum > r.rownum AND ST_Intersects(s.geom, r.geom) AND ST_Area(ST_Intersection(s.geom, r.geom)) > 0.5 
), 
result (geom, ret) AS (
    SELECT ST_Difference(ST_Union(r.geom),q.geom) AS geom, r.ret FROM r JOIN (SELECT r.ret,ST_UNION(COALESCE(r2.geom,ST_GeomFromText('POLYGON EMPTY'))) as geom FROM r LEFT JOIN r AS r2 ON r.ret<@r2.ret AND r.ret!=r2.ret GROUP BY r.ret) AS q on r.ret=q.ret GROUP BY r.ret,q.geom 
) 
SELECT geom, ST_Area(geom) AS area, ret FROM result ORDER BY ret 
+0

Cảm ơn bạn, rất thông minh thực sự sử dụng tự tham gia như thế! – Eggplant