reinlined snek
This commit is contained in:
11
snek/src/load.lisp
Normal file
11
snek/src/load.lisp
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
(load "~/quicklisp/setup")
|
||||
|
||||
(proclaim '(inline last1 single append1 conc1 mklist))
|
||||
(proclaim '(optimize speed))
|
||||
|
||||
(load "snek/src/utils")
|
||||
(load "snek/src/lutils")
|
||||
(load "snek/src/lshapes")
|
||||
(load "snek/src/snek")
|
||||
(load "snek/src/sandpaint")
|
131
snek/src/lshapes.lisp
Normal file
131
snek/src/lshapes.lisp
Normal file
@@ -0,0 +1,131 @@
|
||||
|
||||
|
||||
(defun random-float (&optional (x 1.0))
|
||||
(random (coerce x 'float)))
|
||||
|
||||
|
||||
(defun random-float* (&optional (x 1.0))
|
||||
(- x (* 2.0 (random (coerce x 'float)))))
|
||||
|
||||
|
||||
|
||||
; geometry
|
||||
|
||||
|
||||
(defun l-on-spiral (i itt rad &key (x 0.0) (y 0.0) (rot 1.0))
|
||||
(ladd
|
||||
(list x y)
|
||||
(lscale
|
||||
(cos-sin (* i (/ (* PI rot) itt)))
|
||||
(* (/ i itt) rad))))
|
||||
|
||||
|
||||
(defun l-on-circle (i itt rad &key (x 0.0) (y 0.0))
|
||||
(ladd
|
||||
(list x y)
|
||||
(lscale
|
||||
(cos-sin (/ (* i PI 2.0) itt))
|
||||
rad)))
|
||||
|
||||
|
||||
(defun l-on-line (i itt x1 x2)
|
||||
(ladd
|
||||
x1
|
||||
(lscale
|
||||
(lsub x2 x1)
|
||||
(/ i itt))))
|
||||
|
||||
|
||||
(defun l-rand-on-circle (rad &key (x 0.0) (y 0.0))
|
||||
(ladd
|
||||
(list x y)
|
||||
(lscale
|
||||
(cos-sin (random (* PI 2.0)))
|
||||
rad)))
|
||||
|
||||
|
||||
(defun l-rand-in-circle (rad &key (x 0.0) (y 0.0))
|
||||
(let ((ab (sort (list (random 1.0) (random 1.0)) #'<)))
|
||||
(ladd
|
||||
(list x y)
|
||||
(lscale
|
||||
(cos-sin (* 2 pi (apply #'/ ab)))
|
||||
(* (second ab) rad)))))
|
||||
|
||||
|
||||
(defun l-rand-in-box (sx sy &key (x 0.0) (y 0.0))
|
||||
(ladd
|
||||
(list (random-float* sx) (random-float* sy))
|
||||
(list x y)))
|
||||
|
||||
|
||||
(defun l-rand-on-line (x1 x2)
|
||||
(ladd
|
||||
x1
|
||||
(lscale (lsub x2 x1) (random 1.0))))
|
||||
|
||||
|
||||
(defun l-rand-on-spiral (rad &key (x 0.0) (y 0.0) (rot 1.0))
|
||||
(let ((i (random 1.0)))
|
||||
(ladd
|
||||
(list x y)
|
||||
(lscale
|
||||
(cos-sin (* i (* PI rot)))
|
||||
(* i rad)))))
|
||||
|
||||
|
||||
(defun l-polygon (n rad &key (x 0.0) (y 0.0) (rot 0.0))
|
||||
(loop for i from 0 to n
|
||||
collect
|
||||
(ladd
|
||||
(list x y)
|
||||
(lscale
|
||||
(cos-sin (+ rot (* (/ i n) 2 pi)))
|
||||
rad))))
|
||||
|
||||
|
||||
(defun path-rel-lengths (points)
|
||||
(destructuring-bind
|
||||
(steps total)
|
||||
(loop
|
||||
with l
|
||||
for i from 0 to (2- (length points))
|
||||
do
|
||||
(setf l (ldst (nth i points) (nth (1+ i) points)))
|
||||
sum l into total
|
||||
collect l into steps
|
||||
finally
|
||||
(return (list steps total)))
|
||||
|
||||
(append
|
||||
(list 0)
|
||||
(loop for s in steps
|
||||
sum (/ s total) into summed
|
||||
collect
|
||||
summed))))
|
||||
|
||||
|
||||
(defun -diff-scale (a b s) (/ (- b a) s))
|
||||
|
||||
(defun path-transform (p points lengths)
|
||||
(let ((ind 0))
|
||||
; TODO use return instead
|
||||
(loop
|
||||
for n in lengths
|
||||
for i from 0
|
||||
do
|
||||
(setf ind i)
|
||||
until (< p n))
|
||||
|
||||
(let ((s (-diff-scale
|
||||
(nth (1- ind) lengths)
|
||||
p
|
||||
(- (nth ind lengths) (nth (1- ind) lengths))))
|
||||
(pb (nth ind points))
|
||||
(pa (nth (1- ind) points)))
|
||||
(ladd
|
||||
pa
|
||||
(lscale
|
||||
(lsub pb pa)
|
||||
s)))))
|
||||
|
143
snek/src/lutils.lisp
Normal file
143
snek/src/lutils.lisp
Normal file
@@ -0,0 +1,143 @@
|
||||
|
||||
(defmacro cos-sin (a)
|
||||
(with-gensyms (aname)
|
||||
`(let ((,aname ,a))
|
||||
(list (cos ,aname) (sin ,aname)))))
|
||||
|
||||
(defmacro sin-cos (a)
|
||||
(with-gensyms (aname)
|
||||
`(let ((,aname ,a))
|
||||
(list (sin ,aname) (cos ,aname)))))
|
||||
|
||||
|
||||
(defmacro 2d-square-loop ((x y s) &body body)
|
||||
(with-gensyms (sname)
|
||||
`(let ((,sname ,s))
|
||||
(loop for ,x from 0 below ,sname do
|
||||
(loop for ,y from 0 below ,sname do
|
||||
,@body)))))
|
||||
|
||||
|
||||
(defun lscale (a s)
|
||||
(mapcar (lambda (x) (* x s)) a))
|
||||
|
||||
(defun liscale (a s)
|
||||
(mapcar (lambda (x) (/ x s)) a))
|
||||
|
||||
|
||||
(defun lsub (a b)
|
||||
(mapcar #'- a b))
|
||||
|
||||
|
||||
(defun lisub (a b)
|
||||
(mapcar #'- b a))
|
||||
|
||||
|
||||
(defun ladd (a b)
|
||||
(mapcar #'+ a b))
|
||||
|
||||
|
||||
(defun lmult (a b)
|
||||
(mapcar #'* a b))
|
||||
|
||||
|
||||
(defun ldot (a b)
|
||||
(apply #'+ (lmult a b)))
|
||||
|
||||
|
||||
(defun ldiv (a b)
|
||||
(mapcar #'/ a b))
|
||||
|
||||
|
||||
(defun lidiv (a b)
|
||||
(mapcar #'/ b a))
|
||||
|
||||
|
||||
(defun llenn (a)
|
||||
(reduce #'+ (mapcar (lambda (x) (* x x)) a)))
|
||||
|
||||
|
||||
(defun llen (a)
|
||||
(sqrt (llenn a)))
|
||||
|
||||
|
||||
(defun ldst (a b)
|
||||
(llen (lsub a b)))
|
||||
|
||||
|
||||
(defun lnorm (a)
|
||||
(let ((l (llen a)))
|
||||
(cond
|
||||
((<= l 0) a)
|
||||
(t (lscale a (/ 1.0 l))))))
|
||||
|
||||
|
||||
(defun lnsub (a b)
|
||||
(lnorm (lsub a b)))
|
||||
|
||||
|
||||
(defun lnadd (a b)
|
||||
(lnorm (ladd a b)))
|
||||
|
||||
|
||||
(defun lmid (a b)
|
||||
(lscale (ladd a b) 0.5))
|
||||
|
||||
|
||||
(defun lsum (a)
|
||||
(reduce #'+ a))
|
||||
|
||||
|
||||
(defun lround (l)
|
||||
(mapcar #'round l))
|
||||
|
||||
|
||||
(defun lget (ii a)
|
||||
(loop for i in ii
|
||||
collect (nth i a)))
|
||||
|
||||
|
||||
(defun l-rand-get (l)
|
||||
(nth (random (list-length l)) l))
|
||||
|
||||
|
||||
(defun leql (a b)
|
||||
(mapcar #'eql a b))
|
||||
|
||||
|
||||
(defun lgeq (a b)
|
||||
(mapcar #'>= a b))
|
||||
|
||||
|
||||
(defun lleq (a b)
|
||||
(mapcar #'<= a b))
|
||||
|
||||
|
||||
(defun range (n)
|
||||
(loop for x from 0 to (1- n)
|
||||
collect x))
|
||||
|
||||
|
||||
(defun linspace (a b n)
|
||||
(loop for i from 0 to (1- n)
|
||||
collect (+ a (* i (/ (- b a) (1- n))))))
|
||||
|
||||
|
||||
(defun lget (ii a)
|
||||
(loop for i in ii
|
||||
collect (nth i a)))
|
||||
|
||||
|
||||
; TODO: add dim option
|
||||
(defun l-get-as-list (arr row)
|
||||
(mapcar
|
||||
(lambda (d) (aref arr row d))
|
||||
(list 0 1)))
|
||||
|
||||
|
||||
(defun l-set-from-list (arr row vals)
|
||||
(mapcar
|
||||
(lambda (d v) (setf (aref arr row d) v))
|
||||
(list 0 1)
|
||||
vals))
|
||||
|
187
snek/src/sandpaint.lisp
Normal file
187
snek/src/sandpaint.lisp
Normal file
@@ -0,0 +1,187 @@
|
||||
|
||||
(defpackage :sandpaint
|
||||
(:use :common-lisp))
|
||||
|
||||
|
||||
(ql:quickload "ZPNG")
|
||||
|
||||
|
||||
; UTILS
|
||||
|
||||
|
||||
(defun -scale-convert (v &key (scale 1.0d0) (gamma 1.0d0))
|
||||
(setf v (expt (/ v scale) gamma)))
|
||||
|
||||
|
||||
(defun -unsigned-256 (v)
|
||||
(cond
|
||||
((> v 1.0d0) 255)
|
||||
((< v 0.0d0) 0)
|
||||
(t (round (* 255 v)))))
|
||||
|
||||
|
||||
(defun to-double-float (l)
|
||||
(mapcar (lambda (x) (coerce x 'double-float)) l))
|
||||
|
||||
|
||||
(defun -setf-operator-over (vals x y i -alpha color)
|
||||
(setf
|
||||
(aref vals x y i)
|
||||
(+ (* (aref vals x y i) -alpha) color)))
|
||||
|
||||
(defun -operator-over (size vals x y r g b a)
|
||||
(if (and (>= x 0) (< x size) (>= y 0) (< y size))
|
||||
(let ((ia (- 1.0 a)))
|
||||
(-setf-operator-over vals x y 0 ia r)
|
||||
(-setf-operator-over vals x y 1 ia g)
|
||||
(-setf-operator-over vals x y 2 ia b)
|
||||
(-setf-operator-over vals x y 3 ia a))))
|
||||
|
||||
|
||||
(defun -sandpaint-edge (vals size num v1 v2 r g b a)
|
||||
(loop for i from 1 to num
|
||||
do
|
||||
(destructuring-bind (x y)
|
||||
(lround (l-rand-on-line v1 v2))
|
||||
(-operator-over size vals x y r g b a))))
|
||||
|
||||
|
||||
(defun copy-rgba-array-to-from (target source size)
|
||||
(2d-square-loop (x y size)
|
||||
(loop for i from 0 to 3 do
|
||||
(setf (aref target x y i) (aref source x y i)))))
|
||||
|
||||
|
||||
|
||||
; SNEK SAND PAINT
|
||||
|
||||
|
||||
(defstruct sandpaint
|
||||
(vals nil :read-only nil)
|
||||
(size -1 :type integer :read-only nil)
|
||||
(r 0.0d0 :type double-float :read-only nil)
|
||||
(g 0.0d0 :type double-float :read-only nil)
|
||||
(b 0.0d0 :type double-float :read-only nil)
|
||||
(a 1.0d0 :type double-float :read-only nil))
|
||||
|
||||
|
||||
(defun sandpaint*
|
||||
(size
|
||||
&key
|
||||
(active '(1.0d0 1.0d0 1.0d0 1.0d0))
|
||||
(bg '(0.0d0 0.0d0 0.0d0 1.0d0)))
|
||||
(destructuring-bind (ar ag ab aa br bg bb ba)
|
||||
(mapcar
|
||||
(lambda (c) (coerce c 'double-float))
|
||||
(append active bg))
|
||||
|
||||
(let ((vals (make-rgba-array size)))
|
||||
(2d-square-loop (x y size)
|
||||
(setf (aref vals x y 0) (* ba br))
|
||||
(setf (aref vals x y 1) (* ba bg))
|
||||
(setf (aref vals x y 2) (* ba bb))
|
||||
(setf (aref vals x y 3) ba))
|
||||
|
||||
(make-sandpaint
|
||||
:size size
|
||||
:r (* ar aa)
|
||||
:g (* ag aa)
|
||||
:b (* ab aa)
|
||||
:a aa
|
||||
:vals vals))))
|
||||
|
||||
|
||||
(defun sandpaint-set-rgba (sand rgba)
|
||||
(destructuring-bind (r g b a)
|
||||
(to-double-float rgba)
|
||||
(setf (sandpaint-r sand) (* r a))
|
||||
(setf (sandpaint-g sand) (* g a))
|
||||
(setf (sandpaint-b sand) (* b a))
|
||||
(setf (sandpaint-a sand) a)))
|
||||
|
||||
|
||||
(defun sandpaint-edges (sand s num)
|
||||
(with-struct (sandpaint- size vals r g b a) sand
|
||||
(with-all-edges (s ee)
|
||||
(destructuring-bind (v1 v2)
|
||||
(get-verts ee from s)
|
||||
(-sandpaint-edge
|
||||
vals size num v1 v2 r g b a)))))
|
||||
|
||||
|
||||
; TODO implement wrapper
|
||||
;(defun -sandpaint-vert-box (vals size mx my grains w h r g b a)
|
||||
; (loop for i from 0 to grains do
|
||||
; (destructuring-bind (x y)
|
||||
; (mapcar #'round (l-rand-in-box w h :x mx :y my))
|
||||
; (-operator-over size vals x y r g b a))))
|
||||
|
||||
(defun -sandpaint-vert (vals size x y r g b a)
|
||||
(-operator-over size vals x y r g b a))
|
||||
|
||||
(defun sandpaint-verts (sand s)
|
||||
(with-struct (sandpaint- size vals r g b a) sand
|
||||
(with-all-verts (s v)
|
||||
(destructuring-bind (x y)
|
||||
(get-vert v from s)
|
||||
(-sandpaint-vert vals size (round x) (round y) r g b a)))))
|
||||
|
||||
|
||||
(defun -offset-rgba (new-vals old-vals size x y nxy i)
|
||||
(destructuring-bind (nx ny)
|
||||
(mapcar #'round nxy)
|
||||
(if (and (>= nx 0) (< nx size) (>= ny 0) (< ny size))
|
||||
(setf (aref new-vals nx ny i) (aref old-vals x y i)))))
|
||||
|
||||
(defun sandpaint-chromatic-aberration (sand C s)
|
||||
(with-struct (sandpaint- size vals) sand
|
||||
(let ((new-vals (make-rgba-array size)))
|
||||
(copy-rgba-array-to-from new-vals vals size)
|
||||
|
||||
(2d-square-loop (x y size)
|
||||
(let* ((xy (list x y))
|
||||
(dx (liscale
|
||||
(lsub
|
||||
(ladd (l-rand-in-circle 1.0) xy)
|
||||
C)
|
||||
s)))
|
||||
(-offset-rgba new-vals vals size x y (ladd xy dx) 0)
|
||||
(-offset-rgba new-vals vals size x y (lsub xy dx) 2)))
|
||||
|
||||
(setf (sandpaint-vals sand) new-vals))))
|
||||
|
||||
|
||||
(defun -pixel-hack (sand)
|
||||
(let ((vals (sandpaint-vals sand)))
|
||||
(setf (aref vals 0 0 3) 0.5d0)))
|
||||
|
||||
|
||||
(defun -png-tuple (vals x y gamma)
|
||||
(let ((a (aref vals x y 3)))
|
||||
(list
|
||||
(-unsigned-256 (-scale-convert (aref vals x y 0) :scale a :gamma gamma))
|
||||
(-unsigned-256 (-scale-convert (aref vals x y 1) :scale a :gamma gamma))
|
||||
(-unsigned-256 (-scale-convert (aref vals x y 2) :scale a :gamma gamma))
|
||||
(-unsigned-256 (-scale-convert a :gamma gamma)))))
|
||||
|
||||
(defun sandpaint-save (sand name &key (gamma 1.0))
|
||||
(if (not name) (error "missing result file name."))
|
||||
(with-struct (sandpaint- size vals) sand
|
||||
(let ((png
|
||||
(make-instance
|
||||
'zpng::pixel-streamed-png
|
||||
:color-type :truecolor-alpha
|
||||
:width size
|
||||
:height size)))
|
||||
|
||||
(with-open-file
|
||||
(stream name
|
||||
:direction :output
|
||||
:if-exists :supersede
|
||||
:if-does-not-exist :create
|
||||
:element-type '(unsigned-byte 8))
|
||||
(zpng:start-png png stream)
|
||||
(2d-square-loop (x y size)
|
||||
(zpng:write-pixel (-png-tuple vals y x gamma) png))
|
||||
(zpng:finish-png png)))))
|
||||
|
408
snek/src/snek.lisp
Normal file
408
snek/src/snek.lisp
Normal file
@@ -0,0 +1,408 @@
|
||||
|
||||
(defpackage :snek
|
||||
(:use :common-lisp))
|
||||
|
||||
|
||||
|
||||
; MACROS
|
||||
|
||||
|
||||
(defmacro insert-vert (v into snk)
|
||||
(declare (ignore into))
|
||||
(with-gensyms (cname vname)
|
||||
`(let ((,vname ,v)
|
||||
(,cname (snek-num-verts ,snk)))
|
||||
(setf (aref (snek-verts ,snk) ,cname 0) (coerce (first ,vname) 'float))
|
||||
(setf (aref (snek-verts ,snk) ,cname 1) (coerce (second ,vname) 'float))
|
||||
(- (incf (snek-num-verts ,snk)) 1))))
|
||||
|
||||
|
||||
(defmacro get-vert (v from snk)
|
||||
(declare (ignore from))
|
||||
(with-gensyms (vname)
|
||||
`(let ((,vname ,v))
|
||||
(list (aref (snek-verts ,snk) ,vname 0)
|
||||
(aref (snek-verts ,snk) ,vname 1)))))
|
||||
|
||||
|
||||
(defmacro get-verts (vv from snk)
|
||||
(declare (ignore from))
|
||||
(with-gensyms (vname v)
|
||||
`(let ((,vname ,vv))
|
||||
(loop for ,v in ,vname collect
|
||||
(list (aref (snek-verts ,snk) ,v 0)
|
||||
(aref (snek-verts ,snk) ,v 1))))))
|
||||
|
||||
|
||||
(defmacro get-edge (e from snk)
|
||||
(declare (ignore from))
|
||||
(with-gensyms (ename)
|
||||
`(let ((,ename ,e))
|
||||
(list (aref (snek-edges, snk) ,ename 0)
|
||||
(aref (snek-edges ,snk) ,ename 1)))))
|
||||
|
||||
|
||||
(defmacro insert-edge (e into snk)
|
||||
(declare (ignore into))
|
||||
(with-gensyms (ename edges num)
|
||||
`(let ((,ename ,e)
|
||||
(,edges (snek-edges ,snk))
|
||||
(,num (snek-num-edges ,snk)))
|
||||
(cond
|
||||
((-binary-edge-search ,edges ,ename ,num)
|
||||
nil)
|
||||
((eql (first ,ename) (second ,ename))
|
||||
nil)
|
||||
(t
|
||||
(setf (snek-num-edges ,snk) (+ 2 ,num))
|
||||
(-find-insert-edge ,edges ,num ,ename)
|
||||
(sort
|
||||
(-find-insert-edge ,edges (1+ ,num) (reverse ,ename))
|
||||
#'<))))))
|
||||
|
||||
|
||||
(defmacro remove-edge (e from snk)
|
||||
(declare (ignore from))
|
||||
(with-gensyms (ename lname edges num)
|
||||
`(let ((,ename ,e)
|
||||
(,edges (snek-edges ,snk))
|
||||
(,num (snek-num-edges ,snk)))
|
||||
|
||||
(setf (snek-num-edges ,snk) (- ,num (loop for ,lname in
|
||||
(list
|
||||
(-find-remove-edge ,edges ,num ,ename)
|
||||
(-find-remove-edge ,edges (1- ,num) (reverse ,ename)))
|
||||
sum ,lname)))
|
||||
(- ,num (snek-num-edges ,snk)))))
|
||||
|
||||
|
||||
(defmacro get-one-ring (of v from snk)
|
||||
(declare (ignore from) (ignore of))
|
||||
(with-gensyms (vname)
|
||||
`(let ((,vname ,v))
|
||||
(-one-ring (snek-edges ,snk) ,vname (snek-num-edges ,snk)))))
|
||||
|
||||
|
||||
(defmacro with-snek ((snk) &body body)
|
||||
`(do-alts
|
||||
(remove-if-not
|
||||
#'alt-p
|
||||
(flatten (list ,@body))) ,snk))
|
||||
|
||||
|
||||
(defmacro with-snek-print ((snk) &body body)
|
||||
(declare (ignore snk))
|
||||
`(print
|
||||
(remove-if-not
|
||||
#'alt-p
|
||||
(flatten (list ,@body)))))
|
||||
|
||||
|
||||
(defmacro with-rnd-edge ((snk i) &body body)
|
||||
`(if (> (snek-num-edges ,snk) 0)
|
||||
(let ((,i (l-get-as-list
|
||||
(snek-edges ,snk)
|
||||
(random (snek-num-edges ,snk)))))
|
||||
(list ,@body))
|
||||
nil))
|
||||
|
||||
|
||||
(defmacro with-rnd-vert ((snk i) &body body)
|
||||
`(let ((,i (random (snek-num-verts ,snk))))
|
||||
(list ,@body)))
|
||||
|
||||
|
||||
(defun -get-force-alterations (u v f)
|
||||
(list
|
||||
(move-vert v f)
|
||||
(move-vert u (lscale f -1.0))))
|
||||
|
||||
(defmacro force (snk v1 v2 r)
|
||||
(with-gensyms (vname v1name v2name a b aname rname)
|
||||
`(let ((,v1name ,v1)
|
||||
(,v2name ,v2)
|
||||
(,vname (snek-verts ,snk))
|
||||
(,rname ,r))
|
||||
(-get-force-alterations
|
||||
,v1 ,v2
|
||||
(lscale
|
||||
(lnsub
|
||||
(l-get-as-list ,vname ,v1name)
|
||||
(l-get-as-list ,vname ,v2name))
|
||||
,rname)))))
|
||||
|
||||
|
||||
(defmacro with-rnd-vert-value ((snk i) &body body)
|
||||
`(let ((,i (l-rand-get (snek-verts ,snk))))
|
||||
(list ,@body)))
|
||||
|
||||
|
||||
(defmacro with-all-verts ((snk i) &body body)
|
||||
`(loop for ,i from 0 below (snek-num-verts ,snk)
|
||||
collect (list ,@body)))
|
||||
|
||||
|
||||
|
||||
(defmacro with-all-edges ((snk i) &body body)
|
||||
(with-gensyms (kname)
|
||||
`(loop
|
||||
with ,i
|
||||
for ,kname from 0 below (snek-num-edges ,snk)
|
||||
do
|
||||
(setf ,i (l-get-as-list (snek-edges ,snk) ,kname))
|
||||
if (< (first ,i) (second ,i))
|
||||
collect (list ,@body))))
|
||||
|
||||
|
||||
(defmacro with-prob (p &body body)
|
||||
(with-gensyms (pname)
|
||||
`(let ((,pname ,p))
|
||||
(if (< (random 1.0) ,p)
|
||||
(list ,@body)))))
|
||||
|
||||
|
||||
|
||||
; SNEK
|
||||
|
||||
(defstruct snek
|
||||
(edges nil :read-only nil)
|
||||
(verts nil :read-only nil)
|
||||
(num-edges 0 :type integer :read-only nil)
|
||||
(num-verts 0 :type integer :read-only nil)
|
||||
(max-num 100000 :type integer :read-only t))
|
||||
|
||||
|
||||
(defun snek* (&optional (max-num 100000))
|
||||
(make-snek
|
||||
:edges (make-int-array max-num)
|
||||
:verts (make-float-array max-num)
|
||||
:max-num max-num))
|
||||
|
||||
|
||||
(defun -one-ring (edges v num)
|
||||
(loop for i from 0 below num
|
||||
if (eql v (aref edges i 0))
|
||||
collect (l-get-as-list edges i)))
|
||||
|
||||
|
||||
(defun -edge-compare (a b c d)
|
||||
(or
|
||||
(and (>= a b) (>= c d))
|
||||
(> a b)))
|
||||
|
||||
|
||||
(defun -binary-edge-insert-search (arr target num)
|
||||
(let ((left 0)
|
||||
(right (1- num)))
|
||||
(do () ((< right left) left)
|
||||
(let ((mid (floor (+ left right) 2)))
|
||||
(cond
|
||||
((not (-edge-compare
|
||||
(first target)
|
||||
(aref arr mid 0)
|
||||
(second target)
|
||||
(aref arr mid 1)))
|
||||
(setf right (1- mid)))
|
||||
(t
|
||||
(setf left (1+ mid))))))))
|
||||
|
||||
|
||||
;TODO: is this tail recursive?
|
||||
(defun -binary-edge-search (arr target num &key (left 0) (right nil))
|
||||
(destructuring-bind (a c) target
|
||||
(if (eql right nil)
|
||||
(setf right (1- num)))
|
||||
(let ((mid (floor (+ left right) 2)))
|
||||
(cond
|
||||
((< right left) nil)
|
||||
((and
|
||||
(eql a (aref arr mid 0))
|
||||
(eql c (aref arr mid 1)))
|
||||
mid)
|
||||
((not (-edge-compare a (aref arr mid 0) c (aref arr mid 1)))
|
||||
(-binary-edge-search arr target num :left left :right (1- mid)))
|
||||
(t (-binary-edge-search arr target num :left (1+ mid) :right right))))))
|
||||
|
||||
|
||||
(defun -insert-edge (edges edge pos num)
|
||||
(loop for i from 0 below (- num pos) do
|
||||
(let ((left (- num (1+ i)))
|
||||
(right (- num i)))
|
||||
(setf (aref edges right 0) (aref edges left 0))
|
||||
(setf (aref edges right 1) (aref edges left 1))))
|
||||
(setf (aref edges pos 0) (first edge))
|
||||
(setf (aref edges pos 1) (second edge)))
|
||||
|
||||
|
||||
(defun -find-insert-edge (edges num e)
|
||||
(-insert-edge
|
||||
edges
|
||||
e
|
||||
(-binary-edge-insert-search edges e num)
|
||||
num)
|
||||
e)
|
||||
|
||||
|
||||
(defun -remove-edge (edges pos num)
|
||||
(loop for i from pos to (2- num) do
|
||||
(setf (aref edges i 0) (aref edges (1+ i) 0))
|
||||
(setf (aref edges i 1) (aref edges (1+ i) 1)))
|
||||
(l-set-from-list edges (1- num) (list 0 0)))
|
||||
|
||||
|
||||
(defun -find-remove-edge (edges num e)
|
||||
(let ((p (-binary-edge-search edges e num)))
|
||||
(if p
|
||||
(progn
|
||||
(-remove-edge edges p num) 1)
|
||||
0)))
|
||||
|
||||
|
||||
|
||||
; ALTERATIONS
|
||||
|
||||
|
||||
; MOVE VERT
|
||||
|
||||
(defstruct (move-vert-alt
|
||||
(:constructor move-vert (v xy &key (rel t))))
|
||||
(rel t :type boolean :read-only t)
|
||||
(xy nil :type list :read-only t)
|
||||
(v -1 :type integer :read-only t))
|
||||
|
||||
|
||||
(defun do-move-vert-alt (a snk)
|
||||
(let ((verts (snek-verts snk)))
|
||||
(with-struct (move-vert-alt- v xy rel) a
|
||||
(if rel
|
||||
(l-set-from-list
|
||||
verts v
|
||||
(ladd
|
||||
(l-get-as-list verts v)
|
||||
xy))
|
||||
(l-set-from-list verts v xy)))))
|
||||
|
||||
|
||||
|
||||
; APPEND EDGE
|
||||
|
||||
(defstruct (append-edge-alt
|
||||
(:constructor append-edge (v xy &key (rel t))))
|
||||
(xy nil :type list :read-only t)
|
||||
(v -1 :type integer :read-only t)
|
||||
(rel t :type boolean :read-only t))
|
||||
|
||||
|
||||
(defun do-append-edge-alt (a snk)
|
||||
(with-struct (append-edge-alt- v xy rel) a
|
||||
(cond
|
||||
(rel
|
||||
(insert-vert (ladd (get-vert v from snk) xy) into snk))
|
||||
(t
|
||||
(insert-vert xy into snk)))
|
||||
|
||||
(insert-edge
|
||||
(list
|
||||
v
|
||||
(1- (snek-num-verts snk)))
|
||||
into snk)))
|
||||
|
||||
|
||||
; JOIN VERTS
|
||||
|
||||
(defstruct (join-verts-alt
|
||||
(:constructor join-verts (v1 v2)))
|
||||
(v1 -1 :type integer :read-only t)
|
||||
(v2 -1 :type integer :read-only t))
|
||||
|
||||
|
||||
(defun do-join-verts-alt (a snk)
|
||||
(with-struct (join-verts-alt- v1 v2) a
|
||||
(insert-edge (list v1 v2) into snk)))
|
||||
|
||||
|
||||
; SPLIT EDGE
|
||||
|
||||
(defstruct (split-edge-alt
|
||||
(:constructor split-edge (e)))
|
||||
(e nil :type list :read-only t))
|
||||
|
||||
|
||||
(defun do-split-edge-alt (a snk)
|
||||
(with-struct (split-edge-alt- e) a
|
||||
(let ((res (remove-edge e from snk))
|
||||
(verts (snek-verts snk)))
|
||||
(destructuring-bind (a b) e
|
||||
(if (> res 1)
|
||||
(let ((c (insert-vert
|
||||
(lmid (l-get-as-list verts a)
|
||||
(l-get-as-list verts b))
|
||||
into snk)))
|
||||
(insert-edge (list a c) into snk)
|
||||
(insert-edge (list c b) into snk)))))))
|
||||
|
||||
|
||||
; ALTERATION UTILS
|
||||
|
||||
(defun do-alt (a snk)
|
||||
(cond
|
||||
((append-edge-alt-p a) (do-append-edge-alt a snk))
|
||||
((move-vert-alt-p a) (do-move-vert-alt a snk))
|
||||
((join-verts-alt-p a) (do-join-verts-alt a snk))
|
||||
((split-edge-alt-p a) (do-split-edge-alt a snk))))
|
||||
|
||||
|
||||
(defun do-alts (alts snk)
|
||||
(dolist (a alts) (do-alt a snk)))
|
||||
|
||||
|
||||
(defun alt-p (a)
|
||||
(cond
|
||||
((append-edge-alt-p a) t)
|
||||
((move-vert-alt-p a) t)
|
||||
((join-verts-alt-p a) t)
|
||||
((split-edge-alt-p a) t)
|
||||
(t nil)))
|
||||
|
||||
|
||||
|
||||
; OTHER UTILS
|
||||
|
||||
(defun edge-length (snk e)
|
||||
(with-struct (snek- verts) snk
|
||||
(apply #'ldst (mapcar (lambda (v) (l-get-as-list verts v)) e))))
|
||||
|
||||
|
||||
(defun snek-init-circle (snk num rad &key (x 0.0) (y 0.0))
|
||||
(let ((verts (loop for i from 0 below num collect
|
||||
(insert-vert
|
||||
(ladd
|
||||
(list x y)
|
||||
(lscale (cos-sin (/ (* i PI 2.0) num)) rad)) into snk))))
|
||||
|
||||
(loop for i from 0 below num do
|
||||
(insert-edge (list (nth i verts) (nth (mod (1+ i) num) verts))
|
||||
into snk))))
|
||||
|
||||
(defun snek-init-line (snk num a b)
|
||||
(let ((verts (loop for i from 0 below num collect
|
||||
(insert-vert (l-on-line i num a b) into snk))))
|
||||
|
||||
(loop for i from 0 below num do
|
||||
(insert-edge (list (nth i verts) (nth (mod (1+ i) num) verts))
|
||||
into snk))))
|
||||
|
||||
|
||||
(defun show-snek-edges (snk)
|
||||
(let ((edges (snek-edges snk)))
|
||||
(loop for i from 0 below (snek-num-edges snk) do
|
||||
(print (aref edges i 0))
|
||||
(prin1 (aref edges i 1)))))
|
||||
|
||||
|
||||
(defun show-snek-verts (snk)
|
||||
(let ((verts (snek-verts snk)))
|
||||
(loop for i from 0 below (snek-num-verts snk) do
|
||||
(print (aref verts i 0))
|
||||
(prin1 (aref verts i 1)))))
|
||||
|
110
snek/src/utils.lisp
Normal file
110
snek/src/utils.lisp
Normal file
@@ -0,0 +1,110 @@
|
||||
|
||||
(defun .1* (l) (* l 0.1))
|
||||
|
||||
(defun .25* (l) (* l 0.25))
|
||||
|
||||
(defun .5* (l) (* l 0.5))
|
||||
|
||||
(defun 2* (l) (* l 2))
|
||||
|
||||
(defun 3* (l) (* l 3))
|
||||
|
||||
(defun 4* (l) (* l 4))
|
||||
|
||||
(defun 2+ (l) (+ l 2))
|
||||
|
||||
(defun 2- (l) (- l 2))
|
||||
|
||||
|
||||
(defun make-rgba-array (size)
|
||||
(make-array
|
||||
(list size size 4)
|
||||
:adjustable nil
|
||||
:initial-element 0.0d0
|
||||
:element-type 'double-float))
|
||||
|
||||
|
||||
(defun make-float-array (rows &key (cols 2) (initial 0.0))
|
||||
(make-array
|
||||
(list rows cols)
|
||||
:adjustable t
|
||||
:initial-element initial
|
||||
:element-type 'float ))
|
||||
|
||||
|
||||
(defun make-int-array (rows &key (cols 2) (initial 0))
|
||||
(make-array
|
||||
(list rows cols)
|
||||
:adjustable t
|
||||
:initial-element initial
|
||||
:element-type 'integer))
|
||||
|
||||
|
||||
;http://cl-cookbook.sourceforge.net/os.html
|
||||
(defun cmd-args ()
|
||||
(or #+SBCL *posix-argv*
|
||||
#+LISPWORKS system:*line-arguments-list*
|
||||
#+CMU extensions:*command-line-words*
|
||||
nil))
|
||||
|
||||
|
||||
;(defun flatten (l)
|
||||
; (cond
|
||||
; ((null l) nil)
|
||||
; ((atom l) (list l))
|
||||
; (t (loop for a in l appending (flatten a)))))
|
||||
|
||||
|
||||
; below code is from from On Lisp by Paul Graham.
|
||||
; http://ep.yimg.com/ty/cdn/paulgraham/onlisp.lisp
|
||||
|
||||
; This code is copyright 1993 by Paul Graham, but anyone who wants
|
||||
; to use the code in any nonprofit activity, or distribute free
|
||||
; verbatim copies (including this notice), is encouraged to do so.
|
||||
|
||||
|
||||
(defun flatten (x)
|
||||
(labels ((rec (x acc)
|
||||
(cond ((null x) acc)
|
||||
((atom x) (cons x acc))
|
||||
(t (rec (car x) (rec (cdr x) acc))))))
|
||||
(rec x nil)))
|
||||
|
||||
|
||||
(defun group (source n)
|
||||
(if (zerop n) (error "zero length"))
|
||||
(labels ((rec (source acc)
|
||||
(let ((rest (nthcdr n source)))
|
||||
(if (consp rest)
|
||||
(rec rest (cons (subseq source 0 n) acc))
|
||||
(nreverse (cons source acc))))))
|
||||
(if source (rec source nil) nil)))
|
||||
|
||||
|
||||
(defun mkstr (&rest args)
|
||||
(with-output-to-string (s)
|
||||
(dolist (a args) (princ a s))))
|
||||
|
||||
|
||||
(defun symb (&rest args)
|
||||
(values (intern (apply #'mkstr args))))
|
||||
|
||||
|
||||
(defmacro with-gensyms (syms &body body)
|
||||
`(let ,(mapcar #'(lambda (s) `(,s (gensym)))
|
||||
syms)
|
||||
,@body))
|
||||
|
||||
|
||||
(defmacro mac (expr)
|
||||
`(pprint (macroexpand-1 ',expr)))
|
||||
|
||||
|
||||
(defmacro with-struct ((name . fields) struct &body body)
|
||||
(let ((gs (gensym)))
|
||||
`(let ((,gs ,struct))
|
||||
(let ,(mapcar #'(lambda (f)
|
||||
`(,f (,(symb name f) ,gs)))
|
||||
fields)
|
||||
,@body))))
|
||||
|
Reference in New Issue
Block a user