Skip to content

Instantly share code, notes, and snippets.

@quoll
Created November 17, 2012 18:51
Show Gist options
  • Save quoll/4098786 to your computer and use it in GitHub Desktop.
Save quoll/4098786 to your computer and use it in GitHub Desktop.
Mandelbrot in Clojure using Java 2D
(ns test.mandelbrot
"Simple Mandelbrot generator.
Trying to optimize. Pulling apart math operations."
(:gen-class)
(:use [test.complex :only (abs2 times plus)])
(:import [test.complex Complex]
[java.awt Graphics Color Dimension]
[java.awt.event KeyListener KeyEvent]
[java.awt.image BufferedImage]
[javax.swing JPanel JFrame SwingUtilities]))
(set! *unchecked-math* true)
(def min-x -2.0)
(def max-x 1.0)
(def min-y -1.0)
(def max-y 1.0)
(def limit 1000)
(def window-name "Mandelbrot")
(def default-width 300)
(def default-height 200)
(defn ^int scaled-color [^long count] (long (* (Math/log (inc count)) 37)))
(def colors (map #(Color. (scaled-color %) 0 0) (range limit)))
(defn ^Color int-to-color [i] (nth colors i))
(defn ^Color mandelbrotColor [^double cr ^double ci]
(loop [zr 0.0, zi 0.0, zrr 0.0, zii 0.0, count 0]
(if (>= count limit)
Color/BLUE
(let [new-zr (+ (- zrr zii) cr)
new-zi (+ (* zr zi 2) ci)
new-zrr (* new-zr new-zr)
new-zii (* new-zi new-zi)]
(if (>= (+ new-zrr new-zii) 4.0)
(int-to-color count)
(recur new-zr new-zi new-zrr new-zii (inc count)))))))
(defn ^Graphics plot [^Graphics g [x y c]]
(.setColor g c)
(.fillRect g x y 1 1)
g)
(defn render [^Graphics g ^long width ^long height]
(let [math-width (- max-x min-x)
math-height (- max-y min-y)
t (System/currentTimeMillis)]
(letfn [(coord-2-math [^long x ^long y]
[(+ (/ (* math-width x) width) min-x) (- max-y (/ (* y math-height) height))])]
(reduce plot g
(map (fn [[a b]] [a b (apply mandelbrotColor (coord-2-math a b))]) (for [x (range width) y (range height)] [x y]))))
(println "Render: " (- (System/currentTimeMillis) t) "ms")))
(defn get-image- [^long width ^long height]
(let [image (BufferedImage. width height BufferedImage/TYPE_INT_RGB)]
(render (.createGraphics image) width height)
image))
(def get-image (memoize get-image-))
(defn new-drawer []
(proxy [JPanel] []
(paint [^Graphics graphics-context]
(let [^int width (proxy-super getWidth)
^int height (proxy-super getHeight)]
(.drawImage graphics-context (get-image width height) 0 0 nil)))))
(defn show-window []
(let [^JPanel drawing-obj (new-drawer)
^JFrame frame (JFrame. window-name)
closer (proxy [KeyListener] []
(keyPressed [^KeyEvent e] (when (= (.getKeyChar e) \q) (.dispose frame)))
(keyReleased [e])
(keyTyped [e]))]
(.setPreferredSize drawing-obj (Dimension. default-width default-height))
(.add (.getContentPane frame) drawing-obj)
(doto frame
; (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
(.pack)
(.setBackground Color/WHITE)
(.addKeyListener closer)
(.setVisible true))))
(defn start-window []
(SwingUtilities/invokeLater #(show-window)))
(defn -main [& args] (start-window))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment