Çok geometriden çözünmüş tampon oluşturma (Paylaşılan öznitelik ve uzamsal kesişime göre birleştirme)


10

Çok noktalı giriş özelliklerinden çözünmüş tamponlar oluşturmam gerekiyor. Aşağıdaki örnekte, giriş tablosu 4 özellik içermektedir. Özellik #2iki nokta geometrisinden oluşur. Bir tampon oluşturduktan sonra, 4 çokgen geometrisi elde ediyorum:

resim açıklamasını buraya girin

Sonucu gruplamanın bir yolu var mı? Puan tamponlar #1ve #2eritilir ve tek bir çoklu-çokgen özelliği olmalıdır ( a).

Şimdiye kadar yaptığım:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/) AS geom
FROM
public.multipoints)
AS sub_qry;

DÜZENLE:

-- create sample geometries

CREATE TABLE public.multipoints (
gid serial NOT NULL,
geom geometry(MultiPoint, 31256),
CONSTRAINT multipoints_pkey PRIMARY KEY (gid)
);

CREATE INDEX sidx_multipoints_geom
ON public.multipoints
USING gist
(geom);

INSERT INTO public.multipoints (gid, geom) VALUES
(1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),
(2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),
(3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
(4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256));

Alt sorguları çok fazla kullanıyorsunuz. Bu, kümelemek istediğiniz öznitelikte GROUP BY ile olan yeteneğinizi gösterir.
Vince

Bu nedenle, bir uzamsal birlik ve sonra özellik numarasına dayalı bir birlik yapmalısınız, bu yüzden yukarıdaki şemadan 3 çokgenlik bekliyorsunuz. Bunun iki adımlı bir süreç gerektireceğinden şüpheleniyorum, ancak bir cevap vermeden önce soruda net olmak istedim.
John Powell

Evet, arabellek çokgenlerini birleştirmek ve girdi özelliklerinin sayısına göre sonucu toplamak istiyorum.
eclipsed_by_the_moon

herhangi bir güncelleme var mı_ Bunun sizin için işe yarayıp yaramadığını bilmek istiyorum, görebildiğim kadarıyla soruyu cevapladım.
John Powell

Geç cevap verdiğim için üzgünüm, birkaç gündür çevrimiçi değilim.
eclipsed_by_the_moon

Yanıtlar:


7

Bazı rasgele noktalarla başlayarak, OP görüntüsünde, ilk ikisinin mekansal olarak kesiştiği yerlere taklit etme girişiminde, 2. ve 3. aynı özellik kimliğine (2) sahip, mekansal olarak kesişmeyen veya sahip olmayan birkaç nokta daha var. aynı öznitelikte, aşağıdaki sorgu 3 küme üretir:

WITH 
  temp (id, geom) AS 
     (VALUES (1, ST_Buffer(ST_Makepoint(0, 0), 2)),
        (2, ST_Buffer(ST_MakePoint(-0.7,0.5), 2)),
        (2, ST_Buffer(ST_MakePoint(10, 10), 2)), 
        (3, ST_Buffer(ST_MakePoint(-2, 12), 2)), 
        (4, ST_Buffer(ST_MakePoint(5, -6), 2))),
 unions(geoms) AS 
      (SELECT ST_Union(geom) FROM temp GROUP BY id),
 clusters(geoms) AS 
      (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
         FROM unions),
 multis(id, geoms) AS 
      (SELECT row_number() over() as id, geoms FROM clusters)
 SELECT ST_UNION(d.geom) FROM 
      (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

Burada birkaç adım var:

  1. kullanmak ST_Unionözelliğe göre ilk gruba, kimliğine göre, gruplama
  2. ST_ClusterIntersectingmekansal olarak kesişen aynı gruptaki insanları birleştirmek için kullanın
  3. kümelerin her birine bir kimlik ekleyin (tablo multis) - bunu doğrudan ClusterIntersecting'te yapmaya çalışmak, 1
  4. 2. adımdaki dökümlenmiş geometrileri, 3. adımdaki kimliğe göre gruplandırın - bu çözülme kısmıdır. Bu, küme A'nızdaki üst üste gelen iki çokgenin üst üste gelmek yerine adım 2'nin sonunda olduğu gibi birbirine birleştirilmesine neden olur.

Oldukça uzun, ama işe yarıyor (ve daha kısa bir yol olduğuna eminim).

QGIS'de WKT aracını kullanmak (ve düzenleme araçlarıyla ne kadar korkunç olduğumu keşfetmek), a olarak etiketlenmiş kümeyi görebileceğiniz aşağıdaki gibi kümeler üretir - yani tek renk.

resim açıklamasını buraya girin

Bir ST_AsText finaline ST_UNION (d.geom) koyarsanız, sonuçları doğrudan görebilirsiniz.

Yorumlarda daha fazla bilgi DÜZENLEYİN: Noktalarla başlarken tamponu orijinal çözümüme dahil etmeniz gerekecek - bu da şemayı taklit etmek için başlangıçta geçici CTE'ye koydum. Tamponları CTE sendikalarına eklemek daha kolay olacaktır, böylece tüm geometrileri bir kerede yapabilirsiniz. Dolayısıyla, örnek olarak 1000 arabellek mesafesi kullanıldığında, aşağıdakiler artık beklendiği gibi 3 küme döndürmektedir.

WITH temp(id, geom) AS 
  (VALUES 
      (1, ST_SetSRID(ST_GeomFromText('MultiPoint(12370 361685)'), 31256)),   
      (2, ST_SetSRID(ST_GeomFromText('MultiPoint(13520 360880, 19325 364350)'), 31256)),                                                
      (3, ST_SetSRID(ST_GeomFromText('MultiPoint(11785 367775)'), 31256)),
      (4, ST_SetSRID(ST_GeomFromText('MultiPoint(19525 356305)'), 31256))
),                                              
unions(geoms) AS 
  (SELECT st_buffer(ST_Union(geom), 1000) FROM temp GROUP BY id),
clusters(geoms) AS 
  (SELECT ST_CollectionExtract(unnest(ST_ClusterIntersecting(geoms)), 3) 
     FROM unions),
multis(id, geoms) AS 
  (SELECT row_number() over() as id, geoms FROM clusters)
SELECT id, ST_UNION(d.geom) FROM 
  (SELECT id, (ST_DUMP(geoms)).geom FROM multis) d GROUP BY id;

Üzgünüm sana geri dönmek çok uzun sürdü. QGIS'de tampon geometrilerini görselleştirmekte biraz sorun yaşıyorum. Ben kullanarak sorguyu değiştirmek için çalıştık ST_SetSRID, ST_Multive ::geometry(Multipolygon, /*SRID*/), ama şu anda işe yaramıyor.
eclipsed_by_the_moon

Tamam, kodunuzu ve daha da iyi bazı verileri gönderebilirseniz, yardımcı olabilirim.
John Powell

Örnek noktaları oluşturmak için bazı SQL ekledim.
eclipsed_by_the_moon

Bugün biraz bağlandım, en kısa sürede geri döneceğim. Çok noktalı sorguya da çalışmak zorunda kalacak.
John Powell

3

Bunu yapmanın bir yolu, ST_Uniontüm tamponlara birlikte, ST_Dumpsonuçtaki poligonun bileşenlerini elde etme ve ST_Intersectsher bir kümede kaç tane / hangi noktayı oluşturduğunu bulmak için giriş noktalarına geri birleşmektir .

Bu, çağrı yapmadan önce noktaları bir araya getirerek birleştirme gerektirmeden yapılabilir ST_Buffer. Aynı çözünmüş tampon içinde iki noktanın bulunabilmesi için, bunlardan daha kısa bir mesafe arasındaki sıçramalarla erişilebilmelidir eps. Bu, yalnızca aşağıdakiler kullanılarak çözülebilen minimum bağlantı kümeleme sorunudur ST_ClusterDBSCAN:

SELECT
  cluster_id,
  ST_Union(ST_Buffer(geom, 1000)) AS geom,
  count(*)                        AS num_points,
  array_agg(point_id)             AS point_ids
FROM (
  SELECT
    point_id,
    ST_ClusterDBSCAN(geom, eps := 2000, minpoints := 1) OVER() AS cluster_id ,
    geom
  FROM points) sq
 GROUP BY cluster_id;

PostGIS arabellekleri mükemmel daireler olmadığından ve 1000m aralıkla iki nokta iki 500m arabellekle bağlanamayabileceğinden, bunun arabellek ilkiyle aynı sonucu vermeyeceğini unutmayın.


Benzer bir fikrimiz var gibi görünüyor. Sizinkini test etmedim, ama eminim işe yarıyor ve benimkinden daha temiz.
John Powell

PostGIS 2.2.1'in ST_ClusterDBSCAN'ı desteklemediği anlaşılıyor. PostGIS 2.3.2'yi yükledim, ancak pgAdmin'deki yeni postgis uzantıları hala sürüm 2.2.1.
eclipsed_by_the_moon

0

Bu cevaba göre alt sorgunuzda ST_DUMP yapmak istiyorsunuz.

Bunun gibi bir şey:

-- collect all buffers to a single multi-polygon feature
-- dissolve overlapping polygon geometries
CREATE TABLE public.pg_multibuffer AS SELECT
    row_number() over() AS gid,
    sub_qry.*
FROM (SELECT
    ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8))::geometry(MultiPolygon, /*SRID*/)) AS geom
FROM
public.multipoints)
AS sub_qry;

Bunun nedeni ST_UNION, tüm özelliklerin çözünmüş bir ST_DUMPçokgenini döndürür ve bunu ayrı ayrı çokgen özelliklerine (çözülmüş olan) ayırır.


1
Bu gerçekten işe yaramaz, çünkü istenen çok parçalı çokgeni kümelemek için gerekli olan tüm özellikler kaybedilmiş olacaktır.
Vince

Denedim ST_Multi((ST_Dump(ST_Union(ST_Buffer(geom, 1000, 8)))).geom)::geometry(MultiPolygon, /*SRID*/) AS geom, ancak bu 3 yerine 4 özellik oluşturur.
eclipsed_by_the_moon

Oh, doğru, numaraya göre gruplandırmak ister misin? Senden GROUP_BYönce ihtiyacın olacak ST_UNION.
Alex Leith
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.