File: dda.l

package info (click to toggle)
euslisp 9.31%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 55,448 kB
  • sloc: ansic: 41,610; lisp: 3,339; makefile: 286; sh: 238; asm: 138; python: 53
file content (151 lines) | stat: -rw-r--r-- 4,186 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
;;;;****************************************************************
;;;; D D A (Digital Differential Analyzer)
;;;; (c) 1998, Toshihiro Matsui, Electrotechnical Laboratory
;;;; line, ellipse (circle) generator
;;;

(export '(dda line-dda ellipse-dda circle-dda draw-ellipse
	  ellipse-dda dda-line))

(defclass DDA :super propertied-object :slots ((count :integer)))

(defclass line-DDA :super DDA
  :slots ((x :integer) (y :integer)
	  (dx :integer) (dy :integer)
	  (err :integer) (errinc :integer) (errdec :integer)
	  (xyinc :integer) (length :integer)
	  (update-method))
  )

(defclass ellipse-DDA :super DDA
	:slots (finished xcenter ycenter
		(a :float) (b :float)
		(m  :float) (eps :float)
		(ix :integer) (iy :integer) (x :float) (y :float)
		(ix1 :integer) (iy1 :integer) (x1 :float) (y1 :float)))
(defclass circle-DDA :super ellipse-DDA)

(defmethod DDA
 (:init ()
   (setq count 0)
   self)
 )
 
(defmethod line-DDA
 (:init (x0 y0 x1 y1)
    (send-super :init)
    (let (adx ady)
       (setq dx (- x1 x0)
	     dy (- y1 y0)
	     adx (abs dx)
	     ady (abs dy)
	     err 0
  	     errdec (* 2 (abs (- ady adx)))
	     errinc (* 2 (if (> adx ady) ady adx))
	     x x0
	     y y0
             length (1+ (max adx ady)))
    (cond ((> adx ady)
	   (setq err (- (* 2 ady) adx))
	   (setq xyinc (if (> dy 0) 1 -1))
	   (setq update-method :update-x-major) )
	  (t ; y is major
	   (setq err (- (* 2 adx) ady))
	   (setq xyinc (if (> dx 0) 1 -1))
	   (setq update-method :update-y-major) )
	) )
    self)
 (:update-x-major ()
     (cond ((> err 0)
	    (incf y xyinc)
	    (decf err errdec))
	   (t (incf err errinc)))
     (incf x (if (> dx 0) 1 -1)) )
 (:update-y-major ()
     (cond ((> err 0)
	    (incf x xyinc)
	    (decf err errdec))
	   (t (incf err errinc)))
     (incf y (if (> dy 0) 1 -1)) )
 (:next ()	; composed only by integer additions and subtractions
    (if (> (incf count) length) (return-from :next nil))
    (prog1 (list x y) (send self update-method))
	;; call either :update-x-major or :update-y-major
  )
 )

;;****************************************************************

(defun dda-line (x0 y0 x1 y1)
   (let ((ddax (instance line-dda :init x0 y0 x1 y1))
	 (p)
	 (points))
     (while (setq p (send ddax :next)) (push p points))
     (nreverse points)) )

;;****************************************************************


(defmethod ellipse-dda
 (:init (param-a param-b &optional (x-center 0) (y-center 0))
    (send-super :init)
    (setq finished nil)
    (setq xcenter x-center ycenter y-center)
    (setq a (float param-a) b (float param-b))
    (setq m (/ (* a a) (* b b)))
    (setq eps (expt 2 (- (ceiling (/ (log b) (log 2))))))
    (setq x1 (float a) y1 0.0)
    (setq ix1 (round x1) iy1 (round y1))
    (setq ix ix1 iy iy1 y 0)
    self)
 (:next ()
        (incf count)
	(when (and (< y 0) (>= y1 0.0))
	    (setq finished t)
	    (return-from :next nil))
	(setq x x1 y y1)
	(setq x1 (- x (* eps m y)))
	(setq y1 (+ y (* eps   x1)))
	(setq ix1 (round x1) iy1 (round y1))
	;; (print (list ix1 iy1))
	(cond ((or (/= ix ix1) (/= iy iy1))
		    (setq ix ix1 iy iy1)
		    (list (+ xcenter ix) (+ ycenter iy)))
	      (t (send self :next))    )
	)
  )

(defun dda-ellipse (a b)
    (let (x y x1 y1 ix iy ix1 iy1 eps m one/m (r)) 
	(setq a (float a) b (float b))
	(setq m (/ (* b b) (* a a))
	      one/m (/ 1.0 m))
	(setq eps (expt 2 (- (ceiling (/ (log b) (log 2))))))
	(print (list eps m))
	(setq x1 (float a) y1 0.0)
	(setq ix1 (round x1) iy1 (round y1))
	(setq ix ix1 iy iy1)
	(tagbody 
		loop
		(setq x x1 y y1)
		(setq x1 (- x (* eps one/m y)))
		(setq y1 (+ y (* eps #|m|# x1)))
		(setq ix1 (round x1) iy1 (round y1))
		;; (print (list ix1 iy1))
		(when (or (/= ix ix1) (/= iy iy1))
		    (setq ix ix1 iy iy1)
		    (push (list ix iy) r)
		    (print (list ix iy))
		    )
		(if (not (and (< y 0) (>= y1 0))) (go loop)))
	t))


(defun draw-ellipse (xc yc a b &optional (win *viewsurface*))
   (let ((dda (instance ellipse-dda :init a b xc yc)) xy )
      (while (setq xy (send dda :next))
	(send win :point (car xy) (second xy)))
      (send win :flush)
))

(provide :DDA "@(#)$Id: dda.l,v 1.1.1.1 2003/11/20 07:46:28 eus Exp $")