Hacer crecer una geometría PostGIS en un porcentaje

10

Estoy buscando una manera de agregar un búfer alrededor de una geometría PostGIS, pero el tamaño del búfer debería depender del tamaño de la geometría. Es decir, quiero que cada geometría se amplíe, digamos, un 5%.

La idea es que estoy buscando geometrías de intersección, pero podría haber un error de hasta el 5% asociado con cada una de las cuales quiero tener en cuenta.

Alguien sabe la mejor manera de hacer esto?

La base de datos tiene casi un millón de filas, por lo que prefiero que sea bastante rápido.

James Baker
fuente
2
¿5% de qué? Suponiendo que está utilizando polígonos, ¿es el 5% del ancho más grande, el ancho más estrecho, el cuadro delimitador, la distancia de un vértice desde el centroide ...? Si estás hablando de puntos o líneas, ¡entonces tiene menos sentido!
MerseyViking
Supongo que la distancia entre el vértice y el centroide, o posiblemente un aumento del 5% en el área, también estaría bien. Aumentar el cuadro delimitador está bien si la geometría se escala para luego llenar ese cuadro delimitador. Todas las geometrías son polígonos cerrados (la gran mayoría son cuadriláteros).
James Baker

Respuestas:

8

Los comentarios sugieren que no es necesario alcanzar el 5% con alta precisión. (Si lo hace, tomará mucho tiempo amortiguar un millón de polígonos). Por lo tanto, podemos invocar el Principio de Pizza : reescalar linealmente una entidad 2D por un factor a reescala su área por un ^ 2.

Así es como va el razonamiento:

  • Cuando la forma no es demasiado enrevesada, especialmente si es convexa, el almacenamiento en búfer produce un resultado comparable al cambio de escala de la forma alrededor de un punto central. (Sin embargo, es importante comprender que el almacenamiento en búfer no es equivalente a un cambio de escala para formas que no sean discos. Para algunas formas cóncavas, un "búfer" calculado mediante reescalado podría no incluir partes de la forma original en sí misma. nos vamos a calcular una memoria intermedia genuina de la forma, pero sólo estamos utilizando esta equivalencia aproximada como un heurístico para estimar la cantidad de búfer.)

  • Si el área tamponada debe ser un 5% mayor, entonces la cantidad de reescalado debe ser sqrt (1 + 5/100), que está cerca de 1.025: es decir, deberíamos expandir la forma en un 2.5% en todas las direcciones .

  • De manera equivalente, si pensamos que la forma tiene un "diámetro" (igual a una distancia típica), su radio debería aumentar en un 2.5%. Eso es igual a 2.5% / 2 = 1.25% del diámetro.

  • Podemos estimar un diámetro típico a partir del cuadro delimitador de la forma. Use, digamos, una media aritmética o geométrica de las longitudes laterales de la caja.

Esto sugiere el siguiente flujo de trabajo:

  1. Obtenga el cuadro delimitador de la forma.

  2. Sea e el promedio de las longitudes laterales de la caja.

  3. Amortigua la forma en un 1,25% de e ; es decir, por (5/100) / 4 * e .

Debido a que los pasos 1 y 2 requieren muy poco cálculo, esto se ofrece como una de las soluciones más rápidas posibles. Como verificación de precisión, puede (por supuesto) calcular las áreas de las formas almacenadas en el búfer y compararlas con las áreas originales para ver qué tan cerca están del aumento deseado del 5%. A veces, las áreas protegidas serán incluso más de un 5% más grandes, pero debería ser raro que sean menos, y es imposible que sean considerablemente menos.

Ejemplos

Como verificación e ilustración, consideremos algunas formas simples.

  1. Un disco de radio r tiene un cuadro delimitador con lados de longitud 2 r . Nuestra fórmula calcula e = (5/100) / 4 * 2 * r = r / 40. La forma amortiguada obviamente es un disco concéntrico de radio r + r / 40 = 1.025 r . El área anterior era pi * r ^ 2, mientras que el área nueva es pi * (1.025 r ) ^ 2 = pi * 1.0506 * r ^ 2, que es 5.06% mayor.

  2. Un rectángulo con lados paralelos a los ejes de coordenadas de longitudes r y s da e = ( r + s ) / 2. El área adicional del almacenamiento intermedio del rectángulo proviene de cuatro rectángulos de ancho (5/100) / 4 e = e / 80 = ( r + s ) / 160 que bordean los lados más cuatro cuartos de círculo de radio e / 80 en las esquinas. Descuidando los cuartos de círculo, que serán pequeños en comparación con las otras áreas, el área nueva total es igual a

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

    Cuando r y s no son muy diferentes, podemos calcular que r ^ 2 + s ^ 2 es aproximadamente 2 r * s . Esta aproximación simplifica el área nueva total a 4 r * s / 80 = 5% del área original de r * s , según lo previsto.

whuber
fuente
4

Desea usar una combinación de ST_Scale ( http://postgis.net/docs/ST_Scale.html ) y ST_Translate ( http://postgis.net/docs/ST_Translate.html ), creo. Tenemos un ejemplo de esto en PostGIS en acción y similar en el Capítulo 8. Si no tiene el libro, puede descargar el código de ese capítulo aquí:

http://www.postgis.us/chapter_08

Fragmento del libro Mira el ejemplo 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;
LR1234567
fuente
Trabajos. Ahora parece que también hay, ST_Transscalepero de alguna manera no puedo entender cómo hacer que eso funcione ...
n1000
0

Esto es muy tarde para la fiesta, pero recientemente desarrollé una función personalizada de PostGIS que hace esto, además de reducirla si es necesario:

ST_Dilate

wfgeo
fuente