open.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. #!fold-case
  21. ;;;; Graphics Windows
  22. ;;; The "hardware" OPEN
  23. (define *foreground-color* "white")
  24. (define *background-color* "black")
  25. (define *can-use-colors* #t)
  26. ;;; Defaults for X windows
  27. ; (define *frame-x-position* (if (eq? 'unix microcode-id/operating-system) 750 532))
  28. ;;; FBE start:
  29. ;; (define *frame-x-position* (if (eq? 'unix microcode-id/operating-system) -10 532))
  30. (define *frame-y-position* 0)
  31. ;; (define *frame-width* (if (eq? 'unix microcode-id/operating-system) 400 100))
  32. ;; (define *frame-height* (if (eq? 'unix microcode-id/operating-system) 400 100))
  33. (define *frame-x-position* (if #t -10 532))
  34. (define *frame-width* (if #t 400 100))
  35. (define *frame-height* (if #t 400 100))
  36. (define* (make-display-frame #:optional xmin xmax ymin ymax
  37. frame-width frame-height
  38. frame-x-position frame-y-position
  39. display)
  40. (let ((xmin (if (default-object? xmin) 0.0 xmin))
  41. (xmax (if (default-object? xmax) 1.0 xmax))
  42. (ymin (if (default-object? ymin) 0.0 ymin))
  43. (ymax (if (default-object? ymax) 1.0 ymax))
  44. (frame-x
  45. (if (default-object? frame-x-position)
  46. *frame-x-position*
  47. frame-x-position))
  48. (frame-y
  49. (if (default-object? frame-y-position)
  50. *frame-y-position*
  51. frame-y-position))
  52. (frame-width
  53. (if (default-object? frame-width)
  54. *frame-width*
  55. frame-width))
  56. (frame-height
  57. (if (default-object? frame-height)
  58. *frame-height*
  59. frame-height)))
  60. (if (not (and (integer? frame-width) (> frame-width 0)
  61. (integer? frame-height) (> frame-height 0)))
  62. (error "Bad frame width or height"))
  63. (let ((window
  64. (if (default-object? display)
  65. (make-window frame-width frame-height frame-x frame-y)
  66. (make-window frame-width frame-height frame-x frame-y display))))
  67. (graphics-set-coordinate-limits window xmin ymin xmax ymax)
  68. (graphics-set-clip-rectangle window xmin ymin xmax ymax)
  69. (let ((name (graphics-type-name (graphics-type #f))))
  70. (case name
  71. ((X)
  72. (graphics-operation window 'set-border-color "green")
  73. (graphics-operation window 'set-mouse-color "green"))
  74. ((WIN32) 'nothing-to-do )
  75. ((OS/2) 'nothing-to-do )
  76. (else (error "Unsupported graphics type:" name))))
  77. (graphics-operation window 'set-background-color *background-color*)
  78. (graphics-operation window 'set-foreground-color *foreground-color*)
  79. (graphics-clear window)
  80. window)))
  81. ;;; By CPH, frame maker in display coordinates.
  82. (define* (make-window width height x y #:optional display)
  83. (let ((window
  84. (let ((name (graphics-type-name (graphics-type #f))))
  85. (case name
  86. ((X)
  87. (if (default-object? display) (set! display #f))
  88. (make-window/X11 width height x y display))
  89. ((WIN32)
  90. (if (not (default-object? display))
  91. (error "No remote Win32 display"))
  92. (make-window/win32 width height x y))
  93. ((OS/2)
  94. (if (not (default-object? display))
  95. (error "No remote OS/2 display"))
  96. (make-window/OS2 width height x y))
  97. (else
  98. (error "Unsupported graphics type:" name))))))
  99. (graphics-set-coordinate-limits window 0 (- (- height 1)) (- width 1) 0)
  100. ;;(restore-focus-to-editor)
  101. window))
  102. (define* (make-window/X11 width height x y #:optional display)
  103. (if (default-object? display) (set! display #f))
  104. (let ((window
  105. (make-graphics-device 'X
  106. display
  107. (x-geometry-string x y width height)
  108. true)))
  109. ;; Prevent this window from receiving the keyboard focus.
  110. (if (not (string-ci=? "MacOSX" microcode-id/operating-system-variant))
  111. (x-graphics/disable-keyboard-focus window))
  112. ;; Inform the window manager that this window does not do any
  113. ;; keyboard input.
  114. (x-graphics/set-input-hint window false)
  115. ;; OK, now map the window onto the screen.
  116. (x-graphics/map-window window)
  117. (x-graphics/flush window)
  118. window))
  119. (define (make-window/win32 width height x y)
  120. (let ((window (make-graphics-device 'WIN32 width height 'GRAYSCALE-128)))
  121. (graphics-operation window 'MOVE-WINDOW x y)
  122. window))
  123. (define (make-window/OS2 width height x y)
  124. (let ((window (make-graphics-device 'OS/2 width height)))
  125. ;; X, Y specify the position of the upper-left corner of the
  126. ;; window, in coordinates relative to the upper-left corner of the
  127. ;; display with Y growing down; the OS/2 SET-WINDOW-POSITION
  128. ;; operation specifies the position of the lower-left corner of
  129. ;; the window, in coordinates relative to the lower left corner of
  130. ;; the display, with Y growing up.
  131. (call-with-values (lambda () (graphics-operation window 'DESKTOP-SIZE))
  132. (lambda (dx dy)
  133. dx
  134. (call-with-values
  135. (lambda () (graphics-operation window 'WINDOW-FRAME-SIZE))
  136. (lambda (fx fy)
  137. fx
  138. (graphics-operation window 'SET-WINDOW-POSITION
  139. x
  140. (- dy (+ y fy)))))))
  141. window))
  142. (define (rename-window window name)
  143. (cond ((string? name) 'OK)
  144. ((symbol? name) (set! name (symbol->string name)))
  145. ((number? name) (set! name (number->string name)))
  146. (else (error "Window name must be string")))
  147. (graphics-operation window 'set-window-name name)
  148. (graphics-operation win 'set-icon-name name)
  149. name)
  150. (define (resize-window window width height)
  151. (let ((name (graphics-type-name (graphics-type window))))
  152. (case name
  153. ((X WIN32) (graphics-operation window 'RESIZE-WINDOW width height))
  154. ((OS/2) (graphics-operation window 'SET-WINDOW-SIZE width height))
  155. (else (error "Unsupported graphics type:" name)))))
  156. (define (show-window-size window)
  157. (call-with-values (lambda () (graphics-device-coordinate-limits window))
  158. (lambda (x1 y1 x2 y2)
  159. (newline)
  160. (display `("width:" ,(+ (- x2 x1) 1) " height:" ,(+ (- y1 y2) 1))))))
  161. ;;; Mouse stuff
  162. (define standard-mouse-shape 34)
  163. (define requesting-input-mouse-shape 11)
  164. ;;; Needs to be generalized for OS/2
  165. (define (get-pointer-coordinates window cont)
  166. ;;; cont = (lambda (x y button) ...)
  167. (x-graphics/discard-events window)
  168. (graphics-operation window 'set-mouse-shape requesting-input-mouse-shape)
  169. ((x-graphics/read-button window)
  170. (lambda (x y button)
  171. (graphics-operation window 'set-mouse-shape standard-mouse-shape)
  172. (cont x y button))))
  173. ;;; For gnuplot output
  174. (define *gnuplotting* #f)
  175. (define (start-gnuplot filename)
  176. (if *gnuplotting*
  177. (begin (close-port *gnuplotting*)
  178. (set! *gnuplotting* #f)))
  179. (set! *gnuplotting*
  180. (open-output-file filename))
  181. 'ok)
  182. (define (stop-gnuplot)
  183. (if *gnuplotting*
  184. (begin (close-port *gnuplotting*)
  185. (set! *gnuplotting* #f)))
  186. 'ok)
  187. ;;; For JW
  188. (define frame make-display-frame)
  189. (define plot-frame make-display-frame)
  190. (define (plot-point window x y)
  191. (if *gnuplotting*
  192. (begin (newline *gnuplotting*)
  193. (write x *gnuplotting*)
  194. (display " " *gnuplotting*)
  195. (write y *gnuplotting*)))
  196. (plot-point-internal window x y))
  197. (define (plot-point-internal window x y)
  198. (graphics-draw-point window
  199. (exact->inexact x)
  200. (exact->inexact y)))
  201. (define (plot-line window x0 y0 x1 y1)
  202. (if *gnuplotting*
  203. (begin (newline *gnuplotting*)
  204. (write x0 *gnuplotting*)
  205. (display " " *gnuplotting*)
  206. (write y0 *gnuplotting*)
  207. (write-line x1 *gnuplotting*)
  208. (display " " *gnuplotting*)
  209. (write y1 *gnuplotting*)
  210. (newline *gnuplotting*)))
  211. (plot-line-internal window x0 y0 x1 y1))
  212. (define* (plot-circle win x y radius #:optional eps)
  213. (if (default-object? eps) (set! eps 0.01))
  214. (plot-parametric-fill
  215. win
  216. (lambda (c) (cons (+ x (* radius (cos c)))
  217. (+ y (* radius (sin c)))))
  218. 0. 2pi
  219. (plane-near? eps)))
  220. (define (plot-line-internal window x0 y0 x1 y1)
  221. (graphics-draw-line window
  222. (exact->inexact x0)
  223. (exact->inexact y0)
  224. (exact->inexact x1)
  225. (exact->inexact y1)))
  226. (define (plot-function window f x0 x1 dx)
  227. (if *gnuplotting* (newline *gnuplotting*))
  228. (let loop ((x x0) (fx (f x0)))
  229. (if *gnuplotting*
  230. (begin (newline *gnuplotting*)
  231. (write x *gnuplotting*)
  232. (display " " *gnuplotting*)
  233. (write fx *gnuplotting*)))
  234. (let ((nx (+ x dx)))
  235. (let ((nfx (f nx)))
  236. (plot-line-internal window x fx nx nfx)
  237. (if (< (* (- nx x0) (- nx x1)) 0.)
  238. (loop nx nfx))))))
  239. (define (plot-inverse window f y0 y1 dy)
  240. (if *gnuplotting* (newline *gnuplotting*))
  241. (let loop ((y y0) (fy (f y0)))
  242. (if *gnuplotting*
  243. (begin (newline *gnuplotting*)
  244. (write fy *gnuplotting*)
  245. (display " " *gnuplotting*)
  246. (write y *gnuplotting*)))
  247. (let ((ny (+ y dy)))
  248. (let ((nfy (f ny)))
  249. (plot-line-internal window fy y nfy ny)
  250. (if (< (* (- ny y0) (- ny y1)) 0.)
  251. (loop ny nfy))))))
  252. (define (plot-parametric win f a b dx)
  253. (if *gnuplotting* (newline *gnuplotting*))
  254. (let loop ((x a))
  255. (let ((fx (f x)))
  256. (plot-point win (car fx) (cdr fx))
  257. (if (< x b) (loop (+ x dx))))))
  258. #|
  259. (define (plot-parametric-fill win f a b near?)
  260. (if *gnuplotting* (newline *gnuplotting*))
  261. (let loop ((a a) (xa (f a)) (b b) (xb (f b)))
  262. (let ((m (/ (+ a b) 2)))
  263. (let ((xm (f m)))
  264. (plot-point win (car xm) (cdr xm))
  265. (if (not (and (near? xa xm) (near? xb xm)))
  266. (begin (loop a xa m xm)
  267. (loop m xm b xb)))))))
  268. |#
  269. (define (plot-parametric-fill win f a b near?)
  270. (if *gnuplotting* (newline *gnuplotting*))
  271. (let loop ((a a) (xa (f a)) (b b) (xb (f b)))
  272. (if (not (close-enuf? a b
  273. (* *allowable-roundoffs*
  274. *machine-epsilon*)))
  275. (let ((m (/ (+ a b) 2)))
  276. (let ((xm (f m)))
  277. (plot-point win (car xm) (cdr xm))
  278. (if (not (near? xa xm))
  279. (loop a xa m xm))
  280. (if (not (near? xb xm))
  281. (loop m xm b xb)))))))
  282. ;;; Chap 4
  283. (define make-point cons)
  284. (define abscissa car)
  285. (define ordinate cdr)
  286. (define *allowable-roundoffs* 10)
  287. (define (plot-fun win f a b eps)
  288. (if *gnuplotting* (newline *gnuplotting*))
  289. (plot-parametric-fill
  290. win
  291. (lambda (x) (cons x (f x)))
  292. a b
  293. (plane-near? eps)))
  294. (define (plane-near? eps)
  295. (let ((eps^2 (square eps)))
  296. (lambda (x y)
  297. (< (+ (square (- (car x) (car y)))
  298. (square (- (cdr x) (cdr y))))
  299. eps^2))))
  300. (define (cylinder-near? eps)
  301. (let ((eps^2 (square eps)))
  302. (lambda (x y)
  303. (< (+ (square ((principal-value pi)
  304. (- (car x) (car y))))
  305. (square (- (cdr x) (cdr y))))
  306. eps^2))))
  307. (define (torus-near? eps)
  308. (let ((eps^2 (square eps)))
  309. (lambda (x y)
  310. (< (+ (square ((principal-value pi)
  311. (- (car x) (car y))))
  312. (square ((principal-value pi)
  313. (- (cdr x) (cdr y)))))
  314. eps^2))))
  315. #|
  316. ;;; for example
  317. (define foo (frame -1 1 -1 1))
  318. (show-window-size foo)
  319. (width: 400 height: 400)
  320. (define pi (* 4 (atan 1 1)))
  321. (plot-function foo (lambda (x) (sin (* pi x))) -1 1 .01)
  322. (plot-line foo -.9 0 .9 0)
  323. (plot-line foo 0 -.9 0 .9)
  324. ;;; I pressed left mouse button.
  325. (get-pointer-coordinates foo list)
  326. ;Value 24: (.16791979949874686 .5037593984962406 0)
  327. (graphics-close foo)
  328. (start-gnuplot "plot2")
  329. ;;; Do above stuff
  330. (stop-gnuplot)
  331. |#
  332. ;;; For gjs
  333. (define plotting-window #f)
  334. (define (plot-xy window xs ys)
  335. (if *gnuplotting* (newline *gnuplotting*))
  336. (cond ((or (eq? window 'new) (eq? window #t))
  337. (set! plotting-window
  338. (make-display-frame 0.0 1.0 0.0 1.0)))
  339. ((or (eq? window 'old) (eq? window 'clear) (eq? window #f))
  340. 'done)
  341. ((eq? window plotting-window)
  342. 'done)
  343. (else
  344. (if (graphics-device? plotting-window)
  345. (graphics-close plotting-window))
  346. (set! plotting-window window)))
  347. (if (not (graphics-device? plotting-window))
  348. (error "Plotting window is not initialized"))
  349. (if (eq? window 'clear)
  350. (graphics-clear plotting-window))
  351. (if (vector? xs) (set! xs (vector->list xs)))
  352. (if (vector? ys) (set! ys (vector->list ys)))
  353. (let ((minx (apply min xs))
  354. (maxx (apply max xs))
  355. (miny (apply min ys))
  356. (maxy (apply max ys)))
  357. (let ((dx (- maxx minx))
  358. (dy (- maxy miny)))
  359. (if (zero? dx)
  360. "Range of x is zero."
  361. (if (zero? dy)
  362. "Range of y is zero."
  363. (map (lambda (x y)
  364. (plot-point plotting-window
  365. (/ (- x minx) dx)
  366. (/ (- y miny) dy)))
  367. xs
  368. ys))))
  369. (list minx maxx miny maxy)))
  370. #|
  371. (define xs (iota 700 0.0 0.01))
  372. (length xs)
  373. ;Value: 700
  374. (define ys (map sin xs))
  375. (plot-xy 'new xs ys)
  376. |#
  377. (define (plot-f window f)
  378. (if *gnuplotting* (newline *gnuplotting*))
  379. (cond ((or (eq? window 'new) (eq? window #t))
  380. (set! plotting-window
  381. (make-display-frame 0.0 1.0 0.0 1.0)))
  382. ((or (eq? window 'old) (eq? window 'clear) (eq? window #f))
  383. 'done)
  384. ((eq? window plotting-window)
  385. 'done)
  386. (else
  387. (if (graphics-device? plotting-window)
  388. (graphics-close plotting-window))
  389. (set! plotting-window window)))
  390. (if (not (graphics-device? plotting-window))
  391. (error "Plotting window is not initialized"))
  392. (if (eq? window 'clear)
  393. (graphics-clear plotting-window))
  394. (call-with-values
  395. (lambda ()
  396. (graphics-device-coordinate-limits plotting-window))
  397. (lambda (left bottom right top)
  398. (let ((numx (- right left)))
  399. (call-with-values
  400. (lambda ()
  401. (graphics-coordinate-limits plotting-window))
  402. (lambda (x0 y0 x1 y1)
  403. (plot-function plotting-window
  404. f
  405. x0
  406. x1
  407. (/ (- x1 x0) numx))))))))
  408. #|
  409. (plot-f (frame 0 7 -1 1) cos)
  410. |#
  411. (define gnuplot
  412. (let ((count 0))
  413. (lambda* (fs x0 x1 dx #:optional style save-data?)
  414. (let* ((fs (if (list? fs) fs (list fs)))
  415. (style (if (default-object? style) "" style))
  416. (dirname (->namestring (user-homedir-pathname)))
  417. (file-name (string-append dirname
  418. "temp-display"
  419. (number->string count)))
  420. (clean (if (default-object? save-data?)
  421. (string-append " ; /bin/rm " file-name ".*")
  422. ""))
  423. (data-file-name (string-append "\"" file-name ".data" "\""))
  424. (gnuplot-invoke-string
  425. (string-append "gnuplot -persist " file-name ".gnuplot"))
  426. (gnuplot-control-string
  427. (let flp ((fcol 1)
  428. (ss (string-append data-file-name
  429. " using 1:2"
  430. " " style " ")))
  431. (if (= fcol (length fs))
  432. (string-append "plot" ss)
  433. (flp (+ fcol 1)
  434. (string-append ss ", "
  435. data-file-name
  436. " using 1:" (number->string (+ fcol 2))
  437. " " style " "))))))
  438. (with-output-to-file (string-append file-name ".data")
  439. (lambda ()
  440. (let loop ((x x0))
  441. (begin
  442. (newline)
  443. (write x)
  444. (for-each (lambda (f)
  445. (display " ")
  446. (write (f x)))
  447. fs))
  448. (let ((nx (+ x dx)))
  449. (if (< (* (- nx x0) (- nx x1)) 0.)
  450. (loop nx))))))
  451. (with-output-to-file (string-append file-name ".gnuplot")
  452. (lambda () (display gnuplot-control-string)))
  453. (run-shell-command
  454. (string-append "cd " dirname ";"
  455. gnuplot-invoke-string
  456. " > /dev/null 2>&1"
  457. clean)
  458. 'output #f
  459. 'shell-file-name "/bin/sh")
  460. (set! count (+ count 1))
  461. (if (default-object? save-data?)
  462. "done"
  463. `(data-file-name-is ,data-file-name))
  464. ))))
  465. #|
  466. ;;; Gnuplot can be used to plot any number of functions, with optional style.
  467. ;;; May add further argument to save data files.
  468. (gnuplot sin 0 10 .01)
  469. #| "done" |#
  470. (gnuplot (list sin cos) 0 10 .01)
  471. #| "done" |#
  472. (gnuplot (list sin cos sqrt) 0 10 .01 "with dots")
  473. #| "done" |#
  474. (gnuplot (list sin cos) 0 10 .01 "" #t)
  475. (data-file-name-is "\"/home/gjs/temp-display3.data\"")
  476. |#