2013-03-25 22 views
7

Mekansal bir Tablodaki tüm Çokgenler arasında yinelemeli bir kesişim yapmaya çalışıyorum ve sonuçta ortaya çıkan (çoklu) poliologları ve her bir kesişim hakkında bilgileri elde etmeyi deneyeceğim.PostGIS Çokgenler arasındaki yinelemeli kesişme

bir görüntü (gerçekten ölçekli) açıklamak: Example

en tablodaki A, B, C kare var diyelim. Çıkışta A, B, C, A+B, A+C, B+C, A+B+C çokgen olmasını isterim ve A+B'un A ve B kesişim noktası olduğunu bilmem gerekir.

Şimdiye kadar kesişimleri gerçekleştiren bir sorguya sahibim, ancak orijinal çokgenlerin kesişen kısmını "kesmiyor". Örneğin:

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

Ben A ve A+C poligon üzere hemen olsun sonucun bir görüntü: İşte

Current WRONG result

veri olarak görüntülerde kareler kullanılarak, bir test yazısıdır. area sütununa bakarak, bazı özyinelemeli ST_Difference'ın eksik olduğu açık, sadece nasıl olduğunu anlayamıyorum. Herhangi bir fikir karşılandı.

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

pencere fonksiyonu elbette bu özel örnekte kesinlikle gerekli değildir, ancak bu kod tarafında birkaç şey yapar benim gerçek durumda, basitleştirilmiş bir versiyonudur.

seni her sen ret olduğunu içeren diğer geoms birliği substract zorunda GeoM gelen bu nedenle tüm poligonları var zaten, 2.0

cevap

4

ST_DIFFRENCE özyinelemeli olmak zorunda değildir PostgreSQL 9.2 ve PostGIS kullanıyorum ama ona eşit değil. Bu şekilde çalışmanız gerekir:

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

Teşekkürler, gerçekten çok akıllı, böyle bir kendi kendine birleştirme kullanın! – Eggplant