R/xkcdrect.R

Defines functions xkcdrect

Documented in xkcdrect

## Emilio Torres Manzanera
## University of Oviedo
## Time-stamp: <2018-05-23 17:40 emilio on emilio-despacho>
## ============================================================


##' It draws fuzzy rectangles.
##'
##' This function draws fuzzy rectangles.
##'
##'   It plots rectangles. The following aesthetics are required:
##' \enumerate{
##'   \item xmin
##'   \item ymin
##'   \item xmax
##'   \item ymax
##' }
##' Additionally, you can use the aesthetics of \code{\link[ggplot2]{geom_path}} and \code{\link[ggplot2]{geom_rect}}.
##' @title Draw fuzzy rectangles
##' @param mapping Mapping between variables and aesthetics generated by \code{\link[ggplot2]{aes}}. See Details.
##' @param data Dataset used in this layer.
##' @param borderlinewidth The thickness of the fuzzy border lines. This is the package's implementation of the \code{linewidth} aesthetic.
##' @param bordercolour The colour of the fuzzy border lines.
##' @param borderxjitteramount Horizontal jitter amount for the border.
##' @param borderyjitteramount Vertical jitter amount for the border.
##' @param fillcolour The fill colour of the rectangle.
##' @param ... Optional arguments.
##' @return A layer.
##' @seealso \code{\link[ggplot2]{aes}}, \code{\link[ggplot2]{geom_path}}
##' @keywords manip
##' @import ggplot2
##' @importFrom rlang eval_tidy
##' @export
##' @examples
#' \dontrun{
#' volunteers <- data.frame(year = c(2007:2011),
#'                          number = c(56470, 56998, 59686, 61783, 64251))
#' 
#' xrange <- range(volunteers$year)
#' yrange <- range(volunteers$number)
#' 
#' p <- ggplot() + 
#'      xkcdrect(aes(xmin = year - 0.2, 
#'                   xmax = year + 0.2,
#'                   ymin = number - 500,
#'                   ymax = number + 500),
#'               data = volunteers, 
#'               fillcolour = "pink",
#'               borderlinewidth = 1.2) +
#'      geom_point(aes(x = year, y = number), data = volunteers) +
#'      xkcdaxis(xrange, yrange) +
#'      theme_xkcd()
#' p
#' }
xkcdrect <- function(mapping, data, ...,
                     fillcolour = "grey90", bordercolour = "black",
                     borderlinewidth = 0.5, borderxjitteramount = 0.005,
                     borderyjitteramount = 0.005) {
  
  # Evaluate the mapping to compute xmin, xmax, ymin, ymax
  # Use rlang::eval_tidy to properly evaluate quosures
  data$xmin_computed <- rlang::eval_tidy(mapping$xmin, data = data)
  data$xmax_computed <- rlang::eval_tidy(mapping$xmax, data = data)
  data$ymin_computed <- rlang::eval_tidy(mapping$ymin, data = data)
  data$ymax_computed <- rlang::eval_tidy(mapping$ymax, data = data)
  
  # 1. Fill Layer (uses standard geom_rect)
  filllayer <- geom_rect(mapping, data, fill = fillcolour, colour = NA, ...)
  
  # 2. Border Layers (uses modernized geom_xkcdpath for each side)
  # Now we can reference the computed columns directly
  
  # Upper Line (top edge: xmin,ymax -> xmax,ymax)
  upperline <- geom_xkcdpath(
    mapping = aes(x = xmin_computed, y = ymax_computed, 
                  xend = xmax_computed, yend = ymax_computed),
    data = data,
    colour = bordercolour,
    linewidth = borderlinewidth,
    yjitteramount = borderyjitteramount,
    mask = FALSE,
    ...
  )
  
  # Right Line (right edge: xmax,ymin -> xmax,ymax)
  rightline <- geom_xkcdpath(
    mapping = aes(x = xmax_computed, y = ymin_computed, 
                  xend = xmax_computed, yend = ymax_computed),
    data = data,
    colour = bordercolour,
    linewidth = borderlinewidth,
    xjitteramount = borderxjitteramount,
    mask = FALSE,
    ...
  )
  
  # Left Line (left edge: xmin,ymin -> xmin,ymax)
  leftline <- geom_xkcdpath(
    mapping = aes(x = xmin_computed, y = ymin_computed, 
                  xend = xmin_computed, yend = ymax_computed),
    data = data,
    colour = bordercolour,
    linewidth = borderlinewidth,
    xjitteramount = borderxjitteramount,
    mask = FALSE,
    ...
  )
  
  # Bottom Line (bottom edge: xmin,ymin -> xmax,ymin)
  bottomline <- geom_xkcdpath(
    mapping = aes(x = xmin_computed, y = ymin_computed, 
                  xend = xmax_computed, yend = ymin_computed),
    data = data,
    colour = bordercolour,
    linewidth = borderlinewidth,
    yjitteramount = borderyjitteramount,
    mask = FALSE,
    ...
  )
  
  # Combine all layers
  list(filllayer, upperline, rightline, leftline, bottomline)
}

if (getRversion() >= "2.15.1") utils::globalVariables(c("xmin_computed", "xmax_computed", "ymin_computed", "ymax_computed"))

Try the xkcd package in your browser

Any scripts or data that you put into this service are public.

xkcd documentation built on Nov. 20, 2025, 1:07 a.m.