Aquí hay un mapa de contorno para el que están disponibles todos los polígonos de niveles.
Vamos a preguntar cómo suavizar los polígonos manteniendo todos los vértices preservados en sus ubicaciones exactas.
De hecho, el contorno se realiza sobre los datos de una cuadrícula, puede sugerir que luego suavice los datos de la cuadrícula y, por lo tanto, el contorno resultante será más suave. Tenga en cuenta que esto no funciona como lo deseo, ya que la función de suavizado como el filtro Gaussiano eliminará pequeños paquetes de datos y cambiará el rango de la tercera variable, por ejemplo, la altura que no está permitida en mi aplicación.
En realidad, estoy buscando un fragmento de código (preferiblemente en Python ) que pueda suavizar los polígonos 2D (cualquier tipo: convexo, cóncavo, auto-intersectorial, etc.) razonablemente indoloro (olvide las páginas de códigos) y preciso.
Para su información, hay una función en ArcGIS que hace esto perfectamente, pero el uso de aplicaciones comerciales de terceros no es mi elección para esta pregunta.
1)
Scipy.interpolate:
Como puede ver, las splines resultantes (rojo) no son satisfactorias.
2)
Aquí está el resultado usando el código dado aquí . ¡No está funcionando bien!
3)
Para mí, la mejor solución debería ser algo como la siguiente figura en la que un cuadrado se suaviza gradualmente cambiando solo un valor. Espero un concepto similar para suavizar cualquier forma de polígonos.
Satisfaciendo la condición de que la spline pase los puntos:
4)
Aquí está mi implementación de "idea de whuber" línea por línea en Python en sus datos. Posiblemente hay algunos errores ya que los resultados no son buenos.
K = 2 es un desastre y por lo tanto para k> = 4.
5)
Eliminé un punto en la ubicación problemática y la spline resultante ahora es idéntica a la de Whuber. Pero todavía es una pregunta de por qué el método no funciona en todos los casos.
6)
Un buen suavizado para los datos de Whuber puede ser el siguiente (dibujado por un software de gráficos vectoriales) en el que se ha agregado un punto extra sin problemas (compárese con la actualización
4):
7)
Vea el resultado de la versión de Python del código de Whuber para algunas formas icónicas:
Tenga en cuenta que el método parece no funcionar para las polilíneas. Para la esquina, la polilínea (contorno) verde es lo que quiero pero se puso rojo. Esto debe abordarse ya que los mapas de contorno son siempre polilíneas, aunque las polilíneas cerradas pueden tratarse como polígonos como en mis ejemplos. Tampoco es que el problema surgido en la actualización 4 aún no se haya abordado.
8) [mi último]
Aquí está la solución final (¡no perfecta!):
Recuerde que tendrá que hacer algo sobre el área señalada por las estrellas. Quizás haya un error en mi código o el método propuesto necesita un mayor desarrollo para considerar todas las situaciones y proporcionar los resultados deseados.
Respuestas:
La mayoría de los métodos para spline secuencias de números spline polígonos. El truco es hacer que las splines se "cierren" suavemente en los puntos finales. Para hacer esto, "envuelve" los vértices alrededor de los extremos. Luego spline las coordenadas x e y por separado.
Aquí hay un ejemplo de trabajo en
R
. Utiliza elspline
procedimiento cúbico predeterminado disponible en el paquete de estadísticas básicas. Para obtener más control, sustituya casi cualquier procedimiento que prefiera: solo asegúrese de que se divide entre los números (es decir, los interpola) en lugar de simplemente usarlos como "puntos de control".Para ilustrar su uso, creemos un polígono pequeño (pero complicado).
Spline usando el código anterior. Para suavizar la spline, aumente el número de vértices de 100; para que sea menos suave, disminuya el número de vértices.
Para ver los resultados, trazamos (a) el polígono original en rojo discontinuo, mostrando el espacio entre el primer y el último vértice (es decir, sin cerrar su polilínea límite); y (b) la spline en gris, mostrando una vez más su espacio. (Debido a que el espacio es tan pequeño, sus puntos finales se resaltan con puntos azules).
fuente
Sé que esta es una publicación antigua, pero apareció en Google por algo que estaba buscando, así que pensé en publicar mi solución.
No veo esto como un ejercicio de ajuste de curva 2D, sino más bien como uno 3D. Al considerar los datos como 3D, podemos asegurarnos de que las curvas nunca se crucen entre sí, y podemos usar la información de otros contornos para mejorar nuestra estimación para la actual.
El siguiente extracto de iPython utiliza la interpolación cúbica proporcionada por SciPy. Tenga en cuenta que los valores z que he trazado no son importantes, siempre y cuando todos los contornos sean equidistantes en altura.
Los resultados aquí no se ven los mejores, pero con tan pocos puntos de control siguen siendo perfectamente válidos. Observe cómo se estira la línea verde ajustada para seguir el contorno azul más ancho.
fuente
Escribí casi exactamente el paquete que está buscando ... pero estaba en Perl, y fue hace más de una década: GD :: Polyline . Utilizaba curvas de Bezier cúbicas 2D y "suavizaba" un polígono o "polilínea" arbitrario (mi nombre para lo que ahora se llama comúnmente "LineString").
El algoritmo consistió en dos pasos: dados los puntos en el Polígono, agregue dos puntos de control Bezier entre cada punto; luego llame a un algoritmo simple para hacer una aproximación por partes de la spline.
La segunda parte es fácil; La primera parte fue un poco de arte. Aquí fue la idea: considerar un "segmento de control de" un Vertex N:
vN
. El segmento de control fue de tres puntos colineales:[cNa, vN, cNb]
. El punto central era el vértice. La pendiente de este control seg fue igual a la pendiente del Vértice N-1 al Vértice N + 1. La longitud de la porción izquierda de este segmento era 1/3 de la longitud del Vértice N-1 al Vértex N, y la longitud de la porción derecha de este segmento era 1/3 de la longitud del Vértice N al Vértex N + 1.Si la curva original era cuatro vértices:
[v1, v2, v3, v4]
entonces el cada vértice ahora conseguir un segmento de control de la forma:[c2a, v2, c2b]
. Une estos juntos de esta manera:[v1, c1b, c2a, v2, c2b, c3a, v3, c3b, c4a, v4]
y mójalos de cuatro en cuatro como los cuatro puntos de Bezier:,[v1, c1b, c2a, v2]
luego[v2, c2b, c3a, v3]
, y así sucesivamente. Como[c2a, v2, c2b]
eran co-lineales, la curva resultante será suave en cada vértice.Por lo tanto, esto también cumple con su requisito de parametrizar la "tensión" de la curva: use un valor menor que 1/3 para una curva "más ajustada", una más grande para un ajuste "más circular". En cualquier caso, la curva resultante siempre pasa por los puntos dados originales.
Esto dio como resultado una curva suave que "circunscribió" el Polígono original. También tenía alguna forma de "inscribir" una curva suave ... pero no veo eso en el código CPAN.
De todos modos, en este momento no tengo una versión disponible en Python, ni tengo ninguna figura. PERO ... si / cuando porto esto a Python, me aseguraré de publicar aquí.
fuente