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))
|