@@ -49,11 +49,12 @@ callouts.default <- function(x, y=NULL, labels=NA, length=0.1, angle='auto', cex
4949 return ()
5050 }
5151
52- stopifnot(angle == ' auto' | (angle > = 0 & angle < = 360 ))
52+ stopifnot(all( angle == ' auto' | is.na (angle ) | ( angle > = 0 & angle < = 360 ) ))
5353
5454 x <- x [! is.na(labels )]
5555 y <- y [! is.na(labels )]
5656 labels <- labels [! is.na(labels )]
57+ if (length(angle ) > 1 ){angle [! is.na(labels )]}
5758
5859 # // to do: possibly support angle and length as vectors equal in length to x
5960 x.usr <- par(" usr" )[c(1 ,2 )]
@@ -66,30 +67,58 @@ callouts.default <- function(x, y=NULL, labels=NA, length=0.1, angle='auto', cex
6667 xrange <- diff(x.usr )
6768 yrange <- diff(y.usr )
6869
69- if (angle != " auto" ) {
70- x1 <- x + length * xrange * cos(2 * pi * (angle / 360 ))
71- y1 <- y + length * yrange * sin(2 * pi * (angle / 360 ))
70+ calc_x1y1 <- function (x , y , angle , length , xrange , yrange , x.usr , y.usr ){
71+
72+ if (is.na(angle ) | angle == " auto" ) {
73+ auto.angle <- c(30 , 330 , 150 , 210 )
74+ x1 <- sapply(auto.angle , function (a ) {
75+ x + length * xrange * cos(2 * pi * (a / 360 ))
76+ })
77+ y1 <- sapply(auto.angle , function (a ) {
78+ y + length * yrange * sin(2 * pi * (a / 360 ))
79+ })
80+
81+ good.y1 <- y1 > = y.usr [1 ] & y1 < = y.usr [2 ]
82+ good.x1 <- x1 > = x.usr [1 ] & x1 < = x.usr [2 ]
83+ good.pt <- good.y1 & good.x1
84+ if (! is.null(dim(good.pt ))){
85+ angle <- auto.angle [apply(good.pt , 1 , function (z ){
86+ ifelse(! any(z ), 1 , min(which(z )))
87+ })]
88+ } else {
89+ angle <- auto.angle [ifelse(! any(good.pt ), 1 , min(which(good.pt )))]
90+ }
91+ x1 <- x + length * xrange * cos(2 * pi * (angle / 360 ))
92+ y1 <- y + length * yrange * sin(2 * pi * (angle / 360 ))
93+ } else {
94+ x1 <- x + length * xrange * cos(2 * pi * (angle / 360 ))
95+ y1 <- y + length * yrange * sin(2 * pi * (angle / 360 ))
96+ }
97+
98+ return (list (x1 = x1 , y1 = y1 , angle = angle ))
99+ }
100+
101+ if (length(angle ) == 1 ){
102+ x1_y1_angle <- calc_x1y1(x = x , y = y , angle = angle ,
103+ length , xrange , yrange , x.usr , y.usr )
104+ x1 <- x1_y1_angle $ x1
105+ y1 <- x1_y1_angle $ y1
106+ angle <- x1_y1_angle $ angle
72107 } else {
73- auto.angle <- c(30 , 330 , 150 , 210 )
74- x1 <- sapply(auto.angle , function (a ) {
75- x + length * xrange * cos(2 * pi * (a / 360 ))
76- })
77- y1 <- sapply(auto.angle , function (a ) {
78- y + length * yrange * sin(2 * pi * (a / 360 ))
79- })
108+ stopifnot(length(x )%% length(angle ) == 0 ) # stop if the defined angles aren't a multiple of the points
109+ stopifnot(! is.character(angle )) # stop if it's not a numeric vector ('auto' is not used for the vector)
110+
111+ num_pts <- length(x )
112+ x1 <- vector(mode = " numeric" , length = num_pts )
113+ y1 <- vector(mode = " numeric" , length = num_pts )
80114
81- good.y1 <- y1 > = y.usr [1 ] & y1 < = y.usr [2 ]
82- good.x1 <- x1 > = x.usr [1 ] & x1 < = x.usr [2 ]
83- good.pt <- good.y1 & good.x1
84- if (! is.null(dim(good.pt ))){
85- angle <- auto.angle [apply(good.pt , 1 , function (z ){
86- ifelse(! any(z ), 1 , min(which(z )))
87- })]
88- } else {
89- angle <- auto.angle [ifelse(! any(good.pt ), 1 , min(which(good.pt )))]
115+ for (r in seq(num_pts )){
116+ x1_y1_angle <- calc_x1y1(x = x [r ], y = y [r ], angle = angle [r ],
117+ length , xrange , yrange , x.usr , y.usr )
118+ x1 [r ] <- x1_y1_angle $ x1
119+ y1 [r ] <- x1_y1_angle $ y1
120+ angle [r ] <- x1_y1_angle $ angle
90121 }
91- x1 <- x + length * xrange * cos(2 * pi * (angle / 360 ))
92- y1 <- y + length * yrange * sin(2 * pi * (angle / 360 ))
93122 }
94123
95124 pos <- rep(1 , length(angle ))
0 commit comments