Skip to content

Instantly share code, notes, and snippets.

@mvarela
Created October 29, 2017 09:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mvarela/19b0cfae8d2ba343d469faf22bbcc1df to your computer and use it in GitHub Desktop.
Save mvarela/19b0cfae8d2ba343d469faf22bbcc1df to your computer and use it in GitHub Desktop.
De Jong attractors
(ns ifs.de-jong
(:require [clojure.core.matrix :as m]
[com.evocomputing.colors :as c]
[clojure.core.matrix.stats :as mstats])
(:import [java.io File]
[javax.imageio ImageIO]
[java.awt Color]
[java.awt.image
BufferedImage]))
(defn- next-point [coeffs [x y]]
(let [[a b c d] coeffs
xn (- (Math/sin (* y a)) (Math/cos (* x b)))
yn (- (Math/sin (* c x)) (Math/cos (* d y)))]
[xn yn]))
(defn- create-mapping [size]
(let [scale-and-bin (fn [[x y]] (let [mult (/ size 4)
xform (fn [i] (int (* mult (+ 2 i))))
xx (xform x)
yy (xform y)]
[xx yy]))]
scale-and-bin))
(defn- de-jong
[coeffs size start-point num-iter]
(let [np (partial next-point coeffs)
points (take num-iter (iterate np start-point))
hist (m/new-matrix :vectorz (inc size) (inc size))
scale (create-mapping size)
counter (fn [[x y]]
(m/mset! hist x y (inc (m/mget hist x y))))
do-count (map (comp counter scale) points)]
(do (dorun do-count)
hist)))
(defn- shade-bw
"Value is normalized between 0 and 1, and it represents the density of points at
the position being considered"
[value]
(let [v (if (zero? value) 255 (int (* 255 value)))]
(bit-or (bit-shift-left v 16)
(bit-shift-left v 8)
v)))
(defn- shade-inverted
"Value is normalized between 0 and 1, and it represents the density of points at
the position being considered"
[value]
(let [vgamma (Math/pow value 1/2)
[r g b] (if (zero? vgamma)
[0 0 0]
;(c/hsl-to-rgb 245 60 (* 100 (- 1 vgamma ))))]
(c/hsl-to-rgb 245 30 (- 100 (* 50 (- 1 vgamma)))))]
(bit-or (bit-shift-left r 16)
(bit-shift-left g 8)
b)))
(defn- shade
"Value is normalized between 0 and 1, and it represents the density of points at
the position being considered"
[value]
(let [vgamma (Math/pow value 1/3)
v (if (zero? vgamma)
255
(- 255 (int (* 255 vgamma))))]
(bit-or (bit-shift-left v 16)
(bit-shift-left v 8)
v)))
(defn- do-png [hist name shader]
(ImageIO/write
(let [size ((comp dec first) (m/shape hist))
max-val (m/ereduce max 0 hist)
out (new BufferedImage size size BufferedImage/TYPE_3BYTE_BGR)
normalize (fn [x y]
(let [v (m/mget hist x y)]
(/ v max-val)))]
(doseq [x (range size)
y (range size)]
(.setRGB out x y (shader (normalize x y))))
out)
"png"
(new File name)))
(defn do-de-jong [coeffs size num-iter shader]
(let [coeff-str (clojure.string/join "_" (map str coeffs))
name (str "out-" coeff-str "-" (str size) "-" (str num-iter) ".png")
hist (de-jong coeffs size [0 0] num-iter)]
(do-png hist name shader)))
(do
(do-de-jong [0.970 -1.899 1.381 -1.506] 5000 5e6 shade-inverted)
(do-de-jong [1.4 -2.3 2.4 -2.1] 5000 5e6 shade-inverted)
(do-de-jong [-0.709 1.638 0.452 1.740] 5000 5e6 shade-inverted)
(do-de-jong [1.4191403 -2.2841523 2.4275403 -2.177196] 5000 5e6 shade-inverted)
(do-de-jong [1.02 -1.02 4 -4] 5000 5e6 shade-inverted)
(do-de-jong [1.4191403 -2.2841523 2.4275403 -2.177196] 2000 5e6 shade)
(do-de-jong [-1 4 -2 3] 2000 5e6 shade)
(do-de-jong [Math/PI (* -1 (/ Math/PI 6)) (* Math/PI 2) (- (Math/PI))] 2000 5e6 shade))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment