[racket] plot pixel position
Sorry for the delay. I hacked together something that lets you drag
points around on a plot (attached).
Is there a way to access area's plot->dc? For this example I wanted to
ask if the mouse was within 2 pixels of any point.
When dragging the point around on the plot, it looks like I'm seeing
multiple repaints queueing up. It's especially bad on Linux where I can
move the mouse a bunch and then watch all the repaints happen over the
next few seconds. I'm trying to figure out if this can be improved.
Question for GUI experts: Is there a reason why multiple repaint
requests in the queue should not be coalesced into a single paint?
Thanks,
Dave
On 04/01/2014 05:41 PM, Neil Toronto wrote:
> On 04/01/2014 02:17 PM, David Vanderson wrote:
>> Plot is fantastic - thanks so much!
>>
>> Is there a way to hook into the interactive features of plot so, for
>> instance, the user could click to add data or drag data points around?
>>
>> I'm using plot/dc to draw onto a canvas, and I'd be more than happy just
>> to be able to ask a plot to translate a pixel position to the
>> corresponding axes' positions. I know that plot does this for the
>> zooming feature, but is there a way for external code to do it?
>
> There's not an easy way right now.
>
> If you don't mind copying code, you can take some from `plot/dc' here:
>
> pkgs/plot-pkgs/plot-lib/plot/private/no-gui/plot2d.rkt
>
> The main thing you need is access to the `area' object, which has a
> public `dc->plot' method that translates device context coordinates
> into plot coordinates. I'm sorry it's not easier. :/
>
> It will be someday, I promise! I've lately decided that "2D and 3D
> games that use Plot to render scenes" will be two of my main test
> cases. Games are the most interactive uses I can think of, and they
> need to be fast, so that should cover pretty much everyone's
> interactivity needs.
>
> Neil ⊥
>
>
-------------- next part --------------
#lang racket/gui
(require plot
(lib "plot/private/no-gui/plot2d-utils.rkt")
(lib "plot/private/plot2d/plot-area.rkt"))
(define data
(vector (list 1 1)
(list 3 4)))
(define *area* #f)
(define (draw-screen canvas dc)
(define renderer-tree
(points data))
(define x 0)
(define y 0)
(define width 400)
(define height 400)
(define x-min 0)
(define x-max 10)
(define y-min 0)
(define y-max 10)
; this shamefully ripped out of the plot code for plot/dc
; so we can access the area object
(define renderer-list (get-renderer-list renderer-tree))
(define bounds-rect (get-bounds-rect renderer-list x-min x-max y-min y-max))
(define-values (x-ticks x-far-ticks y-ticks y-far-ticks)
(get-ticks renderer-list bounds-rect))
(define area (make-object 2d-plot-area%
bounds-rect x-ticks x-far-ticks y-ticks y-far-ticks dc x y width height))
(plot-area area renderer-list)
(set! *area* area))
(define frame
(new frame%
(label "Interactive Plot")
(width 400)
(height 400)))
(define drag-point #f)
(define dragx #f)
(define dragy #f)
(define my-canvas
(class canvas%
(define/override (on-event event)
(define x (send event get-x))
(define y (send event get-y))
(cond
((send event button-down? 'left)
(set! drag-point #f) ; just in case we missed the button-up?
(define cur (send *area* dc->plot (vector x y)))
(for (((d i) (in-indexed data)))
(when (and
((abs (- (first d) (vector-ref cur 0))) . < . 0.1)
((abs (- (second d) (vector-ref cur 1))) . < . 0.1))
(set! drag-point i)))
(set! dragx x)
(set! dragy y))
((send event dragging?)
(when (and *area* drag-point)
(define prev (send *area* dc->plot (vector dragx dragy)))
(define cur (send *area* dc->plot (vector x y)))
(define dx (- (vector-ref cur 0) (vector-ref prev 0)))
(define dy (- (vector-ref cur 1) (vector-ref prev 1)))
;(printf "change ~v\n" (list dx dy))
(vector-set! data drag-point
(list (+ (first (vector-ref data drag-point)) dx)
(+ (second (vector-ref data drag-point)) dy)))
(send this refresh))
(set! dragx x)
(set! dragy y))))
(super-new)))
(define canvas
(new my-canvas
(parent frame)
(paint-callback draw-screen)))
(send frame show #t)