Библиотека графических изображений для Haskell? - PullRequest
22 голосов
/ 26 апреля 2010

Я работаю над программой Haskell для игры в пространственные игры: у меня есть график группы «людей», играющих в дилемму заключенного, но только с их непосредственными соседями и копирующих стратегии людей, которые добиваются лучших результатов.

Я достиг точки, когда мне нужно нарисовать образ мира, и именно здесь я столкнулся с проблемами. Две из возможных геометрий просты: если у людей по четыре или восемь соседей каждый, то я представляю каждую из них как заполненный квадрат (с цветом, соответствующим стратегии) ​​и выкладываю на них плоскость. Однако у меня также есть ситуация, когда у людей есть шесть соседей (шестиугольники) или три соседа (треугольники).

Тогда мой вопрос: Какая библиотека на Хаскеле хороша для создания изображений и рисования на них фигур? Я бы предпочел, чтобы она создавала PNG, но я не настолько требователен. Первоначально я использовал Graphics.GD , но он экспортирует только привязки к функциям для рисования точек, линий, дуг, эллипсов и не повернутых прямоугольников, что недостаточно для моих целей (если я не хочу рисовать шестиугольники пиксель за пикселем *). Я рассмотрел использование foreign import, но это немного затрудняет работу (отчасти потому, что функция рисования полигонов требует массива структур gdPoint), и, учитывая, что мои требования могут расти, было бы неплохо использовать - Решение Хаскелла и не надо облажаться с FFI (хотя, если толчок придет, я готов это сделать). Есть предложения?

* То, что - это , на самом деле тоже вариант; любые советы о том, как это сделать, также приветствуются, хотя я думаю, что библиотека будет проще.

РЕДАКТИРОВАТЬ: Большое спасибо всем за ваши предложения. К сожалению, я не смог собрать все необходимые библиотеки gtk2hs, что исключало множество решений. По разным причинам, после того как я попробовал все ваши ответы, не смог установить ряд библиотек и обнаружил, что другие не могут делать то, что я хотел, я решил просто экспортировать больше FFI для libgd и использовал это вместо этого.

Ответы [ 5 ]

11 голосов
/ 27 апреля 2010

Диаграммы выглядят круто, но если вы хотите избежать фиксации и оставаться сверхлегким, вы можете сгенерировать svg напрямую. Кража у Конрада Барского на 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 )

запустите t2 и загрузите файл в Firefox или другую программу, поддерживающую svg.

t2.svg, экспорт png http://img30.imageshack.us/img30/2245/93715707.png

6 голосов
/ 26 апреля 2010

Я использовал HOpenGL раньше, но проблема в том (насколько я могу судить) он не может отображаться в файл, но только экран; то же самое (опять же, насколько Я могу сказать), кажется, верно для SDL и Wx. Я посмотрю в Каире, хотя.

Почему-то я не могу ответить на это сообщение, поэтому я должен процитировать его. Вы не правы в отношении GL и SDL, вы можете создать внеэкранную поверхность / буфер или рендеринг в текстуру. Этим библиотекам не нужна такая функция (и в этом тоже нет особого смысла), потому что вы можете сделать это сами довольно легко, получив доступ к пикселям в буфере и записав их самостоятельно, даже с помощью экранных буферов вы можете получить доступ к данным пикселей.

Буквально на днях я показал кому-то, как это сделать с привязками Haskell SDL:

http://hpaste.org/fastcgi/hpaste.fcgi/view?id=25047

Используйте библиотеку, которая может записывать в файлы .PNG, они, скорее всего, возьмут необработанный указатель на пиксельный буфер, который можно получить из SDL / GL, или скопируют его в формат, который необходим библиотеке.

Я только что обнаружил привязку Haskell для библиотеки DevIL , которая может выводить файлы .PNG. Проверьте функцию под названием writeImageFromPtr

5 голосов
/ 26 апреля 2010

Каир - хорошая ставка, если вы хотите создавать PNG. Wumpus также выглядит многообещающе, хотя я никогда не использовал его. Если вам просто нужно увидеть это на экране, Graphics-Drawing Combinators - это простой интерфейс для OpenGL, который будет делать то, что вам нужно, в несколько строк (см. example.hs в дистрибутиве).

3 голосов
/ 27 апреля 2010

Проверить диаграммы:

http://hackage.haskell.org/cgi-bin/hackage-scripts/package/diagrams

Примеры довольно хорошие.

2 голосов
/ 26 апреля 2010

Что такое хорошая библиотека на Haskell для создания изображений и рисования на них фигур?

У вас есть несколько вариантов, на мой взгляд, для игр использовалось следующее :

Это наиболее распространенные, и вы можете просто выбрать, основываясь на особенностях / знакомстве.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...