missing quote in coerce
[woropt.git] / bresenham.lisp
blob884c7f2eb815de89a25fd4b2724b16b2fa3f4689
1 (defpackage :bresenham
2 (:use :cl :vol :vector)
3 (:export #:scan-convert-line3))
5 (in-package :bresenham)
7 ;; 1986 kaufman
8 (defun scan-convert-line3x (x1 y1 z1 x2 y2 z2 vol)
9 (declare (fixnum x1 y1 z1 x2 y2 z2)
10 ((simple-array (unsigned-byte 8) 3) vol)
11 (values (simple-array (unsigned-byte 8) 3) &optional))
12 ;; x2 - x1 has to be the biggest difference between endpoint
13 ;; coordinates
14 (let* ((x x1)
15 (delx (- x2 x1))
16 ;; initialization for y
17 (y y1)
18 (ddy (- y2 y1))
19 (dely (abs ddy))
20 (ysign (signum ddy))
21 (dy (- (* 2 dely) delx)) ;; decision variable along y
22 (yinc1 (* 2 dely)) ;; increment along y for dy<0
23 (yinc2 (* 2 (- dely delx))) ;; inc along y for dy>=0
24 ;; same initialization for z
25 (z z1)
26 (ddz (- z2 z1))
27 (delz (abs ddz))
28 (zsign (signum ddz))
29 (dz (- (* 2 delz) delx))
30 (zinc1 (* 2 delz))
31 (zinc2 (* 2 (- delz delx))))
32 (when (<= delx 0)
33 (error "x2 is <= x1."))
34 (setf (aref vol z y x) 255)
35 (loop while (< x x2) do
36 (incf x) ;; step in x
37 (if (< dy 0) ;; then no change in y
38 (incf dy yinc1) ;; update dy
39 (progn
40 (incf dy yinc2) ;; update dy, and
41 (incf y ysign)));; increment/decrement y
43 (if (< dz 0)
44 (incf dz zinc1)
45 (progn
46 (incf dz zinc2)
47 (incf z zsign)))
48 (setf (aref vol z y x) 255)))
49 vol)
50 ;; start from scan-convert-line3x and replace x->$, y->x, $->y
51 (defun scan-convert-line3y (x1 y1 z1 x2 y2 z2 vol)
52 (declare (fixnum x1 y1 z1 x2 y2 z2)
53 ((simple-array (unsigned-byte 8) 3) vol)
54 (values (simple-array (unsigned-byte 8) 3) &optional))
55 (let* ((y y1)
56 (dely (- y2 y1))
57 (x x1)
58 (ddx (- x2 x1))
59 (delx (abs ddx))
60 (xsign (signum ddx))
61 (dx (- (* 2 delx) dely))
62 (xinc1 (* 2 delx))
63 (xinc2 (* 2 (- delx dely)))
64 (z z1)
65 (ddz (- z2 z1))
66 (delz (abs ddz))
67 (zsign (signum ddz))
68 (dz (- (* 2 delz) dely))
69 (zinc1 (* 2 delz))
70 (zinc2 (* 2 (- delz dely))))
71 (when (<= dely 0)
72 (error "y2 is <= y1."))
73 (setf (aref vol z y x) 255)
74 (loop while (< y y2) do
75 (incf y)
76 (if (< dx 0)
77 (incf dx xinc1)
78 (progn
79 (incf dx xinc2)
80 (incf x xsign)))
81 (if (< dz 0)
82 (incf dz zinc1)
83 (progn
84 (incf dz zinc2)
85 (incf z zsign)))
86 (setf (aref vol z y x) 255)))
87 vol)
88 ;; replace x->$, z->x, $->z
89 (defun scan-convert-line3z (x1 y1 z1 x2 y2 z2 vol)
90 (declare (fixnum x1 y1 z1 x2 y2 z2)
91 ((simple-array (unsigned-byte 8) 3) vol)
92 (values (simple-array (unsigned-byte 8) 3) &optional))
93 (let* ((z z1)
94 (delz (- z2 z1))
95 (y y1)
96 (ddy (- y2 y1))
97 (dely (abs ddy))
98 (ysign (signum ddy))
99 (dy (- (* 2 dely) delz))
100 (yinc1 (* 2 dely))
101 (yinc2 (* 2 (- dely delz)))
102 (x x1)
103 (ddx (- x2 x1))
104 (delx (abs ddx))
105 (xsign (signum ddx))
106 (dx (- (* 2 delx) delz))
107 (xinc1 (* 2 delx))
108 (xinc2 (* 2 (- delx delz))))
109 (when (<= delz 0)
110 (error "z2 is <= z1."))
111 (setf (aref vol z y x) 255)
112 (loop while (< z z2) do
113 (incf z)
114 (if (< dy 0)
115 (incf dy yinc1)
116 (progn
117 (incf dy yinc2)
118 (incf y ysign)))
120 (if (< dx 0)
121 (incf dx xinc1)
122 (progn
123 (incf dx xinc2)
124 (incf x xsign)))
125 (setf (aref vol z y x) 255)))
126 vol)
128 (defun scan-convert-line3 (start end vol)
129 (declare (vec-i start end)
130 ((simple-array (unsigned-byte 8) 3) vol)
131 (values (simple-array (unsigned-byte 8) 3) &optional))
132 (let* ((diff (v--i end start))
133 (ls (list (list (vec-i-x diff) 2)
134 (list (vec-i-y diff) 1)
135 (list (vec-i-z diff) 0)))
136 (diffa (mapcar #'(lambda (e) (list (abs (first e))
137 (second e))) ls))
138 ;; find the direction with the biggest difference
139 (sorted-diff-a (sort diffa #'> :key #'car))
140 (main-direction (second (first sorted-diff-a))) ;; 2 corresponds to x, 1->y, 0->z
141 ;; find the order in which to deliver the points
142 (main-diff (aref diff main-direction))
143 ;; we have to swap the points when main-diff is negative
144 (swap-points? (< main-diff 0))
145 ;; create the function name to dispatch to
146 (function (ecase main-direction
147 (2 #'scan-convert-line3x)
148 (1 #'scan-convert-line3y)
149 (0 #'scan-convert-line3z))))
150 (when (eq 0 main-diff)
151 (error "start and end point are the same."))
152 (if swap-points?
153 (funcall function
154 (vec-i-x end)
155 (vec-i-y end)
156 (vec-i-z end)
157 (vec-i-x start)
158 (vec-i-y start)
159 (vec-i-z start)
160 vol)
161 (funcall function
162 (vec-i-x start)
163 (vec-i-y start)
164 (vec-i-z start)
165 (vec-i-x end)
166 (vec-i-y end)
167 (vec-i-z end)
168 vol))))
171 #+nil
172 (time
173 (let ((vol (make-array (list 128 128 128) :element-type '(unsigned-byte 8))))
174 (save-stack-ub8 "/home/martin/tmp/line"
175 (scan-convert-line3 (make-vec-i :x 0 :y 0 :z 0)
176 (make-vec-i :x 120 :y 127 :z 127)
177 vol))))