[racket] plot pixel position

From: David Vanderson (david.vanderson at gmail.com)
Date: Tue Apr 15 14:59:48 EDT 2014

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?


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))
          ((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))))
(define canvas
  (new my-canvas
       (parent frame)
       (paint-callback draw-screen)))

(send frame show #t)

Posted on the users mailing list.