# ---- Trajectory plotting ----
# ---- Private functions ----
.drawTurningAngles <- function(x, turning.angles, text.displacement.angles = c(pi / 6, -pi / 8)) {
.textAngle <- function(positive) ifelse(positive, text.displacement.angles[1], text.displacement.angles[2])
# There are n steps, but n+1 coordinates
n <- nrow(x) - 1
steps <- x[1:n,]
angles <- x[2:(n+1),]
meanStepLength <- mean(TrajStepLengths(x))
segLen <- 0.8 * meanStepLength
textDisplacement <- 0.3 * meanStepLength
labels <- parse(text = paste("Delta[", 1:n, "]", sep=""))
if (tolower(turning.angles) == "directed") {
# Plot angles which represent angular errors, which reset at each step
graphics::segments(steps$x, steps$y, steps$x + .8 * meanStepLength, steps$y, col = "darkgrey", lty = 2)
textAngle <- Arg(angles$displacement) +
.textAngle(Arg(x$displacement[1]) < Arg(angles$displacement))
graphics::text(steps$x + textDisplacement * cos(textAngle), steps$y + textDisplacement * sin(textAngle),
labels = labels)
plotrix::draw.arc(steps$x, steps$y,
angle1 = Arg(x$displacement[1]), angle2 = Arg(angles$displacement),
radius = 0.4 * meanStepLength)
} else if (tolower(turning.angles) == "random") {
# Plot angles which represent angular errors, which accumulate
graphics::segments(steps$x, steps$y,
steps$x + segLen * cos(Arg(steps$displacement)),
steps$y + segLen * sin(Arg(steps$displacement)),
col = "darkgrey", lty = 2)
textAngle <- Arg(angles$displacement) +
.textAngle(Arg(steps$displacement) < Arg(angles$displacement))
graphics::text(steps$x + textDisplacement * cos(textAngle), steps$y + textDisplacement * sin(textAngle),
labels = labels)
plotrix::draw.arc(steps$x, steps$y,
angle1 = Arg(steps$displacement), angle2 = Arg(angles$displacement),
radius = 0.4 * meanStepLength)
} else {
stop(sprintf("Invalid turning.angles (%s), must be one of 'random' or 'directed'", turning.angles))
}
}
# Private
.drawTrajExtras <- function(x, draw.start.pt = TRUE, start.pt.cex = .8, start.pt.pch = 16, start.pt.col = "black", turning.angles = NULL, ...) {
if (draw.start.pt) {
graphics::points(x$x[1], x$y[1], pch = start.pt.pch, cex = start.pt.cex, col = start.pt.col)
}
if (!is.null(turning.angles)) {
.drawTurningAngles(x, turning.angles)
}
}
# ---- Public functions ----
#' Plot method for trajectories
#'
#' The \code{plot} method for Trajectory objects.
#'
#' @param x An object of class "Trajectory", the trajectory to be plotted.
#' @param add If TRUE, the trajectory is added to the current plot.
#' @param draw.start.pt If TRUE, draws a dot at the start point of the
#' trajectory.
#' @param start.pt.cex Scale to apply when drawing the start point dot.
#' @param start.pt.pch Pch (i.e. plot character, symbol or shape) to apply when
#' drawing the start point dot.
#' @param start.pt.col Colour to apply when drawing the start point dot.
#' @param turning.angles If \code{"random"} or \code{"directed"}, draws step turning
#' angles. \code{"directed"} assumes errors are relative to the first recorded
#' step angle. \code{"random"} assumes errors are relative to the previous step.
#' @param xlim,ylim,xlab,ylab,asp,ann,axes,frame.plot plotting parameters with useful defaults.
#' @param ... Additional arguments are passed to both \code{\link[graphics]{plot}} and \code{\link[graphics]{lines}}.
#'
#' @seealso \code{\link{TrajFromCoords}}
#' @examples
#' set.seed(42)
#' trj <- TrajGenerate(angularErrorSd = 1.3)
#' plot(trj)
#'
#' @importFrom grDevices extendrange
#'
#' @export
plot.Trajectory <- function(x, add = FALSE,
draw.start.pt = TRUE, start.pt.cex = 0.8, start.pt.pch = 16, start.pt.col = "black",
turning.angles = NULL,
xlim = grDevices::extendrange(x$x), ylim = grDevices::extendrange(x$y),
xlab = ifelse(is.null(TrajGetUnits(x)), "x", sprintf("x (%s)", TrajGetUnits(x))),
ylab = ifelse(is.null(TrajGetUnits(x)), "y", sprintf("y (%s)", TrajGetUnits(x))),
ann = graphics::par("ann"), axes = TRUE, frame.plot = axes,
asp = 1, ...) {
if (!add) {
graphics::plot(NULL, xlim = xlim, ylim = ylim, xlab = xlab, ylab = ylab, asp = asp,
ann = ann, axes = axes, frame.plot = frame.plot, ...)
}
graphics::lines(x, draw.start.pt = draw.start.pt,
start.pt.cex = start.pt.cex, start.pt.pch = start.pt.pch, start.pt.col = start.pt.col,
turning.angles = turning.angles, ...)
}
#' Add Trajectory lines to a plot
#'
#' The \code{lines} method for Trajectory objects.
#'
#' @param x An object of class "Trajectory", the trajectory to be plotted.
#' @param draw.start.pt If TRUE, draws a dot at the start point of the
#' trajectory.
#' @param start.pt.cex Scale to apply when drawing the start point dot.
#' @param start.pt.pch Pch (i.e. plot character, symbol or shape) to apply when
#' drawing the start point dot.
#' @param start.pt.col Colour to apply when drawing the start point dot.
#' @param turning.angles If \code{"random"} or \code{"directed"}, draws step turning
#' angles. \code{"directed"} assumes errors are relative to the first recorded
#' step angle. \code{"random"} assumes errors are relative to the previous step.
#' @param ... Additional arguments are passed to \code{\link[graphics]{lines}}.
#'
#' @export
lines.Trajectory <- function(x, draw.start.pt = TRUE, start.pt.cex = 0.8, start.pt.pch = 16, start.pt.col = "black", turning.angles = NULL, ...) {
graphics::lines(y ~ x, data = x, ...)
.drawTrajExtras(x, draw.start.pt, start.pt.cex, start.pt.pch = start.pt.pch, start.pt.col = start.pt.col, turning.angles, ...)
}
#' Add Trajectory points to a plot
#'
#' The \code{points} method for Trajectory objects.
#'
#' @param x An object of class "Trajectory", the trajectory to be plotted.
#' @param draw.start.pt If TRUE, draws a dot at the start point of the
#' trajectory.
#' @param turning.angles If \code{"random"} or \code{"directed"}, draws step turning
#' angles. \code{"directed"} assumes errors are relative to the first recorded
#' step angle. \code{"random"} assumes errors are relative to the previous step.
#' @param ... Additional arguments are passed to \code{\link[graphics]{points}}.
#'
#' @export
points.Trajectory <- function(x, draw.start.pt = TRUE, turning.angles = NULL, ...) {
graphics::points(y ~ x, data = x, ...)
.drawTrajExtras(x, draw.start.pt, turning.angles, ...)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.