;;; Mandelbrot set fractal.
(define centerx -0.5) ; real axis coordinate
(define centery 0.0) ; imaginary axis coordinate
(define width 4.5) ; real axis view width
(define ITERATIONS 20)
(define radius^2 16.0)
(define zr 0.0)
(define zi 0.0)
(define (map-monochrome value) ; input value : 0 .. 511
(if (<= value 255)
value
(begin
(set! value (- value 256))
(+ (* value 256 256) (* value 256) 255))))
(define (modulus x y)
(sqrt (+ (* x x) (* y y))))
(define (plot x y r g b)
(plotRGB ctx x y r g b)) ; interface to javascript
(define (plot-pixel x y value)
(let
((r (remainder value 256))
(g (remainder (quotient value 256) 256))
(b (remainder (quotient value (* 256 256)) 256)))
(plot x y r g b)))
(define (display-pixel-value n-iter x y)
(let
((mu
(if (= n-iter ITERATIONS)
0.0
(+ n-iter (- 1.0 (/ (log (log (modulus zr zi))) (log 2.0)))))))
(let
((value (inexact->exact (truncate
(* 512.0 (/ mu ITERATIONS))))))
(plot-pixel x y (map-monochrome value)))))
(define (save c x y)
(set! zr x)
(set! zi y)
c)
(define (iterate-pixel r i step x y radius^2)
(let ((cr (+ r (* (exact->inexact x) step)))
(ci (+ i (* (exact->inexact y) step))))
(let loop ((zr cr)
(zi ci)
(c 0))
(if (= c ITERATIONS)
(save c zr zi)
(let ((zr^2 (* zr zr))
(zi^2 (* zi zi)))
(if (> (+ zr^2 zi^2) radius^2)
(save c zr zi)
(let ((new-zr (+ (- zr^2 zi^2) cr))
(new-zi (+ (* 2.0 (* zr zi)) ci)))
(loop new-zr new-zi (+ c 1)))))))))
(define (mandel r i step width height)
(do ((y (- height 1) (- y 1))) ((< y 0))
(do ((x 0 (+ x 1))) ((= x width))
(display-pixel-value (iterate-pixel r i step x y radius^2) x y))))
(define (upper-left-x center-x width)
(- center-x (* width 0.5)))
(define (upper-left-y center-y width)
(- center-y (* width 0.5)))
(define (get-step image-size width)
(/ width image-size))
(define (mandelbrot)
(let
((image-width 320) ; display resolution
(image-height 240)) ; display resolution
(let
((height (* image-height (/ width image-width))))
(mandel
(upper-left-x centerx width)
(upper-left-y centery height)
(get-step image-width width)
image-width image-height))))
(define (mouseClick x y)
(set! centerx
(+ (upper-left-x centerx width) (* width (/ (exact->inexact x) 320))))
(let
((height (* 240 (/ width 320))))
(set! centery
(+ (upper-left-y centery height) (* height (/ (exact->inexact y) 240)))))
(set! width (* 0.3 width)))