diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b05396e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.hi +*.o +flame +flame.png diff --git a/flame.elm b/flame.elm index 269374d..4f474d5 100644 --- a/flame.elm +++ b/flame.elm @@ -8,6 +8,8 @@ import Random l !! n = if n == 0 then head l else (tail l) !! (n-1) -- negative of a number (I don't like writing 0-x). neg x = 0-x +-- too useful +concatmap f l = concat (map f l) -- Colors (theme is solarized) base03 = rgb 0 43 54 @@ -32,9 +34,12 @@ mybase = rgba 108 113 196 (2/3) -- draw a point at position (x,y) point = filled mybase . rect 1 1 +colorpoint ((x,y),n) = filled (rgb n n n) . rect 1 1 $ (x,y) + -- fill the background with color base3 -background w h = filled base3 ( rect w h (div w 2,div h 2)) +background w h = collage w h + [filled base03 $ rect w h (div w 2,div h 2)] -- RANDOM PART nextint n = @@ -112,27 +117,34 @@ rot phi = aff $ M (cos phi) (sin phi) 0.0 (neg (sin phi)) (cos phi) 0.0 zoom z = aff $ M z 0 0 0 z 0 -- The final transformation to transform the final result (zoom,rotate,translate) -final = trans (480,300) . zoom 500 . rot (neg 0.747) +final = trans (280,200) . zoom 300 . rot (neg 0.747) -sierpset startpoint rands = +sierpset startpoint rands tmpres = if rands == [] - then [] + then tmpres else let randval=(head rands) `rem` (length fs) newpoint = (fs !! randval) startpoint - savepoint = final newpoint + roundPoint (x,y) = (round x,round y) + savepoint = roundPoint ( final newpoint ) + oldvalue = Dict.lookup savepoint tmpres + newvalue = 1 + (Maybe.fromMaybe 0 oldvalue) + newtmpres = Dict.insert savepoint newvalue tmpres in - savepoint:(sierpset newpoint (tail rands)) + (sierpset newpoint (tail rands) newtmpres) -concatmap f l = concat (map f l) -sierpinsky = drop 30 $ concatmap (\s -> sierpset (0.0,0.0) (randlist s 4000)) [1..5] +sierpinsky = sierpset (0.0,0.0) (randlist 0 1000000) Dict.empty scene (x,y) (w,h) = let - inpoint (x,y) = x>=0 && x<=w && y>=0 && y<=h - in collage w h $ - background w h: - map point (filter inpoint sierpinsky) + inpoint ((x,y),_) = x>=0 && x<=w && y>=0 && y<=h + in layers + [ background w h + , collage w h $ + map colorpoint $ + filter inpoint $ + Dict.toList $ sierpinsky + ] -main = scene <~ Mouse.position ~ Window.dimensions +main = scene (0,0) (500,500) diff --git a/haskell/flame-img.hs b/haskell/flame-img.hs deleted file mode 100644 index 3114415..0000000 --- a/haskell/flame-img.hs +++ /dev/null @@ -1,185 +0,0 @@ -module Main where - -import Data.HashMap as Dict -- cabal install HashMap -import Data.Maybe as Maybe -import Data.Word (Word8) - -import Codec.Picture -- cabal install juicyPixels FTW -import Control.Monad -import System.Environment (getArgs) -data Global = Global { imgWidth :: Int - , imgHeight :: Int - , nbPoints :: Int } - -type YMap = Map (Int,Int) Int - --- Basic functions - --- -- nth element of a list --- l !! n = if n == 0 then head l else (tail l) !! (n-1) --- negative of a number (I don't like writing 0-x). -neg x = 0-x - -rgb :: Int -> Int -> Int -> (Int,Int,Int) -rgb = (,,) -rgba = (,,,) --- Colors (theme is solarized) -base03 = rgb 0 43 54 -base02 = rgb 7 54 66 -base01 = rgb 88 110 117 -base00 = rgb 101 123 131 -base0 = rgb 131 148 150 -base1 = rgb 147 161 161 -base2 = rgb 238 232 213 -base3 = rgb 253 246 227 -yellow = rgb 181 137 0 -orange = rgb 203 75 22 -red = rgb 220 50 47 -magenta = rgb 211 54 130 -violet = rgb 108 113 196 -blue = rgb 38 139 210 -cyan = rgb 42 161 152 -green = rgb 133 153 0 - --- Default text color -mybase = rgba 108 113 196 (2/3) - --- RANDOM PART -nextint n = - let - a = 22695477 - c = 1 - m = 2^32 - in - (a*n + c) `rem` m - --- generate a random sequence of length k starting with some seed -randlist seed k = if (k<0) then [] else (nextint seed):randlist (nextint seed) (k-1) - --- generate a random sequence of points of length k starting with some seed -randcouples seed k = if (k<0) then [] - else - let ns = nextint seed - nns = nextint ns - in (ns,nns):randcouples nns (k-1) --- END OF PSEUDO RANDOM NUMBER GENERATION - - -{- - - Flame Set - - - - S = U_{i} F_i(S) - - - - F_i being transformations - - General form: - - F = affine . linearcomp [variation] . affine - - affine is a linear function (x,y) -> (ax+by+c,dx+ey+f) - - variation is some kind of function with some contraction properties - ex: (x,y) -> (x,y), (sin x, sin y), etc... - - linearcomp [f] is a linear composition of functions: (x,y) -> Sum vi*f(x,y) --} - -data Matrice = M Float Float Float Float Float Float -aff (M a b c d e f) (x,y) = (a*x + b*y + c, d*x + e*y +f) - --- Some affine functions to generate the sierpinsky set --- Equivalent to --- sierp = [ \(x,y)->(x/2,y/2) --- , \(x,y)->((x+1)/2,y/2) --- , \(x,y)->(x/2,(y+1)/2) ] -sierp = [ aff $ M - 0.5 0.0 0.0 - 0.0 0.5 0.0 - , aff $ M - 0.5 0.0 0.5 - 0.0 0.5 0.0 - , aff $ M - 0.5 0.0 0.0 - 0.0 0.5 0.5 - ] - --- Some variations -vs = [ \(x,y) -> (x,y) - , \(x,y) -> (sin x, sin y) - , \(x,y) -> let r2 = x*x+y*y in (x/r2,y/r2) - , \(x,y) -> let r2 = x*x+y*y in (x*(sin r2) - y*(cos r2),x*(cos r2) + y * (sin r2)) - , \(x,y) -> let r = sqrt (x^2+y^2) in ((x - y)*(x + y)/r,2*x*y/r) - ] - --- Some final functions -fs :: [(Float,Float) -> (Float,Float)] -fs = [ (vs !! 3) . (sierp !! 0) - , (vs !! 3) . (sierp !! 1) - , (vs !! 3) . (sierp !! 2)] - --- Transformation functions --- translate -trans (tx,ty) = aff $ M 1 0 tx 0 1 ty --- rotate -rot phi = aff $ M (cos phi) (sin phi) 0.0 (neg (sin phi)) (cos phi) 0.0 --- zoom -zoom z = aff $ M z 0 0 0 z 0 - --- The final transformation to transform the final result (zoom,rotate,translate) -final = trans (280,200) . zoom 300 . rot (neg 0.747) - -sierpset :: (Float,Float) -> [Int] -> YMap -> YMap -sierpset startpoint rands tmpres = - if rands == [] - then tmpres - else - let - roundPoint (x,y) = (round x,round y) - randval=(head rands) `rem` (length fs) - newpoint = (fs !! randval) startpoint - savepoint = roundPoint ( final newpoint ) - oldvalue = Dict.lookup savepoint tmpres - newvalue = 1 + (Maybe.fromMaybe 0 oldvalue) - newtmpres = savepoint `seq` newvalue `seq` Dict.insert savepoint newvalue tmpres - in - sierpset newpoint (tail rands) newtmpres - -sierpinsky :: Int -> YMap -sierpinsky n = sierpset (0.0,0.0) (randlist 0 n) Dict.empty - -scene env = - let - w = imgWidth env - h = imgHeight env - n = nbPoints env - inpoint ((x,y),_) = x>=0 && x<=w && y>=0 && y<=h - in (Prelude.filter inpoint) . Dict.toList $ (sierpinsky n) - - -initGlobalParams args = - Global { imgWidth = read (args !! 0) - , imgHeight = read (args !! 1) - , nbPoints = read (args !! 2) } - -imageFromDict :: YMap -> Int -> Int -> Image PixelRGB8 -imageFromDict dict width height = generateImage colorOfPoint width height - where - maxnb :: Int - maxnb = Dict.fold max 0 dict - colorOfPoint :: Int -> Int -> PixelRGB8 - colorOfPoint x y = let nb = fromMaybe 0 (Dict.lookup (x,y) dict) - val :: Word8 - val = fromIntegral $ div (255*nb) maxnb - in if nb == 0 then PixelRGB8 0 0 0 - else PixelRGB8 val val val - -writeImage :: Int -> Int -> Int -> YMap -> IO () -writeImage w h n dict = writePng "flame.png" $ imageFromDict dict w h - -main :: IO () -main = do - args <- getArgs - if (length args<3) - then print $ "Usage flame w h n" - else do - env <- return (initGlobalParams args) - w <- return (imgWidth env) - h <- return (imgHeight env) - n <- return (nbPoints env) - -- mapM_ (print) (scene env) - writeImage w h n (sierpinsky n) diff --git a/haskell/flame.hs b/haskell/flame.hs deleted file mode 100644 index b39e02a..0000000 --- a/haskell/flame.hs +++ /dev/null @@ -1,159 +0,0 @@ -module Main where - -import Data.HashMap as Dict -import Data.Maybe as Maybe - -import Control.Monad -import System.Environment (getArgs) -data Global = Global { imgWidth :: Int - , imgHeight :: Int - , nbPoints :: Int } - --- Basic functions - --- -- nth element of a list --- l !! n = if n == 0 then head l else (tail l) !! (n-1) --- negative of a number (I don't like writing 0-x). -neg x = 0-x - -rgb :: Int -> Int -> Int -> (Int,Int,Int) -rgb = (,,) -rgba = (,,,) --- Colors (theme is solarized) -base03 = rgb 0 43 54 -base02 = rgb 7 54 66 -base01 = rgb 88 110 117 -base00 = rgb 101 123 131 -base0 = rgb 131 148 150 -base1 = rgb 147 161 161 -base2 = rgb 238 232 213 -base3 = rgb 253 246 227 -yellow = rgb 181 137 0 -orange = rgb 203 75 22 -red = rgb 220 50 47 -magenta = rgb 211 54 130 -violet = rgb 108 113 196 -blue = rgb 38 139 210 -cyan = rgb 42 161 152 -green = rgb 133 153 0 - --- Default text color -mybase = rgba 108 113 196 (2/3) - --- RANDOM PART -nextint n = - let - a = 22695477 - c = 1 - m = 2^32 - in - (a*n + c) `rem` m - --- generate a random sequence of length k starting with some seed -randlist seed k = if (k<0) then [] else (nextint seed):randlist (nextint seed) (k-1) - --- generate a random sequence of points of length k starting with some seed -randcouples seed k = if (k<0) then [] - else - let ns = nextint seed - nns = nextint ns - in (ns,nns):randcouples nns (k-1) --- END OF PSEUDO RANDOM NUMBER GENERATION - - -{- - - Flame Set - - - - S = U_{i} F_i(S) - - - - F_i being transformations - - General form: - - F = affine . linearcomp [variation] . affine - - affine is a linear function (x,y) -> (ax+by+c,dx+ey+f) - - variation is some kind of function with some contraction properties - ex: (x,y) -> (x,y), (sin x, sin y), etc... - - linearcomp [f] is a linear composition of functions: (x,y) -> Sum vi*f(x,y) --} - -data Matrice = M Float Float Float Float Float Float -aff (M a b c d e f) (x,y) = (a*x + b*y + c, d*x + e*y +f) - --- Some affine functions to generate the sierpinsky set --- Equivalent to --- sierp = [ \(x,y)->(x/2,y/2) --- , \(x,y)->((x+1)/2,y/2) --- , \(x,y)->(x/2,(y+1)/2) ] -sierp = [ aff $ M - 0.5 0.0 0.0 - 0.0 0.5 0.0 - , aff $ M - 0.5 0.0 0.5 - 0.0 0.5 0.0 - , aff $ M - 0.5 0.0 0.0 - 0.0 0.5 0.5 - ] - --- Some variations -vs = [ \(x,y) -> (x,y) - , \(x,y) -> (sin x, sin y) - , \(x,y) -> let r2 = x*x+y*y in (x/r2,y/r2) - , \(x,y) -> let r2 = x*x+y*y in (x*(sin r2) - y*(cos r2),x*(cos r2) + y * (sin r2)) - , \(x,y) -> let r = sqrt (x^2+y^2) in ((x - y)*(x + y)/r,2*x*y/r) - ] - --- Some final functions -fs = [ (vs !! 3) . (sierp !! 0) - , (vs !! 3) . (sierp !! 1) - , (vs !! 3) . (sierp !! 2)] - --- Transformation functions --- translate -trans (tx,ty) = aff $ M 1 0 tx 0 1 ty --- rotate -rot phi = aff $ M (cos phi) (sin phi) 0.0 (neg (sin phi)) (cos phi) 0.0 --- zoom -zoom z = aff $ M z 0 0 0 z 0 - --- The final transformation to transform the final result (zoom,rotate,translate) -final = trans (280,200) . zoom 300 . rot (neg 0.747) - -sierpset startpoint rands tmpres = - if rands == [] - then tmpres - else - let - roundPoint (x,y) = (round x,round y) - randval=(head rands) `rem` (length fs) - newpoint = (fs !! randval) startpoint - savepoint = roundPoint ( final newpoint ) - oldvalue = Dict.lookup savepoint tmpres - newvalue = 1 + (Maybe.fromMaybe 0 oldvalue) - newtmpres = Dict.insert savepoint newvalue tmpres - in - sierpset newpoint (tail rands) newtmpres - -sierpinsky n = sierpset (0.0,0.0) (randlist 0 n) Dict.empty - -scene env = - let - w = imgWidth env - h = imgHeight env - n = nbPoints env - inpoint ((x,y),_) = x>=0 && x<=w && y>=0 && y<=h - in (Prelude.filter inpoint) . Dict.toList $ (sierpinsky n) - - -initGlobalParams args = - Global { imgWidth = read (args !! 0) - , imgHeight = read (args !! 1) - , nbPoints = read (args !! 2) } - -main :: IO () -main = do - args <- getArgs - if (length args<3) - then print $ "Usage flame w h n" - else do - env <- return (initGlobalParams args) - mapM_ (print) (scene env)