File: viewit.lisp

package info (click to toggle)
cl-clue 20050302
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 5,964 kB
  • ctags: 2,647
  • sloc: lisp: 32,019; makefile: 63; sh: 38
file content (223 lines) | stat: -rw-r--r-- 6,754 bytes parent folder | download | duplicates (6)
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
;;; viewit.lisp -*- Package: User -*-
;;;
;;; Example of use of pictures to draw line charts.
;;; Very much work in progress. Not really ready for
;;; prime time.
;;;
;;; try (testme (make-pt-seq '(0 1 2 3 2 3 5 6 10)))
;;;
;;; To remove graphic from display
;;; (killit)
;;;
;;; Paul Werkowski
;;;
(in-package :user)
(use-package :clue)
(use-package :pictures)

(defvar *default-host* "localhost")

;;; first some CLUE setup
(defparameter *database* (xlib:make-resource-database))
(defvar *display* (open-contact-display 'test :host "localhost"))

(eval-when (load eval)
  (define-resources
      (* background) :wheat
      (* foreground) :black
      (* highlight) :yellow
      (* font) "fixed")

  (when (and (boundp '*display*)(xlib:display-p *display*))
    ;; Grab resource values from server.
    (xlib:wm-resources 
     *database*
     (xlib:screen-root (xlib:display-default-screen *display*))))
  
  (define-resources
    (* top y) 80
    (* top x) 10
    (* plot background) :blue
    (* tactical foreground) :red
    (* tactical plane color) :red
    (* tactical dish color) :green
    (* gunner bg-color) :skyblue
    (* gunner fg-color) :black
    (* gunner ax-color) :blue))


;;; Some Pictures stuff
(defvar *top*)
(defvar *all* nil)
(defvar *view*)
(defvar *rectangle*)
(defvar *line*)
(defvar *polygon*)
(defvar *label*)
(defvar *scene*)



;;; This  leaves the view active after exiting. Need to
;;; run disable-clx-event-handling when done.
;;; (showit2 (make-scene)) produces a blank display suitable
;;; for experimenting with objects,
;;;  eg (scene-insert *scene* (make-line 10 10 50 50))
;;;     (refresh-view *view*)
;;;
(defun showit2(&optional (scene (make-scene))
			 &key
			 (width 100)(height 100))
  (let* ((top (make-contact 'top-level-shell
			    :parent *display*
			    :state :mapped
			    :wm-title "Demo"
			    :x 30
			    :y 30))
	 (scene-parent (make-scene :elements (list scene)))
	 ;; A vew connects the graphic to the xwindow system via
	 ;; a CLUE contact object. This lets event handlers work.
	 (view (make-view
		:parent top
		:width width
		:height height
		;; Seems a graphic parent is needed for proper transforming
		;; so wrap the input scene in one of its own
		:graphic scene-parent
		)))
    (setq *scene* scene
	  *view* view
	  *top* top)
    (push top *all*)
    ;; This is needed to let labels find scale factor.
    (setf (graphic-view scene-parent) view)
    (loop while (process-next-event *display* 1))
    (ext:enable-clx-event-handling
     *display* #'(lambda(display)
		   (process-next-event display 0)))))

(defun killit()
  (ext:disable-clx-event-handling *display*)
  (do ((x (pop *all*)(pop *all*)))
      ((not x))
    (destroy x)))

(defun make-pt-seq(seq &optional (dx 1.0))
  (etypecase seq
    (list
     (loop
       for y in seq
       and x upfrom 0.0 by dx
       append (list x y)))
    (vector
     (loop
       for y across seq
       and x upfrom 0.0 by dx
       append (list x y)))))
      
(defun ensure-polypoint (seq)
  (if (typep seq 'polypoint)
      seq
      (make-polyline seq)))

(defun get-combined-extent (list-of-graphics)
  (when list-of-graphics
    (let ((tmp-extent (make-extent-rect)))
      (dolist (g list-of-graphics tmp-extent)
	(let ((e (graphic-extent g)))
	  (cond ((and (valid-extent-p e)(valid-extent-p tmp-extent))
		 (extent-combine e tmp-extent))
		((and (valid-extent-p e)(not (valid-extent-p tmp-extent)))
		 (extent-copy e tmp-extent))))))))

(defun make-chart (list-of-curves
		   &key
		   (width 100)(height 100)
		   xlow xhgh ylow yhgh)
  "Lets say each curve is a polypoint in the same coordinate
   world (forgetting for now any annotations)
   The idea is to build up a scene tree that can be scaled
   to the \"world-coordinate\" (really window coordinate)
   system of the view.
   The x/y keys are used to establish the boundaries of
   our coordinate system. Else these are derived from the
   max extent of the components."
  (let* ((curves (mapcar 'ensure-polypoint list-of-curves))
	 (extent (get-combined-extent curves))
	 (xlow (or xlow (extent-rect-xmin extent)))
	 (xhgh (or xhgh (extent-rect-xmax extent)))
	 (ylow (or ylow (extent-rect-ymin extent)))
	 (yhgh (or yhgh (extent-rect-ymax extent)))
	 (xscale (/ width (- xhgh xlow)))
	 (yscale (/ height (- yhgh ylow)))
	 (x0 0)
	 (y0 0))
    (declare (ignore x0 y0))
    (let ((scene (make-scene :elements curves)))
      (move-transform scene (- xlow) (- ylow))
      (scale-transform scene xscale yscale)
      scene)))



(defun testme(seq &key (width 400)(height 300) yhgh ylow)
  (let* ((seq (if (and (listp seq)(numberp (first seq)))
		  (list seq) seq))
	 (ymax (reduce 'max (mapcar #'point-seq-y-max seq)))
	 (ymin (reduce 'min (mapcar #'point-seq-y-min seq)))
	 (xmin (reduce 'min (mapcar #'point-seq-x-min seq)))
	 (xmax (reduce 'max (mapcar #'point-seq-x-max seq)))
	 (xorg (and (not (zerop (- (signum ymax)(signum ymin))))
		    (list (list xmin 0 xmax 0))))
	 (scene (make-chart (append seq xorg)
			    :yhgh yhgh :ylow ylow
			    :width width :height height)))
    (showit2 scene :width width :height height )))


(defun good-extents (low hgh)
  (let* ((range (- hgh low))
	 (logr (ceiling (log range 10))))
    (cond ((= logr 2)
	   ;; 10+ -> 100
	   (values (* (floor   low 10) 10)
		   (* (ceiling hgh 10) 10)))
	  (t (values low hgh)))))

(defun make-xgrid(xlow ylow xhgh yhgh by)
  (format t "xgrid ~a ~a ~a ~a~%" xlow ylow xhgh yhgh)
  (let ((res nil))
    (do ((x xlow (+ x by)))
	((> x xhgh))
      (push (list x ylow x yhgh) res))
    (nreverse res)))

(defun make-ygrid(xlow ylow xhgh yhgh by)
  (format t "ygrid ~a ~a ~a ~a~%" xlow ylow xhgh yhgh)
  (let ((res nil))
    (do ((y ylow (+ y by)))
	((> y yhgh))
      (push (list xlow y xhgh y) res))
    (nreverse res)))

(defun make-xy-grid (xmin ymin xmax ymax)
  (multiple-value-bind (xgl xgh)(good-extents xmin xmax)
    (multiple-value-bind (ygl ygh) (good-extents ymin ymax)
      (let ((ygrid (make-ygrid xgl ygl xgh ygh 10))
	    (xgrid (make-xgrid xgl ygl xgh ygh 20)))
	(nconc xgrid ygrid)))))

(defun show/grid(seq &key (width 400)(height 300) yhgh ylow)
  (let* ((seq (if (and (listp seq)(numberp (first seq)))
		  (list seq) seq))
	 (ymax (reduce 'max (mapcar #'point-seq-y-max seq)))
	 (ymin (reduce 'min (mapcar #'point-seq-y-min seq)))
	 (xmin (reduce 'min (mapcar #'point-seq-x-min seq)))
	 (xmax (reduce 'max (mapcar #'point-seq-x-max seq)))
	 (xorg (and (not (zerop (- (signum ymax)(signum ymin))))
		    (list (list xmin 0 xmax 0))))
	 (grid (make-xy-grid xmin (or ylow ymin) xmax (or yhgh ymax)))
	 (scene (make-chart (append seq xorg grid)
			    :yhgh yhgh :ylow ylow
			    :width width :height height)))
    (showit2 scene :width width :height height )))