12 votos

Problema de validez del polígono de lazo o de reloj de arena cuando el punto de auto cruce no está definido

Usando Python2.7 y shapely, permita que:

import shapely
coords = [(0, 0), (0, 2), (2, 0), (2, 2), (0, 0)]
bowtie = shapely.geometry.Polygon(coords)
bowtie.is_valid

lo cual da como resultado:

Auto-intersección en o cerca del punto 1 1
Out[2]: False

Entonces intentemos el método buffer(0) como se describe en la documentación (http://toblerity.org/shapely/manual.html):

limpio = bowtie.buffer(0)
tipo(limpio)

lo cual da como resultado:

Out[4]: shapely.geometry.polygon.Polygon

La diferencia entre el ejemplo en la documentación es que en este caso presente, el punto de cruce no está definido en las coordenadas originales, por lo que no resulta en un multipolígono y no es realmente consistente con estas coordenadas iniciales, como muestra este comando:

limpio.wkt

cuando devuelve:

Out[16]: 'POLYGON ((0 0, 0 2, 1 1, 0 0))'

Y la imagen resultante para una mejor comprensión visual:

polígono limpio de la pajarita vs polígono original de la pajarita auto-intersectante

Con:
Rojo: polígono original auto-intersectante
Turquesa: polígono de pajarita limpio con el método buffer(0) (solo una mitad del polígono original. Ten cuidado con el efecto de escalamiento diferente en iPython...)

Pregunta:
¿Cómo se puede recuperar fácilmente la forma original con una geometría válida para poder realizar más operaciones como intersecciones, etc?

7voto

bugmenot123 Puntos 770

Un hack diferente sería usar solo el exterior de la corbata de lazo, intersectándola consigo misma (generando un MultiLineString), poligonizando eso (generando Polígonos) y finalmente agregándolo en un MultiPolígono:

be = bowtie.exterior
mls = be.intersection(be)
polígonos = polygonize(mls)
corbata_valida = MultiPolígono(polígonos)
print(corbata_valida)

MULTIPOLÍGONO (((0 0, 0 2, 1 1, 0 0)), ((2 0, 1 1, 2 2, 2 0)))

1voto

Tokyo Dan Puntos 132

En mi caso, exterior estaba devolviendo LinearRing, y de todas formas, la intersección consigo mismo no funcionaba porque el polígono original no era válido. Terminé encontrando esta respuesta que fue más útil.

Este es el código que se me ocurrió:

coords = [[0,0],[1,1],[0,1],[1,0],[0,0]]
line_non_simple = shapely.geometry.LineString(coords)
mls = shapely.ops.unary_union(line_non_simple)
polygons = list(shapely.ops.polygonize(mls))
shapely.geometry.MultiPolygon(polygons)

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