Imagen de la biblioteca de dibujo para Haskell?
graphics (5)
Estoy trabajando en un programa de Haskell para jugar juegos espaciales: tengo una gráfica de un grupo de "individuos" jugando el Dilema del Prisionero, pero solo con sus vecinos inmediatos, y copiando las estrategias de las personas que mejor hacen.
He llegado a un punto en el que necesito dibujar una imagen del mundo, y aquí es donde he encontrado problemas. Dos de las posibles geometrías son fáciles: si las personas tienen cuatro u ocho vecinos cada una, entonces las represento como un cuadrado relleno (con el color correspondiente a la estrategia) y las cubro con el plano. Sin embargo, también tengo una situación en la que las personas tienen seis vecinos (hexágonos) o tres vecinos (triángulos).
Mi pregunta, entonces, es: ¿qué es una buena biblioteca de Haskell para crear imágenes y dibujar formas en ellas? Preferiría que creara PNG, pero no soy increíblemente exigente. Originalmente estaba usando Graphics.GD , pero solo exporta enlaces a funciones para dibujar puntos, líneas, arcos, elipses y rectángulos no rotados, lo cual no es suficiente para mis propósitos (a menos que quiera dibujar hexágonos píxel por píxel *) . Estudié el uso de foreign import
, pero está resultando un poco molesto (en parte porque la función de dibujo de polígonos requiere una matriz de estructuras gdPoint
), y dado que mis requisitos pueden crecer, sería bueno usar una solución en Haskell y no tengo que andar con la FFI (aunque si se trata de un empujón, estoy dispuesto a hacerlo). ¿Alguna sugerencia?
* Esa es también una opción, en realidad; Cualquier consejo sobre cómo hacerlo también sería apreciado, aunque creo que una biblioteca sería más fácil.
EDIT: Muchas gracias a todos por sus sugerencias. Desafortunadamente, no pude obtener todas las bibliotecas requeridas de gtk2hs para construir, lo que descartó muchas soluciones. Por una variedad de razones, después de que intenté todas sus respuestas, no pude instalar varias bibliotecas y descubrí que otras no podían hacer lo que quería, terminé decidiendo simplemente exportar más FFI para libgd y las usé en su lugar.
¿Qué es una buena biblioteca de Haskell para crear imágenes y dibujar formas en ellas?
Tienes bastantes opciones, en mi opinión, todas las siguientes se han utilizado para juegos :
Esos son los más comunes, y puede elegir según las características / familiaridad.
He usado HOpenGL antes, pero el problema es que (por lo que puedo decir) no se puede procesar en un archivo, solo en la pantalla; lo mismo (de nuevo, por lo que puedo decir) parece ser cierto para SDL y Wx. Aunque miraré el Cairo.
Por alguna razón no puedo responder a esta publicación, así que tengo que citarla. Si no está al tanto de GL y SDL, puede crear una superficie / búfer fuera de pantalla o render-to-texture. Esas bibliotecas no necesitan esa función (y tampoco tiene mucho sentido) porque puede hacerlo usted mismo fácilmente accediendo a los píxeles en el búfer y escribiéndolos usted mismo, incluso con los búferes de pantalla puede acceder a los datos de píxeles.
Justo el otro día le mostré a alguien cómo hacer esto con los enlaces de Haskell SDL:
http://hpaste.org/fastcgi/hpaste.fcgi/view?id=25047
Utilice una biblioteca que pueda escribir en archivos .PNG, lo más probable es que tomen un puntero en bruto al píxel que puede obtener de SDL / GL o lo copien en un formato que la biblioteca necesita.
Acabo de encontrar un enlace de Haskell para la biblioteca DevIL que puede generar archivos .PNG. Echa un vistazo a la función llamada writeImageFromPtr
Echa un vistazo a los diagramas:
http://hackage.haskell.org/cgi-bin/hackage-scripts/package/diagrams
Los ejemplos son bastante buenos.
Los diagramas se ven muy bien, pero si desea evitar comprometerse y mantenerse súper ligero, podría generar svg directamente. Robo de Conrad Barski en http://www.lisperati.com/haskell/
type Point = (Float,Float)
type Color = (Int,Int,Int)
type Polygon = [Point]
writePoint :: Point -> String
writePoint (x,y) = (show x)++","++(show y)++" "
writePolygon :: (Color,Polygon) -> String
writePolygon ((r,g,b),p) = "<polygon points=/""++(concatMap writePoint p)++"/" style=/"fill:#cccccc;stroke:rgb("++(show r)++","++(show g)++","++(show b)++");stroke-width:2/"/>"
writePolygons :: [(Color,Polygon)] -> String
writePolygons p = "<svg xmlns=/"http://www.w3.org/2000/svg/">"++(concatMap writePolygon p)++"</svg>"
colorize :: Color -> [Polygon] -> [(Color,Polygon)]
colorize = zip.repeat
rainbow@[red,green,blue,yellow,purple,teal] = map colorize [(255,0,0),(0,255,0),(0,0,255),(255,255,0),(255,0,255),(0,255,255)]
t0 = writeFile "tut0.svg" $ writePolygons (blue [[(100,100),(200,100),(200,200),(100,200)],[(200,200),(300,200),(300,300),(200,300)]])
hexagon c r = translateTo c basicHexagon where
basicHexagon = top ++ (negate r, 0):bottom
top = [(r,0),(r * cos 1,(r * sin 1)),(negate (r * cos 1), r * (sin 1))]
bottom = map (/(x,y)->(x,negate y)) (reverse top)
translateTo (x,y) poly = map f poly where f (a,b)= ((a+x),(b+y))
t1 = writeFile "t1.svg" $ writePolygons (blue [hexagon (100,100) 50] )
hexField r n m = let
mkHex n = hexagon (1.5*n*(r*2),(r*2)) r
row n = map mkHex [1..n]
aRow = row n
in concat [map (offset (r*x)) aRow |x<-[1..m]]
offset r polys = map (oh r) polys where
oh r pt@(x,y) = (x+(1.5*r),y+(r*sin 1))
t2 = writeFile "t2.svg" $ writePolygons (blue $ hexField 50 4 5 )
ejecute t2 y cargue el archivo en Firefox o en algún otro programa que admita svg.
t2.svg, png exportado http://img30.imageshack.us/img30/2245/93715707.png
Cairo es una buena apuesta si quieres generar PNGs. Wumpus también parece prometedor, aunque nunca lo he usado. Si solo necesita verlo en la pantalla, graphics-drawingcombinators es una interfaz fácil para OpenGL que hará lo que necesita en unas pocas líneas (vea example.hs
en la distribución).