File: renderer2d.scrbl

package info (click to toggle)
racket 7.2%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 125,432 kB
  • sloc: ansic: 258,980; pascal: 59,975; sh: 33,650; asm: 13,558; lisp: 7,124; makefile: 3,329; cpp: 2,889; exp: 499; python: 274; xml: 11
file content (994 lines) | stat: -rw-r--r-- 53,323 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
#lang scribble/manual

@(require "common.rkt")

@title[#:tag "renderer2d"]{2D Renderers}

@declare-exporting[plot]
@defmodule*/no-declare[(plot) #:link-target? #f]

@section[#:tag "renderer2d-function-arguments"]{2D Renderer Function Arguments}

Functions that return 2D renderers always have these kinds of arguments:
@itemlist[
          @item{Required (and possibly optional) arguments representing the graph to plot.}
          @item{Optional keyword arguments for overriding calculated bounds, with the default value @(racket #f).}
          @item{Optional keyword arguments that determine the appearance of the plot.}
          @item{The optional keyword argument @(racket #:label), which specifies the name of the renderer in the legend.}]

We will take @(racket function), perhaps the most commonly used renderer-producing function, as an example.

@bold{Graph arguments.} The first argument to @(racket function) is the required @(racket f), the function to plot.
It is followed by two optional arguments @(racket x-min) and @(racket x-max), which specify the renderer's @italic{x} bounds.
(If not given, the @italic{x} bounds will be the plot area @italic{x} bounds, as requested by another renderer or specified to @(racket plot) using @(racket #:x-min) and @(racket #:x-max).)

These three arguments define the @deftech{graph} of the function @(racket f), a possibly infinite set of pairs of points @(racket x),@(racket (f x)).
An infinite graph cannot be plotted directly, so the renderer must approximately plot the points in it.
The renderer returned by @(racket function) does this by drawing lines connected end-to-end.

@bold{Overriding bounds arguments.} Next in @(racket function)'s argument list are the keyword arguments @(racket #:y-min) and @(racket #:y-max), which override the renderer's calculated @italic{y} bounds if given.

@bold{Appearance arguments.} The next keyword argument is @(racket #:samples), which determines the quality of the renderer's approximate plot (higher is better).
Following @(racket #:samples) are @(racket #:color), @(racket #:width), @(racket #:style) and @(racket #:alpha), which determine the color, width, style and opacity of the lines comprising the plot.

In general, the keyword arguments that determine the appearance of plots follow consistent naming conventions.
The most common keywords are @(racket #:color) (for fill and line colors), @(racket #:width) (for line widths), @(racket #:style) (for fill and line styles) and @(racket #:alpha).
When a function needs both a fill color and a line color, the fill color is given using @(racket #:color), and the line color is given using @(racket #:line-color) (or some variation, such as @(racket #:line1-color)). Styles follow the same rule.

Every appearance keyword argument defaults to the value of a parameter.
This allows whole families of plots to be altered with little work.
For example, setting @(racket (line-color 3)) causes every subsequent renderer that draws connected lines to draw its lines in blue.

@bold{Label argument.} Lastly, there is @(racket #:label). If given, the @(racket function) renderer will generate a label entry that @(racket plot) puts in the legend.

Not every renderer-producing function has a @(racket #:label) argument; for example, @(racket error-bars).


@section{2D Point Renderers}

@defproc[(points [vs  (sequence/c (sequence/c #:min-count 2 real?))]
                 [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
                 [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
                 [#:sym sym point-sym/c (point-sym)]
                 [#:color color plot-color/c (point-color)]
                 [#:fill-color fill-color (or/c plot-color/c 'auto) 'auto]
                 [#:x-jitter x-jitter (>=/c 0) (point-x-jitter)]
                 [#:y-jitter y-jitter (>=/c 0) (point-y-jitter)]
                 [#:size size (>=/c 0) (point-size)]
                 [#:line-width line-width (>=/c 0) (point-line-width)]
                 [#:alpha alpha (real-in 0 1) (point-alpha)]
                 [#:label label (or/c string? #f) #f]
                 ) renderer2d?]{
Returns a @tech{renderer} that draws points. Use it, for example, to draw 2D scatter plots.

The renderer sets its bounds to the smallest rectangle that contains the points.
Still, it is often necessary to override these bounds, especially with randomized data. For example,
@interaction[#:eval plot-eval
                    (parameterize ([plot-width    150]
                                   [plot-height   150]
                                   [plot-x-label  #f]
                                   [plot-y-label  #f])
                      (define xs (build-list 20 (λ _ (random))))
                      (define ys (build-list 20 (λ _ (random))))
                      (list (plot (points (map vector xs ys)))
                            (plot (points (map vector xs ys)
                                          #:x-min 0 #:x-max 1
                                          #:y-min 0 #:y-max 1))))]
Readers of the first plot could only guess that the random points were generated in [0,1] × [0,1].

The @racket[#:sym] argument may be any integer, a Unicode character or string, or a symbol in
@racket[known-point-symbols].
Use an integer when you need different points but don't care exactly what they are.

When @racket[x-jitter] is non-zero, all points are translated by a random amount
at most @racket[x-jitter] from their original position along the x-axis.
A non-zero @racket[y-jitter] similarly translates points along the y-axis.
Jitter is added in both directions so total spread is twice the value given.
To be precise, each point @racket[p] is moved to a random location inside a rectangle centered at
@racket[p] with width at most twice @racket[x-jitter] and height at most twice @racket[y-jitter]
subject to the constraint that new points lie within
[@racket[x-min], @racket[x-max]] and [@racket[y-min], @racket[y-max]]
if these bounds are non-@racket[#f].

@interaction[#:eval plot-eval
                    (plot
                      (points (for/list ([_i (in-range 1000)])
                                (list 0 0))
                              #:alpha 0.4
                              #:x-jitter 1
                              #:y-jitter 1
                              #:sym 'fullcircle1
                              #:color "blue")
                      #:x-min -2 #:x-max 2 #:y-min -2 #:y-max 2)]

Randomly moving data points is almost always a bad idea, but jittering in a controlled manner can
sometimes be useful.
For example:
@margin-note{More examples of jittering:
  @hyperlink["http://kieranhealy.org/blog/archives/2015/02/03/another-look-at-the-california-vaccination-data/"]{Another Look at the California Vaccination Data}
  and
  @hyperlink["https://pavelfatin.com/typing-with-pleasure/"]{Typing with Pleasure}}

@itemlist[
  @item{To highlight the size of a dense (or @hyperlink["https://en.wiktionary.org/wiki/overplotting"]{overplotted}) sample.}
  @item{To see the distribution of 1-dimensional data; as a substitute for box or violin plots.}
  @item{To anonymize spatial data, showing i.e. an office's neighborhood but hiding its address.}
]
}

@defproc[(vector-field
          [f (or/c (-> real? real? (sequence/c real?))
                   (-> (vector/c real? real?) (sequence/c real?)))]
          [x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
          [y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
          [#:samples samples exact-positive-integer? (vector-field-samples)]
          [#:scale scale (or/c real? (one-of/c 'auto 'normalized)) (vector-field-scale)]
          [#:color color plot-color/c (vector-field-color)]
          [#:line-width line-width (>=/c 0) (vector-field-line-width)]
          [#:line-style line-style plot-pen-style/c (vector-field-line-style)]
          [#:alpha alpha (real-in 0 1) (vector-field-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Returns a renderer that draws a vector field.

If @(racket scale) is a real number, arrow lengths are multiplied by @(racket scale).
If @(racket 'auto), the scale is calculated in a way that keeps arrows from overlapping.
If @(racket 'normalized), each arrow is made the same length: the maximum length that would have been allowed by @(racket 'auto).

An example of automatic scaling:
@interaction[#:eval plot-eval
                    (plot (vector-field (λ (x y) (vector (+ x y) (- x y)))
                                        -2 2 -2 2))]
}

@defproc[(error-bars
          [bars (sequence/c (sequence/c #:min-count 3 real?))]
          [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
          [#:color color plot-color/c (error-bar-color)]
          [#:line-width line-width (>=/c 0) (error-bar-line-width)]
          [#:line-style line-style plot-pen-style/c (error-bar-line-style)]
          [#:width width (>=/c 0) (error-bar-width)]
          [#:alpha alpha (real-in 0 1) (error-bar-alpha)]
          ) renderer2d?]{
Returns a renderer that draws error bars.
The first and second element in each vector in @(racket bars) comprise the coordinate; the third is the height.
@interaction[#:eval plot-eval
                    (plot (list (function sqr 1 7)
                                (error-bars (list (vector 2 4 12)
                                                  (vector 4 16 20)
                                                  (vector 6 36 10)))))]
}

@defproc[(candlesticks
          [candles (sequence/c (sequence/c #:min-count 5 real?))]
          [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
          [#:up-color up-color plot-color/c (candlestick-up-color)]
          [#:down-color down-color plot-color/c (candlestick-down-color)]
          [#:line-width line-width (>=/c 0) (candlestick-line-width)]
          [#:line-style line-style plot-pen-style/c (candlestick-line-style)]
          [#:width width (>=/c 0) (candlestick-width)]
          [#:alpha alpha (real-in 0 1) (candlestick-alpha)]
          ) renderer2d?]{
Returns a renderer that draws candlesticks. This is most common when plotting historical prices for financial 
instruments. The first element in each vector of @(racket candles) comprises the x-axis coordinate; the second, third, 
fourth, and fifth elements in each vector comprise the open, high, low, and close, respectively, of the y-axis coordinates.
@interaction[#:eval plot-eval
                    (plot (list (candlesticks (list (vector 2 4 12 4 8)
                                                    (vector 4 16 20 8 12)
                                                    (vector 6 24 36 10 24)))))]
}

@section{2D Line Renderers}

@defproc[(function [f (real? . -> . real?)]
                   [x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
                   [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
                   [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
                   [#:color color plot-color/c (line-color)]
                   [#:width width (>=/c 0) (line-width)]
                   [#:style style plot-pen-style/c (line-style)]
                   [#:alpha alpha (real-in 0 1) (line-alpha)]
                   [#:label label (or/c string? #f) #f]
                   ) renderer2d?]{
Returns a renderer that plots a function of @italic{x}. For example, a parabola:
@interaction[#:eval plot-eval (plot (function sqr -2 2))]
}

@defproc[(inverse [f (real? . -> . real?)]
                  [y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
                  [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
                  [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
                  [#:color color plot-color/c (line-color)]
                  [#:width width (>=/c 0) (line-width)]
                  [#:style style plot-pen-style/c (line-style)]
                  [#:alpha alpha (real-in 0 1) (line-alpha)]
                  [#:label label (or/c string? #f) #f]
                  ) renderer2d?]{
Like @(racket function), but regards @(racket f) as a function of @italic{y}.
For example, a parabola, an inverse parabola, and the reflection line:
@interaction[#:eval plot-eval
                    (plot (list (axes)
                                (function sqr -2 2 #:label "y = x^2")
                                (function (λ (x) x) #:color 0 #:style 'dot #:label "y = x")
                                (inverse sqr -2 2 #:color 3 #:label "x = y^2")))]
}

@defproc[(lines [vs  (sequence/c (sequence/c #:min-count 2 real?))]
                [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
                [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
                [#:color color plot-color/c (line-color)]
                [#:width width (>=/c 0) (line-width)]
                [#:style style plot-pen-style/c (line-style)]
                [#:alpha alpha (real-in 0 1) (line-alpha)]
                [#:label label (or/c string? #f) #f]
                ) renderer2d?]{
Returns a renderer that draws lines.
This is directly useful for plotting a time series, such as a random walk:
@interaction[#:eval plot-eval
                    (plot (lines
                           (reverse
                            (for/fold ([lst (list (vector 0 0))]) ([i  (in-range 1 200)])
                              (match-define (vector x y) (first lst))
                              (cons (vector i (+ y (* 1/100 (- (random) 1/2)))) lst)))
                           #:color 6 #:label "Random walk"))]

The @(racket parametric) and @(racket polar) functions are defined using @(racket lines).
}

@defproc[(parametric [f (real? . -> . (sequence/c real?))]
                     [t-min rational?] [t-max rational?]
                     [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
                     [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
                     [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
                     [#:color color plot-color/c (line-color)]
                     [#:width width (>=/c 0) (line-width)]
                     [#:style style plot-pen-style/c (line-style)]
                     [#:alpha alpha (real-in 0 1) (line-alpha)]
                     [#:label label (or/c string? #f) #f]
                     ) renderer2d?]{
Returns a renderer that plots vector-valued functions of time.
For example, the circle as a function of time can be plotted using
@interaction[#:eval plot-eval
                    (plot (parametric (λ (t) (vector (cos t) (sin t))) 0 (* 2 pi)))]
}

@defproc[(polar [f (real? . -> . real?)]
                [θ-min real? 0] [θ-max real? (* 2 pi)]
                [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
                [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
                [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
                [#:color color plot-color/c (line-color)]
                [#:width width (>=/c 0) (line-width)]
                [#:style style plot-pen-style/c (line-style)]
                [#:alpha alpha (real-in 0 1) (line-alpha)]
                [#:label label (or/c string? #f) #f]
                ) renderer2d?]{
Returns a renderer that plots functions from angle to radius.
Note that the angle parameters @(racket θ-min) and @(racket θ-max) default to @(racket 0) and @(racket (* 2 pi)).

For example, drawing a full circle:
@interaction[#:eval plot-eval (plot (polar (λ (θ) 1)))]
}

@defproc[(density [xs (sequence/c real?)]
                  [bw-adjust (>/c 0) 1]
                  [ws (or/c (sequence/c (>=/c 0)) #f) #f]
                  [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
                  [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
                  [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
                  [#:color color plot-color/c (line-color)]
                  [#:width width (>=/c 0) (line-width)]
                  [#:style style plot-pen-style/c (line-style)]
                  [#:alpha alpha (real-in 0 1) (line-alpha)]
                  [#:label label (or/c string? #f) #f]
                  ) renderer2d?]{
Returns a renderer that plots an estimated density for the given points, which are optionally weighted by @racket[ws].
The bandwidth for the kernel is calculated as @(racket (* bw-adjust 1.06 sd (expt n -0.2))), where @(racket sd) is the standard deviation of the data and @(racket n) is the number of points.
Currently, the only supported kernel is the Gaussian.

For example, to plot an estimated density of the triangle distribution:
@interaction[#:eval plot-eval
                    (plot (list (function (λ (x) (cond [(or (x . < . -1) (x . > . 1))  0]
                                                       [(x . < . 0)   (+ 1 x)]
                                                       [(x . >= . 0)  (- 1 x)]))
                                          -1.5 1.5 #:label "Density")
                                (density (build-list
                                          2000 (λ (n) (- (+ (random) (random)) 1)))
                                         #:color 0 #:width 2 #:style 'dot
                                         #:label "Est. density")))]
}

@defproc[(hrule [y real?]
                [x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
                [#:color color plot-color/c (line-color)]
                [#:width width (>=/c 0) (line-width)]
                [#:style style plot-pen-style/c (line-style)]
                [#:alpha alpha (real-in 0 1) (line-alpha)]
                [#:label label (or/c string? #f) #f]
                ) renderer2d?]{
Draws a horizontal line at @italic{y}.
By default, the line spans the entire plot area width.
}

@defproc[(vrule [x real?]
                [y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
                [#:color color plot-color/c (line-color)]
                [#:width width (>=/c 0) (line-width)]
                [#:style style plot-pen-style/c (line-style)]
                [#:alpha alpha (real-in 0 1) (line-alpha)]
                [#:label label (or/c string? #f) #f]
                ) renderer2d?]{
Draws a vertical line at @italic{x}.
By default, the line spans the entire plot area height.
}

@section{2D Interval Renderers}

These renderers each correspond with a line renderer, and graph the area between two lines.

@defproc[(function-interval
          [f1 (real? . -> . real?)] [f2 (real? . -> . real?)]
          [x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
          [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
          [#:color color plot-color/c (interval-color)]
          [#:style style plot-brush-style/c (interval-style)]
          [#:line1-color line1-color plot-color/c (interval-line1-color)]
          [#:line1-width line1-width (>=/c 0) (interval-line1-width)]
          [#:line1-style line1-style plot-pen-style/c (interval-line1-style)]
          [#:line2-color line2-color plot-color/c (interval-line2-color)]
          [#:line2-width line2-width (>=/c 0) (interval-line2-width)]
          [#:line2-style line2-style plot-pen-style/c (interval-line2-style)]
          [#:alpha alpha (real-in 0 1) (interval-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Corresponds with @(racket function).

@interaction[#:eval plot-eval (plot (function-interval (λ (x) 0) (λ (x) (exp (* -1/2 (sqr x))))
                                                       -4 4 #:line1-style 'transparent))]
}

@defproc[(inverse-interval
          [f1 (real? . -> . real?)] [f2 (real? . -> . real?)]
          [y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
          [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
          [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
          [#:color color plot-color/c (interval-color)]
          [#:style style plot-brush-style/c (interval-style)]
          [#:line1-color line1-color plot-color/c (interval-line1-color)]
          [#:line1-width line1-width (>=/c 0) (interval-line1-width)]
          [#:line1-style line1-style plot-pen-style/c (interval-line1-style)]
          [#:line2-color line2-color plot-color/c (interval-line2-color)]
          [#:line2-width line2-width (>=/c 0) (interval-line2-width)]
          [#:line2-style line2-style plot-pen-style/c (interval-line2-style)]
          [#:alpha alpha (real-in 0 1) (interval-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Corresponds with @(racket inverse).

@interaction[#:eval plot-eval (plot (inverse-interval sin (λ (x) 0) (- pi) pi
                                                      #:line2-style 'long-dash))]
}

@defproc[(lines-interval
          [v1s (sequence/c (sequence/c #:min-count 2 real?))]
          [v2s (sequence/c (sequence/c #:min-count 2 real?))]
          [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
          [#:color color plot-color/c (interval-color)]
          [#:style style plot-brush-style/c (interval-style)]
          [#:line1-color line1-color plot-color/c (interval-line1-color)]
          [#:line1-width line1-width (>=/c 0) (interval-line1-width)]
          [#:line1-style line1-style plot-pen-style/c (interval-line1-style)]
          [#:line2-color line2-color plot-color/c (interval-line2-color)]
          [#:line2-width line2-width (>=/c 0) (interval-line2-width)]
          [#:line2-style line2-style plot-pen-style/c (interval-line2-style)]
          [#:alpha alpha (real-in 0 1) (interval-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Corresponds with @(racket lines).

@interaction[#:eval plot-eval
                    (plot (list
                           (tick-grid)
                           (lines-interval (list #(0 0) #(1 1/2)) (list #(0 1) #(1 3/2))
                                           #:color 4 #:line1-color 4 #:line2-color 4
                                           #:label "Parallelogram")))]
}

@defproc[(parametric-interval
          [f1 (real? . -> . (sequence/c real?))]
          [f2 (real? . -> . (sequence/c real?))]
          [t-min rational?] [t-max rational?]
          [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
          [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
          [#:color color plot-color/c (interval-color)]
          [#:style style plot-brush-style/c (interval-style)]
          [#:line1-color line1-color plot-color/c (interval-line1-color)]
          [#:line1-width line1-width (>=/c 0) (interval-line1-width)]
          [#:line1-style line1-style plot-pen-style/c (interval-line1-style)]
          [#:line2-color line2-color plot-color/c (interval-line2-color)]
          [#:line2-width line2-width (>=/c 0) (interval-line2-width)]
          [#:line2-style line2-style plot-pen-style/c (interval-line2-style)]
          [#:alpha alpha (real-in 0 1) (interval-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Corresponds with @(racket parametric).

@interaction[#:eval plot-eval
                    (define (f1 t) (vector (* 2 (cos (* 4/5 t)))
                                           (* 2 (sin (* 4/5 t)))))
                    (define (f2 t) (vector (* 1/2 (cos t))
                                           (* 1/2 (sin t))))
                    (plot (parametric-interval f1 f2 (- pi) pi))]
}

@defproc[(polar-interval
          [f1 (real? . -> . real?)] [f2 (real? . -> . real?)]
          [θ-min rational? 0] [θ-max rational? (* 2 pi)]
          [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
          [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
          [#:color color plot-color/c (interval-color)]
          [#:style style plot-brush-style/c (interval-style)]
          [#:line1-color line1-color plot-color/c (interval-line1-color)]
          [#:line1-width line1-width (>=/c 0) (interval-line1-width)]
          [#:line1-style line1-style plot-pen-style/c (interval-line1-style)]
          [#:line2-color line2-color plot-color/c (interval-line2-color)]
          [#:line2-width line2-width (>=/c 0) (interval-line2-width)]
          [#:line2-style line2-style plot-pen-style/c (interval-line2-style)]
          [#:alpha alpha (real-in 0 1) (interval-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Corresponds with @(racket polar).

@interaction[#:eval plot-eval
                    (define (f1 θ) (+ 1/2 (* 1/6 (cos (* 5 θ)))))
                    (define (f2 θ) (+ 1 (* 1/4 (cos (* 10 θ)))))
                    (plot (list (polar-axes #:number 10)
                                (polar-interval f1 f2 #:label "[f1,f2]")))]
}

@section{2D Contour (Isoline) Renderers}

@defproc[(isoline
          [f (real? real? . -> . real?)] [z real?]
          [x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
          [y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
          [#:samples samples (and/c exact-integer? (>=/c 2)) (contour-samples)]
          [#:color color plot-color/c (line-color)]
          [#:width width (>=/c 0) (line-width)]
          [#:style style plot-pen-style/c (line-style)]
          [#:alpha alpha (real-in 0 1) (line-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Returns a renderer that plots a contour line, or a line of constant value (height).
A circle of radius @(racket r), for example, is the line of constant value @(racket r) for the distance function:
@interaction[#:eval plot-eval (plot (isoline (λ (x y) (sqrt (+ (sqr x) (sqr y)))) 1.5
                                             -2 2 -2 2 #:label "z"))]
}
In this case, @(racket r) = @(racket 1.5).

This function would have been named @racket[contour], except the name was already used by a deprecated function.
It may be renamed in the future, with @racket[isoline] as an alias.

@defproc[(contours
          [f (real? real? . -> . real?)]
          [x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
          [y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
          [#:samples samples (and/c exact-integer? (>=/c 2)) (contour-samples)]
          [#:levels levels (or/c 'auto exact-positive-integer? (listof real?)) (contour-levels)]
          [#:colors colors (plot-colors/c (listof real?)) (contour-colors)]
          [#:widths widths (pen-widths/c (listof real?)) (contour-widths)]
          [#:styles styles (plot-pen-styles/c (listof real?)) (contour-styles)]
          [#:alphas alphas (alphas/c (listof real?)) (contour-alphas)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Returns a renderer that plots contour lines, or lines of constant value (height).

When @(racket levels) is @(racket 'auto), the number of contour lines and their values are chosen the same way as axis tick positions; i.e. they are chosen to be simple.
When @(racket levels) is a number, @(racket contours) chooses that number of values, evenly spaced, within the output range of @(racket f).
When @(racket levels) is a list, @(racket contours) plots contours at the values in @(racket levels).

For example, a saddle:
@interaction[#:eval plot-eval (plot (contours (λ (x y) (- (sqr x) (sqr y)))
                                              -2 2 -2 2 #:label "z"))]

The appearance keyword arguments assign a color, width, style and opacity @italic{to each contour line}.
Each can be given as a list or as a function from a list of output values of @(racket f) to a list of appearance values.
In both cases, when there are more contour lines than list elements, the colors, widths, styles and alphas in the list repeat.

For example,
@interaction[#:eval plot-eval (plot (contours (λ (x y) (- (sqr x) (sqr y)))
                                              -2 2 -2 2 #:levels 4
                                              #:colors '("blue" "red")
                                              #:widths '(4 1)
                                              #:styles '(solid dot)))]
}

@defproc[(contour-intervals
          [f (real? real? . -> . real?)]
          [x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
          [y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
          [#:samples samples (and/c exact-integer? (>=/c 2)) (contour-samples)]
          [#:levels levels (or/c 'auto exact-positive-integer? (listof real?)) (contour-levels)]
          [#:colors colors (plot-colors/c (listof ivl?)) (contour-interval-colors)]
          [#:styles styles (plot-brush-styles/c (listof ivl?)) (contour-interval-styles)]
          [#:contour-colors contour-colors (plot-colors/c (listof real?)) (contour-colors)]
          [#:contour-widths contour-widths (pen-widths/c (listof real?)) (contour-widths)]
          [#:contour-styles contour-styles (plot-pen-styles/c (listof real?)) (contour-styles)]
          [#:alphas alphas (alphas/c (listof ivl?)) (contour-interval-alphas)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Returns a renderer that fills the area between contour lines, and additionally draws contour lines.

For example, the canonical saddle, with its gradient field superimposed:
@interaction[#:eval plot-eval
                    (plot (list (contour-intervals (λ (x y) (- (sqr x) (sqr y)))
                                                   -2 2 -2 2 #:label "z")
                                (vector-field (λ (x y) (vector (* 2 x) (* -2 y)))
                                              #:color "black" #:label "Gradient")))]
}

@section{2D Rectangle Renderers}

@defproc[(rectangles
          [rects  (sequence/c (sequence/c #:min-count 2 ivl?))]
          [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) #f] [#:y-max y-max (or/c rational? #f) #f]
          [#:color color plot-color/c (rectangle-color)]
          [#:style style plot-brush-style/c (rectangle-style)]
          [#:line-color line-color plot-color/c (rectangle-line-color)]
          [#:line-width line-width (>=/c 0) (rectangle-line-width)]
          [#:line-style line-style plot-pen-style/c (rectangle-line-style)]
          [#:alpha alpha (real-in 0 1) (rectangle-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Returns a renderer that draws rectangles.

The rectangles are given as a sequence of sequences of intervals---each inner
sequence defines the bounds of a rectangle.  Any of the bounds can be
@racket[-inf.0] or @racket[+inf.0], in which case the rectangle extents to the
edge of the plot area in the respective direction.

For example,
@interaction[#:eval plot-eval (plot (rectangles (list (vector (ivl -1 0) (ivl -1 1))
                                                      (vector (ivl 0 2) (ivl 1 2)))))]
}

@defproc[(area-histogram
          [f (real? . -> . real?)]
          [bin-bounds (sequence/c real?)]
          [#:x-min x-min (or/c rational? #f) #f] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) 0] [#:y-max y-max (or/c rational? #f) #f]
          [#:samples samples (and/c exact-integer? (>=/c 2)) (line-samples)]
          [#:color color plot-color/c (rectangle-color)]
          [#:style style plot-brush-style/c (rectangle-style)]
          [#:line-color line-color plot-color/c (rectangle-line-color)]
          [#:line-width line-width (>=/c 0) (rectangle-line-width)]
          [#:line-style line-style plot-pen-style/c (rectangle-line-style)]
          [#:alpha alpha (real-in 0 1) (rectangle-alpha)]
          [#:label label (or/c string? #f) #f]
          ) renderer2d?]{
Returns a renderer that draws a histogram approximating the area under a curve.
The @(racket #:samples) argument determines the accuracy of the calculated areas.
@interaction[#:eval plot-eval
                    (require (only-in plot/utils linear-seq))
                    (define (f x) (exp (* -1/2 (sqr x))))
                    (plot (list (area-histogram f (linear-seq -4 4 10))
                                (function f -4 4)))]
}

@defproc[(discrete-histogram
          [cat-vals (sequence/c (or/c (vector/c any/c (or/c real? ivl? #f))
                                      (list/c any/c (or/c real? ivl? #f))))]
          [#:x-min x-min (or/c rational? #f) 0] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) 0] [#:y-max y-max (or/c rational? #f) #f]
          [#:gap gap (real-in 0 1) (discrete-histogram-gap)]
          [#:skip skip (>=/c 0) (discrete-histogram-skip)]
          [#:invert? invert? boolean? (discrete-histogram-invert?)]
          [#:color color plot-color/c (rectangle-color)]
          [#:style style plot-brush-style/c (rectangle-style)]
          [#:line-color line-color plot-color/c (rectangle-line-color)]
          [#:line-width line-width (>=/c 0) (rectangle-line-width)]
          [#:line-style line-style plot-pen-style/c (rectangle-line-style)]
          [#:alpha alpha (real-in 0 1) (rectangle-alpha)]
          [#:label label (or/c string? #f) #f]
          [#:add-ticks? add-ticks? boolean? #t]
          [#:far-ticks? far-ticks? boolean? #f]
          ) renderer2d?]{
Returns a renderer that draws a discrete histogram.

@examples[#:eval plot-eval
                 (plot (discrete-histogram (list #(A 1) #(B 2) #(B 3)
                                                 (vector 'C (ivl 0.5 1.5)))))]

Use @racket[#:invert? #t] to draw horizontal bars. See @racket[stacked-histogram] for an example.

Each bar takes up exactly one plot unit, and is drawn with @racket[(* 1/2 gap)] empty space on each side.
Bar number @racket[i] is drawn at @racket[(+ x-min (* i skip))].
Thus, the first bar (@racket[i] = @racket[0]) is drawn in the interval between @racket[x-min] (default @racket[0]) and @racket[(+ x-min 1)].

To plot two histograms side-by-side, pass the appropriate @racket[x-min] value to the second renderer. For example,
@interaction[#:eval plot-eval
                    (plot (list (discrete-histogram (list #(a 1) #(b 2) #(c 3) #(d 2)
                                                          #(e 4) #(f 2.5) #(g 1))
                                                    #:label "Numbers per letter")
                                (discrete-histogram (list #(1 1) #(4 2) #(3 1.5))
                                                    #:x-min 8
                                                    #:label "Numbers per number"
                                                    #:color 2 #:line-color 2)))]
Here, the first histogram has @racket[7] bars, so the second is drawn starting at @racket[x-min] = @racket[8].

To interleave histograms, such as when plotting benchmark results, use a @racket[skip] value larger than or equal to the number of histograms, and give each histogram a different @racket[x-min].
For example,
@interaction[#:eval plot-eval
                    (plot (list (discrete-histogram
                                 '(#(Eggs 1.5) #(Bacon 2.5) #(Pancakes 3.5))
                                 #:skip 2.5 #:x-min 0
                                 #:label "AMD")
                                (discrete-histogram
                                 '(#(Eggs 1.4) #(Bacon 2.3) #(Pancakes 3.1))
                                 #:skip 2.5 #:x-min 1
                                 #:label "Intel" #:color 2 #:line-color 2))
                          #:x-label "Breakfast Food" #:y-label "Cooking Time (minutes)"
                          #:title "Cooking Times For Breakfast Food, Per Processor")]
When interleaving many histograms, consider setting the @racket[discrete-histogram-skip] parameter to change @racket[skip]'s default value.
}

@defproc[(stacked-histogram
          [cat-vals (sequence/c (or/c (vector/c any/c (sequence/c real?))
                                      (list/c any/c (sequence/c real?))))]
          [#:x-min x-min (or/c rational? #f) 0] [#:x-max x-max (or/c rational? #f) #f]
          [#:y-min y-min (or/c rational? #f) 0] [#:y-max y-max (or/c rational? #f) #f]
          [#:gap gap (real-in 0 1) (discrete-histogram-gap)]
          [#:skip skip (>=/c 0) (discrete-histogram-skip)]
          [#:invert? invert? boolean? (discrete-histogram-invert?)]
          [#:colors colors (plot-colors/c nat/c) (stacked-histogram-colors)]
          [#:styles styles (plot-brush-styles/c nat/c) (stacked-histogram-styles)]
          [#:line-colors line-colors (plot-colors/c nat/c) (stacked-histogram-line-colors)]
          [#:line-widths line-widths (pen-widths/c nat/c) (stacked-histogram-line-widths)]
          [#:line-styles line-styles (plot-pen-styles/c nat/c) (stacked-histogram-line-styles)]
          [#:alphas alphas (alphas/c nat/c) (stacked-histogram-alphas)]
          [#:labels labels (labels/c nat/c) '(#f)]
          [#:add-ticks? add-ticks? boolean? #t]
          [#:far-ticks? far-ticks? boolean? #f]
          ) (listof renderer2d?)]{
Returns a list of renderers that draw parts of a stacked histogram.
The heights of each bar section are given as a list.
@examples[#:eval plot-eval
                 (plot (stacked-histogram (list #(a (1 1 1)) #(b (1.5 3))
                                                #(c ()) #(d (1/2)))
                                          #:invert? #t
                                          #:labels '("Red" #f "Blue"))
                       #:legend-anchor 'top-right)]
}

@section{2D Plot Decoration Renderers}

@defproc[(x-axis [y real? 0]
                 [#:ticks? ticks? boolean? (x-axis-ticks?)]
                 [#:labels? labels? boolean? (x-axis-labels?)]
                 [#:far? far? boolean? (x-axis-far?)]
                 [#:alpha alpha (real-in 0 1) (x-axis-alpha)])
         renderer2d?]{
Returns a renderer that draws an @italic{x} axis.
}

@defproc[(y-axis [x real? 0]
                 [#:ticks? ticks? boolean? (y-axis-ticks?)]
                 [#:labels? labels? boolean? (y-axis-labels?)]
                 [#:far? far? boolean? (y-axis-far?)]
                 [#:alpha alpha (real-in 0 1) (y-axis-alpha)])
         renderer2d?]{
Returns a renderer that draws a @italic{y} axis.
}

@defproc[(axes [x real? 0] [y real? 0]
               [#:x-ticks? x-ticks? boolean? (x-axis-ticks?)]
               [#:y-ticks? y-ticks? boolean? (y-axis-ticks?)]
               [#:x-labels? x-labels? boolean? (x-axis-labels?)]
               [#:y-labels? y-labels? boolean? (y-axis-labels?)]
               [#:x-alpha x-alpha (real-in 0 1) (x-axis-alpha)]
               [#:y-alpha y-alpha (real-in 0 1) (y-axis-alpha)])
         (listof renderer2d?)]{
Returns a list containing an @(racket x-axis) renderer and a @(racket y-axis) renderer. See @(racket inverse) for an example.
}

@defproc[(polar-axes [#:number num exact-nonnegative-integer? (polar-axes-number)]
                     [#:ticks? ticks? boolean? (polar-axes-ticks?)]
                     [#:labels? labels? boolean? (polar-axes-labels?)]
                     [#:alpha alpha (real-in 0 1) (polar-axes-alpha)])
         renderer2d?]{
Returns a renderer that draws polar axes. See @(racket polar-interval) for an example.
}

@defproc[(x-tick-lines) renderer2d?]{
Returns a renderer that draws vertical lines from the lower @italic{x}-axis ticks to the upper.
}

@defproc[(y-tick-lines) renderer2d?]{
Returns a renderer that draws horizontal lines from the left @italic{y}-axis ticks to the right.
}

@defproc[(tick-grid) (listof renderer2d?)]{
Returns a list containing an @(racket x-tick-lines) renderer and a @(racket y-tick-lines) renderer.
See @(racket lines-interval) for an example.
}

@defproc[(point-label
          [v (sequence/c real?)] [label (or/c string? #f) #f]
          [#:color color plot-color/c (plot-foreground)]
          [#:size size (>=/c 0) (plot-font-size)]
          [#:face face (or/c string? #f) (plot-font-face)]
          [#:family family font-family/c (plot-font-family)]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:angle angle real? (label-angle)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a labeled point.
If @(racket label) is @(racket #f), the point is labeled with its position.

@interaction[#:eval plot-eval
                    (plot (list (function sqr 0 2)
                                (point-label (vector 1 1))))]

The remaining labeled-point functions are defined in terms of this one.
}

@defproc[(point-pict
          [v (sequence/c real?)]
          [pict pict?]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a point with a pict as the label.

@interaction[#:eval plot-eval
                    (require pict)
                    (plot (list (function sqr 0 2)
                                (point-pict (vector 1 1) (standard-fish 40 15))))]

The remaining labeled-pict functions are defined in terms of this one.
}

@defproc[(function-label
          [f  (real? . -> . real?)] [x real?] [label (or/c string? #f) #f]
          [#:color color plot-color/c (plot-foreground)]
          [#:size size (>=/c 0) (plot-font-size)]
          [#:face face (or/c string? #f) (plot-font-face)]
          [#:family family font-family/c (plot-font-family)]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:angle angle real? (label-angle)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a labeled point on a function's graph.

@interaction[#:eval plot-eval
                    (plot (list (function sin (- pi) pi)
                                (function-label sin (* 1/6 pi) "(1/6 π, 1/2)"
                                                #:anchor 'right)))]
}

@defproc[(function-pict
          [f  (real? . -> . real?)] [x real?] [pict pict?]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a point with a pict as the label on a function's graph.
}

@defproc[(inverse-label
          [f  (real? . -> . real?)] [y real?] [label (or/c string? #f) #f]
          [#:color color plot-color/c (plot-foreground)]
          [#:size size (>=/c 0) (plot-font-size)]
          [#:face face (or/c string? #f) (plot-font-face)]
          [#:family family font-family/c (plot-font-family)]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:angle angle real? (label-angle)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a labeled point on a function's inverted graph.
}

@defproc[(inverse-pict
          [f  (real? . -> . real?)] [y real?] [pict pict?]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a point with a pict as the label on a function's inverted graph.
}


@defproc[(parametric-label
          [f (real? . -> . (sequence/c real?))] [t real?] [label (or/c string? #f) #f]
          [#:color color plot-color/c (plot-foreground)]
          [#:size size (>=/c 0) (plot-font-size)]
          [#:face face (or/c string? #f) (plot-font-face)]
          [#:family family font-family/c (plot-font-family)]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:angle angle real? (label-angle)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a labeled point on a parametric function's graph.
}

@defproc[(parametric-pict
          [f (real? . -> . (sequence/c real?))] [t real?] [pict pict?]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a point with a pict as the label on a parametric function's graph.
}


@defproc[(polar-label
          [f (real? . -> . real?)] [θ real?] [label (or/c string? #f) #f]
          [#:color color plot-color/c (plot-foreground)]
          [#:size size (>=/c 0) (plot-font-size)]
          [#:face face (or/c string? #f) (plot-font-face)]
          [#:family family font-family/c (plot-font-family)]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:angle angle real? (label-angle)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a labeled point on a polar function's graph.
}


@defproc[(polar-pict
          [f (real? . -> . real?)] [θ real?] [pict pict?]
          [#:anchor anchor anchor/c (label-anchor)]
          [#:point-color point-color plot-color/c (point-color)]
          [#:point-fill-color point-fill-color (or/c plot-color/c 'auto) 'auto]
          [#:point-size point-size (>=/c 0) (label-point-size)]
          [#:point-line-width point-line-width (>=/c 0) (point-line-width)]
          [#:point-sym point-sym point-sym/c 'fullcircle]
          [#:alpha alpha (real-in 0 1) (label-alpha)]
          ) renderer2d?]{
Returns a renderer that draws a point with a pict as the label on a polar function's graph.
}

@section[#:tag "2d-plot-snip-interactive-overlays"]{Interactive Overlays for 2D plots}

@defmodule[plot/snip]

A plot @racket[snip%] object returned by @racket[plot-snip] can be set up to
provide interactive overlays.  This feature can be used, for example, to show
the current value of the plot function at the mouse cursor.

If the code below is evaluated in DrRacket, the resulting plot will show a
vertical line tracking the mouse and the current plot position is shown on a
label.  This is achieved by adding a mouse callback to the plot snip returned
by @racket[plot-snip].  When the mouse callback is invoked, it will add a
@racket[vrule] at the current X position and a @racket[point-label] at the
current value of the plotted function.

@racketblock[
(require plot)
(define snip (plot-snip (function sin) #:x-min -5 #:x-max 5))
(define (mouse-callback snip event x y)
   (if (and x y)
       (send snip set-overlay-renderers
             (list (vrule x)
                   (point-label (vector x (sin x)))))
       (send snip set-overlay-renderers #f)))
(send snip set-mouse-event-callback mouse-callback)
snip]

Here are a few hints for adding common interactive elements to racket plots:

@itemlist[

@item{The @racket[hrule] and @racket[vrule] renderers can be used to draw
horizontal and vertical lines that track the mouse position}

@item{The @racket[rectangles] renderer can be used to highlight a region on
the plot.  For example, to highlight a vertical region between @racket[_xmin]
and @racket[_xmax], you can use:

@racketblock[
(rectangles (list (vector (ivl _xmin _xmax) (ivl -inf.0 +inf.0)))
            #:alpha 0.2)]
}

@item{A @racket[point-label] renderer can be used to add a point with a
string label to the plot.  To add only the label, use @racket['none] as the
value for the @racket[#:point-sym] argument.}

@item{A @racket[point-pict] renderer can be used to add a point with an
attached @racketmodname[pict] instead of a string label.  This can be used to
draw fancy labels (for example with rounded corners), or any other type of
graphics element.}

@item{A @racket[points] renderer can be used to mark specific locations on
the plot, without specifying a label for them}
]

@defclass[2d-plot-snip% snip% ()]{

An instance of this class is returned by @racket[plot-snip].

@defmethod[(set-mouse-event-callback [callback (or/c plot-mouse-event-callback/c #f)]) any/c]{

Set a callback function to be invoked with mouse events from the snip.  The
callback is invoked with the actual snip object, the @racket[mouse-event%] and
the X, Y position of the mouse in plot coordinates (i.e., the coordinate system
used by the renderers in the plot).  The X and Y values are
@racket[#f] when the mouse is outside the plot area (for example, when the
mouse is over the axis area).

When a callback is installed, the default zoom functionality of the plot snips
is disabled.  This can be restored by calling
@racket[set-mouse-event-callback] with a @racket[#f] argument.

}

@defmethod[(set-overlay-renderers [renderers (or/c (treeof renderer2d?) #f)]) any/c]{

Set a collection of renderers to be drawn
on top of the existing plot.  This can be any combination of 2D renderers, but
it will not be able to modify the axes or the dimensions of the plot area.
Only one set of overlay renderers can be installed; calling this method a
second time will replace the previous overlays.  Specifying @racket[#f] as the
renderers will cause overlays to be disabled.

}
}

@defthing[plot-mouse-event-callback/c contract? #:value (-> (is-a?/c snip%)
                                                            (is-a?/c mouse-event%)
                                                            (or/c real? #f)
                                                            (or/c real? #f)
                                                            any/c)]{
A contract for callback functions passed to @racket[set-mouse-event-callback].
}