Crea un mosaico come il diagramma Voronoi da poligoni disgiunti


12

L'illustrazione seguente mostra il problema :

inserisci qui la descrizione dell'immagine

come in (a) ho una serie di poligoni disgiunti, come geometrie in PostGIS. Ho bisogno di qualcosa come (b) , il "mosaico" di questo insieme di poligoni, costruendolo secondo criteri di "regione di influenza" ... È come una costruzione Voronoi (illustrata da (c) ): in effetti, se i poligoni fossero punti, le regioni di influenza sono Voronoi.

Riassumendo: ho bisogno di un algoritmo SQL (o alcuni specifici per PostGIS) che genera il "mosaico" di un insieme di poligoni disgiunti. (forse un ciclo di piccole operazioni ST_Buffer e ST_Difference)

PS: Ho bisogno, come quello di Voronoi, che la delimitazione dello spazio (una cornice quadrata in (b) ) venga ignorata.


Questo problema è simile a questo riguardo alle linee .

EDIT (dopo il commento @FelixIP)

Preferisco rimanere nell'universo vettoriale , non perdere la precisione (es. Usando ST_DelaunayTriangles e aggiungendo e sottraendo interni dai poligoni originali, adattando loro una soluzione a doppio grafico ) ... Alcuni pacchetti semplici e automatici come pprepair (assistiti come strumenti topologici QGIS non sono automatici). Ma il raster è forse più semplice e consuma meno CPU.

Questa illustrazione del "processo GRID" è valida anche come soluzione, supponendo che possa consentire la stessa precisione e "crescita della regione di influenza euclidea".

inserisci qui la descrizione dell'immagine

In ARCGIS esiste uno strumento di analisi spaziale noto come Allocazione euclidea , quindi forse esiste una soluzione simile a PostGIS , che inizia con l'insieme di poligoni (classificazione, rasterizzazione e ricostruzione dei poligoni).


Grazie @Nir, scusa la confusione con i punti, non sto usando i punti, solo i poligoni come elementi (a) e (b) dell'illustrazione ... Hai un link del tuo indizio sulla soluzione?
Peter Krauss,

In arcgis c'è una soluzione raster chiamata allocazione eucledea o prossimità
FelixIP

Grazie @FelixIP, ho modificato per "well come raster solutions" ;-)
Peter Krauss,

Se cancelli i tuoi poligoni dal loro estensione.aspolygon, rimarrai con il poligono. Skeleton of it gis.stackexchange.com/questions/177/… è ciò di cui hai bisogno, immagino. L'implementazione è un
grosso problema

1
@ Cirillo, posso rivedere i tuoi script ... La prossima settimana. Pubblicare qualcosa che sembra una soluzione con le moderne funzioni di PostGIS sarà un buon primo passo.
Peter Krauss,

Risposte:


1

Quindi, preparerò una torta per te: un piatto di frutta, usando gli strumenti PostGis, come hai richiesto, se ho capito correttamente la domanda e, come ho già detto, la responsabilità per il funzionamento del forno PostGIS è a carico del suo team creativo.

Chiederò di non essere offeso da nessuno nel mio stile umoristico e di capirlo come un gioco!

Il file originale è frutta a fette e forme semplici (di seguito denominate frutta), vedere la Figura 1 di seguito.

inserisci qui la descrizione dell'immagine

Ecco la mia ricetta, e sarò aiutato in questo da cari programmatori, di cui imparerai più avanti. Cominciamo, e per questo creeremo un impasto in cui verranno deposti i nostri frutti, per cui eseguiamo la sceneggiatura:

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

Vedere il risultato nella Figura 2 di seguito

inserisci qui la descrizione dell'immagine

Ora, se ci sono pochi frutti, come nella mia immagine, creare il bordo del buffer esterno sul frutto, o se ci sono molti frutti, creare il bordo del buffer negativo, per il quale eseguire lo script:

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;

E tagliare le linee del buffer attorno a ciascun frutto

UPDATE poly_buff_dump SET geom=ST_RemovePoint(geom, ST_NPoints(geom)-1) WHERE ST_IsClosed(geom)=true; Vedere il risultato nella Figura 3 di seguito

inserisci qui la descrizione dell'immagine

(In realtà, ho pensato che di conseguenza avrei ottenuto linee spezzate (come in un cerchio), ma se le figure sono difficili, a volte si ottengono interruzioni, quelle errate, ad esempio, un lato del rettangolo cadeva, ecc. )

Quindi devi dividere le linee ottenute in modo conveniente per te in segmenti uguali ed estrarre punti da esse

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

Risultato, vedere la Figura 4 di seguito

inserisci qui la descrizione dell'immagine

Ora esegui lo strumento Voronoi, in questo posto ho usato lo strumento suggerito dal link MickyT: /gis//a/172246/120129 , a seguito del quale avrai creato le tabelle con il nome “voronoi "Per il fatto che" il mio primo assistente "è separato dallo chef grazie dallo chef! :-).

Il secondo modo in questo passaggio è eseguire la funzione ST_VoronoiPolygons.

Risultato, vedere la Figura 5 di seguito

inserisci qui la descrizione dell'immagine

Ora, taglia le parti extra eseguendo lo script:

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); Risultato, vedere la Figura 6 di seguito.

inserisci qui la descrizione dell'immagine

Ora esegui lo script per allineare il tipo di geodati in LineString:

create table poly_voronoi_dump as SELECT (ST_Dump(geom)).geom as geom FROM poly_voronoi_cut; E ora chiederò al "mio secondo ufficiale" di assumere i miei doveri e mescolare la torta wel (Jeff - /gis//a/785/120129 ), livellandola in un singolo strato, e per quello , grazie a me per questo!

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 ) ); Ora è il momento di mettermi al lavoro, per il quale eseguo lo script:

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; e un'altra sceneggiatura:

create table poly_voronoi_union_area as SELECT ST_Union(ST_ConvexHull(ST_BuildArea(geom))) as geom FROM poly_voronoi_union GROUP BY id; vedere la figura 7 in basso

inserisci qui la descrizione dell'immagine

Come puoi vedere nella figura, i nostri tagli hanno piccoli livelli, che possono essere rimossi, come opzione usando ST_SnapToGrid (o in un altro modo):

E infine, ritaglieremo la nostra frutta cotta dalla nostra torta, mi sono persino stancato in piedi accanto al forno :-)

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); Risultato vedi figura 8 inserisci qui la descrizione dell'immagine

Tutto da questo giorno, ora tutti impareranno a cuocere deliziose torte - piatto di frutta. Aiutati tutti e scegli i pezzi che ti piacciono, abbastanza per tutti.

(È un peccato che non riesca davvero a sfamare tutte le persone, non con torte elettroniche, ma con torte vere, forse la fame finirebbe sulla Terra ...)

Modifica: la ciliegia sulla torta potrebbe assomigliare a questo :-):

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;

o

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;

Con te è stato buono e giusto Mr.Baker, grazie a tutti e buona fortuna,: -) ...

Soluzioni originali.

Questo script si chiama: ST_VoronoiDiagramsFromPolygons.


1
Ciao, buone illustrazioni e sembra un buon risultato (!). Suggerimento per una breve discussione, vedi la soluzione @geogeek, i passaggi in QGis sembrano i passaggi principali di PostGIS qui ... Perché ne ho bisogno ST_Buffere ST_ConvexHull? Esiste un algoritmo alternativo?
Peter Krauss,

1) Vedi, ST_Buffer e sui poligoni sono creati per ridurre le linee di separazione tra le figure originali durante l'applicazione della funzione Voronoi, quindi, maggiore è la dimensione del buffer che puoi specificare, più uniformemente le linee di separazione saranno costruite come una funzione Voronoi ... 2) ST_Convex Scafo dalla moltitudine di figure su ogni poligono, il poligono di cui abbiamo bisogno ... 3) Oggi, questa è la mia visione di risolvere la tua domanda, non so cosa accadrà a tutti noi e le nostre decisioni in futuro ...
Cyril Mikhalchenko

Un altro importante valore delle linee di buffer è che ci aiuteranno a selezionare i frammenti dal risultato della funzione del Voronoi per creare poligoni combinati per ogni forma ...
Cyril Mikhalchenko

A proposito, accolgo con favore il miglioramento del codice e dell'approccio, in modo che non peggiorino il risultato ...
Cyril Mikhalchenko

1
Ciao Cirillo, sono d'accordo che ST_Buffer è una buona opzione per normalizzare le curve di livello, perfetto (!). A proposito ST_ConvexHull, è solo una curiosità, che tipo di risultati possiamo ottenere dopo la Figura 6, poly_voronoi_unionsenza ST_ConvexHull.
Peter Krauss,

8

I Postgis non hanno una funzione dedicata per voronoi, ma Qgis contiene una funzione vornoi che potrebbe rendere i poligoni voronoi dai punti, quindi usando qgis ho seguito i seguenti passi per ottenere questi risultati:

-make punti da poligoni usando le extract nodesfunzioni.

-make poligoni vornoi usando le funzioni voroi in Qgis.

-creare un join spaziale in Qgis.

-dissolve i risultati.

inserisci qui la descrizione dell'immagine


1
Bella soluzione (!), E grazie dell'illustrazione. Puoi migliorarlo? Vedi il rettangolo sinistro in basso, a Voronoi c'erano 4 punti, e il centro del rettangolo non ha rappresentanza, distorcendo la sua regione (le perdite sono sul triangolo) ... Forse è possibile potenziare facendo un campionamento regolare di ogni poligono ... e forse anche alcuni punti interni.
Peter Krauss,

Uso lo strumento densify in ArcGIS. Ciò migliora significativamente i poligoni di prossimità. +1
FelixIP

3

OK - Ci ho pensato un po 'e ho scoperto che era come qualcosa che ho visto ultimamente.

Prendi i tuoi polis di partenza:

inserisci qui la descrizione dell'immagine

Genera un nuovo attributo con un numero (100 nel mio caso) Usa lo strumento Vettore-> Strumenti di ricerca -> Punti casuali all'interno dei poligoni che genererà (100) punti all'interno di ciascun poligono: inserisci qui la descrizione dell'immagine

Quindi Vector-> Strumenti geometria -> Voronoi per generare polis basati su quel livello punto.

inserisci qui la descrizione dell'immagine

Ora puoi usare lo strumento Vettore -> Query spaziale: seleziona i punti che appartengono a un poligono (o uno dei poligoni). Usa lo strumento di query spaziale per generare una selezione dei tuoi poligoni voronoi che si applicano a quel poligono. Aggiungi un attributo al poligono voroni che corrisponde al poligono di interesse. (Ho appena usato 1,2,3,4)

Ora puoi dissolvere Vector-> Strumenti di geoprocessing-> in base al tuo nuovo attributo.

inserisci qui la descrizione dell'immagine


Grazie @AAmes (!), Le illustrazioni sono buone e il metodo è una buona alternativa ... Ma la domanda riguarda "un algoritmo SQL (o alcuni specifici per PostGIS)" e ora la generosità sull'uso della funzione ST_VoronoiPolygons () , che forse risolvono tutti i problemi con un clic ;-)
Peter Krauss

@AAmes Una rapida ricerca rivela che questo metodo può essere effettivamente utilizzato anche in PostGIS. Come creare punti casuali in un poligono in postgis spiega la creazione di punti da poligoni e da lì dovrebbe essere abbastanza semplice.
Phil G

La mia generosità era per te come incentivo (benvenuto qui!), Ma QUESTA RISPOSTA È PREOCCUPATA per i requisiti di domanda e generosità.
Peter Krauss,

Grazie Peter, ho visto i tuoi appunti ma sfortunatamente non ho avuto l'opportunità di tornare indietro e affrontarli. Non ho ancora alcuna esperienza in PostGIS e mi ci sarebbe voluto più tempo di quello che avevo a disposizione per dare qualsiasi tipo di buona risposta. Spero che la nostra esplorazione di questo spazio sia utile per le persone in futuro, forse se avrò presto una crepa su PostGIS tornerò e prenderò un altro colpo per esercitarsi!
AA

2

I punti casuali sono una buona idea per generare un poligono voronoi dai poligoni, funziona abbastanza bene, ma è piuttosto male per i poligoni vicini: inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

ST_ApproximateMedialAxis è un'altra buona alternativa se si utilizza PostGIS: calcolo dei diagrammi di Voronoi per i poligoni

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.