packages feed

Imlib-0.1: examples/circle-inversion.hs

import Graphics.Imlib
import Data.Array
import System.Random

data Point = Point {x :: Double, y :: Double} deriving (Show, Eq)

data Circle = Circle { centre :: Point, radius :: Double } deriving (Show, Eq)

data Frame = Frame { top :: Double, left :: Double, bottom :: Double, right :: Double }

invert :: Circle -> Point -> Point
invert (Circle (Point a b) r) (Point x y) = Point (a + q*(x-a)) (b + q*(y-b))
      where q = r^2 / ((x-a)^2 + (y-b)^2)

invertRandomly :: StdGen -> [Circle] -> Point -> [Point]
invertRandomly g cs p = p : invertRandomly g' cs (invert (cs !! r) p)
    where (r,g') = randomR (0,length cs - 1) g

floorPoint :: Point -> (Int, Int)
floorPoint (Point x y) = (floor x, floor y)

main = do
     g <- getStdGen
     let cs = [Circle (Point (512+50) (512+50)) 50, Circle (Point 512 (512+50)) 50, Circle (Point (512+50) (512-1)) 50]
         p = Point 450 212
         ps = invertRandomly g cs p
         psf = filter (\(Point x y) -> x >= 0 && x < 1024 && y >= 0 && y < 1024) ps
         a = accumArray (\x y -> ImlibColor 0 255 255 255) 
                        (ImlibColor 0 0 0 0) 
                        ((0,0), (1024, 1024)) 
                        (zip (map floorPoint (take 50000 psf)) (repeat 0))
     buffer <- createImageUsingArray a
     contextSetImage buffer
     imageSetFormat "png"
     saveImage "hello.png"