7
7
# ' @param expand If `TRUE`, the default, adds a small expansion factor the
8
8
# ' the limits to prevent overlap between data and axes. If `FALSE`, limits
9
9
# ' are taken directly from the scale.
10
- # ' @param r.axis.inside If `TRUE`, places the radius axis inside the
11
- # ' panel. If `FALSE`, places the radius axis next to the panel. The default,
12
- # ' `NULL`, places the radius axis outside if the `start` and `end` arguments
13
- # ' form a full circle.
10
+ # ' @param r.axis.inside One of the following:
11
+ # ' * `NULL` (default) places the axis next to the panel if `start` and
12
+ # ' `end` arguments form a full circle and inside the panel otherwise.
13
+ # ' * `TRUE` to place the radius axis inside the panel.
14
+ # ' * `FALSE` to place the radius axis next to the panel.
15
+ # ' * A numeric value, setting a theta axis value at which
16
+ # ' the axis should be placed inside the panel. Can be given as a length 2
17
+ # ' vector to control primary and secondary axis placement separately.
14
18
# ' @param rotate.angle If `TRUE`, transforms the `angle` aesthetic in data
15
19
# ' in accordance with the computed `theta` position. If `FALSE` (default),
16
20
# ' no such transformation is performed. Can be useful to rotate text geoms in
@@ -58,7 +62,10 @@ coord_radial <- function(theta = "x",
58
62
59
63
theta <- arg_match0(theta , c(" x" , " y" ))
60
64
r <- if (theta == " x" ) " y" else " x"
61
- check_bool(r.axis.inside , allow_null = TRUE )
65
+ if (! is.numeric(r.axis.inside )) {
66
+ check_bool(r.axis.inside , allow_null = TRUE )
67
+ }
68
+
62
69
check_bool(expand )
63
70
check_bool(rotate.angle )
64
71
check_number_decimal(start , allow_infinite = FALSE )
@@ -130,12 +137,29 @@ CoordRadial <- ggproto("CoordRadial", Coord,
130
137
},
131
138
132
139
setup_panel_params = function (self , scale_x , scale_y , params = list ()) {
133
- c(
140
+
141
+ params <- c(
134
142
view_scales_polar(scale_x , self $ theta , expand = self $ expand ),
135
143
view_scales_polar(scale_y , self $ theta , expand = self $ expand ),
136
144
list (bbox = polar_bbox(self $ arc , inner_radius = self $ inner_radius ),
137
145
arc = self $ arc , inner_radius = self $ inner_radius )
138
146
)
147
+
148
+ axis_rotation <- self $ r_axis_inside
149
+ if (is.numeric(axis_rotation )) {
150
+ theta_scale <- switch (self $ theta , x = scale_x , y = scale_y )
151
+ axis_rotation <- theta_scale $ transform(axis_rotation )
152
+ axis_rotation <- oob_squish(axis_rotation , params $ theta.range )
153
+ axis_rotation <- theta_rescale(
154
+ axis_rotation , params $ theta.range ,
155
+ params $ arc , 1
156
+ )
157
+ params $ axis_rotation <- rep_len(axis_rotation , length.out = 2 )
158
+ } else {
159
+ params $ axis_rotation <- params $ arc
160
+ }
161
+
162
+ params
139
163
},
140
164
141
165
setup_panel_guides = function (self , panel_params , guides , params = list ()) {
@@ -173,18 +197,17 @@ CoordRadial <- ggproto("CoordRadial", Coord,
173
197
opposite_r <- isTRUE(scales $ r $ position %in% c(" bottom" , " left" ))
174
198
}
175
199
176
- if (self $ r_axis_inside ) {
200
+ if (! isFALSE( self $ r_axis_inside ) ) {
177
201
178
- arc <- rad2deg(self $ arc )
179
202
r_position <- c(" left" , " right" )
180
203
# If both opposite direction and opposite position, don't flip
181
204
if (xor(self $ direction == - 1 , opposite_r )) {
182
- arc <- rev(arc )
183
205
r_position <- rev(r_position )
184
206
}
185
-
186
- guide_params [[" r" ]]$ position <- r_position [1 ]
187
- guide_params [[" r.sec" ]]$ position <- r_position [2 ]
207
+ arc <- rad2deg(panel_params $ axis_rotation ) * self $ direction
208
+ if (opposite_r ) {
209
+ arc <- rev(arc )
210
+ }
188
211
# Set guide text angles
189
212
guide_params [[" r" ]]$ angle <- guide_params [[" r" ]]$ angle %| W | % arc [1 ]
190
213
guide_params [[" r.sec" ]]$ angle <- guide_params [[" r.sec" ]]$ angle %| W | % arc [2 ]
@@ -193,9 +216,9 @@ CoordRadial <- ggproto("CoordRadial", Coord,
193
216
if (opposite_r ) {
194
217
r_position <- rev(r_position )
195
218
}
196
- guide_params [[" r" ]]$ position <- r_position [1 ]
197
- guide_params [[" r.sec" ]]$ position <- r_position [2 ]
198
219
}
220
+ guide_params [[" r" ]]$ position <- r_position [1 ]
221
+ guide_params [[" r.sec" ]]$ position <- r_position [2 ]
199
222
200
223
guide_params [drop_guides ] <- list (NULL )
201
224
guides $ update_params(guide_params )
@@ -223,7 +246,7 @@ CoordRadial <- ggproto("CoordRadial", Coord,
223
246
gdefs [[t ]] <- guides [[t ]]$ get_layer_key(gdefs [[t ]], layers )
224
247
}
225
248
226
- if (self $ r_axis_inside ) {
249
+ if (! isFALSE( self $ r_axis_inside ) ) {
227
250
# For radial axis, we need to pretend that rotation starts at 0 and
228
251
# the bounding box is for circles, otherwise tick positions will be
229
252
# spaced too closely.
@@ -273,14 +296,14 @@ CoordRadial <- ggproto("CoordRadial", Coord,
273
296
},
274
297
275
298
render_axis_v = function (self , panel_params , theme ) {
276
- if (self $ r_axis_inside ) {
299
+ if (! isFALSE( self $ r_axis_inside ) ) {
277
300
return (list (left = zeroGrob(), right = zeroGrob()))
278
301
}
279
302
CoordCartesian $ render_axis_v(panel_params , theme )
280
303
},
281
304
282
305
render_axis_h = function (self , panel_params , theme ) {
283
- if (self $ r_axis_inside ) {
306
+ if (! isFALSE( self $ r_axis_inside ) ) {
284
307
return (list (top = zeroGrob(), bottom = zeroGrob()))
285
308
}
286
309
CoordCartesian $ render_axis_h(panel_params , theme )
@@ -303,8 +326,8 @@ CoordRadial <- ggproto("CoordRadial", Coord,
303
326
if (length(theta_min ) > 0 ) {
304
327
theta_min <- theta_rescale(theta_min , theta_lim , arc , dir )
305
328
}
306
- theta_fine <- seq(self $ arc [1 ], self $ arc [2 ], length.out = 100 )
307
329
330
+ theta_fine <- theta_rescale(seq(0 , 1 , length.out = 100 ), c(0 , 1 ), arc , dir )
308
331
r_fine <- r_rescale(panel_params $ r.major , panel_params $ r.range ,
309
332
panel_params $ inner_radius )
310
333
@@ -345,10 +368,8 @@ CoordRadial <- ggproto("CoordRadial", Coord,
345
368
theta_grid(theta_min , grid_elems [[2 ]], inner_radius , bbox ),
346
369
element_render(
347
370
theme , majorr , name = " radius" ,
348
- x = rescale(rep(r_fine , each = length(theta_fine )) *
349
- rep(sin(theta_fine ), length(r_fine )) + 0.5 , from = bbox $ x ),
350
- y = rescale(rep(r_fine , each = length(theta_fine )) *
351
- rep(cos(theta_fine ), length(r_fine )) + 0.5 , from = bbox $ y ),
371
+ x = rescale(outer(sin(theta_fine ), r_fine ) + 0.5 , from = bbox $ x ),
372
+ y = rescale(outer(cos(theta_fine ), r_fine ) + 0.5 , from = bbox $ y ),
352
373
id.lengths = rep(length(theta_fine ), length(r_fine )),
353
374
default.units = " native"
354
375
)
@@ -359,7 +380,7 @@ CoordRadial <- ggproto("CoordRadial", Coord,
359
380
360
381
border <- element_render(theme , " panel.border" , fill = NA )
361
382
362
- if (! self $ r_axis_inside ) {
383
+ if (isFALSE( self $ r_axis_inside ) ) {
363
384
out <- grobTree(
364
385
panel_guides_grob(panel_params $ guides , " theta" , theme ),
365
386
panel_guides_grob(panel_params $ guides , " theta.sec" , theme ),
@@ -370,14 +391,15 @@ CoordRadial <- ggproto("CoordRadial", Coord,
370
391
371
392
bbox <- panel_params $ bbox
372
393
dir <- self $ direction
373
- arc <- if (dir == 1 ) self $ arc else rev(self $ arc )
374
- arc <- dir * rad2deg(- arc )
394
+ rot <- panel_params $ axis_rotation
395
+ rot <- if (dir == 1 ) rot else rev(rot )
396
+ rot <- dir * rad2deg(- rot )
375
397
376
398
left <- panel_guides_grob(panel_params $ guides , position = " left" , theme )
377
- left <- rotate_r_axis(left , arc [1 ], bbox , " left" )
399
+ left <- rotate_r_axis(left , rot [1 ], bbox , " left" )
378
400
379
401
right <- panel_guides_grob(panel_params $ guides , position = " right" , theme )
380
- right <- rotate_r_axis(right , arc [2 ], bbox , " right" )
402
+ right <- rotate_r_axis(right , rot [2 ], bbox , " right" )
381
403
382
404
grobTree(
383
405
panel_guides_grob(panel_params $ guides , " theta" , theme ),
@@ -426,7 +448,7 @@ CoordRadial <- ggproto("CoordRadial", Coord,
426
448
},
427
449
428
450
setup_params = function (self , data ) {
429
- if (! self $ r_axis_inside ) {
451
+ if (isFALSE( self $ r_axis_inside ) ) {
430
452
place <- in_arc(c(0 , 0.5 , 1 , 1.5 ) * pi , self $ arc )
431
453
if (place [1 ]) {
432
454
return (list (r_axis = " left" , fake_arc = c(0 , 2 ) * pi ))
0 commit comments