Skip to content

Commit 05a3718

Browse files
authored
add color-field 2D renderer (#66)
The new `color-field` 2D renderer allows filling up an area with rectangles of a certain color.
1 parent 0dbfad4 commit 05a3718

File tree

10 files changed

+153
-0
lines changed

10 files changed

+153
-0
lines changed

plot-doc/plot/scribblings/params.scrbl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,14 @@ width should take that into consideration. For example, a width of 86400 may be
310310
as there are 86400 seconds in a day. This candle will be exactly one day in width.
311311
}
312312

313+
@section{Color fields}
314+
315+
@deftogether[((defparam color-field-samples n exact-positive-integer? #:value 20)
316+
(defparam color-field-alpha alpha (real-in 0 1) #:value 1))]{
317+
The default sample rate and opacity used by @racket[color-field].
318+
@history[#:added "7.9"]
319+
}
320+
313321
@section{Contours and Contour Intervals}
314322

315323
@deftogether[(

plot-doc/plot/scribblings/renderer2d.scrbl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,22 @@ fourth, and fifth elements in each vector comprise the open, high, low, and clos
198198
(vector 6 24 36 10 24)))))]
199199
}
200200

201+
@defproc[(color-field
202+
[f (or/c (-> real? real? plot-color/c)
203+
(-> (vector/c real? real?) plot-color/c))]
204+
[x-min (or/c rational? #f) #f] [x-max (or/c rational? #f) #f]
205+
[y-min (or/c rational? #f) #f] [y-max (or/c rational? #f) #f]
206+
[#:samples samples exact-positive-integer? (color-field-samples)]
207+
[#:alpha alpha (real-in 0 1) (color-field-alpha)]
208+
) renderer2d?]{
209+
Returns a renderer that draws rectangles filled with a color based on the center point.
210+
211+
@interaction[#:eval plot-eval
212+
(plot (color-field (λ (x y) (if (< (+ (sqr x) (sqr y)) 1) (random 10) 'black))
213+
-2 2 -2 2))]
214+
@history[#:added "7.9"]
215+
}
216+
201217
@section{2D Line Renderers}
202218

203219
@defproc[(function [f (real? . -> . real?)]

plot-lib/plot/no-gui.rkt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151
error-bars
5252
candlesticks)
5353

54+
(require "private/plot2d/color-field.rkt")
55+
(provide
56+
color-field)
57+
5458
(require "private/plot2d/line.rkt")
5559
(provide
5660
lines

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@
228228
(defparam candlestick-line-style Plot-Pen-Style 'solid)
229229
(defparam2 candlestick-alpha Real Nonnegative-Real 2/3 (unit-ivl 'candlestick-alpha))
230230

231+
232+
;; color fields
233+
234+
(defparam color-field-samples Positive-Integer 20)
235+
(defparam2 color-field-alpha Real Nonnegative-Real 1 (unit-ivl 'color-field-alpha))
236+
231237
;; Contours
232238

233239
(defparam2 contour-samples Integer Positive-Integer 51 (integer>=2 'contour-samples))

plot-lib/plot/private/common/untyped-utils.rkt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
[else
1111
(λ (x y) (sequence-head-vector name (f (vector x y)) 2))]))
1212

13+
(define (fix-a-field-fun name f)
14+
(cond [(procedure-arity-includes? f 2 #t) f]
15+
[else (λ (x y) (f (vector x y)))]))
16+
1317
(define (fix-vector-field3d-fun name f)
1418
(cond [(procedure-arity-includes? f 3 #t)
1519
(λ (x y z) (sequence-head-vector name (f x y z) 3))]
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#lang typed/racket/base
2+
3+
;; Renderers for points and other point-like things.
4+
5+
(require typed/racket/class racket/match racket/list
6+
plot/utils
7+
"../common/type-doc.rkt"
8+
"../common/utils.rkt")
9+
10+
(require/typed
11+
"../common/untyped-utils.rkt"
12+
[fix-a-field-fun (All (A)
13+
(-> Symbol
14+
(U (-> Real Real A)
15+
(-> (Vector Real Real) A))
16+
(-> Real Real A)))])
17+
18+
(provide (all-defined-out))
19+
20+
;; ===================================================================================================
21+
;; color-field
22+
;; similar to point.rkt/vector-field, but draws a square area with a color
23+
24+
(: color-field-render-fun
25+
(-> (-> Real Real Plot-Color)
26+
Positive-Integer
27+
Nonnegative-Real
28+
2D-Render-Proc))
29+
(define ((color-field-render-fun f samples alpha) area)
30+
(match-define (vector (ivl x-min x-max) (ivl y-min y-max)) (send area get-bounds-rect))
31+
32+
(cond
33+
[(and x-min x-max y-min y-max)
34+
(define xs (linear-seq x-min x-max (+ samples 1) #:start? #t #:end? #t))
35+
(define ys (linear-seq y-min y-max (+ samples 1) #:start? #t #:end? #t))
36+
37+
(send area put-alpha alpha)
38+
(send area put-pen 'black 0 'transparent)
39+
(for ([x- (in-list xs)]
40+
[x+ (in-list (cdr xs))])
41+
(define x (/ (+ x- x+) 2))
42+
(for ([y- (in-list ys)]
43+
[y+ (in-list (cdr ys))])
44+
(define y (/ (+ y- y+) 2))
45+
(define c (f x y))
46+
(send area put-brush c 'solid)
47+
(send area put-rect (vector (ivl x- x+)
48+
(ivl y- y+)))))
49+
empty]
50+
[else empty]))
51+
52+
(:: color-field
53+
(->* [(U (-> Real Real Plot-Color)
54+
(-> (Vector Real Real) Plot-Color))]
55+
[(U Real #f) (U Real #f)
56+
(U Real #f) (U Real #f)
57+
#:samples Positive-Integer
58+
#:alpha Nonnegative-Real]
59+
renderer2d))
60+
(define (color-field f [x-min #f] [x-max #f] [y-min #f] [y-max #f]
61+
#:samples [samples (color-field-samples)]
62+
#:alpha [alpha (color-field-alpha)])
63+
(define fail/pos (make-raise-argument-error 'vector-field3d f x-min x-max y-min y-max))
64+
(define fail/kw (make-raise-keyword-error 'vector-field3d))
65+
(cond
66+
[(and x-min (not (rational? x-min))) (fail/pos "#f or rational" 1)]
67+
[(and x-max (not (rational? x-max))) (fail/pos "#f or rational" 2)]
68+
[(and y-min (not (rational? y-min))) (fail/pos "#f or rational" 3)]
69+
[(and y-max (not (rational? y-max))) (fail/pos "#f or rational" 4)]
70+
[(or (> alpha 1) (not (rational? alpha))) (fail/kw "real in [0,1]" '#:alpha alpha)]
71+
[else
72+
(let ([f ((inst fix-a-field-fun Plot-Color) 'color-field f)])
73+
(renderer2d (vector (ivl x-min x-max) (ivl y-min y-max)) #f default-ticks-fun
74+
(color-field-render-fun
75+
f samples alpha)))]))
76+

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@
161161
candlestick-line-width
162162
candlestick-line-style
163163
candlestick-alpha
164+
color-field-samples
165+
color-field-alpha
164166
contour-samples
165167
contour-levels
166168
contour-colors

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#lang racket
2+
(require rackunit
3+
plot
4+
racket/draw
5+
racket/runtime-path
6+
"../helpers.rkt")
7+
8+
;; Tests for: https://github.com/racket/plot/pull/66 : color-field
9+
(define (do-plot-color-field output-fn)
10+
(output-fn
11+
(color-field
12+
(λ (x y)
13+
(define z (make-rectangular x y))
14+
(if (< (magnitude z) 1)
15+
(cond
16+
[(< (magnitude z) 0.5) 'red]
17+
[(< (angle z) 0) 'blue]
18+
[else 'green])
19+
'black))
20+
-2 2 -2 2)))
21+
22+
(define-runtime-path pr66-color-field-data "./test-data/pr66-1.dat")
23+
24+
(define pr66-test-suite
25+
(test-suite
26+
"PR#66: color-field"
27+
(test-case "pr66-color-field"
28+
(check-draw-steps do-plot-color-field pr66-color-field-data))))
29+
30+
(module+ test
31+
(require rackunit/text-ui)
32+
(run-tests pr66-test-suite))
33+
34+
;;
35+
36+
37+
5.46 KB
Binary file not shown.
9.91 KB
Loading

0 commit comments

Comments
 (0)