src/looms/002-wobbly-lines.lisp @ 3e7390e1f690
Add some trees, and mutate the l-systems sometimes
author |
Steve Losh <steve@stevelosh.com> |
date |
Tue, 20 Feb 2018 20:12:23 -0500 |
parents |
af3a843d3c40 |
children |
e70271703422 |
(in-package :flax.looms.002-wobbly-lines)
;;;; Data ---------------------------------------------------------------------
(defvar *brush* nil)
(defvar *hue* nil)
(defvar *hue-increment* nil)
(defparameter *swing* 0.03)
(defparameter *background* (hsv 0 0 0.05))
;;;; Elements -----------------------------------------------------------------
(defstruct (line (:conc-name "")
(:constructor line (points)))
(points (error "Required") :type vector))
(define-with-macro (line :conc-name "") points)
;;;; Element Conversion -------------------------------------------------------
(defun convert (line opacity)
(list (flax.drawing::path (coerce (points line) 'list)
:color (hsv *hue* 0.9 1)
:opacity opacity)))
;;;; Generation ---------------------------------------------------------------
(defun initial (segments)
(line
(iterate
(for x :from 0.0 :to (+ 1.0 least-positive-single-float) :by (/ 1.0 segments))
(collect (coord x 0.5) :result-type 'vector))))
;;;; Tick ---------------------------------------------------------------------
(defun perturb-point (point)
(incf (y point) (random-range-inclusive (- *swing*) *swing* #'rand)))
(defun perturb-line (line)
(map nil #'perturb-point (points line)))
(defun smooth-line (line)
(iterate
(with points = (points line))
(with final = (1- (length points)))
(for c :in-vector points :with-index i)
(for y = (y c))
(for l = (or (unless (zerop i) (y (aref points (1- i)))) y))
(for r = (or (unless (= final i) (y (aref points (1+ i)))) y))
(zapf (y c) (/ (+ % % l r) 4.0))))
(defun tick (line)
(perturb-line line)
(smooth-line line)
(zapf *hue* (mod (+ % *hue-increment*) 1.0d0)))
;;;; Main ---------------------------------------------------------------------
(defun loom (seed ticks filename width height)
(with-seed seed
(flax.drawing:with-rendering (image filename width height
:padding 0.0
:background *background*)
(let ((line (initial 300))
(*hue* (random-range 0.0d0 1.0d0 #'rand))
(*hue-increment* (/ (random-range 0.15d0 0.3d0 #'rand) ticks))
(mode (random-elt '(:opaque :transparent :fade) #'rand)))
(dotimes (tick ticks)
(when (dividesp tick (/ (expt 10 (floor (log (1- ticks) 10))) 2))
(print tick))
(when (and (eq mode :fade) (dividesp tick 10))
(flax.drawing:fade image *background* 0.04d0))
(flax.drawing:render image (convert line (if (eq mode :transparent)
(/ 95.0d0 ticks)
1.0d0)))
(tick line))
mode))))
;; (time (loom nil 1000 "out.png" 800 300))