src/looms/001-triangles.lisp @ d3a901ef3501
Loom 2
| author | Steve Losh <steve@stevelosh.com> |
|---|---|
| date | Sun, 04 Feb 2018 00:02:49 -0500 |
| parents | 3ab52c60dfee |
| children | fbdceb03ce0e |
(in-package :flax.looms.001-triangles) ;;;; Triangle Subdivision ;;; ;;; Based on http://www.tylerlhobbs.com/writings/triangle-subdivision ;;;; Utils -------------------------------------------------------------------- (defun round-to (number divisor) (* divisor (round number divisor))) ;;;; Elements ----------------------------------------------------------------- (defstruct (triangle (:conc-name "")) (a (coord 0 0) :type coord) (b (coord 0 0) :type coord) (c (coord 0 0) :type coord)) (define-with-macro (triangle :conc-name "") a b c) (defun triangle (a b c) (make-triangle :a a :b b :c c)) ;;;; Element Conversion ------------------------------------------------------- (defun convert-triangle (triangle) (with-triangle (triangle) (flax.drawing:triangle a b c))) (defun convert (universe) (mapcar #'convert-triangle universe)) ;;;; Generation --------------------------------------------------------------- (defun initial-triangles () (list (triangle (coord 0 1) (coord 1 1) (coord 0 0)) (triangle (coord 1 0) (coord 1 1) (coord 0 0)))) (defun split-triangle-evenly (triangle) (with-triangle (triangle) (let* ((n 1/2) (p (coord (lerp (x b) (x c) n) (lerp (y b) (y c) n)))) (list (triangle p b a) (triangle p a c))))) (defun generate-universe-even (depth &aux (triangles (initial-triangles))) (do-repeat depth (zapf triangles (mappend #'split-triangle-evenly %))) triangles) (defun find-longest-side (triangle) (with-triangle (triangle) (let* ((ab (distance a b)) (bc (distance b c)) (ca (distance c a)) (longest (max ab bc ca))) (cond ((= longest ab) (list c a b)) ((= longest bc) (list a c b)) ((= longest ca) (list b c a)) (t (error "what?")))))) (defun split-triangle-self-balancing (triangle) (destructuring-bind (a b c) (find-longest-side triangle) (let ((p (-<> (random-gaussian 0.5 0.1 #'rand) (clamp 0.3 0.7 <>) (round-to <> 1/100) (clerp b c <>)))) (list (triangle p b a) (triangle p a c))))) (defun generate-universe-balancing (depth seed) (losh::clear-gaussian-spare) (with-seed seed (gathering (labels ((should-stop-p (iteration) (or (= depth iteration) (and (> iteration 6) (randomp (map-range 0 depth 0.0 0.05 iteration) #'rand)))) (recur (triangle &optional (iteration 0)) (if (should-stop-p iteration) (gather triangle) (map nil (rcurry #'recur (1+ iteration)) (split-triangle-self-balancing triangle))))) (map nil #'recur (initial-triangles)))))) ;;;; Main --------------------------------------------------------------------- (defun loom (seed depth filename width height) (flax.drawing:with-rendering (image filename width height) (flax.drawing:render image (convert (generate-universe-balancing depth seed))))) ;; (time (loom 12 18 "out.pnm" 3000 3000))