diff options
author | Colin Okay <colin@cicadas.surf> | 2022-07-17 12:42:42 -0500 |
---|---|---|
committer | Colin Okay <colin@cicadas.surf> | 2022-07-17 12:42:42 -0500 |
commit | 53019e4770d1cf9999201e261fd6d93ab3c0d849 (patch) | |
tree | e3ff351b917577149705271c42aa877b665e6cd3 /src/grid-geometry.lisp | |
parent | b72153a73875fc0081d072b90ac411c0eaef08a8 (diff) |
[wip]
Diffstat (limited to 'src/grid-geometry.lisp')
-rw-r--r-- | src/grid-geometry.lisp | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/grid-geometry.lisp b/src/grid-geometry.lisp new file mode 100644 index 0000000..cef69f8 --- /dev/null +++ b/src/grid-geometry.lisp @@ -0,0 +1,70 @@ +;;; grid-geometry.lisp + +(in-package :wheelwork ) + +(defmacro with-grid-line + ((x y) (start-x start-y) (end-x end-y) &body body) + "Execute BODY for X and Y assigned to integer values in a line +connecting the integer point START-X , START-Y and END-X, END-Y. " + (with-gensyms (sx sy ex ey distance step progress xdiff ydiff) + `(loop + with ,sx = ,start-x + with ,sy = ,start-y + with ,ex = ,end-x + with ,ey = ,end-y + with ,xdiff = (- ,ex ,sx) + with ,ydiff = (- ,ey, sy) + with ,distance = (max (abs ,xdiff) (abs ,ydiff)) + for ,step from 0 to ,distance + for ,progress = (if (zerop ,distance) 0.0 (/ ,step ,distance)) + for ,x = (round (+ ,start-x (* ,progress ,xdiff))) + for ,y = (round (+ ,start-y (* ,progress ,ydiff))) + do (progn ,@body)))) + +(defmacro with-grid-path + ((x y) (path &key autoclosep interiorp) &body body) + (with-gensyms (points x1 y1 x2 y2 more) + (let ((autoclose-block + (when autoclosep + `(destructuring-bind (,x2 ,y2) (first ,points) + (with-grid-line (,x2 ,y2) (,x1 ,y1) ,@body))))) + `(let ((,points ,path)) + (loop + for ((,x1 ,y) (,x2 ,y2) . ,more) on ,points + while ,x2 do + (with-grid-line (,x ,y) (,x1 ,y1) (,x2 ,y2) ,@body) + finally (progn ,autoclose-block)))))) + +(defun grid-bbox-for (poly) + "POLY is a list of pairs of xy coordinates. Return a pair of +pairs, ((min-x min-y) (max-x max-y)), representing the bottom left and +top right corners of the bounding box for POLY " + (loop for (x y) in poly + minimizing x into x-min + maximizing x into x-max + minimizing y into y-min + maximizing y into y-max + finally (return (list (list x-min y-min) + (list x-max y-max))))) + +(defmacro with-grid-poly-interior + ((x y) perimeter &body body) + "PERMIETER is expected to evaluate to a list of contiguous points, +representing the permimeter a polygon in 2d space. Execute BODY for +each point interior to this polygon." + (with-gensyms (points bottom left top right) + `(let ((,points ,permieter)) + (destructuring-bind ((,left ,bottom) (,right ,top)) (grid-bbox-for ,points) + (loop ) + ))) + ) + +(defmacro with-grid-circle + ((x y) (cx cy radius &key interiorp) &body body) + (with-gensyms (rad sx sy) + (let ((comparator + (if interiorp '>= '=))) + `(let ((,sx ,cx) (,sy ,cy) (,rad ,radius)) + (with-grid-rect (,x ,y) ((- ,sx ,rad) (- ,sy ,rad) (+ ,sx ,rad) (+ ,sy ,rad)) + (when (,comparator ,rad (round (euclidean-dist ,x ,y ,sx ,sy))) + ,@body)))))) |