gridpattern gridpattern hex sticker

CRAN Status Badge R-CMD-check Coverage Status

Table of Contents

Overview

gridpattern provides grid.pattern() and patternGrob() functions to use with R’s grid graphics system. They fill in a user-specified boundary path with a user-specified pattern. These pattern grobs include enhanced versions of the patterns originally contained within Mike FC’s awesome ggpattern package as well as original “pch”, “polygon_tiling”, “regular_polygon”, “rose”, “text”, “wave”, and “weave” patterns.

{gridpattern} currently provides {grid} grob support for the following patterns:

  1. ambient: noise array patterns powered by the ambient package
  2. circle: circle geometry patterns
  3. crosshatch: crosshatch geometry patterns
  4. gradient: gradient array/geometry patterns
  5. image: image array patterns
  6. magick: imagemagick array patterns
  7. none (equivalent to grid::null())
  8. placeholder: placeholder image array patterns
  9. plasma: plasma array patterns
  10. pch: plotting character geometry patterns
  11. polygon_tiling: polygon tiling patterns
  12. regular_polygon: regular polygon geometry patterns
  13. rose: rose curve array/geometry patterns
  14. stripe: stripe geometry patterns
  15. text: text array/geometry patterns
  16. wave: wave geometry patterns
  17. weave: weave geometry patterns
  18. custom geometry-based patterns
  19. custom array-based patterns

Installation

To install the development version use the following command in R:

remotes::install_github("trevorld/gridpattern")

Examples

library("grid")
library("gridpattern")
x_hex <- 0.5 + 0.5 * cos(seq(2 * pi / 4, by = 2 * pi / 6, length.out = 6))
y_hex <- 0.5 + 0.5 * sin(seq(2 * pi / 4, by = 2 * pi / 6, length.out = 6))
grid.pattern_circle(x_hex, y_hex, density = 0.5, grid = "hex_circle",
                    fill = c("blue", "yellow", "red"))

grid.pattern_regular_polygon(x_hex, y_hex, shape = c("convex4", "star8", "circle"),
                             colour = "black", fill = c("blue", "yellow", "red"), 
                             density = c(0.45, 0.42, 0.4), spacing = 0.08, angle = 0)

grid.pattern_regular_polygon(x_hex, y_hex, shape = "convex6", grid = "hex",
                             color = "transparent", fill = c("white", "grey", "black"),
                             density = 1.0, spacing = 0.1)

gp <- gpar(fill = c("yellow", "blue", "red"))
grid.pattern_polygon_tiling(x_hex, y_hex, type = "truncated_hexagonal", 
                            spacing = 0.15, gp = gp)

blue <- grDevices::rgb(0.35, 0.70, 0.90)
yellow <- grDevices::rgb(0.95, 0.90, 0.25)
red <- grDevices::rgb(0.80, 0.40, 0.00)
green <- grDevices::rgb(0.00, 0.60, 0.50)
grid.rect(gp = gpar(fill = yellow, col = NA))
gp <- gpar(fill = red, col = "black")
grid.pattern_stripe(grid = "hex_circle", density = 0.25, spacing = 0.3, 
                    angle = 0, gp = gp)
grid.pattern_stripe(grid = "hex_circle", density = 0.25, spacing = 0.3, 
                    angle = -60, gp = gp)
grid.pattern_stripe(grid = "hex_circle", density = 0.25, spacing = 0.3, 
                    angle = 60, gp = gp)
gp <- gpar(fill = blue, col = "black")
grid.pattern_regular_polygon(shape = "convex12", grid = "hex_circle", rot = 15,
                             density = 0.82, spacing = 0.3, angle = 0, gp = gp)
gp <- gpar(fill = green, col = "black")
scale <- star_scale(12, 30)
grid.pattern_regular_polygon(shape = "star12", grid = "hex_circle", rot = 15,
                             density = 0.82, spacing = 0.3, angle = 0, gp = gp,
                             scale = scale)

gp <- gpar(fill = c("blue", "red", "yellow", "green"), col = "black")
grid.newpage()
grid.pattern_rose(x_hex, y_hex,
                  spacing = 0.18, density = 0.5, angle = 0,
                  frequency = c(2, 6/4, 5/4, 3/7), gp = gp)

playing_card_symbols <- c("\u2660", "\u2665", "\u2666", "\u2663")
grid.pattern_text(x_hex, y_hex,
                 shape = playing_card_symbols,
                 colour = c("black", "red", "red", "black"),
                 size = 24, spacing = 0.12, angle = 0)

grid.pattern_wave(x_hex, y_hex, colour = "black", type = "sine",
                  fill = c("red", "blue"), density = 0.4,
                  spacing = 0.15, angle = 0,
                  amplitude = 0.05, frequency = 1 / 0.20)

grid.pattern_weave(x_hex, y_hex, type = "satin", 
             colour = "black", fill = "lightblue", fill2 =  "yellow",
             density = 0.3)

Using these patterns with the “ggpattern” package

The patterns provided by gridpattern can be used to create custom ggpattern geometry-based patterns.

Here is an example of creating a new “multicolor_stripe” pattern that supports comma-separated pattern_fill and/or pattern_colour aesthetics:

library("ggpattern") # remotes::install_github("coolbutuseless/ggpattern")
library("ggplot2", warn.conflicts = FALSE)
library("gridpattern")

multicolor_stripe_pattern <- function(params, boundary_df, aspect_ratio, 
                                      legend = FALSE) {
    args <- as.list(params)
    args <- args[grep("^pattern_", names(args))]

    args$pattern_colour <- strsplit(args$pattern_colour, ",")[[1]]
    args$pattern_fill <- strsplit(args$pattern_fill, ",")[[1]]

    args$pattern <- "stripe"
    args$x <- boundary_df$x
    args$y <- boundary_df$y
    args$id <- boundary_df$id
    args$prefix <- ""

    do.call(gridpattern::patternGrob, args)
}

options(ggpattern_geometry_funcs = list(multicolor_stripe = multicolor_stripe_pattern))
df <- data.frame(trt = c("a", "b", "c"), outcome = c(2.3, 1.9, 3.2))
ggplot(df, aes(trt, outcome)) +
    geom_col_pattern(aes(fill = trt), colour = 'black', 
                     pattern = 'multicolor_stripe',
                     pattern_fill = "grey30,grey70,white,grey70")

And here is an example of creating a “tiling3” pattern that creates three-color polygon tilings using the fill colour, the pattern_fill colour, and their “average” color.

tiling3_pattern <- function(params, boundary_df, aspect_ratio, legend = FALSE) {
    args <- as.list(params)
    args <- args[grep("^pattern_", names(args))]

    # hexagonal tiling using "regular_polygon" pattern
    args$pattern <- "polygon_tiling"

    # three-color tiling using `fill`, `pattern_fill` and their "average"
    avg_col <- gridpattern::mean_col(params$fill, params$pattern_fill)
    args$pattern_fill <- c(params$fill, avg_col, args$pattern_fill)

    args$x <- boundary_df$x
    args$y <- boundary_df$y
    args$id <- boundary_df$id
    args$prefix <- ""

    do.call(gridpattern::patternGrob, args)
}

options(ggpattern_geometry_funcs = list(tiling3 = tiling3_pattern))
df <- data.frame(trt = c("a", "b", "c"), outcome = c(2.3, 1.9, 3.2))
ggplot(df, aes(trt, outcome)) +
    geom_col_pattern(aes(fill = trt, pattern_type = trt), 
                     pattern = 'tiling3', pattern_angle = 45) +
    scale_pattern_type_manual(values = c("hexagonal", "tetrakis_square", "rhombille")) +
    theme(legend.key.size = unit(1.5, 'cm'))

Using these patterns with the “piecepackr” package

piecepackr allows the use of custom grob functions to completely customize the appearance of one’s game pieces. {piecepackr} comes with a variety of convenience functions such as pp_shape() to facilitate creating custom game pieces using custom grob functions. Here is an example of creating “patterned” checkers filled with uniform polygon tilings by using pp_shape() objects’ pattern() method powered by {gridpattern}:

library("grid")
library("gridpattern")
library("piecepackr")

tilings <- c("hexagonal", "snub_square", "pythagorean",
             "truncated_square", "triangular", "trihexagonal")
patternedCheckerGrobFn <- function(piece_side, suit, rank, cfg) {
    opt <- cfg$get_piece_opt(piece_side, suit, rank)
    shape <- pp_shape(opt$shape, opt$shape_t, opt$shape_r, opt$back)
    gp_pattern <- gpar(col=opt$suit_color, fill=c(opt$background_color, "white"))
    pattern_grob <- shape$pattern("polygon_tiling", type = tilings[suit],
                                  spacing = 0.3, name = "pattern",
                                  gp = gp_pattern, angle = 0)
    gp_border <- gpar(col=opt$border_color, fill=NA, lex=opt$border_lex)
    border_grob <- shape$shape(gp=gp_border, name = "border")
    grobTree(pattern_grob, border_grob)
}
checkers1 <- as.list(game_systems()$checkers1)
checkers1$grob_fn.bit <- patternedCheckerGrobFn
checkers1 <- pp_cfg(checkers1)

x1 <- c(1:3, 1:2, 1)
x2 <- c(6:8, 7:8, 8)
df <- tibble::tibble(piece_side = c("board_face", rep_len("bit_back", 24L)),
                     suit = c(6L, rep(c(1L, 3L, 4L, 5L), each = 6L)),
                     rank = 8L,
                     x = c(4.5, x1, rev(x1), x2, rev(x2)),
                     y = c(4.5, rep(c(1,1,1, 2,2, 3, 6, 7,7, 8,8,8), 2)))

pmap_piece(df, cfg=checkers1, default.units="in")