5 votos

Algoritmo PostGIS para unir puntos de dos geometrías que están dentro de un radio especificado

Quiero encontrar un algoritmo de PostGIS para unir los puntos de dos geometrías que están "cerca" el uno del otro.

Eso es: Quiero una función, que toma como entrada dos geometrías, y devuelve 1 geometría, que consiste en puntos de la primera geometría, la segunda geometría, y puntos que están en radio especificado de ambos geometrías.

Actualmente estoy utilizando dicha función para esto (el radio de tolerancia es de 2 metros):

SELECCIONE ST_AsText( ST_Buffer( ST_Union( ST_Buffer( ST_GeomFromText( 'POLÍGONO ((0 0, 0 4,5, -2 4,5, -2 5,5, 0 5,5, 0 10, 1 10, 1 0, 0 0))', 3301 ), 2 ), ST_Buffer( ST_GeomFromText( 'POLÍGONO ((2 5, 5 8, 5 2, 2 5))', 3301 ), 2 ) ) , -2) );

Funciona razonablemente bien para unir puntos de dos geometrías, que están cerca la una de la otra.

Sin embargo, tiene efectos secundarios. Por ejemplo:

Geometrías de entrada:

Input geometries

Geometría resultante:

Resulting geometry

Como se puede ver en la imagen, se añade un área extra a la geometría "azul" donde están los ángulos obtusos. Esto es así porque al utilizar

ST_Buffer(ST_Buffer(geom, tolerance), -tolerance) 

añade espacio adicional a los lugares donde hay ángulos obtusos.

¿Existe un algoritmo que produzca el resultado que pido? La naturaleza exacta de cómo se "pegan" las dos geometrías entre sí no es tan importante. El algoritmo de pegado deja una curva suave, pero algo como esto también sería un resultado válido (dibujado a mano, traté de añadir puntos que están en la distancia de 2 metros de ambas geometrías):

example of valid result

Si hay muchos algoritmos, el más rápido será el que mejor se adapte a mis necesidades. Pero para comparar, los algoritmos más lentos también serán bienvenidos (votados), si sobresalen por algún otro criterio.

4voto

Magda Puntos 11

Intentaré documentar las cosas que ya he probado. Tal vez esto ayude a otros a proporcionar buenas ideas.

He leído el manual sobre la función ST_Buffer: ST_Buffer

Hay opciones interesantes sobre cómo funciona la función ST_Buffer:

  • 'quad_segs=#' : número de segmentos utilizados para aproximar un cuarto de círculo (por defecto 8).
  • 'endcap=round|flat|square' : estilo de endcap (por defecto es "round", necesita GEOS-3.2 o superior para un valor diferente). 'butt' también se acepta como sinónimo de 'flat'.
  • 'join=round|mitre|bevel' : estilo de unión (por defecto "round", necesita GEOS-3.2 o superior para un valor diferente). También se acepta 'mitre' como sinónimo de 'mitre'.
  • 'mitre_limit=#.#' : límite de relación de inglete (sólo afecta al estilo de unión a inglete). 'miter_limit' también se acepta como sinónimo de 'mitre_limit'.

He intentado utilizar "join=mitre" al hacer un buffer negativo. Código:

SELECT ST_AsText(
  ST_Buffer(
  ST_Union(
  ST_Buffer(
  ST_GeomFromText(
  'POLYGON ((0 0, 0 4.5, -2 4.5, -2 5.5, 0 5.5, 0 10, 1 10, 1 0, 0 0))', 3301 
 ), 2 
 )
 , 
 ST_Buffer(
  ST_GeomFromText(
  'POLYGON ((2 5, 5 8, 5 2, 2 5))', 3301 
 ), 2 
 ) 
 )
  , -2, 'join=mitre'
 ) 
);

El resultado está aquí:

Result_round_mitre

No es lo que esperaba.

Entonces lo intenté:

SELECT ST_AsText(
  ST_Buffer(
  ST_Union(
  ST_Buffer(
  ST_GeomFromText(
  'POLYGON ((0 0, 0 4.5, -2 4.5, -2 5.5, 0 5.5, 0 10, 1 10, 1 0, 0 0))', 3301 
 ), 2, 'join=mitre'
 )
 , 
 ST_Buffer(
  ST_GeomFromText(
  'POLYGON ((2 5, 5 8, 5 2, 2 5))', 3301 
 ), 2, 'join=mitre'
 ) 
 )
  , -2, 'join=mitre'
 ) 
);

Curiosamente, esto devolvió la geometría original:

Result_mitre_mitre

El uso de la unión en bisel dio resultados aún más antinaturales. Me parece que jugar con el tipo de unión no es suficiente :)

EDIT: He hecho una prueba más y quizá deba reconsiderar mi afirmación anterior. La unión de Mitre tiene algunas propiedades interesantes.

Diferentes geometrías de entrada:

Different input geometries

Resultado de la unión a inglete:

Result using mitre join

Como se puede ver en los gráficos, la forma de la geometría unida depende del tamaño del ángulo del triángulo. Si las geometrías de entrada fueran paralelas, la unión a inglete daría el resultado deseado.

Esto necesita más pruebas.

EDIT2: No, la unión a inglete no es una opción viable. Caso de prueba:

Geometrías iniciales:

Initial geometries

Resultado:

After mitre joining

En el lado izquierdo, la geometría inicial ha cambiado de forma. Así que no, la unión a inglete no es la respuesta a este problema.

EDIT3: El compañero de trabajo ha añadido una variación interesante:

SELECT ST_AsText(
  ST_Buffer(
  ST_Union(
  ST_Buffer(
  ST_GeomFromText(
  'POLYGON ((0 0, 0 4.5, -2 4.5, -2 5.5, 0 5.5, 0 10, 1 10, 1 0, 0 0))', 3301 
 ), 2 , 'join=mitre'
 )
 , 
 ST_Buffer(
  ST_GeomFromText(
  'POLYGON ((2 5, 5 8, 5 2, 2 5))', 3301 
 ), 2 , 'join=mitre'
 ) 
 )
  , -2, 'join=mitre mitre_limit=1.4141'
 ) 
);

Mitre join 4

Esto es muy parecido a lo que pregunté en el primer post. Consideraré la posibilidad de utilizarlo.

Sobre el parámetro "mitre-limit=1.4141":

Es 1/sin(a/2), donde a es el ángulo entre dos segmentos consecutivos. 1,4141 significa que, cuando el ángulo es de 90 grados o menos, se utilizará join=bevel en lugar de join=mitre.

2voto

Lars Mæhlum Puntos 4569

ST_ConcaveHull debería resolver esto.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X