Identificando polígonos "largos y estrechos" con PostGIS

10

Tengo un conjunto de polígonos que representan grandes áreas, por ejemplo, barrios de la ciudad. Quiero identificar las grandes áreas superpuestas entre ellos.

Pero hay un problema: a veces estos polígonos se superponen a lo largo de sus perímetros (porque fueron dibujados con poca precisión). Esto generará superposiciones largas y estrechas que no me importan.

Pero otras veces habrá grandes superposiciones de polígonos robustos, lo que significa grandes áreas donde el polígono de un vecindario se superpone a otro. Quiero seleccionar solo estos.

Vea la imagen a continuación de solo las superposiciones. Imagine que quisiera seleccionar solo el polígono azul en la esquina inferior izquierda.

superposición

Podría mirar áreas, pero a veces las angostas son tan largas que terminan teniendo áreas tan grandes como el polígono azul. Intenté hacer una relación de área / perímetro, pero eso también arrojó resultados mixtos.

Incluso he intentado usar ST_MinimumClearance, pero a veces las áreas grandes tendrán una parte estrecha unida o dos vértices muy cercanos.

¿Alguna idea de otros enfoques?


Al final, lo que mejor funcionó para mí fue usar un búfer negativo, como lo sugieren @Cyril y @FGreg a continuación.

Usé algo como:

ST_Area(ST_Buffer(geom, -10)) as neg_buffer_area

En mi caso, las unidades eran metros, entonces 10 m de amortiguación negativa.

Para polígonos estrechos, esta área devolvió cero (también, la geometría estaría vacía). Luego usé esta columna para filtrar los polígonos estrechos.

bplmp
fuente
44
Ciertamente, la relación área / perímetro podría usarse para esto.
Vince
Es difícil saber dónde están los distintos polígonos de la imagen, pero hacer algo como esto gis.stackexchange.com/a/265233/64838 podría funcionar. Calcule el cuadro delimitador rotado mínimo y luego descarte los de ancho o altura pequeños.
FGreg
También podría intentar usar un búfer negativo como se describe aquí: ¿Cómo puedo identificar polígonos realmente delgados en mi archivo de forma?
FGreg

Respuestas:

5

Intentaría crear un búfer negativo, si come polígonos delgados, entonces es bueno, si no come el polígono, entonces es mío ... :-)

ejecute este script, habiendo establecido previamente 2/3 del ancho de los polígonos lineales ...

create table name_table as
SELECT ST_Buffer(
(ST_Dump(
(ST_Union(
ST_Buffer(
(geom),-0.0001))))).geom,
0.0001)) as geom from source_table

OS: -) ...

Cyril Mikhalchenko
fuente
Al final, su sugerencia es lo que mejor funcionó para mí. Terminé usando algo como ST_Area(ST_Buffer(geom, -10)), -10 siendo -10 metros en mi caso. Si algo devuelve 0 de esa expresión, entonces podría filtrarlo.
bplmp
9

En lugar de área / perímetro, es mejor usar el área dividida por el cuadrado del perímetro (o su inverso).

Esto también se llama "índice de forma". El cuadrado del perímetro dividido por el área tiene un valor mínimo de 4 * Pi () (en el caso de un disco, que es la geometría 2D más compacta), por lo que puede normalizarse por 4 * Pi () para un fácil interpretación (los valores normalizados cercanos a 1 significan que tiene objetos muy compactos y los cuadrados tienen valores de aproximadamente 1.27).

EDITAR: Un umbral en el área sería útil para eliminar los artefactos muy pequeños, que podrían ser compactos. Entonces el índice de forma mostraría un mejor contraste. EDITAR: además de esta respuesta, el uso de ST_Snap podría ayudarlo a resolver el problema antes de que ocurra.

radouxju
fuente
¡Gracias! Pero no estoy seguro de cómo ST_Snap podría ayudar en este caso ... Si lo hice bien, ¿estás sugiriendo algo así (o.overlap_perimeter^2 / o.overlap_area) / (4 * Pi()) as overlap_ratio? Esto está teniendo peores resultados para mí que solo el área / perímetro.
bplmp
Ahora, de o.overlap_perimeter / (4 * sqrt(o.overlap_area)) as overlap_ratioacuerdo con este documento, pero aún peores resultados (aunque es difícil cuantificar lo que quiero decir con peor) isprs-ann-photogramm-remote-sens-spatial-inf-sci.net/I-7/135/… , página 183.
bplmp
2
Gracias por esto, nunca había oído hablar del "índice de forma". Siempre pensé que usar un rectángulo de límite mínimo era la mejor manera de responder a este tipo de preguntas. Encontré esto, repository.asu.edu/attachments/111230/content/… , que es interesante.
John Powell
@JohnPowell papel interesante, gracias. Veo que lo que sé como índice de forma se llama índice de circularidad en el documento. Mi problema con los rectángulos de límite mínimo es que no funciona con objetos muy cóncavos (por ejemplo, en forma de U)
radouxju
@bplmp ST_Snap lo ayudaría a ajustar los vértices de "casi" polígonos adyacentes para que ya no se superpongan. No hay escala en sus figuras, pero su artefacto parece líneas, por lo que supongo que puede usar un valor de tolerancia que es suficiente para evitar artefactos pero no afecta a los polígonos grandes.
radouxju
5

Una opción sería usar la razón del área del polígono a la línea más larga que se puede dibujar usando sus extremidades. Identificando polígonos largos y estrechos.

select * from polygons where ST_Length(ST_LongestLine(geom, geom)) < ST_Area(geom) * 4

Esto funciona bastante bien para los polígonos astillados. Puede ajustar la proporción (con qué multiplica el área) para satisfacer sus necesidades y proyección.

HeikkiVesanto
fuente
1

Parece que esto podría coincidir con su caso de uso: elimine los polígonos seleccionados

Combina los polígonos seleccionados de la capa de entrada con ciertos polígonos adyacentes borrando su límite común. El polígono adyacente puede ser el que tiene el área más grande o la más pequeña o el que comparte el límite común más grande con el polígono a eliminar.

Eliminar normalmente se usa para deshacerse de los polígonos astillados, es decir, polígonos diminutos que son el resultado de procesos de intersección de polígonos donde los límites de las entradas son similares pero no idénticos.

Parece que le gustaría probar la opción "Límite común más grande".

FGreg
fuente
Ahora me doy cuenta de que pedías soluciones postgis, no soluciones qgis. Mis disculpas, no creo que postgis tenga una función equivalente, pero lo dejaré para la posteridad.
FGreg
0

Esto me parece un caso de uso perfecto para la extensión de topología PostGIS . El parámetro de tolerancia de la topología determinará hasta qué punto permite que los vértices se ajusten a otros polígonos existentes, para hacer frente a la baja precisión de los datos de origen y limpiarlos.

En resumen, la estrategia es:

1. Habilite la extensión de topología

CREATE EXTENSION postgis_topology;

2. Crear una nueva topología vacía

SELECT topology.CreateTopology('neighborhoods_topo', 4326, 1e-7);

El tercer parámetro es la tolerancia, en las unidades del CRS; elígelo sabiamente. Idealmente, desea un CRS donde la unidad es metros. Si la unidad CRS no tiene medidores, como con WGS 84, también conocido como 4326, úselo ST_Transformpara reproyectar sus polígonos.

3. Agregue una columna TopoGeometry a la tabla de polígonos

SELECT topology.AddTopoGeometryColumn('neighborhoods_topo', 'public', 'neighborhoods', 'topogeom', 'POLYGON');

Esto devuelve un nuevo layer_id. Guárdelo, será necesario más tarde. Será una capa 1si comienza desde cero y se incrementará en cada nueva llamada.

4. Agregue todos los polígonos a la topología.

UPDATE public.neighborhoods
SET topogeom = topology.toTopoGeom(geom, 'neighborhoods_topo', 1, 1e-7);

Esto puede llevar varias horas para un gran conjunto de datos, tenga paciencia. 1es el layer_id devuelto anteriormente.

5. Encuentra caras que aparecen en varios vecindarios

Encuentre todas las caras de la topología que están presentes en 2 o más topogeometrías. Dejaré la consulta como ejercicio. Lo más fácil es probablemente con la GetTopoGeomElementsfunción, luego agrupar por identificación facial y mirar las que cuentan 2 o más. Alternativamente, puede crear una nueva tabla con la geometría limpia de la columna topogeom, simplemente convertirla en geometría estándar topogeom::geometryy repetir lo que ya tiene ahora, pero ahora con un conjunto de datos limpio sin superposiciones de la astilla.

François
fuente