-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrectangle.lisp
More file actions
299 lines (263 loc) · 11.6 KB
/
rectangle.lisp
File metadata and controls
299 lines (263 loc) · 11.6 KB
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
;;;-*- Mode:Common-Lisp; Package:PICTURES; Base:10 -*-
;;;
;;;
;;;
;;; TEXAS INSTRUMENTS INCORPORATED
;;; P.O. BOX 149149
;;; AUSTIN, TEXAS 78714-9149
;;;
;;; Copyright (C)1987,1988,1989,1990 Texas Instruments Incorporated.
;;;
;;; Permission is granted to any individual or institution to use, copy, modify,
;;; and distribute this software, provided that this complete copyright and
;;; permission notice is maintained, intact, in all copies and supporting
;;; documentation.
;;;
;;; Texas Instruments Incorporated provides this software "as is" without
;;; express or implied warranty.
;;;
;;; Authors: Delmar Hager, James Dutton, Teri Crowe
;;; Contributors: Kerry Kimbrough, Patrick Hogan, Eric Mielke
(in-package "PICTURES")
;Rectangle Class Definition:
(defclass pictures::rectangle (polygon)
()
(:documentation "A graphic that represents a rectangle in object coordinates."))
;Filled-Rectangle Class Definition:
(defclass filled-rectangle ( rectangle filled-polygon)
()
(:documentation "Filled rectangle class in pictures"))
;Filled-Rectangle-Edge Class Definition:
(defclass filled-rectangle-edge ( rectangle filled-polygon-edge)
()
(:documentation "Filled rectangle edge class in pictures"))
(defun make-rectangle (x-min y-min width height &rest options )
"Make a rectangle with the with the given X-MIN, Y-MIN, WIDTH and HEIGHT.
The following keyword OPTIONS are allowed: GSTATE PARENT SENESITIVITY TRANSFORM PLIST"
(APPLY #'MAKE-INSTANCE 'rectangle
:point-seq (complete-rectangle x-min y-min (+ x-min width) (+ y-min height))
options))
(defun make-filled-rectangle (x-min y-min width height &rest options )
"Make a filled-rectangle with with the given X-MIN, Y-MIN, WIDTH and HEIGHT.
The following keyword OPTIONS are allowed: GSTATE PARENT SENESITIVITY TRANSFORM PLIST"
(APPLY #'MAKE-INSTANCE 'filled-rectangle
:point-seq (complete-rectangle x-min y-min (+ x-min width) (+ y-min height))
options))
(defun make-filled-rectangle-edge (x-min y-min width height &rest options )
"Make a filled-rectangle-edge with the given X-MIN, Y-MIN, WIDTH and HEIGHT.
The following keyword OPTIONS are allowed: GSTATE PARENT SENESITIVITY TRANSFORM PLIST EDGE-GSTATE"
(APPLY #'MAKE-INSTANCE 'filled-rectangle-edge
:point-seq (complete-rectangle x-min y-min (+ x-min width) (+ y-min height))
options))
; Graphic methods for rectangle graphics
(DEFMETHOD rectangle-origin-x ((rectangle rectangle))
(vertex-x rectangle 0))
(DEFMETHOD (SETF rectangle-origin-x) (origin-x (rectangle rectangle) )
(LET ((difference (- origin-x (vertex-x rectangle 0))))
(extent-changed rectangle)
(DOTIMES (pos 4 origin-x)
(SETF (vertex-x rectangle pos) (+ difference (vertex-x rectangle pos)) ))))
(DEFMETHOD rectangle-origin-y ((rectangle rectangle))
(vertex-y rectangle 0))
(DEFMETHOD (SETF rectangle-origin-y) (origin-y (rectangle rectangle) )
(LET ((difference (- origin-y (vertex-y rectangle 0))))
(extent-changed rectangle)
(DOTIMES (pos 4 origin-y)
(SETF (vertex-y rectangle pos) (+ difference (vertex-y rectangle pos)) ))))
(DEFMETHOD rectangle-width ((rectangle rectangle))
(with-slots (vertices) rectangle
(VALUES (distance
(vertex-x rectangle 0) (vertex-y rectangle 0) (vertex-x rectangle 1) (vertex-y rectangle 1)))))
(DEFMETHOD (SETF rectangle-width) (width (rectangle rectangle))
(with-slots (vertices ) rectangle
(extent-changed rectangle)
(MULTIPLE-VALUE-BIND (x y dx dy) (compute-point (VERTEX-X RECTANGLE 0)(VERTEX-Y RECTANGLE 0)
(vertex-x rectangle 1)(vertex-y rectangle 1) width)
(SETF (vertex-x rectangle 1) x)
(SETF (vertex-y rectangle 1) y)
(SETF (vertex-x rectangle 2) (+ (vertex-x rectangle 2) dx))
(SETF (vertex-y rectangle 2) (+ (vertex-y rectangle 2) dy))))
rectangle)
(DEFMETHOD rectangle-height ((rectangle rectangle))
(with-slots (vertices ) rectangle
(VALUES (distance
(vertex-x rectangle 0)
(vertex-y rectangle 0)
(vertex-x rectangle 3)
(vertex-y rectangle 3)))))
(DEFMETHOD (SETF rectangle-height) (height (rectangle rectangle))
(with-slots (vertices ) rectangle
(extent-changed rectangle)
(MULTIPLE-VALUE-BIND (x y dx dy) (compute-point (VERTEX-X RECTANGLE 0)(VERTEX-Y RECTANGLE 0)
(vertex-x rectangle 3)(vertex-y rectangle 3) height)
(SETF (vertex-x rectangle 3) x)
(SETF (vertex-y rectangle 3) y)
(SETF (vertex-x rectangle 2) (+ (vertex-x rectangle 2) dx))
(SETF (vertex-y rectangle 2) (+ (vertex-y rectangle 2) dy)))
rectangle))
(DEFMETHOD rectangle-size ((rectangle rectangle))
(VALUES
(distance
(vertex-x rectangle 0)
(vertex-y rectangle 0)
(vertex-x rectangle 1)
(vertex-y rectangle 1))
(distance
(vertex-x rectangle 0)
(vertex-y rectangle 0)
(vertex-x rectangle 3)
(vertex-y rectangle 3))))
(DEFMETHOD normalize-graphic :around ((rectangle rectangle))
(with-slots (vertices transform) rectangle
(extent-changed rectangle)
(WHEN (AND transform (= (t12 transform)(t21 transform) 0))
(with-slots (vertices transform) rectangle
(transform-point-seq transform vertices)
(SETF transform nil))
)
transform))
(DEFUN compute-point (x1 y1 x2 y2 distance)
(LET* (x y)
(IF (= x1 x2)
(VALUES x1 (+ y1 distance) 0 (- (+ y1 distance) y2 ))
(progn
(SETF y (- y1 (* distance (SIN (ATAN (/ (- y1 y2)(- x1 x2)))))))
(SETF x (- x1 (* distance (COS (ATAN (/ (- y1 y2)(- x1 x2)))))))
(VALUES x y (- x x2) (- y y2))))))
(DEFUN distance (x1 y1 x2 y2)
"the distance between two points"
(SQRT (+ (* (- x1 x2)(- x1 x2))(* (- y1 y2)(- y1 y2)))))
;; Draw the rectangle object in the given view. if min-x, min-y,
;; width, and height are given, then only parts of the object that lie
;; within the given rectangle need to be drawn.
(defmethod draw-graphic ((rectangle rectangle) (view view)
&optional min-x min-y width height)
(declare (type (or null wcoord) min-x min-y width height))
(with-slots (vertices extent transform) rectangle
(WHEN (visible-p rectangle)
(LET ((world-transform (graphic-world-transform rectangle)))
(with-vector temp-vertices
(copy-to-vector vertices temp-vertices)
(transform-point-seq world-transform temp-vertices)
(if (AND world-transform (= (t12 world-transform)(t21 world-transform) 0))
(view-draw-rectangle view ; Yes, use draw-rectangle to draw it
(min-value-vector temp-vertices 0)
(min-value-vector temp-vertices 1)
(- (max-value-vector temp-vertices 0)(min-value-vector temp-vertices 0))
(- (max-value-vector temp-vertices 1)(min-value-vector temp-vertices 1))
(graphic-gstate rectangle))
(view-draw-polygon view ; No, use draw-polygon to draw it
temp-vertices
(graphic-gstate rectangle))
)
))
rectangle)))
;; Draw the filled-rectangle object in the given view. if min-x,
;; min-y, width, and height are given, then only parts of the object
;; that lie within the given rectangle need to be drawn.
(defmethod draw-graphic ((rectangle filled-rectangle) (view view)
&optional min-x min-y width height)
(declare (type (or null wcoord) min-x min-y width height))
(with-slots (vertices transform extent) rectangle
(WHEN (visible-p rectangle)
(LET ((world-transform (graphic-world-transform rectangle)))
(with-vector temp-vertices
(copy-to-vector vertices temp-vertices)
(transform-point-seq (graphic-world-transform rectangle) temp-vertices)
(if (AND world-transform (= (t12 world-transform)(t21 world-transform) 0))
(view-draw-filled-rectangle view ; Yes, use draw-rectangle to draw it
(min-value-vector temp-vertices 0)
(min-value-vector temp-vertices 1)
(- (max-value-vector temp-vertices 0)(min-value-vector temp-vertices 0))
(- (max-value-vector temp-vertices 1)(min-value-vector temp-vertices 1))
(graphic-gstate rectangle))
(view-draw-filled-polygon view ; No, use draw-polygon to draw it
temp-vertices
(graphic-gstate rectangle))))))))
;; Draw the FILLED-RECTANGLE-EDGE object by first drawing the interior
;; and then boundary. If MIN-X, MIN-Y, WIDTH, and HEIGHT are given,
;; then only parts of the object that lie within the given rectangle
;; need to be drawn.
(defmethod draw-graphic ((rectangle filled-rectangle-edge) (view view)
&optional min-x min-y width height)
(declare (type (or null wcoord) min-x min-y width height))
(with-slots (edge-gstate extent) rectangle
(WHEN (visible-p rectangle)
(LET ((world-transform (graphic-world-transform rectangle)))
(with-slots (vertices transform) rectangle
(with-vector temp-vertices
(copy-to-vector vertices temp-vertices)
(transform-point-seq (graphic-world-transform rectangle) temp-vertices)
; Yes, use draw-fillrectangle to Draw the interior
(if (AND world-transform (= (t12 world-transform)(t21 world-transform) 0))
(progn
(view-draw-filled-rectangle
view
(min-value-vector temp-vertices 0)
(min-value-vector temp-vertices 1)
(- (max-value-vector temp-vertices 0)(min-value-vector temp-vertices 0))
(- (max-value-vector temp-vertices 1)(min-value-vector temp-vertices 1))
(graphic-gstate rectangle))
; Draw the boundary
(view-draw-rectangle
view
(min-value-vector temp-vertices 0)
(min-value-vector temp-vertices 1)
(- (max-value-vector temp-vertices 0)(min-value-vector temp-vertices 0))
(- (max-value-vector temp-vertices 1)(min-value-vector temp-vertices 1))
(edge-gstate rectangle)))
(PROGN
(view-draw-filled-polygon view ; No, use draw-fillpolygon to draw the interior
temp-vertices
(graphic-gstate rectangle))
(view-draw-polygon view ; Draw the boundary
temp-vertices
(edge-gstate rectangle))))))))))
(defmethod scale-transform ((graphic rectangle) scale-x scale-y
&optional (fixed-x 0) (fixed-y 0))
;; Damage from old graphic
(graphic-damage graphic)
(with-slots (transform) graphic
(UNLESS (AND transform (= (t12 transform)(t21 transform) 0))
(COND
((= scale-x 1) (SETF scale-x scale-y))
((= scale-y 1) (SETF scale-y scale-x))
((< scale-x scale-y)(SETF scale-x scale-y))
(t (SETF scale-y scale-x))))
(when (null transform) ; If no transform
(setf transform (make-transform))) ; Create one
(graphic-stack-purge *transform-stack* graphic) ; Notify the transform stack
(PROG1
(scale-transform transform ; Scale it
scale-x scale-y fixed-x fixed-y)
(extent-changed graphic)) ; Notify graphic his extent may have changed
(graphic-damage graphic) ; Damage from new graphic
transform))
;; Private Method: complete-rectangle
;; Compute and return the world coordinates of all four vertices of the given RECTANGLE.
;; Also returns the X and Y lengths of the diagonal.
(defun complete-rectangle (x1 y1 x3 y3 &aux x2 y2 x4 y4)
(PSETF x2 x3
y2 y1
y4 y3
x4 x1)
;; X and Y lengths of the diagonal
(VALUES (vector x1 y1 x2 y2 x3 y3 x4 y4)))
;; private method to determine if a rectangle is ortagonal
(DEFMETHOD orthogonal ((rectangle rectangle) (view view))
(with-slots (vertices) rectangle
(LET ((x1 (VERTEX-X RECTANGLE 0) )
(y1 (VERTEX-Y RECTANGLE 0))
(x3 (vertex-x rectangle 2))
(y3 (vertex-y rectangle 2))
(epsilon (view-pixel-size view))) ; World size of one pixel in this view
(if (or (<= (abs (- x1 x3)) epsilon) ; Is rectangle orthogonal?
(<= (abs (- y1 y3)) epsilon))
t
nil))))
(DEFUN point-in-rectangle (x y xmin ymin height width )
"this function determines if a given point is within the extent bound of a graphic"
(And (>= x xmin )
(<= x (+ xmin height))
(>= y ymin)
(<= y (+ ymin width))))