| ---
|
| title: "Basic Usage Tutorial"
|
| subtitle: "Step-by-step guide to creating your first puzzles"
|
| ---
|
|
|
| ```{r}
|
|
|
|
|
|
|
| setup_path <- if (file.exists("quarto/_setup.R")) "quarto/_setup.R" else "../_setup.R"
|
| source(setup_path)
|
| ```
|
|
|
|
|
|
|
| This tutorial walks you through creating puzzles with jigsawR, from simple examples to more complex configurations.
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
|
|
| devtools::install_github("pjt222/jigsawR")
|
|
|
|
|
| library(jigsawR)
|
| ```
|
|
|
|
|
|
|
| Let's create a simple rectangular puzzle. Choose your approach:
|
|
|
| ::: {.panel-tabset}
|
|
|
|
|
|
|
| The ggpuzzle approach integrates with ggplot2 for quick visualization:
|
|
|
| ```{r}
|
|
|
|
|
| library(ggplot2)
|
| library(viridis)
|
|
|
| ggplot() +
|
| geom_puzzle_rect(
|
| aes(fill = after_stat(piece_id)),
|
| cols = 4, rows = 3,
|
| width = 400, height = 300,
|
| seed = 42
|
| ) +
|
| scale_fill_viridis_c(name = "Piece ID") +
|
| coord_fixed() +
|
| theme_minimal() +
|
| labs(title = "My First Puzzle")
|
| ```
|
|
|
| ::: {.callout-tip}
|
| `geom_puzzle_rect()` computes piece geometry and provides `piece_id`, `row`, `col` for mapping.
|
| :::
|
|
|
|
|
|
|
| The API approach gives you full control and access to the SVG data:
|
|
|
| ```{r}
|
|
|
|
|
| result <- generate_puzzle(
|
| type = "rectangular",
|
| grid = c(3, 4),
|
| size = c(300, 400),
|
| seed = 42,
|
| fill_palette = "viridis"
|
| )
|
|
|
|
|
| n_pieces <- length(result$pieces)
|
| canvas_w <- result$canvas_size[1]
|
| canvas_h <- result$canvas_size[2]
|
| cli::cli_alert_info("Number of pieces: {n_pieces}")
|
| cli::cli_alert_info("Canvas size: {canvas_w} x {canvas_h} mm")
|
|
|
|
|
| render_puzzle_preview(result)
|
| ```
|
|
|
| ::: {.callout-tip}
|
| The API returns a list with `$svg_content`, `$pieces`, `$canvas_size`, and `$files`.
|
| :::
|
|
|
| :::
|
|
|
|
|
|
|
| ::: {.panel-tabset}
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
|
|
| p <- ggplot() +
|
| geom_puzzle_rect(
|
| aes(fill = after_stat(piece_id)),
|
| cols = 4, rows = 3,
|
| seed = 42
|
| ) +
|
| scale_fill_viridis_c(guide = "none") +
|
| coord_fixed() +
|
| theme_puzzle()
|
| print(p)
|
|
|
|
|
| ```
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
|
|
| writeLines(result$svg_content, "my_puzzle.svg")
|
| ```
|
|
|
| :::
|
|
|
| ::: {.callout-note}
|
| API generates SVG files, while ggpuzzle uses ggplot2's `ggsave()` for PNG/PDF export.
|
| :::
|
|
|
|
|
|
|
|
|
|
|
| ::: {.panel-tabset}
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
| ggplot() +
|
| geom_puzzle_hex(
|
| aes(fill = after_stat(piece_id)),
|
| rings = 3,
|
| seed = 42
|
| ) +
|
| scale_fill_viridis_c(option = "plasma", guide = "none") +
|
| coord_fixed() +
|
| theme_puzzle() +
|
| labs(title = "Hexagonal Puzzle")
|
| ```
|
|
|
|
|
|
|
| ```{r}
|
|
|
| hex_result <- generate_puzzle(
|
| type = "hexagonal",
|
| grid = c(3),
|
| size = c(200),
|
| seed = 42,
|
| fill_palette = "plasma"
|
| )
|
|
|
| render_puzzle_preview(hex_result)
|
| ```
|
|
|
| :::
|
|
|
|
|
|
|
| ::: {.panel-tabset}
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
| ggplot() +
|
| geom_puzzle_conc(
|
| aes(fill = after_stat(ring)),
|
| rings = 3,
|
| seed = 42
|
| ) +
|
| scale_fill_viridis_c(option = "cividis", name = "Ring") +
|
| coord_fixed() +
|
| theme_puzzle() +
|
| labs(title = "Concentric Puzzle")
|
| ```
|
|
|
|
|
|
|
| ```{r}
|
|
|
| conc_result <- generate_puzzle(
|
| type = "concentric",
|
| grid = c(3),
|
| size = c(200),
|
| seed = 42,
|
| fill_palette = "cividis"
|
| )
|
|
|
| render_puzzle_preview(conc_result)
|
| ```
|
|
|
| :::
|
|
|
|
|
|
|
| ::: {.panel-tabset}
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
| ggplot() +
|
| geom_puzzle_voronoi(
|
| aes(fill = after_stat(piece_id)),
|
| n_cells = 20,
|
| width = 250, height = 200,
|
| seed = 42
|
| ) +
|
| scale_fill_viridis_c(option = "turbo", guide = "none") +
|
| coord_fixed() +
|
| theme_puzzle() +
|
| labs(title = "Voronoi Puzzle")
|
| ```
|
|
|
|
|
|
|
| ```{r}
|
|
|
| vor_result <- generate_puzzle(
|
| type = "voronoi",
|
| grid = c(20),
|
| size = c(200, 250),
|
| seed = 42,
|
| fill_palette = "turbo"
|
| )
|
|
|
| render_puzzle_preview(vor_result)
|
| ```
|
|
|
| :::
|
|
|
|
|
|
|
|
|
|
|
| ::: {.panel-tabset}
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
| make_offset_plot <- function(off) {
|
| ggplot() +
|
| geom_puzzle_rect(
|
| aes(fill = after_stat(piece_id)),
|
| cols = 3, rows = 2,
|
| offset = off,
|
| seed = 42
|
| ) +
|
| scale_fill_viridis_c(guide = "none") +
|
| coord_fixed() +
|
| theme_puzzle() +
|
| labs(title = paste0("offset = ", off))
|
| }
|
|
|
| print(make_offset_plot(0) + make_offset_plot(10) + make_offset_plot(20))
|
| ```
|
|
|
| ## API
|
|
|
| ```{r}
|
| #| label: separation-modes-api
|
| #| layout-ncol: 3
|
| #| fig-cap:
|
| #| - "Complete puzzle (offset = 0)"
|
|
|
|
|
|
|
|
|
| r0 <- generate_puzzle(type = "rectangular", grid = c(2, 3), size = c(200, 300), offset = 0, seed = 42, fill_palette = "viridis")
|
| r10 <- generate_puzzle(type = "rectangular", grid = c(2, 3), size = c(200, 300), offset = 10, seed = 42, fill_palette = "viridis")
|
| r20 <- generate_puzzle(type = "rectangular", grid = c(2, 3), size = c(200, 300), offset = 20, seed = 42, fill_palette = "viridis")
|
|
|
| render_puzzle_preview(r0)
|
| render_puzzle_preview(r10)
|
| render_puzzle_preview(r20)
|
| ```
|
|
|
| :::
|
|
|
|
|
|
|
| The ggpuzzle approach makes it easy to apply different color schemes using ggplot2's scale functions.
|
|
|
| ```{r}
|
|
|
|
|
|
|
|
|
|
|
|
|
| print(ggplot() +
|
| geom_puzzle_hex(
|
| aes(fill = after_stat(piece_id)),
|
| rings = 2, diameter = 150, seed = 42
|
| ) +
|
| scale_fill_viridis_c(option = "plasma", guide = "none") +
|
| coord_fixed() +
|
| theme_puzzle() +
|
| labs(title = "Plasma"))
|
|
|
| print(ggplot() +
|
| geom_puzzle_hex(
|
| aes(fill = after_stat(piece_id)),
|
| rings = 2, diameter = 150, seed = 42
|
| ) +
|
| scale_fill_viridis_c(option = "magma", guide = "none") +
|
| coord_fixed() +
|
| theme_puzzle() +
|
| labs(title = "Magma"))
|
| ```
|
|
|
| ::: {.callout-note}
|
| For the API approach, colors are controlled through SVG styling. See the [Customization Tutorial](customization.qmd) for advanced coloring techniques.
|
| :::
|
|
|
|
|
|
|
| The `seed` parameter ensures you get the same puzzle every time:
|
|
|
| ::: {.panel-tabset}
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| plot_with_seed <- function(s) {
|
| ggplot() +
|
| geom_puzzle_hex(
|
| aes(fill = after_stat(piece_id)),
|
| rings = 2,
|
| seed = s
|
| ) +
|
| scale_fill_viridis_c(guide = "none") +
|
| coord_fixed() +
|
| theme_puzzle() +
|
| labs(title = paste("seed =", s))
|
| }
|
|
|
| print(plot_with_seed(42))
|
| print(plot_with_seed(123))
|
| ```
|
|
|
|
|
|
|
| ```{r}
|
|
|
|
|
| p1 <- generate_puzzle(type = "hexagonal", grid = c(2), size = c(100), seed = 42)
|
| p2 <- generate_puzzle(type = "hexagonal", grid = c(2), size = c(100), seed = 42)
|
|
|
| identical(p1$svg_content, p2$svg_content)
|
|
|
|
|
| p3 <- generate_puzzle(type = "hexagonal", grid = c(2), size = c(100), seed = 123)
|
| identical(p1$svg_content, p3$svg_content)
|
| ```
|
|
|
| :::
|
|
|
| ::: {.callout-tip}
|
| Both approaches use the same deterministic RNG, so `seed = 42` generates identical piece shapes whether you use the API or ggpuzzle.
|
| :::
|
|
|
|
|
|
|
| You've learned to:
|
|
|
| 1. ✅ Install and load jigsawR
|
| 2. ✅ Generate puzzles using both **API** and **ggpuzzle** approaches
|
| 3. ✅ Save puzzles as SVG (API) or PNG (ggpuzzle)
|
| 4. ✅ Create different puzzle types (rectangular, hexagonal, concentric, voronoi, random, snic)
|
| 5. ✅ Customize offset and colors
|
| 6. ✅ Use seeds for reproducibility
|
|
|
| **Choosing an approach:**
|
|
|
| - **API** (`generate_puzzle()`): Best for SVG export, programmatic manipulation, and custom rendering
|
| - **ggpuzzle** (`geom_puzzle_*()`): Best for quick visualization, ggplot2 integration, and color customization
|
|
|
|
|
|
|
| - [Customization Tutorial](customization.qmd) - Colors, themes, and advanced styling
|
| - [Fusion Groups Tutorial](fusion-groups.qmd) - Merge pieces with PILES notation
|
| - [API Reference](../api/generate-puzzle.qmd) - Complete parameter documentation
|
|
|