Overview
Voronoi puzzles create organic, natural-looking pieces based on Voronoi tessellation. Each piece is a convex polygon formed by the regions closest to a set of seed points. The result resembles patterns found in nature, like honeycomb cells, giraffe spots, or cracked mud.
Cell Count Variations
make_vor_cells <- function (n) {
ggplot () +
geom_puzzle_voronoi (
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_vor_cells (10 ) + make_vor_cells (25 ) + make_vor_cells (50 ))
# Generate cell count previews in a grid
cells <- c (10 , 25 , 50 )
items <- lapply (cells, function (n) {
generate_puzzle (type = "voronoi" , grid = c (n), size = c (200 , 200 ), seed = 42 , fill_palette = "turbo" )
})
render_puzzle_grid (items, ncol = 3 , labels = paste (cells, "cells" ))
Voronoi puzzles adapt to any aspect ratio - wide, square, or tall. See the Aspect Ratios Tutorial for examples comparing all puzzle types.
Color Palettes
make_vor_palette <- function (pal) {
ggplot () +
geom_puzzle_voronoi (
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_vor_palette ("viridis" ) + make_vor_palette ("magma" ) + make_vor_palette ("plasma" )) /
(make_vor_palette ("inferno" ) + make_vor_palette ("cividis" ) + make_vor_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 = "voronoi" , grid = c (20 ), size = c (200 , 200 ), seed = 42 , fill_palette = pal)
})
render_puzzle_grid (items, ncol = 3 , labels = palettes)
Fill Direction
Control the spatial order of color assignment. This is distinct from palette_invert which reverses the dark↔︎light ends of the palette.
make_direction_plot <- function (dir) {
ggplot () +
geom_puzzle_voronoi (
aes (fill = after_stat (fill_order)),
n_cells = 20 ,
fill_direction = dir,
seed = 42
) +
scale_fill_viridis_c (option = "viridis" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = paste0 ("fill_direction = \" " , dir, " \" " ))
}
print (make_direction_plot ("forward" ) + make_direction_plot ("reverse" ))
directions <- c ("forward" , "reverse" )
items <- lapply (directions, function (dir) {
generate_puzzle (type = "voronoi" , grid = c (20 ), size = c (200 , 200 ), seed = 42 , fill_palette = "viridis" , fill_direction = dir)
})
render_puzzle_grid (items, ncol = 2 , labels = paste0 ("fill_direction = \" " , directions, " \" " ))
Offset (Separation)
make_vor_offset <- function (off) {
ggplot () +
geom_puzzle_voronoi (
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_vor_offset (0 ) + make_vor_offset (5 ) + make_vor_offset (10 ) + make_vor_offset (20 ))
# Generate offset previews in a grid
offsets <- c (0 , 5 , 10 , 20 )
items <- lapply (offsets, function (off) {
generate_puzzle (type = "voronoi" , 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 Variations
Different seeds create completely different tessellations:
make_vor_seed <- function (s) {
ggplot () +
geom_puzzle_voronoi (
aes (fill = after_stat (piece_id)),
n_cells = 15 ,
seed = s
) +
scale_fill_viridis_c (option = "magma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = paste0 ("seed = " , s))
}
print (make_vor_seed (1 ) + make_vor_seed (42 ) + make_vor_seed (123 ) + make_vor_seed (999 ))
# Generate seed variation previews in a grid
seeds <- c (1 , 42 , 123 , 999 )
items <- lapply (seeds, function (s) {
generate_puzzle (type = "voronoi" , grid = c (15 ), size = c (200 , 200 ), seed = s, fill_palette = "magma" )
})
render_puzzle_grid (items, ncol = 4 , labels = paste ("seed =" , seeds))
Fusion Groups
Merge pieces together using PILES notation:
# Standard
print (ggplot () +
geom_puzzle_voronoi (
aes (fill = after_stat (piece_id)),
n_cells = 12 ,
seed = 42
) +
scale_fill_viridis_c (option = "magma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "Standard" ))
# Adjacent pieces fused
print (ggplot () +
geom_puzzle_voronoi (
aes (fill = after_stat (piece_id)),
n_cells = 12 ,
seed = 42 ,
fusion_groups = "1-2-3,5-6"
) +
scale_fill_viridis_c (option = "magma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "Pieces fused" ))
# Standard
result_standard <- generate_puzzle (
type = "voronoi" ,
grid = c (12 ),
size = c (200 , 200 ),
seed = 42 ,
fill_palette = "magma"
)
render_puzzle_preview (result_standard, title = "Standard" )
# Adjacent pieces fused
result_fused <- generate_puzzle (
type = "voronoi" ,
grid = c (12 ),
size = c (200 , 200 ),
seed = 42 ,
fill_palette = "magma" ,
fusion_groups = "1-2-3,5-6"
)
render_puzzle_preview (result_fused, title = "Pieces fused" )
Large Voronoi Puzzle
ggplot () +
geom_puzzle_voronoi (
aes (fill = after_stat (piece_id)),
n_cells = 80 ,
width = 400 , height = 300 ,
seed = 789
) +
scale_fill_viridis_c (option = "turbo" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "80-Cell Voronoi Puzzle" )
result <- generate_puzzle (
type = "voronoi" ,
grid = c (80 ),
size = c (300 , 400 ),
seed = 789 ,
fill_palette = "turbo"
)
render_puzzle_preview (result, max_width = "600px" )
Parameters Reference
n_cells
integer
12
Number of Voronoi cells (pieces)
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
point_distribution
string
“fermat”
Seed point distribution method
fusion_groups
string
NULL
PILES notation for fusing pieces
About Voronoi Tessellation
Voronoi tessellation divides a plane into regions based on distance to seed points. Each region consists of all points closer to its seed than to any other seed. This creates:
Convex polygons : Each piece is a convex polygon
Natural appearance : Resembles patterns in nature
Variable sizes : Piece sizes depend on seed point distribution
Code Example
ggplot () +
geom_puzzle_voronoi (
aes (fill = after_stat (piece_id)),
n_cells = 35 ,
width = 400 , height = 300 ,
seed = 42 ,
offset = 5
) +
scale_fill_viridis_c (option = "turbo" , guide = "none" ) +
coord_fixed () +
theme_puzzle ()
# Generate puzzle
result <- generate_puzzle (
type = "voronoi" ,
grid = c (35 ), # 35 cells
size = c (300 , 400 ), # height=300mm, width=400mm
seed = 42 ,
offset = 5
)
# writeLines(result$svg_content, "voronoi_puzzle.svg")
# Preview
render_puzzle_preview (result)
When to Use Voronoi
Voronoi puzzles are ideal for:
Organic themes : Nature, landscapes, biological subjects
Artistic effects : Modern art, abstract designs
Variable difficulty : More cells = harder puzzle
Unique designs : Every seed creates a different pattern