【问题标题】:PostGIS recursive intersection between polygonsPostGIS多边形之间的递归交集
【发布时间】:2013-03-15 06:31:46
【问题描述】:

我正在尝试在空间表中的所有多边形之间执行递归交集,并获取生成的(多)多边形以及每个多边形的每个交叉点的信息。

一张图片(不是真的按比例)来解释它:

假设一个表格中有A, B, C 方格。我想在输出中有A, B, C, A+B, A+C, B+C, A+B+C 多边形,我需要知道A+BAB 的交集等等。

到目前为止,我有一个执行相交的查询,但它并没有“切断”原始多边形的相交部分。例如:

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

我现在得到的AA+C 多边形的结果图像:

这是一个测试脚本,使用图像中的正方形作为数据。查看area 列,很明显缺少一些递归ST_Difference,我只是不知道怎么做。欢迎任何想法。

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

当然,在这个特定示例中,窗口函数并不是绝对必要的,但是这段代码是我真实案例的简化版本,它还做了一些额外的事情。

我正在使用 PostgreSQL 9.2 和 PostGIS 2.0

【问题讨论】:

    标签: sql postgresql postgis


    【解决方案1】:

    ST_DIFFRENCE 不必是递归的,您已经拥有所有多边形,因此您必须从每个几何图形中减去包含该 ret 但不等于它的其他几何图形的并集。这行得通,所以你应该这样做:

        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
    

    【讨论】:

    • 谢谢你,使用这样的自我加入确实非常聪明!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 2021-11-02
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多