Skip to content

Commit c457141

Browse files
authored
Add support for specifying the aspect ratio of the plot area (#88)
A new `#:aspect-ratio` keyword argument was added to all the plot functions, allowing the user some more control over the plot area.
1 parent 9189c8f commit c457141

35 files changed

+311
-45
lines changed

plot-compat/plot/private/compat.rkt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
(define bm (make-bitmap (ceiling width) (ceiling height)))
166166
(define dc (make-object bitmap-dc% bm))
167167
(define area (make-object 2d-plot-area%
168-
bounds-rect x-ticks x-ticks y-ticks y-ticks '() dc 0 0 width height))
168+
bounds-rect x-ticks x-ticks y-ticks y-ticks '() dc 0 0 width height #f))
169169

170170
(define data+axes (mix x-axis-data y-axis-data data))
171171

@@ -214,7 +214,7 @@
214214
(define bm (make-bitmap (ceiling width) (ceiling height)))
215215
(define dc (make-object bitmap-dc% bm))
216216
(define area (make-object 3d-plot-area%
217-
bounds-rect x-ticks x-ticks y-ticks y-ticks z-ticks z-ticks '() dc 0 0 width height))
217+
bounds-rect x-ticks x-ticks y-ticks y-ticks z-ticks z-ticks '() dc 0 0 width height #f))
218218

219219
(send area start-plot)
220220
(send area start-renderer bounds-rect)

plot-doc/plot/scribblings/params.scrbl

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,29 @@ If @(racket #t), @(racket plot-file) and @(racket plot3d-file) open a dialog whe
3939

4040
@section{General Appearance}
4141

42+
@defparam[plot-aspect-ratio ratio (or/c (and/c rational? positive?) #f) #:value #f]{
43+
44+
Controls the aspect ratio of the plot area, independently from the width and
45+
height of the entire plot.
46+
47+
When the aspect ratio is @(racket #f), the plot area fill fill the entire
48+
area of the plot, leaving room only for the axis labels and title.
49+
50+
When an aspect ratio is a positive number, the plot area will maintain this
51+
aspect ratio, possibly leaving empty areas around the plot.
52+
53+
This feature is useful when the aspect ratio needs to be maintained for the
54+
plot output to look correct, for example when plotting a circle:
55+
56+
@interaction[#:eval plot-eval
57+
(parameterize ([plot-aspect-ratio 1/1]
58+
[plot-background "lightyellow"])
59+
(plot (polar (lambda (t) 1)) #:width 400 #:height 200))]
60+
61+
@history[#:added "8.1"]
62+
63+
}
64+
4265
@deftogether[((defparam plot-title title (or/c string? #f) #:value #f)
4366
(defparam plot-x-label label (or/c string? #f) #:value "x axis")
4467
(defparam plot-y-label label (or/c string? #f) #:value "y axis")
@@ -117,7 +140,7 @@ For example, the value @racket['(columns 1 equal-size)] will place the legend en
117140
top to bottom and all entries will have the same height. A value of @racket['(rows 2 'compact)] will
118141
place legend entries horizontally on two rows -- this type of layout is useful when the legend is
119142
placed at the top or bottom of the plot.
120-
143+
121144
@history[#:added "7.9"]
122145
}
123146

@@ -333,11 +356,11 @@ The default width, pen color/width/style, and opacity used by @racket[error-bars
333356
(defparam candlestick-line-width pen-width (>=/c 0) #:value 1)
334357
(defparam candlestick-line-style pen-style plot-pen-style/c #:value 'solid)
335358
(defparam candlestick-alpha alpha (real-in 0 1) #:value 2/3))]{
336-
The default width, pen color/width/style, and opacity used by @racket[candlesticks]. Both the up (a candle whose
337-
open value is lower than its close value) color and the down (a candle whose open value is higher than its close
338-
value) color can be specified independently. The width parameter will be important to specify if your x-axis is
339-
in units like days, weeks, or months. Because dates are actually represented as seconds from an epoch, your
340-
width should take that into consideration. For example, a width of 86400 may be useful for x-axis values in days
359+
The default width, pen color/width/style, and opacity used by @racket[candlesticks]. Both the up (a candle whose
360+
open value is lower than its close value) color and the down (a candle whose open value is higher than its close
361+
value) color can be specified independently. The width parameter will be important to specify if your x-axis is
362+
in units like days, weeks, or months. Because dates are actually represented as seconds from an epoch, your
363+
width should take that into consideration. For example, a width of 86400 may be useful for x-axis values in days
341364
as there are 86400 seconds in a day. This candle will be exactly one day in width.
342365
}
343366

plot-doc/plot/scribblings/plotting.scrbl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Each 3D plotting procedure behaves the same way as its corresponding 2D procedur
2828
[#:title title (or/c string? pict? #f) (plot-title)]
2929
[#:x-label x-label (or/c string? pict? #f) (plot-x-label)]
3030
[#:y-label y-label (or/c string? pict? #f) (plot-y-label)]
31+
[#:aspect-ratio aspect-ratio (or/c (and/c rational? positive?) #f) (plot-aspect-ratio)]
3132
[#:legend-anchor legend-anchor legend-anchor/c (plot-legend-anchor)]
3233
[#:out-file out-file (or/c path-string? output-port? #f) #f]
3334
[#:out-kind out-kind plot-file-format/c 'auto]
@@ -51,6 +52,9 @@ When @(racket #:out-file) is given, @(racket plot) writes the plot to a file usi
5152

5253
When given, the @(racket x-min), @(racket x-max), @(racket y-min) and @(racket y-max) arguments determine the bounds of the plot, but not the bounds of the renderers. For example,
5354

55+
When given, the @(racket aspect-ratio) argument defines the aspect ratio of
56+
the plot area, see @(racket plot-aspect-ratio) for more details.
57+
5458
@interaction[#:eval plot-eval
5559
(plot (function (λ (x) (sin (* 4 x))) -1 1)
5660
#:x-min -1.5 #:x-max 1.5 #:y-min -1.5 #:y-max 1.5)]
@@ -62,6 +66,7 @@ Please set the @(racket plot-foreground) and @(racket plot-background) parameter
6266
The @(racket #:lncolor) keyword argument is also accepted for backward compatibility but deprecated. It does nothing.
6367

6468
@history[#:changed "7.9" "Added support for pictures for #:title, #:x-label and #:y-label. And to plot the legend outside the plot-area with #:legend-anchor"]
69+
@history[#:changed "8.1" "Added #:aspect-ratio"]
6570
}
6671

6772
@defproc[(plot3d [renderer-tree (treeof (or/c renderer3d? nonrenderer?))]
@@ -76,6 +81,7 @@ The @(racket #:lncolor) keyword argument is also accepted for backward compatibi
7681
[#:x-label x-label (or/c string? pict? #f) (plot-x-label)]
7782
[#:y-label y-label (or/c string? pict? #f) (plot-y-label)]
7883
[#:z-label z-label (or/c string? pict? #f) (plot-z-label)]
84+
[#:aspect-ratio aspect-ratio (or/c (and/c rational? positive?) #f) (plot-aspect-ratio)]
7985
[#:legend-anchor legend-anchor legend-anchor/c (plot-legend-anchor)]
8086
[#:out-file out-file (or/c path-string? output-port? #f) #f]
8187
[#:out-kind out-kind plot-file-format/c 'auto]
@@ -88,13 +94,17 @@ When @(racket #:out-file) is given, @(racket plot3d) writes the plot to a file u
8894

8995
When given, the @(racket x-min), @(racket x-max), @(racket y-min), @(racket y-max), @(racket z-min) and @(racket z-max) arguments determine the bounds of the plot, but not the bounds of the renderers.
9096

97+
When given, the @(racket aspect-ratio) argument defines the aspect ratio of
98+
the plot area, see @(racket plot-aspect-ratio) for more details.
99+
91100
@bold{Deprecated keywords.} The @(racket #:fgcolor) and @(racket #:bgcolor) keyword arguments are currently supported for backward compatibility, but may not be in the future.
92101
Please set the @(racket plot-foreground) and @(racket plot-background) parameters instead of using these keyword arguments.
93102
The @(racket #:lncolor) keyword argument is also accepted for backward compatibility but deprecated. It does nothing.
94103

95104
The @(racket #:az) and @(racket #:alt) keyword arguments are backward-compatible, deprecated aliases for @(racket #:angle) and @(racket #:altitude), respectively.
96105

97106
@history[#:changed "7.9" "Added support for pictures for #:title, #:x-label and #:y-label. And to plot the legend outside the plot-area with #:legend-anchor"]
107+
@history[#:changed "8.1" "Added #:aspect-ratio"]
98108
}
99109

100110
@defproc[(plot-snip [<plot-argument> <plot-argument-contract>] ...)

plot-gui-lib/plot/private/gui/plot2d.rkt

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#:title (U String pict #f)
6767
#:x-label (U String pict #f)
6868
#:y-label (U String pict #f)
69+
#:aspect-ratio (U Nonnegative-Real #f)
6970
#:legend-anchor Legend-Anchor]
7071
(Instance Snip%)))
7172
(define (plot-snip renderer-tree
@@ -76,6 +77,7 @@
7677
#:title [title (plot-title)]
7778
#:x-label [x-label (plot-x-label)]
7879
#:y-label [y-label (plot-y-label)]
80+
#:aspect-ratio [aspect-ratio (plot-aspect-ratio)]
7981
#:legend-anchor [legend-anchor (plot-legend-anchor)])
8082
(define fail/kw (make-raise-keyword-error 'plot-snip))
8183
(cond
@@ -89,6 +91,8 @@
8991
[(and title (not (or (string? title) (pict? title)))) (fail/kw "#f, string or pict" '#:title title)]
9092
[(and x-label (not (or (string? x-label) (pict? x-label)))) (fail/kw "#f, string or pict" '#:x-label x-label)]
9193
[(and y-label (not (or (string? y-label) (pict? y-label)))) (fail/kw "#f, string or pict" '#:y-label y-label)]
94+
[(and aspect-ratio (not (and (rational? aspect-ratio) (positive? aspect-ratio))))
95+
(fail/kw "#f or positive real" '#:aspect-ratio aspect-ratio)]
9296
[(not (legend-anchor/c legend-anchor)) (fail/kw "legend-anchor/c" '#:legend-anchor legend-anchor)])
9397

9498
(parameterize ([plot-title title]
@@ -116,7 +120,7 @@
116120
(define new-area
117121
(make-object 2d-plot-area%
118122
bounds-rect x-ticks x-far-ticks y-ticks y-far-ticks legend
119-
dc 0 0 width height))
123+
dc 0 0 width height aspect-ratio))
120124
(set! area new-area)
121125
(plot-area new-area renderer-list))
122126
(values bm area))
@@ -137,6 +141,7 @@
137141
#:title (U String pict #f)
138142
#:x-label (U String pict #f)
139143
#:y-label (U String pict #f)
144+
#:aspect-ratio (U Nonnegative-Real #f)
140145
#:legend-anchor Legend-Anchor]
141146
(Instance Frame%)))
142147
(define (plot-frame renderer-tree
@@ -147,6 +152,7 @@
147152
#:title [title (plot-title)]
148153
#:x-label [x-label (plot-x-label)]
149154
#:y-label [y-label (plot-y-label)]
155+
#:aspect-ratio [aspect-ratio (plot-aspect-ratio)]
150156
#:legend-anchor [legend-anchor (plot-legend-anchor)])
151157
(define fail/kw (make-raise-keyword-error 'plot-frame))
152158
(cond
@@ -160,6 +166,8 @@
160166
[(and title (not (or (string? title) (pict? title)))) (fail/kw "#f, string or pict" '#:title title)]
161167
[(and x-label (not (or (string? x-label) (pict? x-label)))) (fail/kw "#f, string or pict" '#:x-label x-label)]
162168
[(and y-label (not (or (string? y-label) (pict? y-label)))) (fail/kw "#f, string or pict" '#:y-label y-label)]
169+
[(and aspect-ratio (not (and (rational? aspect-ratio) (positive? aspect-ratio))))
170+
(fail/kw "#f or positive real" '#:aspect-ratio aspect-ratio)]
163171
[(not (legend-anchor/c legend-anchor)) (fail/kw "legend-anchor/c" '#:legend-anchor legend-anchor)])
164172

165173
;; make-snip will be called in a separate thread, make sure the
@@ -171,7 +179,8 @@
171179
(plot-snip
172180
renderer-tree
173181
#:x-min x-min #:x-max x-max #:y-min y-min #:y-max y-max #:width width #:height height
174-
#:title title #:x-label x-label #:y-label y-label #:legend-anchor legend-anchor)))
182+
#:title title #:x-label x-label #:y-label y-label #:legend-anchor legend-anchor
183+
#:aspect-ratio aspect-ratio)))
175184
(make-snip-frame make-snip width height (if title (format "Plot: ~a" title) "Plot")))
176185

177186
;; ===================================================================================================
@@ -186,6 +195,7 @@
186195
#:title (U String pict #f)
187196
#:x-label (U String pict #f)
188197
#:y-label (U String pict #f)
198+
#:aspect-ratio (U Nonnegative-Real #f)
189199
#:legend-anchor Legend-Anchor
190200
#:out-file (U Path-String Output-Port #f)
191201
#:out-kind (U 'auto Image-File-Format)
@@ -201,6 +211,7 @@
201211
#:title [title (plot-title)]
202212
#:x-label [x-label (plot-x-label)]
203213
#:y-label [y-label (plot-y-label)]
214+
#:aspect-ratio [aspect-ratio (plot-aspect-ratio)]
204215
#:legend-anchor [legend-anchor (plot-legend-anchor)]
205216
#:out-file [out-file #f]
206217
#:out-kind [out-kind 'auto]
@@ -226,6 +237,8 @@
226237
[(and title (not (or (string? title) (pict? title)))) (fail/kw "#f, string or pict" '#:title title)]
227238
[(and x-label (not (or (string? x-label) (pict? x-label)))) (fail/kw "#f, string or pict" '#:x-label x-label)]
228239
[(and y-label (not (or (string? y-label) (pict? y-label)))) (fail/kw "#f, string or pict" '#:y-label y-label)]
240+
[(and aspect-ratio (not (and (rational? aspect-ratio) (positive? aspect-ratio))))
241+
(fail/kw "#f or positive real" '#:aspect-ratio aspect-ratio)]
229242
[(not (legend-anchor/c legend-anchor)) (fail/kw "legend-anchor/c" '#:legend-anchor legend-anchor)]
230243
[(and out-kind (not (plot-file-format/c out-kind))) (fail/kw "plot-file-format/c" '#:out-kind out-kind)]
231244
[(not (plot-file-format/c out-kind)) (fail/kw "plot-file-format/c" '#:out-kind out-kind)]
@@ -241,18 +254,21 @@
241254
(plot-file
242255
renderer-tree out-file out-kind
243256
#:x-min x-min #:x-max x-max #:y-min y-min #:y-max y-max #:width width #:height height
244-
#:title title #:x-label x-label #:y-label y-label #:legend-anchor legend-anchor))
257+
#:title title #:x-label x-label #:y-label y-label #:legend-anchor legend-anchor
258+
#:aspect-ratio aspect-ratio))
245259

246260
(cond [(plot-new-window?)
247261
(define frame
248262
(plot-frame
249263
renderer-tree
250264
#:x-min x-min #:x-max x-max #:y-min y-min #:y-max y-max #:width width #:height height
251-
#:title title #:x-label x-label #:y-label y-label #:legend-anchor legend-anchor))
265+
#:title title #:x-label x-label #:y-label y-label #:legend-anchor legend-anchor
266+
#:aspect-ratio aspect-ratio))
252267
(send frame show #t)
253268
(void)]
254269
[else
255270
(plot-snip
256271
renderer-tree
257272
#:x-min x-min #:x-max x-max #:y-min y-min #:y-max y-max #:width width #:height height
258-
#:title title #:x-label x-label #:y-label y-label #:legend-anchor legend-anchor)])))
273+
#:title title #:x-label x-label #:y-label y-label #:legend-anchor legend-anchor
274+
#:aspect-ratio aspect-ratio)])))

0 commit comments

Comments
 (0)