Skip to content

Commit 8e0e382

Browse files
authored
Document the plot-metrics interface (#103)
Pull request #90 implements the plot-metrics interface, a mechanism that allows the user to determine the location of elements on the plot image itself, so plots can be further decorated, it is based on a request in issue #83. While this functionality has been available for a while now, it was not documented. This PR adds documentation to this interface, so users can discover the functionality and use it.
1 parent 9df19f3 commit 8e0e382

File tree

6 files changed

+165
-26
lines changed

6 files changed

+165
-26
lines changed

plot-doc/plot/scribblings/plotting.scrbl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Each 3D plotting procedure behaves the same way as its corresponding 2D procedur
3232
[#:legend-anchor legend-anchor legend-anchor/c (plot-legend-anchor)]
3333
[#:out-file out-file (or/c path-string? output-port? #f) #f]
3434
[#:out-kind out-kind plot-file-format/c 'auto]
35-
) (or/c (is-a?/c snip%) void?)]{
35+
) (or/c (and/c (is-a?/c snip%) (is-a?/c plot-metrics<%>)) void?)]{
3636
Plots a 2D renderer or list of renderers (or more generally, a tree of renderers), as returned by @(racket points), @(racket function), @(racket contours), @(racket discrete-histogram), and others.
3737

3838
By default, @(racket plot) produces a Racket value that is displayed as an image and can be manipulated like any other value.
@@ -85,7 +85,7 @@ The @(racket #:lncolor) keyword argument is also accepted for backward compatibi
8585
[#:legend-anchor legend-anchor legend-anchor/c (plot-legend-anchor)]
8686
[#:out-file out-file (or/c path-string? output-port? #f) #f]
8787
[#:out-kind out-kind plot-file-format/c 'auto]
88-
) (or/c (is-a?/c snip%) void?)]{
88+
) (or/c (and/c (is-a?/c snip%) (is-a/c plot-metrics<%>)) void?)]{
8989
Plots a 3D renderer or list of renderers (or more generally, a tree of renderers), as returned by @(racket points3d), @(racket parametric3d), @(racket surface3d), @(racket isosurface3d), and others.
9090

9191
When the parameter @(racket plot-new-window?) is @(racket #t), @(racket plot3d) opens a new window to display the plot and returns @(racket (void)).
@@ -108,9 +108,9 @@ The @(racket #:az) and @(racket #:alt) keyword arguments are backward-compatible
108108
}
109109

110110
@defproc[(plot-snip [<plot-argument> <plot-argument-contract>] ...)
111-
(is-a?/c 2d-plot-snip%)]
111+
(and/c (is-a?/c 2d-plot-snip%) (is-a?/c plot-metrics<%>))]
112112
@defproc[(plot3d-snip [<plot-argument> <plot-argument-contract>] ...)
113-
(is-a?/c snip%)]
113+
(and/c (is-a?/c snip%) (is-a?/c plot-metrics<%>))]
114114
@defproc[(plot-frame [<plot-argument> <plot-argument-contract>] ...)
115115
(is-a?/c frame%)]
116116
@defproc[(plot3d-frame [<plot-argument> <plot-argument-contract>] ...)
@@ -142,13 +142,13 @@ for more details.
142142
[#:<plot3d-keyword> <plot3d-keyword> <plot3d-keyword-contract>] ...)
143143
void?]
144144
@defproc[(plot-pict [<plot-argument> <plot-argument-contract>] ...)
145-
pict?]
145+
plot-pict?]
146146
@defproc[(plot3d-pict [<plot3d-argument> <plot3d-argument-contract>] ...)
147-
pict?]
147+
plot-pict?]
148148
@defproc[(plot-bitmap [<plot-argument> <plot-argument-contract>] ...)
149-
(is-a?/c bitmap%)]
149+
(and/c (is-a?/c bitmap%) (is-a?/c plot-metrics<%>))]
150150
@defproc[(plot3d-bitmap [<plot3d-argument> <plot3d-argument-contract>] ...)
151-
(is-a?/c bitmap%)]{
151+
(and/c (is-a?/c bitmap%) (is-a?/c plot-metrics<%>))]{
152152
Plot to different non-GUI backends.
153153
These procedures accept the same arguments as @(racket plot) and @(racket plot3d), except deprecated keywords, and @racket[#:out-file] and @racket[#:out-kind].
154154

@@ -182,15 +182,15 @@ Use @(racket plot-bitmap) or @(racket plot3d-bitmap) to create a @(racket bitmap
182182
[width (>=/c 0)]
183183
[height (>=/c 0)]
184184
[#:<plot-keyword> <plot-keyword> <plot-keyword-contract>] ...)
185-
void?]
185+
(is-a?/c plot-metrics<%>)]
186186
@defproc[(plot3d/dc [renderer-tree (treeof (or/c renderer3d? nonrenderer?))]
187187
[dc (is-a?/c dc<%>)]
188188
[x real?]
189189
[y real?]
190190
[width (>=/c 0)]
191191
[height (>=/c 0)]
192192
[#:<plot3d-keyword> <plot3d-keyword> <plot3d-keyword-contract>] ...)
193-
void?]{
193+
(is-a?/c plot-metrics<%>)]{
194194
Plot to an arbitrary device context, in the rectangle with width @(racket width), height @(racket height), and upper-left corner @(racket x),@(racket y).
195195
These procedures accept the same arguments as @(racket plot) and @(racket plot3d), except deprecated keywords, and @racket[#:out-file] and @racket[#:out-kind].
196196

plot-doc/plot/scribblings/utils.scrbl

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,136 @@ Convert @racket[plot-time]s to real seconds, and vice-versa.
582582
(plot-time+ (plot-time 32 0 12 1)
583583
(plot-time 32 0 14 1))]
584584
}
585+
586+
@section{Plot Metrics}
587+
588+
@definterface[plot-metrics<%> ()]{
589+
590+
The @racket[plot-metrics<%>] interface allows obtaining plot area positions
591+
on the plots returned by @racket[plot], @racket[plot-snip],
592+
@racket[plot-bitmap], @racket[plot/dc], as well as their 3D variants,
593+
@racket[plot3d], @racket[plot3d-snip], @racket[plot3d-bitmap] and
594+
@racket[plot3d/dc]. All plot objects returned by these functions implement
595+
this interface.
596+
597+
For plots created by @racket[plot-pict] and @racket[plot3d-pict], there is a
598+
separate set of functions that provide the same functionality, for example,
599+
see @racket[plot-pict-bounds].
600+
601+
@defmethod[(get-plot-bounds) (vectorof (vector/c real? real?))]{
602+
603+
Return the bounds of the plot as a vector of minimum and maximum values,
604+
one for each axis in the plot. For 2D plots, this method returns a vector
605+
of two elements, for the X and Y axes, while 3D plots return a vector of
606+
three elements for the X, Y and Z axes.
607+
608+
The values returned are in plot coordinates, to obtain the coordinates on
609+
the drawing surface (i.e. image coordinates), use @method[plot-metrics<%>
610+
plot->dc] on these bounds.
611+
612+
Plot bounds for interactive plots, like those produced by @racket[plot]
613+
and @racket[plot-snip], can change as the user zoom in and out the plot,
614+
@method[plot-metrics<%> get-plot-bounds] always returns the current bounds
615+
of the plot, but they might be invalidated by a user operation.
616+
617+
}
618+
619+
@defmethod[(plot->dc [coordinates (vectorof real?)]) (vectorof real?)]{
620+
621+
Convert @racket[coordinates] from plot coordinate system to the drawing
622+
coordinate system (that is, image coordinates). For 2D plots,
623+
@racket[coordinates] is a vector of two values, the X and Y coordinates on
624+
the plot, while for 3D plots it is a vector of three values, the X, Y and
625+
Z coordinates.
626+
627+
This method can be used, for example, to determine the actual location on
628+
the image where the coordinates @racket[0], @racket[0] are. It can also
629+
be used to determine the location of the plot area inside the image, by
630+
calling it on the plot bounds returned by @method[plot-metrics<%> get-plot-bounds].
631+
632+
For interactive plots, the coordinates might change as the user zooms in
633+
and out the plot.
634+
635+
}
636+
637+
@defmethod[(dc->plot [coordinates (vectorof real?)]) (vectorof real?)]{
638+
639+
For 2D plots, this method returns the 2D plot coordinates that correspond
640+
to the input @racket[coordinates], which are in the draw context
641+
coordinate system.
642+
643+
For 3D plots, this method returns a 3D position on the plane perpendicular
644+
to the user view for the plot. Together with the normal vector for this
645+
plane, returned by @method[plot-metrics<%> plane-vector], the projection
646+
line can be reconstructed.
647+
648+
This is the reverse operation from @method[plot-metrics<%> plot->dc] and
649+
same remark about the user zooming in and out the plot applies.
650+
651+
}
652+
653+
@defmethod[(plane-vector) (vectorof real?)]{
654+
655+
Return the unit vector representing the normal of the screen through the
656+
plot origin. For 2D plots this always returns @racket[#(0 0 1)], for 3D
657+
plots this unit vector can be used to reconstruct plot coordinates from
658+
draw context coordinates.
659+
660+
For interactive 3D plots, the returned value will change if the user
661+
rotates the plot.
662+
663+
}
664+
665+
@history[#:added "8.1"]
666+
}
667+
668+
@defproc[(plot-pict? [any any/c]) boolean?]{
669+
670+
Return @racket[#t] if @racket[any] is a plot returned by @racket[plot-pict].
671+
This can be used to determine if the functions @racket[plot-pict-bounds],
672+
@racket[plot-pict-plot->dc], @racket[plot-pict-dc->plot] and
673+
@racket[plot-pict-plane-vector] can be called on it.
674+
675+
@history[#:added "8.1"]
676+
677+
}
678+
679+
@defproc[(plot-pict-bounds [plot plot-pict?]) (vectorof (vector/c real? real?))]{
680+
681+
Return the bounds of the plot returned by @racket[plot-pict]. See
682+
@method[plot-metrics<%> get-plot-bounds] for more details.
683+
684+
@history[#:added "8.1"]
685+
686+
}
687+
688+
@defproc[(plot-pict-plot->dc [plot plot-pict?] [coordinates (vectorof real?)])
689+
(vectorof real?)]{
690+
691+
Convert the plot @racket[coordinates] to draw context coordinates for the
692+
@racket[plot]. See @method[plot-metrics<%> plot->dc] for more details.
693+
694+
@history[#:added "8.1"]
695+
696+
}
697+
698+
@defproc[(plot-pict-dc->plot [plot plot-pict?] [coordinates (vectorof real?)])
699+
(vectorof real?)]{
700+
701+
Convert the draw contect @racket[coordinates] to plot coordinates for the
702+
@racket[plot]. See @method[plot-metrics<%> dc->plot] for more details.
703+
704+
@history[#:added "8.1"]
705+
706+
}
707+
708+
@defproc[(plot-pict-plane-vector [plot plot-pict?]) (vectorof real?)]{
709+
710+
Return the unit vector representing the normal of the screen through the
711+
plot origin. For 2D plots this always returns @racket[#(0 0 1)], for 3D
712+
plots this can be used to reconstruct plot coordinates from draw context
713+
coordinates. See @method[plot-metrics<%> plane-vector] for more details.
714+
715+
@history[#:added "8.1"]
716+
717+
}

plot-lib/plot/private/common/plotmetrics.rkt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,26 @@
33
;; Untyped interface / contract
44
(module untyped racket/base
55
(require racket/class
6-
racket/contract
7-
racket/match
8-
racket/draw)
6+
racket/contract)
97

108
(provide plot-metrics<%>
11-
plot-metrics-object/c)
9+
plot-metrics-object/c
10+
interface?)
1211

13-
(define plot-metrics<%> (interface ()
14-
get-plot-bounds
15-
dc->plot
16-
plot->dc
17-
plane-vector
18-
get-plot-metrics-functions))
12+
(define plot-metrics<%>
13+
(interface ()
14+
get-plot-bounds
15+
dc->plot
16+
plot->dc
17+
plane-vector
18+
get-plot-metrics-functions))
1919

2020
(define plot-metrics-object/c
2121
(object/c [get-plot-bounds (->m (vectorof (vector/c real? real?)))]
2222
[plot->dc (->m (vectorof real?) (vectorof real?))]
2323
[dc->plot (->m (vectorof real?) (vectorof real?))]
2424
[plane-vector (->m (vectorof real?))]
25-
[get-plot-metrics-functions (->m (values (-> (vectorof (vector/c real? real?)))
25+
[get-plot-metrics-functions (->m (list/c (-> (vectorof (vector/c real? real?)))
2626
(-> (vectorof real?) (vectorof real?))
2727
(-> (vectorof real?) (vectorof real?))
2828
(-> (vectorof real?))))]))
@@ -81,7 +81,6 @@
8181

8282
(define plot-metrics% (plot-metrics-mixin object%))
8383

84-
8584
(struct plot-pict pict ([bounds : (Vectorof (Vectorof Real))]
8685
[plot->dc : (-> (Vectorof Real) (Vectorof Real))]
8786
[dc->plot : (-> (Vectorof Real) (Vectorof Real))]
@@ -94,4 +93,4 @@
9493

9594
(plot-pict (pict-draw P) (pict-width P) (pict-height P) (pict-ascent P)
9695
(pict-descent P) (pict-children P) (pict-panbox P) (pict-last P)
97-
(bounds) ->dc ->plot (plane)))
96+
(bounds) ->dc ->plot (plane)))

plot-lib/plot/private/utils-and-no-gui.rkt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
Legend-Anchor)
2222

2323
(require "common/plotmetrics.rkt")
24+
(require (only-in (submod "common/plotmetrics.rkt" untyped) plot-metrics<%>))
2425

2526
(provide
2627
Plot-Metrics<%>
28+
plot-metrics<%>
2729
plot-pict?
2830
Plot-Pict
2931
plot-pict-bounds

plot-lib/plot/utils.rkt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
(require "private/utils-and-no-gui.rkt")
44
(provide (all-from-out "private/utils-and-no-gui.rkt"))
5+
(provide plot-metrics<%>)
56

67
(require "private/common/contract.rkt"
78
"private/common/leftover-contracts.rkt"

plot-test/plot/tests/PRs/90.rkt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
#lang racket
2-
(require rackunit
3-
racket/draw pict (only-in racket/gui/base sleep/yield)
4-
plot (submod plot/private/common/plotmetrics untyped))
2+
(require pict
3+
plot
4+
racket/draw
5+
(only-in racket/gui/base
6+
sleep/yield)
7+
rackunit)
8+
59

610
; tests for PR#90, https://github.com/racket/plot/pull/90
711
; "Plotmetrics: access/calculate data about the plot area"

0 commit comments

Comments
 (0)