2011-07-26 9 views
17

Estoy buscando una implementación que calcule formas alfa en dos dimensiones. Estoy ejecutando ubuntu. Preferiría una utilidad de línea de comandos para esta tarea, pero también estaría bien con una biblioteca de Python.¿Cómo puedo encontrar la forma alfa (casco cóncavo) de una nube de 2d?

En Google he encontrado muchas implementaciones que calculan formas alfa. Pero ninguno de ellos produce lo que quiero. Como entrada, tengo una lista de dos puntos dimensionales (por ejemplo, un par de flotadores por línea en un archivo de texto). Como salida quiero otra lista de dos puntos dimensionales con la misma escala.

He intentado instalar los últimos enlaces python de cgal, pero estos no han sido compatibles desde hace tiempo y ya no se compilan en Ubuntu 11.04 (también probé Ubuntu 10.04 y no tuve suerte). Clustr, un proyecto desarrollado en flickr por Aaron Straup Cope tampoco compilará en Ubuntu 11.04 (probablemente porque también está vinculado a bibliotecas CGAL más antiguas).

También probé this implementation de un Ken Clarkson en Bell Labs. Emite casi lo que quiero, el resultado parece estar en otra escala y convierte los flotadores en entradas.

También probé las vinculaciones de python de dionysus. Estos compilados, pero cuando alimenté la función fill_alpha2D_complex(points, f) con mi lista de puntos, la salida no era la que esperaba. No era una lista de dos puntos dimensionales, sino que parece ser un "diagrama de persistencia". No sé lo que eso significa.

¿Alguien sabe de una solución simple a este problema?

ACTUALIZACIÓN: Quiero imprimir los puntos asociados con la forma alfa donde está a punto de no estar conectado. Creo que esto significa "darme los puntos asociados con el valor alfa más pequeño para que la forma esté conectada".

ACTUALIZACIÓN Ahora descubrí cómo conseguir lo que quiero de Ken Clarkson's implementation y (más o menos lo que quiero) del dionysus implementation. La implementación de Clarkson estaba haciendo lo correcto, solo sacaba los índices de los puntos en lugar de los puntos en sí (la misma historia con dionysus), y necesitaba obtener algunas banderas opcionales correctas. El contenedor que escribí está debajo. Esta solución es ideal porque produce una forma alfa que está conectada y no contiene agujeros. Alpha se establece automáticamente. Dionysus, por otro lado, no descubre automáticamente estos valores de alfa. Además, la implementación de Clarkson se puede configurar para generar una imagen ps de la forma (con el indicador -afps). Para obtener el código de Clarkson para compilar con la versión no antigua de GCC, debe seguir el paso descrito here. El siguiente código puede ser utilizado como una biblioteca o como un solo envoltorio:

#!/usr/bin/python -O 

import sys, os 
import subprocess 
import tempfile 

hull_path = "./hull.exe" 

def get_alpha_shape(points): 
    # Write points to tempfile 
    tmpfile = tempfile.NamedTemporaryFile(delete=False) 
    for point in points: 
     tmpfile.write("%0.7f %0.7f\n" % point) 
    tmpfile.close() 

    # Run hull 
    command = "%s -A -m1000000 -oN < %s" % (hull_path, tmpfile.name) 
    print >> sys.stderr, "Running command: %s" % command 
    retcode = subprocess.call(command, shell=True) 
    if retcode != 0: 
     print >> sys.stderr, "Warning: bad retcode returned by hull. Retcode value:" % retcode 
    os.remove(tmpfile.name) 

    # Parse results 
    results_file = open("hout-alf") 
    results_file.next() # skip header 
    results_indices = [[int(i) for i in line.rstrip().split()] for line in results_file] 
# print "results length = %d" % len(results_indices) 
    results_file.close() 
    os.remove(results_file.name) 

    return [(points[i], points[j]) for i,j in results_indices] 

if __name__ == "__main__": 
    points = [tuple([float(i) for i in line.rstrip().split()]) for line in sys.stdin] 
    for point_i, point_j in get_alpha_shape(points): 
     sys.stdout.write("%0.7f,%0.7f\t%0.7f,%0.7f\n" % (point_i[0], point_i[1], point_j[0], point_j[1])) 
    sys.exit(0) 
+1

Una simple lista de puntos no puede describir una forma alfa, ya que ni siquiera está necesariamente conectada. –

+0

Solo quiero un lindo límite de una nube de puntos. Pero si esta descripción no es lo suficientemente exacta, consulte mi actualización en la pregunta. – conradlee

+0

una forma alfa conectada aún puede no ser muy agradable, es decir, contener agujeros. –

Respuesta

3

encontré this en la documentación de Dioniso, que podrían darle la forma alfa:

complex = Filtration() 
fill_alpha2D_complex(points, complex) 
alphashape = [s for s in complex if s.data[0] <= .5] 

Entonces yo creo que necesita para hacer algo como:

for simplex in alphashape: 
    print [v for v in simplex.vertices] 
+0

Eso imprime una larga lista de tuplas. La mayoría de las tuplas tienen un miembro, algunas tienen dos o tres. Hay alrededor de cinco mil de estas tuplas, a pesar de que mi entrada original consistió en alrededor de mil puntos. En cambio, esperaba una lista de dos puntos dimensionales que tenían menos miembros que la entrada. – conradlee

+0

Después de algunas explicaciones del autor de dionysus, he llegado a la conclusión de que esta respuesta es correcta. Los enteros en cada una de las tuplas son los índices de los puntos. Las tuplas con dos miembros son bordes, aquellos con tres son triángulos. El ".5" es el valor de alfa. Hay una manera de determinar el valor más pequeño de alfa de modo que la forma resultante esté conectada. Si tengo tiempo, colocaré este código en la pregunta. – conradlee

+0

bien, lo publiqué. al final, opté por "casco" sobre dionisio por las razones que describo en la solución (que he agregado a la pregunta) más arriba. – conradlee

Cuestiones relacionadas