Episode 35: Intro to Fractals
author |
Steve Losh <steve@stevelosh.com> |
date |
Tue, 05 Jul 2016 13:58:12 +0000 |
parents |
15245c6a668a
|
children |
e2a3c62c574d
|
branches/tags |
(none) |
files |
package.lisp src/2d/demo.lisp src/2d/vectors.lisp |
Changes
--- a/package.lisp Sun Jul 03 16:12:41 2016 +0000
+++ b/package.lisp Tue Jul 05 13:58:12 2016 +0000
@@ -119,6 +119,7 @@
#:vec-to-string
#:with-vec
#:with-vecs
+ #:vec-to-list
))
(defpackage #:coding-math.2d.hitboxes
--- a/src/2d/demo.lisp Sun Jul 03 16:12:41 2016 +0000
+++ b/src/2d/demo.lisp Tue Jul 05 13:58:12 2016 +0000
@@ -1,6 +1,7 @@
(in-package #:coding-math.2d.demo)
;;;; Config
+(setf *bypass-cache* t)
(defparameter *width* 600)
(defparameter *height* 400)
@@ -19,6 +20,20 @@
(background (gray 1))
,@body))
+(defun oob-p (p &optional (r 0.0))
+ (or (outsidep (- 0 r) (+ *width* r) (vec-x p))
+ (outsidep (- 0 r) (+ *height* r) (vec-y p))))
+
+(defun real-time ()
+ (/ (get-internal-real-time) internal-time-units-per-second))
+
+(defun random-location ()
+ (make-random-vec *width* *height*))
+
+(defun random-location-centered ()
+ (make-vec (random-range (- *center-x*) *center-x*)
+ (random-range (- *center-y*) *center-y*)))
+
;;;; Sketch
(defun draw-particle (p)
@@ -50,67 +65,84 @@
(collect (vec-x p))
(collect (vec-y p))))))
-
-(defun move-star (star x y)
- (let ((center (getf star :center)))
- (setf (particle-x center) x
- (particle-y center) y
+(defun draw-triangle (p1 p2 p3)
+ #+sketch-polygon-fn-is-fucked (polygon (vec-x p1) (vec-y p1)
+ (vec-x p2) (vec-y p2)
+ (vec-x p3) (vec-y p3))
+ (let ((vertices (list (vec-to-list p1)
+ (vec-to-list p2)
+ (vec-to-list p3))))
+ (sketch::draw-shape :triangles vertices vertices)))
- (getf star :points)
- (iterate
- (repeat 10)
- (for a :from (getf star :angle) :by (/ tau 10))
- (for iteration :from 0)
- (for r = (* (getf star :radius)
- (if (evenp iteration) 1.0 0.5)))
- (collect (vec-add (particle-pos center)
- (make-vec-md r a)))))))
-(defun make-star (angle radius)
- (let ((star (list :center (make-particle 0 0 :radius 5)
- :angle angle
- :radius radius
- :points nil)))
- (move-star star (random *width*) (random *height*))
- star))
+(defun midpoint (p1 p2)
+ (vec-mul (vec-add p1 p2) 1/2))
-(defun draw-star (star)
- (draw-particle (getf star :center))
- ; (draw-polygon (getf star :points))
- (iterate
- (with points = (getf star :points))
- (for (p1 . p2) :pairs-of-list points)
- (draw-circle p1 3)
- (draw-line p1 p2)))
+(defun sierpinski (n p1 p2 p3)
+ ;; 1
+ ;;
+ ;; a b
+ ;;
+ ;; 2 c 3
+ (if (zerop n)
+ (draw-triangle p1 p2 p3)
+ (let ((pa (midpoint p1 p2))
+ (pb (midpoint p1 p3))
+ (pc (midpoint p2 p3))
+ (m (1- n)))
+ (sierpinski m p1 pb pa)
+ (sierpinski m p2 pa pc)
+ (sierpinski m p3 pc pb))))
-(defun oob-p (p &optional (r 0.0))
- (or (outsidep (- 0 r) (+ *width* r) (vec-x p))
- (outsidep (- 0 r) (+ *height* r) (vec-y p))))
+(defun koch (n p1 p2)
+ (if (zerop n)
+ (draw-line p1 p2)
+ ;; b
+ ;; /\
+ ;; / \
+ ;; 1--a c--2
+ (let* ((unit (vec-div (vec-sub p2 p1) 3))
+ (pa (vec-add p1 unit))
+ (pc (vec-sub p2 unit))
+ (angled-unit (make-vec-md (vec-magnitude unit)
+ (+ (vec-angle unit) (/ tau 6))))
+ (pb (vec-add pa angled-unit))
+ (m (1- n)))
+ (koch m p1 pa)
+ (koch m pa pb)
+ (koch m pb pc)
+ (koch m pc p2))))
-(defun stars-collide-p (star-1 star-2)
+(defun random-triangle ()
+ (list (random-location-centered)
+ (random-location-centered)
+ (random-location-centered)))
+
+(defun random-equilateral-triangle (min-size max-size)
(iterate
- main
- (for (p1 . p2) :pairs-of-list (getf star-1 :points))
- (iterate
- (for (p3 . p4) :pairs-of-list (getf star-2 :points))
- (with-vecs ((x11 y11) p1
- (x12 y12) p2
- (x21 y21) p3
- (x22 y22) p4)
- (in main
- (thereis (xys-segments-intersection-point
- x11 y11 x12 y12 x21 y21 x22 y22)))))))
+ (with r = (random-range min-size max-size))
+ (with a = (random tau))
+ (with c = (random-location-centered))
+ (for (x y) :in (sketch::ngon-vertices 3 (vec-x c) (vec-y c) r r a))
+ (collect (make-vec x y))))
(defsketch cm
- ((width *width*) (height *height*) (y-axis :down) (title "Coding Math 2D")
+ ((width *width*) (height *height*) (y-axis :up) (title "Coding Math 2D")
+ (copy-pixels t)
(mouse (make-vec 0 0))
+ (frame 0)
+ (start-time (real-time))
+ (current-time 0)
+ (previous-time 0)
+ (total-time 0)
;; Data
- (star-1 (make-star (random tau) (random-range 30.0 70.0)))
- (star-2 (make-star (random tau) (random-range 30.0 70.0)))
- (dragging nil)
+ (n 0)
+ (limit 6)
+ (spoints (random-triangle))
+ (kpoints (random-equilateral-triangle 100 300))
;; Pens
(particle-pen (make-pen :fill (gray 0.9) :stroke (gray 0.4)))
(black-pen (make-pen :stroke (rgb 0 0 0) :fill (rgb 0.4 0.4 0.4) :weight 1 :curve-steps 50))
@@ -118,20 +150,29 @@
(green-pen (make-pen :stroke (rgb 0 0.6 0) :fill (rgb 0 0.9 0) :weight 1 :curve-steps 50))
(blue-pen (make-pen :stroke (rgb 0 0 0.6) :fill (rgb 0 0 0.9) :weight 1 :curve-steps 50))
)
- (with-setup
- ;;
- (in-context
+ (setf previous-time current-time
+ current-time (real-time))
+ (incf total-time (- current-time previous-time))
+ (incf frame)
+ ;;
+ (in-context
+ (when (> total-time 0.5)
+ (setf total-time 0
+ n (mod (1+ n) limit))
+ (translate *center-x* *center-y*)
+ (background (gray 1))
(draw-axes *width* *height*)
- (with-pen red-pen
- (draw-star star-1))
- (with-pen blue-pen
- (draw-star star-2))
- (when (stars-collide-p star-1 star-2)
- (text "BOOM!" *center-x* *center-y*))
+ (with-pen (make-pen :fill (gray 0))
+ (apply #'sierpinski n spoints))
+ (with-pen (make-pen :stroke (rgb 0.8 0 0) :weight (- limit n))
+ (iterate
+ (for (a . b) :pairs-of-list kpoints)
+ (koch n a b)
+ )
+ ))
+ )
+ ;;
- )
- ;;
- )
)
@@ -140,30 +181,13 @@
(with-slots (mouse) instance
(setf mouse (make-vec x (- *height* y)))
;;
- (with-slots (dragging) instance
- (when dragging
- (move-star dragging x y)
- )
- )
;;
)
)
-(defun draw-time ()
- (text (format nil "~d" (get-internal-real-time))
- 300 300))
(defun mousedown-left (instance x y)
(declare (ignorable instance x y))
- (with-slots (dragging star-1 star-2) instance
- (let ((p1 (getf star-1 :center))
- (p2 (getf star-2 :center))
- (target (make-vec x y)))
- (cond
- ((circle-point-collide-p p1 target) (setf dragging star-1))
- ((circle-point-collide-p p2 target) (setf dragging star-2))
- (t nil)
- )))
)
(defun mousedown-right (instance x y)
--- a/src/2d/vectors.lisp Sun Jul 03 16:12:41 2016 +0000
+++ b/src/2d/vectors.lisp Tue Jul 05 13:58:12 2016 +0000
@@ -118,3 +118,6 @@
(defun vec-distance-between (v0 v1)
(distance (vec-x v0) (vec-y v0)
(vec-x v1) (vec-y v1)))
+
+(defun vec-to-list (v)
+ (list (vec-x v) (vec-y v)))