Overview
Hexagonal puzzles create stunning honeycomb patterns. Each hexagonal piece connects to up to six neighbors through elegantly curved tabs. The result is a visually striking circular puzzle.
Ring Variations
Hexagonal puzzles are defined by the number of rings:
# 2 rings
print (ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 2 , seed = 42
) +
scale_fill_viridis_c (option = "plasma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "2 rings" ))
# 3 rings
print (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 = "3 rings" ))
# 4 rings
print (ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 4 , seed = 42
) +
scale_fill_viridis_c (option = "plasma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "4 rings" ))
# 2 rings
result_2 <- generate_puzzle (
type = "hexagonal" ,
grid = c (2 ),
size = c (200 ),
seed = 42 ,
do_warp = TRUE ,
do_trunc = TRUE ,
fill_palette = "plasma"
)
render_puzzle_preview (result_2) # 2 rings
# 3 rings
result_3 <- generate_puzzle (
type = "hexagonal" ,
grid = c (3 ),
size = c (200 ),
seed = 42 ,
do_warp = TRUE ,
do_trunc = TRUE ,
fill_palette = "plasma"
)
render_puzzle_preview (result_3) # 3 rings
# 4 rings
result_4 <- generate_puzzle (
type = "hexagonal" ,
grid = c (4 ),
size = c (200 ),
seed = 42 ,
do_warp = TRUE ,
do_trunc = TRUE ,
fill_palette = "plasma"
)
render_puzzle_preview (result_4) # 4 rings
Warp and Truncation
Hexagonal puzzles support two key transformations:
# Default: warped and truncated
print (ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 3 ,
do_warp = TRUE , do_trunc = TRUE ,
seed = 42
) +
scale_fill_viridis_c (option = "magma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "warp + trunc" ))
# Warped but not truncated (extends beyond circle)
print (ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 3 ,
do_warp = TRUE , do_trunc = FALSE ,
seed = 42
) +
scale_fill_viridis_c (option = "magma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "warp only" ))
# Default: warped and truncated
result_warp_trunc <- generate_puzzle (
type = "hexagonal" ,
grid = c (3 ),
size = c (200 ),
seed = 42 ,
do_warp = TRUE ,
do_trunc = TRUE ,
fill_palette = "magma"
)
render_puzzle_preview (result_warp_trunc)
# Warped but not truncated
result_warp_only <- generate_puzzle (
type = "hexagonal" ,
grid = c (3 ),
size = c (200 ),
seed = 42 ,
do_warp = TRUE ,
do_trunc = FALSE ,
fill_palette = "magma"
)
render_puzzle_preview (result_warp_only)
Color Palettes
make_hex_palette <- function (pal) {
ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 3 , seed = 42
) +
scale_fill_viridis_c (option = pal, guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = pal)
}
print ((make_hex_palette ("viridis" ) + make_hex_palette ("magma" ) + make_hex_palette ("plasma" )) /
(make_hex_palette ("inferno" ) + make_hex_palette ("cividis" ) + make_hex_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 = "hexagonal" , grid = c (3 ), size = c (200 ), seed = 42 , do_warp = TRUE , do_trunc = TRUE , fill_palette = pal)
})
render_puzzle_grid (items, ncol = 3 , labels = palettes)
Fill Direction
Control the spatial order of color assignment. For hexagonal puzzles, "reverse" reverses colors within each ring while keeping the center piece unchanged. This is distinct from palette_invert which reverses the dark↔︎light ends of the palette.
make_direction_plot <- function (dir) {
ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (fill_order)),
rings = 3 ,
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 = "hexagonal" , grid = c (3 ), size = c (200 ), seed = 42 , do_warp = TRUE , do_trunc = TRUE , fill_palette = "viridis" , fill_direction = dir)
})
render_puzzle_grid (items, ncol = 2 , labels = paste0 ("fill_direction = \" " , directions, " \" " ))
Offset (Separation)
make_hex_offset <- function (off) {
ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 3 ,
offset = off, seed = 42
) +
scale_fill_viridis_c (option = "viridis" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = paste0 ("offset = " , off))
}
print (make_hex_offset (0 ) + make_hex_offset (5 ) + make_hex_offset (10 ) + make_hex_offset (15 ))
# Generate offset previews in a grid
offsets <- c (0 , 5 , 10 , 15 )
items <- lapply (offsets, function (off) {
generate_puzzle (type = "hexagonal" , grid = c (3 ), size = c (200 ), seed = 42 , do_warp = TRUE , do_trunc = TRUE , offset = off, fill_palette = "viridis" )
})
render_puzzle_grid (items, ncol = 4 , labels = paste ("offset =" , offsets))
Fusion Groups
Special keywords for hexagonal puzzles:
# Center merged with ring 1
print (ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 3 ,
fusion_groups = "center-ring1" ,
seed = 42
) +
scale_fill_viridis_c (option = "plasma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "center + ring1" ))
# Ring 2 pieces merged
print (ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 3 ,
fusion_groups = "ring2" ,
seed = 42
) +
scale_fill_viridis_c (option = "plasma" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "ring2" ))
# Center merged with ring 1
result_center_ring1 <- generate_puzzle (
type = "hexagonal" ,
grid = c (3 ),
size = c (200 ),
seed = 42 ,
do_warp = TRUE ,
do_trunc = TRUE ,
fusion_groups = "center-ring1" ,
fill_palette = "plasma"
)
render_puzzle_preview (result_center_ring1)
# Ring 2 pieces merged
result_ring2 <- generate_puzzle (
type = "hexagonal" ,
grid = c (3 ),
size = c (200 ),
seed = 42 ,
do_warp = TRUE ,
do_trunc = TRUE ,
fusion_groups = "ring2" ,
fill_palette = "plasma"
)
render_puzzle_preview (result_ring2)
Large Puzzles
ggplot () +
geom_puzzle_hex (
aes (fill = after_stat (piece_id)),
rings = 5 ,
seed = 123
) +
scale_fill_viridis_c (option = "turbo" , guide = "none" ) +
coord_fixed () +
theme_puzzle () +
labs (title = "5-Ring Hexagonal Puzzle (61 pieces)" )
result <- generate_puzzle (
type = "hexagonal" ,
grid = c (5 ),
size = c (300 ),
seed = 123 ,
do_warp = TRUE ,
do_trunc = TRUE ,
fill_palette = "turbo"
)
render_puzzle_preview (result, max_width = "500px" )
Parameters Reference
rings
integer
3
Number of concentric rings
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
do_warp
logical
FALSE (API) / TRUE (ggpuzzle)
Apply circular warping
do_trunc
logical
FALSE (API) / TRUE (ggpuzzle)
Truncate to boundary
fusion_groups
string
NULL
PILES notation for fusing pieces
PILES Keywords
Special keywords available for hexagonal puzzles:
center
The center piece (piece 1)
ring1
All pieces in ring 1
ring2
All pieces in ring 2
ringN
All pieces in ring N
boundary
All outer boundary pieces
Code Example
# Generate puzzle
result <- generate_puzzle (
type = "hexagonal" ,
grid = c (4 ), # 4 rings
size = c (250 ), # 250mm diameter
seed = 42 ,
do_warp = TRUE ,
do_trunc = TRUE ,
offset = 5
)
# writeLines(result$svg_content, "hexagonal_puzzle.svg")
render_puzzle_preview (result)
# Access piece info
n_pieces <- length (result$ pieces)
cli:: cli_alert_info ("Generated {n_pieces} pieces" )