File: extent.lisp

package info (click to toggle)
clue 20011230
  • links: PTS
  • area: main
  • in suites: woody
  • size: 6,112 kB
  • ctags: 2,646
  • sloc: lisp: 31,991; makefile: 40; sh: 24
file content (193 lines) | stat: -rw-r--r-- 7,223 bytes parent folder | download | duplicates (4)
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
;;;-*- 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")


;Vectors for coordinate storage
;  These are used to reduce cons'ing during extent computations.
;; CMUCL porting note. The use of adjustable array is not very efficient,
;; but is pervasive in this code. For now, just leave it alone.
(defvar *extent-vector*
  (make-array '(8) :adjustable t :fill-pointer t))

;;;  Extent-cache Mixin Definition:
(EXPORT '(
	  make-extent-rect
	  extent-rect-xmin
	  extent-rect-ymin
	  extent-rect-xmax
	  extent-rect-ymax
	  extent
	  extent-valid-p
	  valid-extent-p
	  extent-changed
	  extent-copy
	  extent-transform
	  extent-move
	  extent-combine
	  ))

(defclass extent-cache ()
  ((extent
    :type	extent-rect
    :initform	(make-extent-rect)
    :accessor	extent
    :documentation
    "Defines the minimum containing rectangle in object coordinates of a graphic")
   
   (extent-valid-p
    :type	boolean
    :initform	nil
    :reader	extent-valid-p
    :documentation
    "Because of caching, is the extent valid?")
   )
  
  (:documentation
   "Mixin for efficient handling of extents on a first in,
    first out presistent stack"))


;Method: extent-changed
;  The given EXTENT-CACHE may have changed.  Invalidate it and notify its parent.
;  No useful value is returned.

(defmethod extent-changed ((extent-cache extent-cache))

  (with-slots (extent-valid-p) extent-cache
    (setf extent-valid-p nil)
    (when (graphic-parent extent-cache)
      (extent-changed (graphic-parent extent-cache)))))


;Function: extent-combine
;  Combine EXTENT-1 with EXTENT-2 by computing their union (the smallest
;  rectangle that encloses both).  If either extent-rect is undefined (nil)
;  then the result is also nil.  Put the result in EXTENT-2 and return it.

(defun extent-combine (extent-1 extent-2)
  (declare (type (or null extent-rect) extent-1 extent-2))

    (if (and extent-1 extent-2)	; Are they both there?
	(if (and (extent-rect-valid extent-1)(extent-rect-valid extent-2))
	    (psetf				; Yes, combine them
	     (extent-rect-xmin extent-2) (min (extent-rect-xmin extent-2)
					      (extent-rect-xmin extent-1))
	     (extent-rect-xmax extent-2) (max (extent-rect-xmax extent-2)
					      (extent-rect-xmax extent-1))
	     (extent-rect-ymin extent-2) (min (extent-rect-ymin extent-2)
					      (extent-rect-ymin extent-1))
	     (extent-rect-ymax extent-2) (max (extent-rect-ymax extent-2)))
	    (progn
	      (warn "Attempt to combine invalid EXTENT-RECT ~a"
		    (if (extent-rect-valid extent-1) extent-2 extent-1))
	      (if (extent-rect-valid extent-1)
		  (setf extent-2 extent-1))))
	(when extent-2			; Make result undefined if necessary
	  (setf extent-2 nil)))

    extent-2)				; Return the combined extent


;Function: extent-copy
;  Copy SRC into DEST.  Both extents-rects should exist.  DEST is returned.

(defun extent-copy (src dest)
  (declare (type extent-rect src dest))
  (psetf (extent-rect-xmin dest) (extent-rect-xmin src)
         (extent-rect-xmax dest) (extent-rect-xmax src)
         (extent-rect-ymin dest) (extent-rect-ymin src)
         (extent-rect-ymax dest) (extent-rect-ymax src)
	 (extent-rect-valid dest)(extent-rect-valid src))

  dest)


;Method: graphic-extent
;  If the given EXTENT-CACHE is currently valid, return its extent-rect.
;  Otherwise, call extent-compute to actually compute the extent for the
;  EXTENT-CACHE, copy it into the cache, and then set extent-valid-p to t.
;  If the extent computation returns an undefined extent (nil) then nil is
;  returned and the cache remains invalid.

(defmethod graphic-extent ((extent-cache extent-cache))

  (with-slots ((cache extent) extent-valid-p) extent-cache
    (if extent-valid-p				; Is the cache valid?
        cache					; Yes, just return it
        (let ((new-extent			; No, compute it
                (extent-compute extent-cache)))
          (when new-extent			; Was it defined?
            (extent-copy new-extent cache)	; Yes, copy it into cache
            (setf extent-valid-p t)		; Cache is valid now
            cache)))))				; Return new extent


;Function: extent-transform
;  Apply the TRANSFORM to the EXTENT-RECT and return a transformed
;  extent-rect.  The extent is transformed as a full rectangle and then a
;  new extent is computed using the minimums and maximums from the
;  transformed rectangle.  If RESULT-EXTENT is specified, then the result
;  is placed there and returned as the function value.  If RESULT-EXTENT is
;  nil, a new extent-rect is created and used to store the result.
;  EXTENT-RECT is not modified.  Either EXTENT-RECT or TRANSFORM may be
;  nil.  A nil EXTENT-RECT means "undefined extent" and nil is returned.  A
;  nil TRANSFORM means the identity transform and a copy of EXTENT-RECT is
;  returned.

(defun extent-transform (transform extent-rect
                            &optional (result (make-extent-rect)))
  (declare (type (or null transform) transform))
  (declare (type (or null extent-rect) extent-rect))
  (SETF (FILL-POINTER *extent-vector*) 8)
  (when extent-rect		; "Undefined" transformed is still "undefined"
    (if transform		; Is it the identity transform?
        (progn			; No, apply it to extent-rect
	  ; Build vector of all four corners
          (setf (aref *extent-vector* 0) (extent-rect-xmin extent-rect)
		(aref *extent-vector* 2) (extent-rect-xmin extent-rect)
		(aref *extent-vector* 4) (extent-rect-xmax extent-rect)
		(aref *extent-vector* 6) (extent-rect-xmax extent-rect)
		
		(aref *extent-vector* 1) (extent-rect-ymin extent-rect)
		(aref *extent-vector* 3) (extent-rect-ymax extent-rect)
		(aref *extent-vector* 5) (extent-rect-ymax extent-rect)
		(aref *extent-vector* 7) (extent-rect-ymin extent-rect))
	  (transform-point-seq transform *extent-vector*)  ; Transform it
	  (setf (extent-rect-xmin result)
		(min-value-vector *extent-vector* 0)	; Find min/max
		(extent-rect-xmax result) (max-value-vector *extent-vector* 0)
		(extent-rect-ymin result) (min-value-vector *extent-vector* 1)
		(extent-rect-ymax result) (max-value-vector *extent-vector* 1)))

        (extent-copy extent-rect result)) ; Yes, just copy extent-rect

    result))						; Return new extent

        

(DEFUN extent-move (extent delta-x delta-y)

  (SETF (extent-rect-xmin extent) (+ (extent-rect-xmin extent) delta-x)) 
  (SETF (extent-rect-ymin extent) (+ (extent-rect-ymin extent) delta-y))
  (SETF (extent-rect-xmax extent) (+ (extent-rect-xmax extent) delta-x)) 
  (SETF (extent-rect-ymax extent) (+ (extent-rect-ymax extent) delta-y)))