FField/0000755000175100001440000000000012163223261011417 5ustar hornikusersFField/MD50000644000175100001440000000045512163223261011733 0ustar hornikusersbae2188cf1dd86cb21f4443d7bd2160e *DESCRIPTION df390c53434517b304ac5db487184641 *NAMESPACE ca897fa5edc1a80a0a0916745efbd0f3 *R/FField.R f3a5e5f2dd1fda0614be120e439e59c3 *man/FField-package.Rd 4b0e35c9143509bad2a375cbec3d15c1 *man/FFieldPtRep.Rd 93c24e31f005f923ee5230173250a448 *man/FFieldPtRepDemo.Rd FField/man/0000755000175100001440000000000012163040241012165 5ustar hornikusersFField/man/FFieldPtRepDemo.Rd0000755000175100001440000000103612163043264015400 0ustar hornikusers\name{FFieldPtRepDemo} \alias{FFieldPtRepDemo} \title{Label placement using force field simulation} \description{ Demonstrates force field simulation of interaction of set of points to place labels on a scatterplot. } \usage{ FFieldPtRepDemo() } \details{ Points experience repulsion from one another and attraction to their original positions. Coordinates are normalized and unadjusted and adjusted plots provided. } \examples{ FFieldPtRepDemo() } \seealso{ \link{FField-package} \code{\link{FFieldPtRep}} } FField/man/FFieldPtRep.Rd0000755000175100001440000000440512163152766014606 0ustar hornikusers\name{FFieldPtRep} \alias{FFieldPtRep} \title{Force field simulation for a set of points} \description{ Force field simulation of interaction of set of points. } \usage{ FFieldPtRep(coords, rep.fact = 20, rep.dist.lmt = 10, attr.fact = 0.2, adj.max = 0.1, adj.lmt = 0.5, iter.max = 10000) } \arguments{ \item{coords}{ matrix or data.frame consisting of two columns (x and y coordinates). } \item{rep.fact}{ repulsion force factor. } \item{rep.dist.lmt}{ repulsion distance limit. } \item{attr.fact}{ attraction force factor. } \item{adj.max}{ maximum position adjustment at each iteration. } \item{adj.lmt}{ position adjustment limit at which the simulation stops. } \item{iter.max}{ the maximum number of iterations beyond which simulation will end and a warning will be reported. } } \details{ Points experience repulsion from one another and attraction to their original positions. Repulsion is inversely proportional to the square of the distance. Attraction is directly proportional to the distance. Very useful for placing text labels on graphs, such as scatterplots. Depending on the nature of the plot, parameters may need to be masaged for the simulation to converge. Assumes 1x1 coordinate aspect ratio and re-scaling of inputs may be needed. Default arguments are appropriate for adjusting 20-30 labels on a 100x100 area. } \examples{ library(ggplot2) # Normalize coordinates to maintain constant aspect ratio x.fact <- 100 / max(mtcars$wt) y.fact <- 100 / max(mtcars$mpg) # Repel points coords <- FFieldPtRep(coords = cbind(mtcars$wt * x.fact, mtcars$mpg * y.fact), rep.fact = 40) # Convert back to plot coordinates x.t <- coords$x / x.fact y.t <- coords$y / y.fact # Sample plot with repelled labels p2 <- (ggplot(mtcars, aes(x = wt, y = mpg, label = rownames(mtcars))) + geom_point() + geom_text(x = x.t, y = y.t) + geom_segment(data = mtcars, xend = x.t, yend = y.t) + ggtitle("After")) p2 } \seealso{ \link{FField-package} \code{\link{FFieldPtRepDemo}} }FField/man/FField-package.Rd0000755000175100001440000000152712163043447015221 0ustar hornikusers\name{FField-package} \docType{package} \alias{FField} \alias{FField-package} \title{Force field simulation for a set of points} \description{ Force field simulation of interaction of set of points. Very useful for placing text labels on graphs, such as scatterplots. } \details{ FFieldPtRep(): Performs force field simulation of mutual repulsion by set of points. FFieldPtRepDemo(): Demonstrates the utility of FFieldPtRep for placing labels in a scatterplot. } \author{Grigori Kapoustin} \examples{ # Repel points coords <- FFieldPtRep(coords = cbind(mtcars$wt * 100 / max(mtcars$wt), mtcars$mpg * 100 / max(mtcars$mpg)), rep.fact = 40) head(mtcars) head(coords) # Demo FFieldPtRepDemo() } \keyword{package} \seealso{ \code{\link{FFieldPtRep}} \link{FFieldPtRepDemo} }FField/R/0000755000175100001440000000000012162665723011634 5ustar hornikusersFField/R/FField.R0000755000175100001440000001362312163153062013105 0ustar hornikusers# FField.R #################################################################### # FField Package # Author: Grigori Kapoustin, 2013 # License: GPL-3 # Force field simulation for mutual repulsion by set of points. # Very useful for placing text labels on graphs, such as scatterplots. # 'wt' should be regarded as defined globally # when the check tool is applied to this package. if (getRversion() >= '2.15.1') { globalVariables("wt") } FFieldPtRep <- function(coords, rep.fact = 20, rep.dist.lmt = 10, attr.fact = 0.2, adj.max = 0.1, adj.lmt = 0.5, iter.max = 10000) { # Performs force field simulation for mutual repulsion by set of points. # Points experience repulsion from one another and attraction to # their original positions. # Repulsion is inversely proportional to the # square of the distance. # Attraction is directly proportional to the distance. # Very useful for placing text labels on graphs, such as scatterplots. # Depending on the nature of the plot, parameters may need to be masaged # for the simulation to converge. # Assumes 1x1 coordinate aspect ration and re-scaling of inputs # may be needed. # # Args: # coords: matrix or data.frame consisting of two columns # (x and y coordinates). # rep.fact: repulsion force factor. # rep.dist.lmt: repulsion distance limit. # attr.fact: attraction force factor. # adj.max: maximum position adjustment at each iteration. # adj.lmt: position adjustment limit at which the simulation stops. # iter.max: the maximum number of iterations beyond which simulation # will end and a warning will be reported. # # Returns: # coordinates of the points at completion of the simulation if (length(dim(coords)) != 2) { stop("FFieldPtRep: dim(coords) must be 2\n") } if (ncol(coords) < 2) { stop("FFieldPtRep: ncol(coords) must be >= 2\n") } if (nrow(coords) < 2) { stop("FFieldPtRep: nrow(coords) must be >= 2\n") } coords <- as.data.frame(coords) colnames(coords)[(1:2)] <- c("x", "y") coords.orig <- coords FVCalc <- function(vects.x, vects.y, f.fact, f.type = "invsq") { # Force vector calculation common code d.sq <- (vects.x ^ 2 + vects.y ^ 2) d <- sqrt(d.sq) # Normalize the vectors vects.x <- vects.x / d vects.y <- vects.y / d # Get the force vector matrices if (f.type == "invsq") { d.sq[d >= rep.dist.lmt] <- Inf vect.f.x <- vects.x / d.sq * f.fact vect.f.y <- vects.y / d.sq * f.fact } else if (f.type == "lin") { vect.f.x <- vects.x * d * f.fact vect.f.y <- vects.y * d * f.fact } else { stop("FFieldPtRep: Unexpected f.type\n") } # Remove NaNs that occur when d == 0 # (occuring when calculating the repulsion of point # and itself and the attraction of point at the origin and the origin). vect.f.x[is.na(vect.f.x)] <- 0 vect.f.y[is.na(vect.f.y)] <- 0 # Combine the force vectors acting upon each point f.vect <- cbind(colSums(vect.f.x), colSums(vect.f.y)) return (f.vect) } iter <- 0 repeat { # Calculate repulsion forces. # Direction is from other points to a given point. vects.x <- apply(coords, 1, function(c) (c[1] - coords$x)) vects.y <- apply(coords, 1, function(c) (c[2] - coords$y)) f.rep.v <- FVCalc(vects.x = vects.x, vects.y = vects.y, f.fact = rep.fact, f.type = "invsq") # Calculate attraction forces. # Direction is from each point to its original position. vects.orig <- coords.orig - coords f.attr.v <- FVCalc(vects.x = t(as.matrix(vects.orig$x)), vects.y = t(as.matrix(vects.orig$y)), f.fact = attr.fact, f.type = "lin") # Combine the forces. f.v <- f.rep.v + f.attr.v if (all(abs(f.v) <= adj.lmt)) { break() } # Adjust the coordinates mv.vect <- apply(f.v, c(1, 2), function(x) sign(x) * min(abs(x), adj.max)) coords <- coords + mv.vect if ((iter <- iter + 1) > iter.max) { warning("FFieldPtRep: Maximum iterations exceeded ", "without convergence.\n") break() } } return(coords) } FFieldPtRepDemo <- function() { # Demonstrates the utility of FFieldPtRep for placing labels # in a scatterplot. # # Args: # none # # Returns: # none library(ggplot2) library(gridExtra) # Sample plot with crowded labels p1 <- (ggplot(mtcars, aes(x = wt, y = mpg, label = rownames(mtcars))) + geom_point() + geom_text() + ggtitle("Before")) # Normalize coordinates to maintain constant aspect ratio x.fact <- 100 / max(mtcars$wt) y.fact <- 100 / max(mtcars$mpg) # Repel points coords <- FFieldPtRep(coords = cbind(mtcars$wt * x.fact, mtcars$mpg * y.fact), rep.fact = 40) # Convert back to plot coordinates x.t <- coords$x / x.fact y.t <- coords$y / y.fact # Sample plot with repelled labels p2 <- (ggplot(mtcars, aes(x = wt, y = mpg, label = rownames(mtcars))) + geom_point() + geom_text(x = x.t, y = y.t) + geom_segment(data = mtcars, xend = x.t, yend = y.t) + ggtitle("After")) grid.arrange(p1, p2) } FField/NAMESPACE0000755000175100001440000000004012162665723012647 0ustar hornikusersexportPattern("^[[:alpha:]]+") FField/DESCRIPTION0000755000175100001440000000077612163223261013142 0ustar hornikusersPackage: FField Type: Package Title: Force field simulation for a set of points Version: 0.1.0 Date: 2013-06-26 Author: Grigori Kapoustin Maintainer: Grigori Kapoustin Description: Force field simulation of interaction of set of points. Very useful for placing text labels on graphs, such as scatterplots. Suggests: ggplot2, gridExtra License: GPL-3 Packaged: 2013-06-28 05:07:46 UTC; gregk NeedsCompilation: no Repository: CRAN Date/Publication: 2013-06-28 08:01:21