This operation flips every point and rotates to the right.|
|
At this stage, it *might* be clear what is going on, but it's not exactly obvious.
@@ -71,7 +71,7 @@ The easiest way to make sense of this is to show the operations on the Barnsley
| -------- | --------- |
| $$f_1(P) = \begin{bmatrix} 0 &0 \\ 0 &0.16 \end{bmatrix}P + \begin{bmatrix} 0 \\ 0 \end{bmatrix}$$ |
|
As an important note: the idea of modifying a resulting image by twiddling the knobs of an affine transform is the heart of many interesting methods, including fractal image compression where a low resolution version of an image is stored along with a reconstructing function set to generate high-quality images on-the-fly {{ "fractal-compression" | cite }}{{ "saupe1994review" | cite }}.
@@ -135,6 +135,8 @@ The biggest differences between the two code implementations is that the Barnsle
[import, lang:"java"](code/java/Barnsley.java)
{% sample lang="coco" %}
[import, lang:"coconut"](code/coconut/barnsley.coco)
+{% sample lang="hs" %}
+[import, lang:"haskell"](code/haskell/Barnsley.hs)
{% endmethod %}
### Bibliography
diff --git a/contents/barnsley/code/haskell/Barnsley.hs b/contents/barnsley/code/haskell/Barnsley.hs
new file mode 100644
index 000000000..bf7024200
--- /dev/null
+++ b/contents/barnsley/code/haskell/Barnsley.hs
@@ -0,0 +1,40 @@
+import Data.Array (Array, bounds, elems, listArray, (!))
+import Data.List (intercalate)
+import System.Random
+
+data Point = Point Double Double
+
+chaosGame :: RandomGen g => g -> Int -> Array Int (Double, (Point -> Point)) -> [Point]
+chaosGame g n hutchinson = take n points
+ where
+ (x, g') = random g
+ (y, g'') = random g'
+
+ cumulProbabilities = scanl1 (+) $ map fst $ elems hutchinson
+ to_choice x = length $ takeWhile (x >) cumulProbabilities
+
+ picks = map to_choice $ randomRs (0, 1) g''
+ step = fmap snd hutchinson
+
+ points = Point x y : zipWith (step !) picks points
+
+affine :: (Double, Double, Double, Double) -> (Double, Double) -> Point -> Point
+affine (xx, xy, yx, yy) (a, b) (Point x y) = Point (a + xx * x + xy * y) (b + yx * x + yy * y)
+
+showPoint :: Point -> String
+showPoint (Point x y) = show x ++ "\t" ++ show y
+
+main :: IO ()
+main = do
+ g <- newStdGen
+ let barnsley =
+ listArray
+ (0, 3)
+ [ (0.01, affine (0, 0, 0, 0.16) (0, 0)),
+ (0.85, affine (0.85, 0.04, -0.04, 0.85) (0, 1.6)),
+ (0.07, affine (0.2, -0.26, 0.23, 0.22) (0, 1.6)),
+ (0.07, affine (-0.15, 0.28, 0.26, 0.24) (0, 0.44))
+ ]
+ points = chaosGame g 100000 barnsley
+
+ writeFile "out.dat" $ intercalate "\n" $ map showPoint points