Clojure + Quil で ジェネラティブアート

積読になっていたマット・ピアソンの「ジェネラティブ・アート」を Clojure と Quil でやってみた。

ch.3 線を引く間違った方法

yをランダム

サンプルの描画部分は以下。

int step = 10;
float lastx = -999;
float lasty = -999;
float y = 50;
int borderx = 20;
int bordery = 10;
for (int x = borderx; x <= width - borderx; x += step) {
  y = bordery + random(height - 2 * bordery);
  if (lastx > -999) {
    line(x, y, lastx, lasty);
  }
  lastx = x;
  lasty = y;
}

これをClojureで書き換えてみる。

(let [step 10
      border-y 10
      ps (for [x (range 50)]    ; x,yを持つマップを50個つくり
           {:x (* x step)
            :y (+ border-y
                  (q/random (- (q/height) 
                               (* border-y 2))))})]
  (doseq [p (partition 2 1 ps)]      ;2個ずつ取得して、
    (let [[{x1 :x, y1 :y} {x2 :x, y2 :y}] p] 
      (q/line x1 y1 x2 y2))))      ;2点間に線を引く

前のYとの差分をランダム

float xstep = 10;
float ystep = 10;
float lastx = 20;
float lasty = 50;
float y = 50;
for (int x = 20; x <= 480; x += step) {
  ystep = random(20) - 10;
  y += ystep;
  line(x, y, lastx, lasty);
  lastx = x;
  lasty = y;
}

Clojureに書き換え。yを決める為に、ひとつ前のyが必要なのでreduceを使ってみたが、もっとシンプルに書けそうな気がする。

(let [step 10
      make-point (fn [col n]
                   (let [y-step  (- (q/random 20) 10)
                         y (+ (:y (last col)) ;前のyから-10~10変える
                              y-step)]
                     (conj col {:x n :y y}))) 
      ps (reduce make-point
                 [{:x 0, :y (/ (q/height) 2)}]
                 (range 0 (q/width) step))]
    (doseq [p (partition 2 1 ps)]
      (let [[{x1 :x, y1 :y} {x2 :x, y2 :y}] p]
        (q/line x1 y1 x2 y2))))