From 53019e4770d1cf9999201e261fd6d93ab3c0d849 Mon Sep 17 00:00:00 2001 From: Colin Okay Date: Sun, 17 Jul 2022 12:42:42 -0500 Subject: [wip] --- src/grid-geometry.lisp | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/grid-geometry.lisp (limited to 'src/grid-geometry.lisp') 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)))))) -- cgit v1.2.3