Skip to content

Commit 2417c22

Browse files
authored
add plot-inset and plot-legend-padding parameters (#124)
... to control the amount of space left unused around the plot edge and plot legend.
1 parent b0da526 commit 2417c22

File tree

11 files changed

+162
-35
lines changed

11 files changed

+162
-35
lines changed

plot-doc/plot/scribblings/params.scrbl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,27 @@ Amount of ambient light, and whether 3D plots are rendered with diffuse and spec
117117

118118
}
119119

120+
@defparam[plot-inset inset (or/c (>=/c 0) (list (>=/c 0) (>=/c 0) (>=/c 0) (>=/c 0))) #:value 0]{
121+
122+
The amount of space around the plot to leave unused, when calculating plot
123+
layouts for ticks and axis labels. The parameter can be specified as a
124+
single value, which applies to all sides of the plot image, or as a list of
125+
four separate values for the left, right, top, and bottom margins of the
126+
plot image.
127+
128+
One example use for this parameter is to avoid clipping tick marks when
129+
lines for plot elements are very thick, see @racket[plot-line-width] and
130+
@racket[line-width]. In such a case, the end of axis ticks can be drawn
131+
beyond the end point of the line, and might be clipped at the edge of the
132+
drawing region. A non-zero @racket[plot-inset] value can be used to avoid
133+
this clipping.
134+
135+
See also @racket[plot-legend-padding] for an equivalent setting for the plot
136+
legend.
137+
138+
@history[#:added "8.11"]
139+
}
140+
120141
@deftogether[((defparam plot-foreground color plot-color/c #:value 0)
121142
(defparam plot-background color plot-color/c #:value 0))]{
122143
The plot foreground and background color.
@@ -161,6 +182,26 @@ For example, the value @racket['(columns 1 equal-size)] will place the legend en
161182
@history[#:added "7.9"]
162183
}
163184

185+
@defparam[plot-legend-padding padding (or/c (>=/c 0) (list (>=/c 0) (>=/c 0) (>=/c 0) (>=/c 0))) #:value 0]{
186+
187+
The amount of space to add between the legend entries and the border drawn
188+
around the legend. The parameter can be specified as a single value, which
189+
applies to all sides, or as a list of four separate values for the left,
190+
right, top, and bottom sides of the legend.
191+
192+
One example use for this parameter is to avoid clipping thick lines used in
193+
legend entries, see @racket[plot-line-width] and @racket[line-width]. In
194+
such a case, the end of the lines can be drawn outside the border of the
195+
legend, a non-zero @racket[plot-legend-padding] value can be used to avoid
196+
this situation.
197+
198+
See also @racket[plot-inset] for a similar setting for the entire plot
199+
image.
200+
201+
@history[#:added "8.11"]
202+
}
203+
204+
164205
@defparam[plot-tick-size size (>=/c 0) #:value 10]{
165206
The length of tick lines, in drawing units.
166207
}

plot-lib/plot/private/common/parameter-groups.rkt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242
arrow-head-size-or-scale
4343
arrow-head-angle
4444
plot-line-cap
45-
line-cap))
45+
line-cap
46+
plot-inset
47+
plot-legend-padding))
4648

4749
(define-parameter-group plot3d-appearance
4850
(plot3d-samples
@@ -114,7 +116,9 @@
114116
(U (List '= Nonnegative-Real) Nonnegative-Real)
115117
Nonnegative-Real
116118
Plot-Pen-Cap
117-
Plot-Pen-Cap)
119+
Plot-Pen-Cap
120+
(U Nonnegative-Real (List Nonnegative-Real Nonnegative-Real Nonnegative-Real Nonnegative-Real))
121+
(U Nonnegative-Real (List Nonnegative-Real Nonnegative-Real Nonnegative-Real Nonnegative-Real)))
118122
;;plot3d-appearance
119123
(List Positive-Integer Real Real Nonnegative-Real Boolean Boolean)
120124
;;plot-labels

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@
7979
(defparam plot-legend-anchor anchor Legend-Anchor 'top-left)
8080
(defparam plot-legend-layout layout Legend-Layout '(columns 1 equal-size))
8181
(defparam2 plot-legend-box-alpha alpha Real Nonnegative-Real 2/3 (unit-ivl 'plot-legend-box-alpha))
82+
(defparam plot-legend-padding
83+
(U
84+
;; A single padding value for all sides
85+
Nonnegative-Real
86+
;; Separate left, right, top, and bottom padding values
87+
(List Nonnegative-Real Nonnegative-Real Nonnegative-Real Nonnegative-Real))
88+
0.0)
8289
(defparam plot-animating? Boolean #f)
8390

8491
(defparam plot-x-axis? Boolean #t)
@@ -108,7 +115,13 @@
108115
(defparam plot-y-far-tick-label-anchor anchor Anchor 'left)
109116

110117
(defparam plot-decorations? Boolean #t)
111-
118+
(defparam plot-inset
119+
(U
120+
;; A single inset value for all sides
121+
Nonnegative-Real
122+
;; Separate left, right, top, and bottom inset values
123+
(List Nonnegative-Real Nonnegative-Real Nonnegative-Real Nonnegative-Real))
124+
0.0)
112125
(defparam plot-pen-color-map (U Symbol #f) #f)
113126
(defparam plot-brush-color-map (U Symbol #f) #f)
114127

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -614,12 +614,17 @@
614614
;; the understanding is that Rect will be the complete dc for a legend outside the plot-area
615615
;; and the plot-area otherwise
616616

617-
(: calculate-legend-parameters (-> (Listof legend-entry) Rect Anchor
617+
(: calculate-legend-parameters (-> (Listof legend-entry)
618+
Rect
619+
Anchor
620+
(U Nonnegative-Real
621+
(List Nonnegative-Real Nonnegative-Real Nonnegative-Real Nonnegative-Real))
622+
618623
(Values Rect (Listof Exact-Rational)
619624
Nonnegative-Exact-Rational (Listof Real) (Listof Real)
620625
Nonnegative-Exact-Rational (Listof Real)
621626
Boolean Nonnegative-Integer)))
622-
(define/private (calculate-legend-parameters legend-entries rect legend-anchor)
627+
(define/private (calculate-legend-parameters legend-entries rect anchor padding)
623628
(define n (length legend-entries))
624629
(define labels (map legend-entry-label legend-entries))
625630
(match-define (vector (ivl x-min x-max) (ivl y-min y-max)) rect)
@@ -692,21 +697,28 @@
692697

693698
;; top-left corner of legend
694699
(define legend-x-min
695-
(case legend-anchor
700+
(case anchor
696701
[(top-left left bottom-left auto) x-min]
697702
[(top-right right bottom-right) (- x-max legend-x-size)]
698703
[(center bottom top) (- (* 1/2 (+ x-min x-max))
699704
(* 1/2 legend-x-size))]))
700705

701706
(define legend-y-min
702-
(case legend-anchor
707+
(case anchor
703708
[(top-left top top-right auto) y-min]
704709
[(bottom-left bottom bottom-right) (- y-max legend-y-size)]
705710
[(center left right) (- (* 1/2 (+ y-min y-max))
706711
(* 1/2 legend-y-size))]))
707712

708-
(define legend-rect (vector (ivl legend-x-min (+ legend-x-min legend-x-size))
709-
(ivl legend-y-min (+ legend-y-min legend-y-size))))
713+
(define legend-rect
714+
(let-values ([(pad-left pad-right pad-top pad-bottom)
715+
(if (list? padding)
716+
(values (list-ref padding 0) (list-ref padding 1) (list-ref padding 2) (list-ref padding 3))
717+
(values padding padding padding padding))])
718+
(vector (ivl (- legend-x-min pad-left)
719+
(+ legend-x-min legend-x-size pad-right))
720+
(ivl (- legend-y-min pad-top)
721+
(+ legend-y-min legend-y-size pad-bottom)))))
710722

711723
;; per entry x/y left/top corners
712724
(define label-x-mins (for/fold ([mins : (Listof Real) (list (+ legend-x-min horiz-gap))]
@@ -732,7 +744,7 @@
732744
[else
733745
(raise-argument-error 'draw-legend "rect-known?" 1 legend-entries rect)]))
734746

735-
(define/public (calculate-legend-rect legend-entries rect legend-anchor)
747+
(define/public (calculate-legend-rect legend-entries rect anchor padding)
736748
;; Change font for correct size calculation in calculate-legend-parameters
737749
(define old-size (send (send dc get-font) get-point-size))
738750
(define old-face (send (send dc get-font) get-face))
@@ -746,7 +758,7 @@
746758
draw-x-size label-x-mins draw-x-mins
747759
draw-y-size label-y-mins
748760
cols? div)
749-
(calculate-legend-parameters legend-entries rect legend-anchor))
761+
(calculate-legend-parameters legend-entries rect anchor padding))
750762

751763
;; Undo change font
752764
(set-font-attribs old-size old-face old-family)
@@ -755,6 +767,7 @@
755767

756768
(define/public (draw-legend legend-entries rect)
757769
(define legend-anchor (plot-legend-anchor))
770+
(define legend-padding (plot-legend-padding))
758771
(when (not (eq? legend-anchor 'no-legend))
759772
(match-define (list (legend-entry #{labels : (Listof (U String pict))}
760773
#{draw-procs : (Listof Legend-Draw-Proc)})
@@ -774,7 +787,7 @@
774787
draw-x-size label-x-mins draw-x-mins
775788
draw-y-size label-y-mins
776789
cols? div)
777-
(calculate-legend-parameters legend-entries rect (legend-anchor->anchor legend-anchor)))
790+
(calculate-legend-parameters legend-entries rect (legend-anchor->anchor legend-anchor) legend-padding))
778791

779792
;; legend background
780793
(set-pen (plot-foreground) 1 'transparent)

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,12 @@
163163
[draw-arrow-glyph (-> (Vectorof Real) Real Real Void)]
164164
[draw-glyphs (-> (Listof (Vectorof Real)) Point-Sym Nonnegative-Real Void)]
165165
[draw-pict (->* [pict (Vectorof Real)] (Anchor Real) Void)]
166-
[calculate-legend-rect (-> (Listof legend-entry) Rect Anchor Rect)]
166+
[calculate-legend-rect (-> (Listof legend-entry)
167+
Rect
168+
Anchor
169+
(U Nonnegative-Real
170+
(List Nonnegative-Real Nonnegative-Real Nonnegative-Real Nonnegative-Real))
171+
Rect)]
167172
[draw-legend (-> (Listof legend-entry) Rect Void)]))
168173

169174
(require "plotmetrics.rkt")

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

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@
257257
legend
258258
(vector (ivl dc-x-min (+ dc-x-min dc-x-size))
259259
(ivl dc-y-min (+ dc-y-min dc-y-size)))
260-
(legend-anchor->anchor legend-anchor)))]
260+
(legend-anchor->anchor legend-anchor)
261+
(plot-legend-padding)))]
261262
[gap (pen-gap)]
262263
[make-print
263264
(λ ([get-bounds : (-> (Listof Real))])
@@ -640,16 +641,23 @@
640641
(define: right : Real 0)
641642
(define: top : Real 0)
642643
(define: bottom : Real 0)
643-
(let-values ([(left-val right-val top-val bottom-val)
644-
(margin-fixpoint 0 dc-x-size 0 dc-y-size
645-
init-left-margin init-right-margin
646-
init-top-margin init-bottom-margin
647-
(λ ([left : Real] [right : Real] [top : Real] [bottom : Real])
648-
(get-param-vs/set-view->dc! left right top bottom)))])
649-
(set! left left-val)
650-
(set! right right-val)
651-
(set! top top-val)
652-
(set! bottom bottom-val))
644+
(let ([inset (plot-inset)])
645+
(let-values ([(left-inset right-inset top-inset bottom-inset)
646+
(if (list? inset)
647+
(values (list-ref inset 0) (list-ref inset 1) (list-ref inset 2) (list-ref inset 3))
648+
(values inset inset inset inset))])
649+
(let-values ([(left-val right-val top-val bottom-val)
650+
(margin-fixpoint
651+
left-inset (- dc-x-size right-inset)
652+
top-inset (- dc-y-size bottom-inset)
653+
init-left-margin init-right-margin
654+
init-top-margin init-bottom-margin
655+
(λ ([left : Real] [right : Real] [top : Real] [bottom : Real])
656+
(get-param-vs/set-view->dc! left right top bottom)))])
657+
(set! left left-val)
658+
(set! right right-val)
659+
(set! top top-val)
660+
(set! bottom bottom-val))))
653661

654662
;; When an aspect ratio has been defined, adjust the margins so that the
655663
;; actual plot area maintains this ratio.

plot-lib/plot/private/plot3d/plot-area.rkt

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,8 @@
422422
legend
423423
(vector (ivl dc-x-min (+ dc-x-min dc-x-size))
424424
(ivl dc-y-min (+ dc-y-min dc-y-size)))
425-
(legend-anchor->anchor legend-anchor)))]
425+
(legend-anchor->anchor legend-anchor)
426+
(plot-legend-padding)))]
426427
[none (λ () (values 0 0 title-margin 0))])
427428
(cond
428429
[legend-rect
@@ -978,16 +979,23 @@
978979
(define: right : Real 0)
979980
(define: top : Real 0)
980981
(define: bottom : Real 0)
981-
(let-values ([(left-val right-val top-val bottom-val)
982-
(margin-fixpoint 0 dc-x-size 0 dc-y-size
983-
init-left-margin init-right-margin
984-
init-top-margin init-bottom-margin
985-
(λ ([left : Real] [right : Real] [top : Real] [bottom : Real])
986-
(get-param-vs/set-view->dc! left right top bottom)))])
987-
(set! left left-val)
988-
(set! right right-val)
989-
(set! top top-val)
990-
(set! bottom bottom-val))
982+
(let ([inset (plot-inset)])
983+
(let-values ([(left-inset right-inset top-inset bottom-inset)
984+
(if (list? inset)
985+
(values (list-ref inset 0) (list-ref inset 1) (list-ref inset 2) (list-ref inset 3))
986+
(values inset inset inset inset))])
987+
(let-values ([(left-val right-val top-val bottom-val)
988+
(margin-fixpoint
989+
left-inset (- dc-x-size right-inset)
990+
top-inset (- dc-y-size bottom-inset)
991+
init-left-margin init-right-margin
992+
init-top-margin init-bottom-margin
993+
(λ ([left : Real] [right : Real] [top : Real] [bottom : Real])
994+
(get-param-vs/set-view->dc! left right top bottom)))])
995+
(set! left left-val)
996+
(set! right right-val)
997+
(set! top top-val)
998+
(set! bottom bottom-val))))
991999

9921000
;; When an aspect ratio has been defined, adjust the margins so that the
9931001
;; actual plot area maintains this ratio.

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@
105105
plot-legend-anchor
106106
plot-legend-box-alpha
107107
plot-legend-layout
108+
plot-legend-padding
108109
plot-decorations?
110+
plot-inset
109111
plot-animating?
110112
plot-pen-color-map
111113
plot-brush-color-map

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#lang racket
2+
3+
(require rackunit
4+
plot racket/runtime-path
5+
"../helpers.rkt")
6+
7+
;; see https://github.com/racket/plot/pull/124
8+
9+
(define-runtime-path pr124-data "./test-data/pr124.dat")
10+
11+
(define (do-plot-pr124 output-fn)
12+
(parameterize
13+
([plot-line-width 15]
14+
[line-width 15]
15+
[plot-inset '(0 10 10 0)]
16+
[plot-pen-color-map 'set1]
17+
[plot-legend-padding '(0 15 0 0)]
18+
[plot-line-cap 'round]
19+
[line-cap 'round])
20+
(output-fn
21+
(list
22+
(function sin -5 5 #:color 0 #:label "sin(x)")
23+
(function cos -5 5 #:color 1 #:label "cos(x)")))))
24+
25+
(define pr124-test-suite
26+
(test-suite
27+
"PR#124: Add plot-inset and plot-legend-padding parameters"
28+
(test-case "pr124"
29+
(check-draw-steps do-plot-pr124 pr124-data))))
30+
31+
(module+ test
32+
(require rackunit/text-ui)
33+
(run-tests pr124-test-suite))
15.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)