Created
November 17, 2012 18:51
-
-
Save quoll/4098786 to your computer and use it in GitHub Desktop.
Mandelbrot in Clojure using Java 2D
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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