Crescere una geometria PostGIS di una percentuale


10

Sto cercando un modo per aggiungere un buffer attorno a una geometria PostGIS, ma la dimensione del buffer dovrebbe dipendere dalla dimensione della geometria. Cioè, voglio che ogni geometria venga ingrandita, diciamo, del 5%.

L'idea è che sto cercando geometrie che si intersecano, ma potrebbe esserci un errore fino al 5% associato a ciascuno di quelli che voglio prendere in considerazione.

Qualcuno conosce il modo migliore per farlo?

Il database ha almsot un milione di righe, quindi preferirei che fosse abbastanza veloce.


2
5% di cosa? Supponendo che tu stia utilizzando i poligoni, è il 5% della larghezza massima, la larghezza più stretta, il riquadro di delimitazione, la distanza di un vertice dal centroide ...? Se stai parlando di punti o linee, allora ha ancora meno senso!
MerseyViking

Immagino che la distanza centro-vertice - o forse un aumento del 5% nell'area sarebbe anche a posto. L'aumento del rettangolo di selezione va bene se la geometria viene ridimensionata per riempire il rettangolo di selezione. Tutte le geometrie sono poligoni chiusi (la stragrande maggioranza sono quadrilateri).
James Baker,

Risposte:


8

I commenti suggeriscono che non è necessario raggiungere il 5% con elevata precisione. (Se lo fa, ci vorrà molto tempo per bufferizzare un milione di poligoni!) Possiamo quindi invocare il principio della pizza : riscalare linearmente una caratteristica 2D di un fattore e ridimensionare la sua area di un ^ 2.

Ecco come va il ragionamento:

  • Quando la forma non è troppo contorta, specialmente se convessa, il buffering produce un risultato paragonabile al riscalare la forma attorno a un punto centrale. (È importante capire, tuttavia, che il buffering non equivale mai al riscalaggio di forme diverse dai dischi. Per alcune forme concave, un "buffer" calcolato tramite riscalamento potrebbe in realtà non includere parti della forma originale stessa! Pertanto, in definitiva ci sarà calcolare un buffer vera e propria della forma, ma siamo solo usando questa equivalenza approssimativa come euristica per stimare la quantità di buffer.)

  • Se l'area bufferizzata deve essere maggiore del 5%, la quantità di riscalamento dovrebbe quindi essere sqrt (1 + 5/100), che è vicino a 1.025: vale a dire, dovremmo voler espandere la forma del 2,5% in tutte le direzioni .

  • Allo stesso modo, se pensiamo che la forma abbia un "diametro" (uguale a una distanza tipica attraverso), il suo raggio dovrebbe aumentare del 2,5%. Questo equivale al 2,5% / 2 = 1,25% del diametro.

  • Possiamo stimare un diametro tipico dal riquadro di delimitazione della forma. Usa, diciamo, una media aritmetica o geometrica delle lunghezze laterali della scatola.

Questo suggerisce il seguente flusso di lavoro:

  1. Ottieni il riquadro di delimitazione della forma.

  2. Sia e la media delle lunghezze laterali della scatola.

  3. Buffer la forma dell'1,25% di e ; cioè da (5/100) / 4 * e .

Poiché i passaggi 1 e 2 richiedono un calcolo molto limitato, questo si offre come una delle soluzioni più rapide possibili. Come controllo dell'accuratezza, puoi (ovviamente) calcolare le aree delle forme bufferate e confrontarle con le aree originali per vedere quanto si avvicinano all'aumento del 5% desiderato. A volte le aree tamponate saranno anche superiori di oltre il 5%, ma dovrebbe essere raro che siano meno, ed è impossibile per loro essere notevolmente inferiori.

Esempi

Come controllo e illustrazione, consideriamo alcune forme semplici.

  1. Un disco di raggio r ha una scatola di delimitazione con lati di lunghezza 2 r . La nostra formula calcola e = (5/100) / 4 * 2 * r = r / 40. La forma tamponata è ovviamente un disco concentrico di raggio r + r / 40 = 1.025 r . La vecchia area era pi * r ^ 2 mentre la nuova area è pi * (1.025 r ) ^ 2 = pi * 1.0506 * r ^ 2, che è maggiore del 5,06%.

  2. Un rettangolo con i lati paralleli agli assi delle coordinate delle lunghezze r e se = ( r + s ) / 2. L'area aggiuntiva dal buffering del rettangolo proviene da quattro rettangoli di larghezza (5/100) / 4 e = e / 80 = ( r + s ) / 160 che bordano i lati più quattro quarti di cerchio di raggio e / 80 agli angoli. Trascurando i quarti di cerchio, che saranno piccoli rispetto alle altre aree, la nuova area totale è uguale

    2 ( r + s ) * ( r + s ) / 160 = ( r ^ 2 + s ^ 2 + 2 r * s ) / 80.

    Quando r e s non sono troppo diversi, possiamo capire che r ^ 2 + s ^ 2 è circa 2 r * s . Questa approssimazione semplifica la nuova area totale a 4 r * s / 80 = 5% dell'area originale di r * s , come previsto.


4

Vuoi usare una combinazione di ST_Scale ( http://postgis.net/docs/ST_Scale.html ) e ST_Translate ( http://postgis.net/docs/ST_Translate.html ) credo. Ne abbiamo un esempio in PostGIS in azione e simili nel capitolo 8. Se non hai il libro, puoi scaricare il codice per quel capitolo qui:

http://www.postgis.us/chapter_08

Snippet dal libro Guarda l'esempio 8.26:

    -- Listing 8.26 Combining Scale and Translation to maintain centroid
    SELECT xfactor, yfactor, 
       ST_Translate(ST_Scale(hex.the_geom, xfactor, yfactor), 
       ST_X(ST_Centroid(the_geom))*(1 - xfactor), 
       ST_Y(ST_Centroid(the_geom))*(1 - yfactor) ) As scaled_geometry
    FROM 
 ( SELECT ST_GeomFromText('POLYGON((0 0,64 64,64 128,0 192,-64 128,-64 64,0 0))') As the_geom)  As hex
    CROSS JOIN (SELECT x*0.5 As xfactor 
        FROM generate_series(1,4) As x) As xf
    CROSS JOIN (SELECT y*0.5 As yfactor
        FROM generate_series(1,4) As y) As yf;

Lavori. Ora sembra che ci sia anche, ST_Transscalema in qualche modo non riesco a capire come farlo funzionare ...
n1000

0

Questo è molto tardi per la festa, ma recentemente ho sviluppato una funzione PostGIS personalizzata che lo fa, oltre a ridurla se necessario:

ST_Dilate

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.