Find the point on each curve which maximizes the distance to the plot border or to another curve.
far.from.others.borders <- function(all.groups,...,debug=FALSE){ group.data <- split(all.groups, all.groups$group) group.list <- list() for(groups in names(group.data)){ ## Run linear interpolation to get a set of points on which we ## could place the label (this is useful for e.g. the lasso path ## where there are only a few points plotted). approx.list <- with(group.data[[groups]], approx(x, y)) if(debug){ with(approx.list, grid.points(x, y, default.units="cm")) } group.list[[groups]] <- data.frame(approx.list, groups) } output <- data.frame() for(group.i in seq_along(group.list)){ one.group <- group.list[[group.i]] ## From Mark Schmidt: "For the location of the boxes, I found the ## data point on the line that has the maximum distance (in the ## image coordinates) to the nearest data point on another line or ## to the image boundary." dist.mat <- matrix(NA, length(one.group$x), 3) colnames(dist.mat) <- c("x","y","other") ## dist.mat has 3 columns: the first two are the shortest distance ## to the nearest x and y border, and the third is the shortest ## distance to another data point. for(xy in c("x", "y")){ xy.vec <- one.group[,xy] xy.mat <- rbind(xy.vec, xy.vec) lim.fun <- get(sprintf("%slimits", xy)) diff.mat <- xy.mat - lim.fun() dist.mat[,xy] <- apply(abs(diff.mat), 2, min) } other.groups <- group.list[-group.i] other.df <- do.call(rbind, other.groups) for(row.i in 1:nrow(dist.mat)){ r <- one.group[row.i,] other.dist <- with(other.df, (x-r$x)^2 + (y-r$y)^2) dist.mat[row.i,"other"] <- sqrt(min(other.dist)) } shortest.dist <- apply(dist.mat, 1, min) picked <- calc.boxes(one.group[which.max(shortest.dist),]) ## Mark's label rotation: "For the angle, I computed the slope ## between neighboring data points (which isn't ideal for noisy ## data, it should probably be based on a smoothed estimate)." left <- max(picked$left, min(one.group$x)) right <- min(picked$right, max(one.group$x)) neighbors <- approx(one.group$x, one.group$y, c(left, right)) slope <- with(neighbors, (y[2]-y[1])/(x[2]-x[1])) picked$rot <- 180*atan(slope)/pi output <- rbind(output, picked) } output }
Please contact Toby Dylan Hocking if you are using directlabels or have ideas to contribute, thanks! |
Documentation website generated from source code version 2021.2.24 (git revision bb6db07 Mon, 14 Jun 2021 22:38:45 +0530) using inlinedocs. |
validate |