SNIC Puzzles

Superpixel-based puzzles from image segmentation

Overview

SNIC (Simple Non-Iterative Clustering) puzzles create pieces based on superpixel segmentation. Unlike regular geometric puzzles, SNIC pieces follow the natural structure of an image, producing organic boundaries that align with visual features. When used without an image, SNIC generates regular superpixel grids ideal for artistic and abstract designs.

NotePackage Requirements

SNIC puzzles require the snic package. Image-based SNIC puzzles also require the magick package for image processing.

install.packages("snic")
install.packages("magick")

Cell Count Variations

make_snic_cells <- function(n) {
  ggplot() +
    geom_puzzle_snic(
      aes(fill = after_stat(piece_id)),
      n_cells = n,
      seed = 42
    ) +
    scale_fill_viridis_c(option = "turbo", guide = "none") +
    coord_fixed() +
    theme_puzzle() +
    labs(title = paste0(n, " cells"))
}

print(make_snic_cells(10) + make_snic_cells(25) + make_snic_cells(50))
# Generate cell count previews in a grid
cells <- c(10, 25, 50)
items <- lapply(cells, function(n) {
  generate_puzzle(type = "snic", grid = c(n), size = c(200, 200), seed = 42, fill_palette = "turbo")
})
render_puzzle_grid(items, ncol = 3, labels = paste(cells, "cells"))

Compactness Variations

The compactness parameter controls how regular the superpixel shapes are. Lower values produce more irregular, image-adaptive shapes; higher values produce more compact, hexagonal shapes.

make_snic_compact <- function(c_val) {
  ggplot() +
    geom_puzzle_snic(
      aes(fill = after_stat(piece_id)),
      n_cells = 20,
      compactness = c_val,
      seed = 42
    ) +
    scale_fill_viridis_c(option = "plasma", guide = "none") +
    coord_fixed() +
    theme_puzzle() +
    labs(title = paste0("compactness = ", c_val))
}

print(make_snic_compact(0.1) + make_snic_compact(0.5) + make_snic_compact(1.0) + make_snic_compact(2.0))
compactness_vals <- c(0.1, 0.5, 1.0, 2.0)
items <- lapply(compactness_vals, function(c_val) {
  generate_puzzle(type = "snic", grid = c(20), size = c(200, 200), seed = 42,
                  compactness = c_val, fill_palette = "plasma")
})
render_puzzle_grid(items, ncol = 4, labels = paste("compactness =", compactness_vals))

Color Palettes

make_snic_palette <- function(pal) {
  ggplot() +
    geom_puzzle_snic(
      aes(fill = after_stat(piece_id)),
      n_cells = 20,
      seed = 42
    ) +
    scale_fill_viridis_c(option = pal, guide = "none") +
    coord_fixed() +
    theme_puzzle() +
    labs(title = pal)
}

print((make_snic_palette("viridis") + make_snic_palette("magma") + make_snic_palette("plasma")) /
(make_snic_palette("inferno") + make_snic_palette("cividis") + make_snic_palette("turbo")))
# Generate all palette previews and combine into a grid
palettes <- c("viridis", "magma", "plasma", "inferno", "cividis", "turbo")
items <- lapply(palettes, function(pal) {
  generate_puzzle(type = "snic", grid = c(20), size = c(200, 200), seed = 42, fill_palette = pal)
})
render_puzzle_grid(items, ncol = 3, labels = palettes)

Offset (Separation)

make_snic_offset <- function(off) {
  ggplot() +
    geom_puzzle_snic(
      aes(fill = after_stat(piece_id)),
      n_cells = 20,
      offset = off, seed = 42
    ) +
    scale_fill_viridis_c(option = "viridis", guide = "none") +
    coord_fixed() +
    theme_puzzle() +
    labs(title = paste0("offset = ", off))
}

print(make_snic_offset(0) + make_snic_offset(5) + make_snic_offset(10) + make_snic_offset(20))
# Generate offset previews in a grid
offsets <- c(0, 5, 10, 20)
items <- lapply(offsets, function(off) {
  generate_puzzle(type = "snic", grid = c(20), size = c(200, 200), seed = 42, offset = off, fill_palette = "viridis")
})
render_puzzle_grid(items, ncol = 4, labels = paste("offset =", offsets))

Seed Type Variations

SNIC supports different seed grid patterns that control the initial placement of superpixel centers:

make_snic_seed_type <- function(st) {
  ggplot() +
    geom_puzzle_snic(
      aes(fill = after_stat(piece_id)),
      n_cells = 20,
      seed_type = st,
      seed = 42
    ) +
    scale_fill_viridis_c(option = "magma", guide = "none") +
    coord_fixed() +
    theme_puzzle() +
    labs(title = st)
}

print(make_snic_seed_type("hexagonal") + make_snic_seed_type("rectangular") +
make_snic_seed_type("diamond") + make_snic_seed_type("random"))
seed_types <- c("hexagonal", "rectangular", "diamond", "random")
items <- lapply(seed_types, function(st) {
  generate_puzzle(type = "snic", grid = c(20), size = c(200, 200), seed = 42,
                  seed_type = st, fill_palette = "magma")
})
render_puzzle_grid(items, ncol = 4, labels = seed_types)

Seed Variations

Different seeds create completely different segmentation patterns:

make_snic_seed <- function(s) {
  ggplot() +
    geom_puzzle_snic(
      aes(fill = after_stat(piece_id)),
      n_cells = 15,
      seed = s
    ) +
    scale_fill_viridis_c(option = "cividis", guide = "none") +
    coord_fixed() +
    theme_puzzle() +
    labs(title = paste0("seed = ", s))
}

print(make_snic_seed(1) + make_snic_seed(42) + make_snic_seed(123) + make_snic_seed(999))
seeds <- c(1, 42, 123, 999)
items <- lapply(seeds, function(s) {
  generate_puzzle(type = "snic", grid = c(15), size = c(200, 200), seed = s, fill_palette = "cividis")
})
render_puzzle_grid(items, ncol = 4, labels = paste("seed =", seeds))

Image-Based Usage

When provided with an image, SNIC creates pieces that follow the image’s visual structure:

# Use the package's bundled sample image
sample_image <- system.file("extdata", "sample_image.jpg", package = "jigsawR")

# Generate SNIC puzzle from an image
result <- generate_puzzle(
  type = "snic",
  grid = c(30),
  size = c(300, 400),
  seed = 42,
  image_path = sample_image,
  compactness = 0.5,
  seed_type = "hexagonal"
)

# Preview
render_puzzle_preview(result)
Tip

Image-based SNIC puzzles adapt piece boundaries to follow edges and features in the image, creating pieces that feel natural and meaningful rather than arbitrary.

Parameters Reference

Parameter Type Default Description
n_cells integer 50 Number of superpixel cells (pieces)
compactness numeric 0.5 Superpixel compactness (0.0-2.0). Higher = more regular shapes
seed_type string “hexagonal” Seed grid pattern: "hexagonal", "rectangular", "diamond", "random"
image_path string NULL Path to image file (optional; enables image-based segmentation)
seed integer random Random seed for reproducibility
offset numeric 0 (mm) Piece separation distance
tabsize numeric 6 (%) Tab size as percentage of edge length
jitter numeric 2 (%) Randomness in tab shape as percentage
min_tab_size numeric 0 (mm) Minimum tab size in millimeters
max_tab_size numeric Inf (mm) Maximum tab size in millimeters
fusion_groups string NULL PILES notation for fusing pieces

Code Example

ggplot() +
  geom_puzzle_snic(
    aes(fill = after_stat(piece_id)),
    n_cells = 30,
    width = 400, height = 300,
    compactness = 0.5,
    seed_type = "hexagonal",
    seed = 42,
    offset = 5
  ) +
  scale_fill_viridis_c(option = "turbo", guide = "none") +
  coord_fixed() +
  theme_puzzle()
# Generate puzzle
result <- generate_puzzle(
  type = "snic",
  grid = c(30),          # 30 cells
  size = c(300, 400),    # height=300mm, width=400mm
  seed = 42,
  compactness = 0.5,
  seed_type = "hexagonal",
  offset = 5
)

# writeLines(result$svg_content, "snic_puzzle.svg")

# Preview
render_puzzle_preview(result)

When to Use SNIC

SNIC puzzles are ideal for:

  • Photo puzzles: Pieces follow image features for a natural feel
  • Artistic designs: Organic superpixel shapes create unique patterns
  • Variable regularity: Compactness controls shape uniformity
  • Grid pattern variety: Four seed types offer distinct visual styles