;;;-*- 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") (export '( line-start-point-x line-start-point-y line-end-point-x line-end-point-y make-line ) 'pictures) ;Line Class Definition: (defclass line (extent-cache graphic) ( (start-x :type wcoord :initarg :start-x :accessor line-start-point-x :documentation "object x-coordinate of start point for the line") (start-y :type wcoord :initarg :start-y :accessor line-start-point-y :documentation "object y-coordinate of start point for the line") (end-x :type wcoord :initarg :end-x :accessor line-end-point-x :documentation "object x-coordinate of end point for the line") (end-y :type wcoord :initarg :end-y :accessor line-end-point-y :documentation "object y-coordinate of end point for the line") ) (:documentation "A graphic that represents a line")) ;Function: make-line ; Return a new line object whose end points are (START-X, START-Y) and ; (END-X, END-Y). (defun make-line (start-x start-y end-x end-y &rest options ) (declare (type wcoord start-x start-y end-x end-y)) (declare (values line)) (apply #'make-instance 'line :start-x start-x :start-y start-y :end-x end-x :end-y end-y options)) ;Method: line-start-point ; Return the coordinates of the START-POINT of the given LINE. (defmethod line-start-point ((line line)) (declare (values start-x start-y)) (with-slots (start-x start-y) line (values start-x start-y))) (defmethod (setf line-start-point-x) :after (start-x (line line)) (declare (type wcoord start-x)) (declare (ignore start-x)) (extent-changed line)) ;Method: line-start-point-y ; Return or change the x coordinate of the START-POINT of the given LINE. (defmethod (setf line-start-point-y) :after (start-y (line line)) (declare (type wcoord start-y)) (declare (ignore start-y)) (extent-changed line)) ;Method: line-end-point ; Return the coordinates of the END-POINT of the given LINE. (defmethod line-end-point ((line line)) (declare (values end-x end-y)) (with-slots (end-x end-y) line (values end-x end-y))) ;Method: line-end-point-x ; Return or change the x coordinate of the END-POINT of the given LINE. (defmethod (setf line-end-point-x) :after (end-x (line line)) (declare (type wcoord end-x)) (declare (IGNORE end-x)) (extent-changed line)) ;Method: line-end-point-y ; Return or change the x coordinate of the END-POINT of the given LINE. (defmethod (setf line-end-point-y) :after (end-y (line line)) (declare (type wcoord end-y)) (declare (IGNORE end-y)) (extent-changed line)) ; Graphic methods for line graphics ;Method: extent-compute ; Compute the extent rectangle for the LINE. ; Note: A graphic's extent rectangle is defined in the object coordinate system. This ; means that each graphic should apply its own transform to its computed extent ; before returning it. (defmethod extent-compute ((line line)) (declare (values (or null extent-rect))) (with-slots (start-x start-y end-x end-y transform) line (let (new-start-x new-start-y new-end-x new-end-y) (multiple-value-setq (new-start-x new-start-y) (transform-point transform start-x start-y)) (multiple-value-setq (new-end-x new-end-y) (transform-point transform end-x end-y)) (make-extent-rect :xmin (min new-start-x new-end-x) :ymin (min new-start-y new-end-y) :xmax (max new-start-x new-end-x) :ymax (max new-start-y new-end-y))))) ;Method: draw-graphic ; Draw the LINE 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. (DEFMACRO line-visible-p (graphic) `(AND (NOT (AND (and min-x min-y width height) ; Was optional rect given (not (graphic-within-p ,graphic min-x min-y width height)) (not (graphic-intersects-p ,graphic min-x min-y width height)))) (PROGN (UNLESS (valid-extent-p (graphic-extent ,graphic))) (OR (>= (/ (- (extent-rect-xmax extent) (extent-rect-xmin extent))(view-scale view) ) (view-pixel-size view)) (= (/ (- (extent-rect-xmax extent) (extent-rect-xmin extent)) (view-scale view) ) 0)) (OR (>= (/ (- (extent-rect-ymax extent) (extent-rect-ymin extent))(view-scale view) ) (view-pixel-size view)) (= (/ (- (extent-rect-ymax extent) (extent-rect-ymin extent)) (view-scale view) ) 0)) ) (viewable-p ,graphic))) (defmethod draw-graphic ((line line) (view view) &optional min-x min-y width height) (declare (type (or null wcoord) min-x min-y width height)) (with-slots (gstate start-x start-y end-x end-y extent) line (WHEN (line-visible-p line) (MULTIPLE-VALUE-BIND (x y) (transform-point (graphic-world-transform line) start-x start-y) (MULTIPLE-VALUE-BIND (x1 y1) (transform-point (graphic-world-transform line) end-x end-y) (view-draw-line view x y x1 y1 (graphic-gstate line))))))) (defmethod draw-graphic-clipped ((graphic line) (view view) min-x min-y width height) (declare (type wcoord min-x min-y width height)) (with-slots (extent) graphic (WHEN (line-visible-p graphic) (SETF (gstate-clip-mask graphic) (clip-mask graphic view min-x min-y width height)) (draw-graphic graphic view) (SETF (gstate-clip-mask graphic) :none)) )) (DEFMETHOD graphic-damage ((graphic line)) "Records graphic as a damaged region in each view to which it is attached." (with-slots ( gstate) graphic (LET ((extent (world-extent graphic))) (WHEN (valid-extent-p extent) (UNLESS (extent-valid-p graphic) (graphic-extent graphic)) (LET* ((xmin (extent-rect-xmin extent)) (ymin (extent-rect-ymin extent))) (do ((g graphic (graphic-parent g))) ((null g)) (dolist (view (graphic-views g)) (LET ((width (COND ((AND (NOT (AND gstate (gstate-line-width graphic))) (= (- (extent-rect-xmax extent) (extent-rect-xmin extent)) 0)) (view-pixel-size view)) ((AND (NOT (AND gstate (gstate-line-width graphic))) (< (- (extent-rect-xmax extent) (extent-rect-xmin extent)) (view-pixel-size view))) (view-pixel-size view)) (t (- (extent-rect-xmax extent) (extent-rect-xmin extent))))) (height (COND ((AND (NOT (AND gstate (gstate-line-width graphic))) (= (- (extent-rect-ymax extent) (extent-rect-ymin extent)) 0)) (view-pixel-size view)) ((AND (NOT (AND gstate (gstate-line-width graphic))) (< (- (extent-rect-ymax extent) (extent-rect-ymin extent))(view-pixel-size view))) (view-pixel-size view)) (t (- (extent-rect-ymax extent) (extent-rect-ymin extent)))))) (view-damage view xmin ymin width height))))))))) (defmethod scale-transform ((graphic line) scale-x scale-y &optional (fixed-x 0) (fixed-y 0)) (DECLARE (IGNORE fixed-x fixed-y)) (declare (type (or (satisfies plusp) (satisfies zerop)) scale-x scale-y)) (declare (type ocoord fixed-x fixed-y)) (declare (values transform)) (graphic-damage graphic) ; Damage from old graphic (with-slots (transform start-x start-y end-x end-y) graphic (COND ((AND (OR (AND (= start-x end-x)(NOT (= scale-x 1)))(AND (= start-y end-y)(NOT (= scale-y 1)))) (NOT transform)) nil) ( t (call-next-method))) (extent-changed graphic) ; Notify graphic his extent may have changed (graphic-damage graphic) ; Damage from new graphic transform)) ;Method: normalize-graphic ; Normalize the LINE by applying its transform to its geometry, changing it ; accordingly, and then setting its transform to nil (the identity transform). ; Nothing of value is returned. (defmethod normalize-graphic :before ((line line)) (with-slots (start-x start-y end-x end-y transform) line (multiple-value-setq (start-x start-y) (transform-point transform start-x start-y)) (multiple-value-setq (end-x end-y) (transform-point transform end-x end-y)))) ;;This method is for determining if a pick is on a line (DEFMETHOD graphic-contains-p ((line line) x y &optional pixel) (DECLARE (type wcoord x y) ) (SETF pixel (/ (OR (AND (graphic-gstate line) (gstate-line-width line)) pixel 2) 2)) (with-slots (start-x start-y end-x end-y transform) line (MULTIPLE-VALUE-BIND (sx sy)(transform-point (graphic-world-transform line) start-x start-y) (MULTIPLE-VALUE-BIND (ex ey) (transform-point (graphic-world-transform line) end-x end-y) (point-on-line-p pixel x y sx sy ex ey) ))) ) ;function for determining if a point is on a line ;no consideration is given to make sure the point is within the endpoints, this check is done by the ;graphic in the method: graphic-contains-p (defun point-on-line-p ( aperture x y x1 y1 x2 y2) (SETF aperture (* 2 aperture)) (COND ( (= (FLOOR x1) (FLOOR x2)) (AND (<= (ABS (- x x1)) aperture) (>= y (MIN y1 y2)) (<= y (MAX y1 y2)))) ;perpendicular line with infinite slope ( (= (FLOOR y1)(FLOOR y2)) (AND (<= (ABS (- y y1)) aperture) (>= x (MIN x1 x2)) (<= x (MAX x1 x2))) ) ;horizontal line (t (<= (MIN (ABS (+ (/ (* (- y2 y1)(- x x1)) (- x2 x1)) y1 (- y)));pp 227-228 Computer Graphics - Harrington (ABS (+ (/ (* (- x2 x1)(- y y1)) (- y2 y1)) x1 (- x)))) aperture) ) ) )