File: snip3d.rkt

package info (click to toggle)
racket 7.2%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 125,432 kB
  • sloc: ansic: 258,980; pascal: 59,975; sh: 33,650; asm: 13,558; lisp: 7,124; makefile: 3,329; cpp: 2,889; exp: 499; python: 274; xml: 11
file content (142 lines) | stat: -rw-r--r-- 5,006 bytes parent folder | download | duplicates (3)
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
#lang racket/base

(require racket/gui/base racket/class racket/match
         plot/private/common/math
         plot/private/common/parameters
         "worker-thread.rkt"
         "snip.rkt")

(provide 3d-plot-snip% make-3d-plot-snip)

(define show-rotate-message? #t)

(struct draw-command (animating? angle altitude width height) #:transparent)

(define (clamp x mn mx) (min* (max* x mn) mx))

(define 3d-plot-snip%
  (class plot-snip%
    (init init-bm saved-plot-parameters)
    (init-field make-bm angle altitude width height)
    
    (inherit set-bitmap get-bitmap
             get-saved-plot-parameters
             set-message stop-message set-message-center reset-message-timeout
             update-thread-running? set-update
             get-left-down-here?)
    
    (super-make-object init-bm saved-plot-parameters)
    
    (define/override (copy)
      (make-object this%
        (get-bitmap) (get-saved-plot-parameters)
        make-bm angle altitude width height))
    
    (define mouse-x 0)
    (define mouse-y 0)
    (define left-click-x 0)
    (define left-click-y 0)
    
    (define last-angle angle)
    (define last-altitude altitude)
    
    (define (set-angle!)
      (define degrees-per-pixel (/ 180 (send (get-bitmap) get-width)))
      (define dx (- mouse-x left-click-x))
      (set! angle (real-modulo (+ last-angle (* dx degrees-per-pixel)) 360)))
    
    (define (set-altitude!)
      (define degrees-per-pixel (/ 180 (send (get-bitmap) get-height)))
      (define dy (- mouse-y left-click-y))
      (set! altitude (clamp (+ last-altitude (* dy degrees-per-pixel)) 0 90)))
    
    (define (start-update-thread animating?)
      (send this start-update-thread
            (λ () (make-worker-thread
                   (match-lambda
                     [(draw-command animating? angle altitude width height)
                      (make-bm animating? angle altitude width height)])))
            (λ (animating?) (draw-command animating? angle altitude width height))
            (λ (rth)
              (define new-bm (worker-thread-try-get rth))
              (cond [(is-a? new-bm bitmap%)
                     (set-bitmap new-bm)
                     (when (not (and (= last-angle angle)
                                     (= last-altitude altitude)))
                       (set-angles-message))
                     #t]
                    [else  #f]))
            animating?))
    
    (define (set-angles-message)
      (set-message (format "angle = ~a\naltitude = ~a"
                           (number->string (inexact->exact (round angle)))
                           (number->string (inexact->exact (round altitude))))
                   #:refresh? #f))
    
    (define (set-click-message)
      (when show-rotate-message?
        (set-message "Click and drag to rotate")))
    
    (define (on-left-down)
      (set! left-click-x mouse-x)
      (set! left-click-y mouse-y)
      (set! last-angle angle)
      (set! last-altitude altitude)
      (set-angles-message)
      (start-update-thread #t)
      (set-update #t))
    
    (define (on-left-up)
      (when (get-left-down-here?)
        (set! last-angle angle)
        (set! last-altitude altitude)
        (when (update-thread-running?)
          (start-update-thread #f)
          (set-update #t))))
    
    (define (on-motion evt last-mouse-x last-mouse-y)
      (cond [(get-left-down-here?)
             (when (not (and (= last-mouse-x mouse-x)
                             (= last-mouse-y mouse-y)))
               (set! show-rotate-message? #f)
               (set-angle!)
               (set-altitude!)
               (unless (update-thread-running?)
                 (start-update-thread #t))
               (set-update #t))]
            [(and (not (send evt get-left-down))
                  (<= 0 mouse-x (send (get-bitmap) get-width))
                  (<= 0 mouse-y (send (get-bitmap) get-height)))
             (set-click-message)]))
    
    (define/override (on-event dc x y editorx editory evt)
      (define evt-type (send evt get-event-type))
      (define last-mouse-x mouse-x)
      (define last-mouse-y mouse-y)
      (set! mouse-x (- (send evt get-x) x))
      (set! mouse-y (- (send evt get-y) y))
      (case evt-type
        [(left-down)  (on-left-down)]
        [(left-up)    (on-left-up)]
        [(motion)     (on-motion evt last-mouse-x last-mouse-y)])
      (super on-event dc x y editorx editory evt))
    
    (define/override (resize w h)
      (when (not (and (= w width) (= h height)))
        (set! width w)
        (set! height h)
        (set-message-center (* 1/2 w) (* 1/2 h))
        (stop-message)
        (when (not (update-thread-running?))
          (start-update-thread #t))
        (set-update #t))
      (super resize w h))
    ))

(define (make-3d-plot-snip
         init-bm saved-plot-parameters
         make-bm angle altitude width height)
  (make-object 3d-plot-snip%
    init-bm saved-plot-parameters
    make-bm angle altitude width height))