Ayrık çokgenlerden Voronoi Diyagramı gibi mozaik oluşturun


12

Aşağıdaki şekilde sorun gösterilmektedir :

resim açıklamasını buraya girin

olarak (a) Ben geometrileri gibi ayrık çokgen, bir dizi PostGIS içinde. Ben bir "etki bölgesi" kriterleri ile inşa (b) , bu çokgenler kümesi "mozaik" gibi bir şeye ihtiyacım var ... (c) ile gösterilen bir Voronoi inşaat gibi : aslında, eğer çokgenler puan, etki bölgeleri Voronoi.

Özetleme: Ben ayrık çokgenler bir dizi "mozaik" üreten bir SQL algoritması (veya PostGIS için bazı özel) gerekir. (belki küçük ST_Buffer ve ST_Difference işlemlerinin bir döngüsü)

Not: Voronoi gibi boşluk sınırlamasının ( (b) ' deki kare bir çerçeve ) göz ardı edilmesine ihtiyacım var.


Bu sorun, çizgilerle ilgili olana benzer .

EDIT (@FelixIP yorumundan sonra)

Vektör evreninde kalmayı, hassasiyetini kaybetmemeyi tercih ediyorum (örn. ST_DelaunayTriangles kullanarak ve orijinal çokgenler tarafından iç mekanların toplanması ve çıkarılması, çift ​​grafik çözümünü uyarlamaları ) ... pprepair ( QGIS topolojik araçları gibi yardımcı) gibi bazı basit ve otomatik paketler otomatik değildir). Ancak raster belki de daha basit ve daha az CPU tüketir.

Bu "GRID süreci" gösterimi aynı hassasiyete ve "öklid etki bölgesinin büyümesine" izin verdiği varsayılarak çözüm olarak da geçerlidir.

resim açıklamasını buraya girin

ARCGIS'de Öklid Tahsisi olarak bilinen bir uzamsal analiz aracı vardır, bu nedenle, çokgen kümesinden başlayarak (çokgenlerin sınıflandırılması, rasterleştirilmesi ve geri getirilmesi) belki de PostGIS benzeri bir çözüm vardır .


Teşekkürler @Nir, noktalar ile karışıklık özür dilerim, puan kullanmıyorum, sadece çokgenler resimde (a) ve (b) öğeleri olarak ... Çözüm hakkında ipucunuz var mı?
Peter Krauss

Arcgis'te, okaliptüs tahsisi veya yakınlığı adı verilen bir raster çözümü var
FelixIP

Teşekkürler @FelixIP, "iyi raster çözümleri" için düzenlenmiş ;-)
Peter Krauss

Çokgenlerinizi kapsamlarından silerseniz. Aspolygon, çokgen kalır. İskeleti gis.stackexchange.com/questions/177/… Sanırım ihtiyacın olan şey bu. Uygulama büyük bir
gerçektir

1
@Cyril, senaryonuzu inceleyebilirim ... Gelecek hafta. Modern PostGIS işlevleriyle çözüm gibi görünen bir şey yayınlamak iyi bir ilk adım olacaktır.
Peter Krauss

Yanıtlar:


2

Bu yüzden, sizin için bir pasta hazırlayacağım - meyve tabağı, PostGIS araçlarını kullanarak, istediğiniz gibi, soruyu doğru bir şekilde anladıysam ve bahsettiğim gibi, PostGIS fırınının işletilmesinin sorumluluğu yaratıcı ekibi tarafından karşılanıyor.

Mizahi tarzımda kimsenin rahatsız olmamasını ve oyun olarak anlamasını isteyeceğim!

Orijinal dosya dilimlenmiş meyve ve basit şekillerdir (bundan sonra meyve olarak anılacaktır), aşağıdaki Şekil 1'e bakın.

resim açıklamasını buraya girin

İşte benim tarifim ve daha sonra öğreneceğiniz sevgili programcılar tarafından bana yardımcı olacağım. Başlayalım ve bunun için meyvelerinizin yerleştirileceği bir hamur oluşturacağız, bunun için senaryoyu çalıştırın:

create table poly_extent as SELECT ST_SetSRID(ST_Buffer(ST_Envelope(ST_Extent(geom)),0.05),4326) as geom FROM poly;

Aşağıdaki Şekil 2'deki sonuca bakın

resim açıklamasını buraya girin

Şimdi, resmimdeki gibi az sayıda meyve varsa, meyvede harici tamponun kenarlığını oluşturun veya çok fazla meyve varsa, komut dosyasını çalıştıran negatif tamponun kenarlığını oluşturun:

create table poly_buff_dump as SELECT ((ST_Dump(ST_Boundary(ST_Union(ST_Buffer((geom),0.01, 'join=mitre mitre_limit=5.0'))))).geom) geom FROM poly;

Ve her meyve etrafında tampon çizgilerini dilimleyin

UPDATE poly_buff_dump SET geom=ST_RemovePoint(geom, ST_NPoints(geom)-1) WHERE ST_IsClosed(geom)=true; Aşağıdaki Şekil 3'teki sonuca bakın

resim açıklamasını buraya girin

(Aslında, sonuç olarak kırık çizgiler elde edeceğimi düşündüm (bir daire gibi), ancak rakamlar zorsa, bazen aralar elde edilir, yanlış olanlar, örneğin, dikdörtgenin bir tarafı düştü vb. )

Sonra elde edilen çizgileri sizin için uygun bir şekilde eşit segmentlere ayırmanız ve onlardan puan almanız gerekir

create table poly_buff_dump_pt as SELECT (ST_DumpPoints((geom))).geom geom FROM poly_buff_segm;

Sonuç, aşağıdaki Şekil 4'e bakın

resim açıklamasını buraya girin

Şimdi Voronoi aracını çalıştırın, bu yerde MickyT bağlantısının önerdiği aracı kullandım: /gis//a/172246/120129 , bunun sonucunda “voronoi adıyla tablolar oluşturacaksınız” “İlk asistanımın” şeften ayrı olması, şefin teşekkürler! :-).

Bu adımdaki ikinci yol ST_VoronoiPolygons işlevini çalıştırmaktır.

Sonuç, aşağıdaki Şekil 5'e bakın

resim açıklamasını buraya girin

Şimdi, komut dosyasını çalıştırarak fazladan parçaları kesin:

create table poly_voronoi_cut as SELECT ST_Intersection(a.geom, b.geom) geom FROM voronoi a INNER JOIN poly_extent b ON ST_Intersects(a.geom, b.geom); Sonuç olarak, aşağıdaki Şekil 6'ya bakın.

resim açıklamasını buraya girin

Şimdi, LineString'deki coğrafi veri türünü hizalamak için komut dosyasını çalıştırın:

create table poly_voronoi_dump as SELECT (ST_Dump(geom)).geom as geom FROM poly_voronoi_cut; Ve şimdi "ikinci dostumdan" görevlerimi yerine getirmesini ve kek kalıbını karıştırmasını isteyeceğim (Jeff - /gis//a/785/120129 ), tek bir katmanda düzleştirelim ve bunun için , bunun için bana teşekkürler!

CREATE TABLE poly_overlay_cut AS SELECT geom FROM ST_Dump(( SELECT ST_Polygonize(geom) AS geom FROM ( SELECT ST_Union(geom) AS geom FROM ( SELECT ST_ExteriorRing(geom) AS geom FROM poly_voronoi_dump) AS lines ) AS noded_lines ) ); Şimdi senaryoyu çalıştırdığım işe gelme zamanı:

create table poly_voronoi_union as SELECT b.id, (ST_ConvexHull(ST_Union(a.geom, b.geom))) geom FROM poly_overlay_cut a INNER JOIN poly_buff_dump b ON ST_Intersects(a.geom, b.geom) GROUP BY b.id, a.geom, b.geom; ve başka bir senaryo:

create table poly_voronoi_union_area as SELECT ST_Union(ST_ConvexHull(ST_BuildArea(geom))) as geom FROM poly_voronoi_union GROUP BY id; aşağıdaki şekil 7'ye bakınız

resim açıklamasını buraya girin

Resimde görebileceğiniz gibi, kesimlerimizin ST_SnapToGrid (veya başka bir şekilde) kullanılarak bir seçenek olarak kaldırılabilen küçük katmanları vardır:

Ve son olarak, pişmiş meyvemizi pastalarımızdan keseceğiz, hatta fırının yanında biraz yorgunum var :-)

create table polygon_voronoi_result as SELECT (ST_Dump(ST_Difference(a.geom, b.geom))).geom as geom FROM poly_voronoi_union_area_snap as a JOIN poly b ON ST_Intersects(a.geom, b.geom); Sonuç bkz. Şekil 8 resim açıklamasını buraya girin

Bugünden itibaren her şey, şimdi herkes lezzetli turta pişirmeyi öğrenecek - meyve tabağı. Herkese yardım et ve herkesi sevdiğin parçaları seç.

(Gerçekten tüm insanları besleyememem üzücü, elektronik keklerle değil, gerçek keklerle, belki de açlık Dünya'da sona erecekti ...)

Düzenleme: Pasta kiraz böyle görünebilir :-):

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM poly),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT ST_Intersection(a.geom, b.geom) geom FROM tblb a JOIN poly_extent b ON ST_Intersects(a.geom,b.geom)),
tbld AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM poly GROUP BY id, geom)
SELECT id, ST_Union(a.geom) as geom FROM tblc a JOIN tbld b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

veya

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM polygons),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM polygons GROUP BY id, geom)
SELECT id, ST_Union(a.geom) geom FROM tblb a JOIN tblc b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

Komut dosyasını gözden geçirin 01.04.2020:

WITH tbla AS (
WITH atbl AS (SELECT id, (ST_ExteriorRing(((ST_Dump(geom)).geom))) geom FROM polygons),
intervals AS (SELECT generate_series (0, 501) as steps)
SELECT steps AS stp, ST_LineInterpolatePoint(geom, steps/(SELECT count(steps)::float-1 FROM intervals)) geom FROM atbl, intervals GROUP BY id, intervals.steps, geom),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM polygons GROUP BY id, geom)
SELECT id, ST_Union(a.geom) geom FROM tblb a JOIN tblc b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

İyi ve adil bir şekilde BayBaker, hepinize teşekkür ederim ve iyi şanslar,: -) ...

Orijinal çözümler.

Bu komut dosyasına ST_VoronoiDiagramsFromPolygons denir.


1
Merhaba, iyi çizimler ve iyi sonuç gibi görünüyor (!). Kısa bir tartışma önerisi, bkz. @Geogeek çözümü, QGis'deki adımlar PostGIS'in ana adımları gibi görünüyor ... Neden e gerek ST_Bufferve ST_ConvexHull? Alternatif bir algoritma var mı?
Peter Krauss

1) Bakınız, ST_Buffer ve çokgenler üzerinde, Voronoi fonksiyonunun uygulanması sırasında orijinal şekiller arasındaki ayırma çizgilerini azaltmak için oluşturulur, bu nedenle, belirtebileceğiniz tampon boyutu ne kadar büyük olursa, ayırma çizgileri o kadar düzgün şekilde bir Voronoi fonksiyonu ... 2) ST_ConvexHer çokgenden çok sayıda figürden, ihtiyacımız olan çokgenden ... 3) Bugün, bu, sorunuzu çözme vizyonum, hepimize ne olacağını bilmiyorum ve gelecekteki kararlarımız ...
Cyril Mikhalchenko

Tampon çizgilerinin bir başka önemli değeri, her bir şekil için birleşik çokgenler oluşturmak için Voronoi'nin işlevinin sonucundan parçaları seçmemize yardımcı olacaklarıdır ...
Cyril Mikhalchenko

Bu arada, kodun ve yaklaşımın iyileştirilmesini memnuniyetle karşılıyorum, böylece sonucu kötüleştirmiyorlar ...
Cyril Mikhalchenko

1
Merhaba Cyril, ST_Buffer'ın kontur çizgilerini normalleştirmek için iyi bir seçenek olduğunu kabul ediyorum, mükemmel (!). Hakkında ST_ConvexHull, Şekil 6'dan sonra poly_voronoi_unionST_ConvexHull olmadan ne tür sonuçlar elde edebileceğimiz sadece bir meraktır.
Peter Krauss

8

Postgis'in voronoi için özel bir işlevi yoktur, ancak Qgis noktalardan voronoi çokgenleri yapabilen vornoi işlevi içerir, bu nedenle qgis'i kullanarak bu sonucu elde etmek için aşağıdaki adımları izledim:

extract nodesFonksiyonları kullanarak çokgenlerden nokta yapabilir .

Qgis voroi fonksiyonları kullanarak vornoi çokgenler yapmak.

- Qgis'te mekansal bir birleşim yapın.

sonuçları çözer.

resim açıklamasını buraya girin


1
Güzel bir çözüm (!) Ve illüstrasyon teşekkürler. Geliştirebilir misiniz? Aşağıdaki sol dikdörtgene bakın, Voronoi'de 4 puan vardı ve dikdörtgenin merkezinin temsil ettiği, bölgesini bozan (kayıp üçgende) ... Belki de her bir çokgenin düzenli bir örneklemesini yapmak mümkündür ... ve belki de bazı iç noktalar.
Peter Krauss

ArcGIS'te yoğunlaştırma aracını kullanıyorum. Bu, yakınlık çokgenlerini önemli ölçüde geliştirir. +1
FelixIP

3

Tamam - Bunu biraz düşündüm ve son zamanlarda baktığım bir şey gibi buldum.

Başlangıç ​​polilerinizi alın:

resim açıklamasını buraya girin

Bir sayı ile yeni bir özellik oluştur (benim durumumda 100) Vektör-> Araştırma araçlarını -> Çokgenler aracının içindeki rastgele noktalar aracını kullanın, bu her çokgenin içinde (100) nokta oluşturur: resim açıklamasını buraya girin

Sonra Vektör-> Geometri araçları -> Voronoi, bu nokta katmanına dayalı polys oluşturmak için.

resim açıklamasını buraya girin

Artık Vektör -> Uzamsal Sorgu aracını kullanabilirsiniz: Bir çokgene (veya çokgenlerden birine) ait noktaları seçin Bu çokgene uygulanan voronoi çokgenlerinizin bir seçimini oluşturmak için uzamsal sorgu aracını kullanın. İlgili poligona karşılık gelen voroni poligonuna bir özellik ekleyin. (Sadece 1,2,3,4 kullandım)

Artık Vektör-> Coğrafi İşleme Araçları-> yeni özelliğinize göre çözünebilirsiniz.

resim açıklamasını buraya girin


Teşekkürler @AAmes (!), Çizimler iyi ve yöntem iyi bir alternatif ... Ama soru "bir SQL algoritması (veya PostGIS için belirli)" hakkında ve şimdi, fonksiyonun kullanımı hakkında ödül ST_VoronoiPolygons () , belki de tek bir tıklamayla tüm sorunu çözer ;-)
Peter Krauss

@AAmes Hızlı arama, bu yöntemin gerçekten PostGIS'de de kullanılabileceğini gösterir. Postgis'te bir çokgendeki rastgele noktaların nasıl oluşturulacağı çokgenlerden nokta oluşturmayı açıklar ve oradan oldukça düz olması gerekir.
Phil G

Benim ödül, teşvik olarak (burada hoş geldiniz!), Ama bu ANSEWER soru ve ödül gereksinimleri için çalışıyor.
Peter Krauss

Teşekkürler Peter, notlarını gördüm ama maalesef geri dönüp ona cevap verme fırsatım olmadı. PostGIS'te henüz bir deneyimim yok ve her türlü iyi yanıtı verebileceğimden daha fazla zamanımı alacaktı. Umarım bu alandaki keşiflerimiz gelecekte insanlara yardımcı olur, belki yakında PostGIS'te bir çatlak alırsam geri döneceğim ve pratik için başka bir balina alacağım!
AA

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.