Utiling geom_arc_bar for creation of geometric art
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Geometry x Colors Experimentation
I’m still obsessing with Pentomino dataset that I have been using.
I love using the ggforce
package for creating stunning visualizations. ggforce
essentially allows you to extend the ggplot2 capabilities, i.e. ggplot2 on steroid. My go-to functions usually include geom_regon, geom_parallel_sets, and geom_circle. But recently, I realized there’s functions I haven’t fully explored, one of them being geom_arc_bar.
Setups and Pakcages Used in This Blog Post
# Load required libraries library(tidyverse) # Data wrangling and general utilities library(ggforce) # Extra geoms for ggplot2 library(cowplot) # Additional plotting helpers library(patchwork) # Combine multiple ggplots effortlessly! # Pentomino Solutions Dataset pento_sol <- read_csv("https://raw.githubusercontent.com/chichacha/pentomino/refs/heads/main/pentomino_solution.csv") ### Convert Solution to XY position data frame pento_sol_df <- pento_sol |> mutate(solution_num = row_number()) |> mutate(sol_text = str_split(sol_text, " ")) |> unnest(sol_text) |> group_by(solution_num) |> mutate(y = row_number()) |> ungroup() |> mutate(sol_text = str_split(sol_text, "")) |> unnest(sol_text) |> group_by(solution_num, y) |> mutate(x = row_number()) |> ungroup() pento_min <- pento_sol_df |> filter(sol_text != ".") |> # exclude the "." cells select(x, y, sol_text, solution_num, dim) |> nest(.by = c(solution_num, dim)) # Just using my retro color palette retro <- c("#00A0B0", "#6A4A3C", "#CC333F", "#EB6841", "#EDC951") retro12 <- colorRampPalette(retro)(12) piece<-c("F","I","L","N","P","T","U","V","W","X","Y","Z") names(retro12) <- piece
Quick Demo of Basic Use geom_arc_bar function
Here’s a demo showing the effects of different geom_arc_bar parameters like segment smoothness (n), expansion or contraction (expand), and rounding of corner (radius). I like that I can draw pie or donut chart without leaving cartesian coordinate.
Simple Example
# Sample data data <- data.frame( x = c(0,0,0,0,0,0), y = c(0,0,0,0,0,0), r0=c(rep(0.5,times=4),0,0), r=c(rep(1,times=4),0.5,0.5), start = c(0, pi/2, pi, 3*pi/2,0,pi), end = c(pi/2, pi, 3*pi/2, 2*pi,pi,2*pi), group=c("A","B","C","D","E","F") ) # Plot using geom_arc_bar ggplot(data) + geom_arc_bar(aes( x0 = x, y0 = y, r0 = r0, r = r, start = start, end = end, fill = group ), color="#fffff3") + geom_arc_bar(aes( x0 = x+2, y0 = y, r0 = r0, r = r, start = start, end = end, fill = group ), color="#fffff3", n=4) + ## n to control the number of points used to draw a full circle. geom_arc_bar(aes( x0 = x+4, y0 = y, r0 = r0, r = r, start = start, end = end, fill = group ), color="#fffff3", expand=unit(-1,"mm")) + ## expand to control expansion, negative value is used to contract geom_arc_bar(aes( x0 = x+6, y0 = y, r0 = r0, r = r, start = start, end = end, fill = group ), color="#fffff3", radius=unit(3,"mm"), n=36) + theme_minimal_grid(font_family="Roboto Condensed") + labs(title = "Fun with geom_arc_bar", fill = "Group") + coord_fixed() + scale_fill_manual(values=c(retro,"#323433")) + scale_x_continuous(breaks=c(0,2,4,6)) + scale_y_continuous(breaks=c(-1,0,1))
Slightly Abstract Pentomino Solutions
What happens when a classic Pentomino puzzle collides with geometric abstraction? These visuals are still valid solutions to the Pentomino problem, but now they blur the line between puzzles and art. By experimenting with shapes, colors, these solutions have transformed into something entirely new: playful geometric art with a hint of order and chaos 🪄🐰🎩
Code
abstract_plot <- function(i){ pento_min$data[[i]] |> arrange(sol_text) |> group_by(sol_text) |> mutate(idx=row_number(), diff_x=x-lag(x,default=1), diff_y=y-lag(y,default=1)) |> ungroup() |> ggplot() + geom_tile(aes(x=x,y=y), fill="#fffff3") + geom_arc_bar(aes(x0=x+0.5,y0=y+0.5,r0=0, r=sqrt(1), start=3*pi/2, end=pi, fill=sol_text), color="transparent", data = . %>% filter(idx==1)) + geom_arc_bar(aes(x0=x-0.5,y0=y-0.5,r0=0, r=sqrt(1), start=0, end=pi/2, fill=sol_text), color="transparent", data = . %>% filter(idx==2)) + geom_arc_bar(aes(x0=x+0.5,y0=y-0.5,r0=0, r=sqrt(1), start=0, end=-pi/2, fill=sol_text), color="transparent", data = . %>% filter(idx==3)) + geom_circle(aes(x0=x,y0=y, r=sqrt(0.25), fill=sol_text), data = . %>% filter(idx==5), color="transparent") + geom_arc_bar(aes(x0=x+0.5,y0=y+0.5,r0=0, r=sqrt(1), start=3*pi/2, end=pi, fill=sol_text), color="transparent", data = . %>% filter(idx==4)) + coord_fixed() + scale_fill_manual(values=retro12) + #scale_color_manual(values=retro12) + theme_nothing() } pento_min |> filter(dim=="8×8a") |> pull(solution_num) |> sample(size=6) |> map(abstract_plot) |> wrap_plots()
Code
library(TSP) abstract_plot2 <- function(i) { my_tsp <-pento_min$data[[i]] |> mutate(sol_text=as.numeric(fct_reorder(sol_text,x*y,sum))*100) |> dist("manhattan") |> TSP::as.TSP() ### available TSP Method without installing extra methods <- c("identity", "random", "nearest_insertion", "cheapest_insertion", "farthest_insertion", "arbitrary_insertion", "nn", "repetitive_nn", "two_opt") my_tsp_path <- solve_TSP(my_tsp, method=methods[3]) ## nearest insertion pento_min$data[[i]][as.integer(my_tsp_path),] |> mutate(idx=row_number()) |> ggplot() + geom_arc_bar(aes(x0=x+0.5,y0=y+0.5,r0=0, r=sqrt(1), start=3*pi/2, end=pi, fill=sol_text), color="transparent", data = . %>% filter(idx%%8==1)) + geom_arc_bar(aes(x0=x-0.5,y0=y-0.5,r0=0, r=sqrt(1), start=0, end=pi/2, fill=sol_text), color="transparent", data = . %>% filter(idx%%8==2)) + geom_arc_bar(aes(x0=x+0.5,y0=y-0.5,r0=0, r=sqrt(1), start=0, end=-pi/2, fill=sol_text), color="transparent", data = . %>% filter(idx%%8==3)) + geom_circle(aes(x0=x,y0=y, r=sqrt(0.25), fill=sol_text), data = . %>% filter(idx%%8==4), color="transparent") + geom_arc_bar(aes(x0=x+0.5,y0=y+0.5,r0=0, r=sqrt(1), start=3*pi/2, end=pi, fill=sol_text), color="transparent", data = . %>% filter(idx%%8==5)) + geom_regon(aes(x0=x,y0=y,r=sqrt(0.5),sides=4, fill=sol_text,angle=0), color="transparent", data = . %>% filter(idx%%8==6)) + geom_regon(aes(x0=x,y0=y,r=sqrt(0.5),sides=4, fill=sol_text,angle=0), color="transparent", data = . %>% filter(idx%%8==7)) + geom_regon(aes(x0=x,y0=y,r=sqrt(0.5),sides=4, fill=sol_text,angle=0), color="transparent", data = . %>% filter(idx%%8==0)) + # geom_text(aes(x=x,y=y, label=idx), color="#fffff330", # family="Futura") + coord_fixed() + scale_fill_manual(values=retro12) + theme_nothing() } pento_min |> filter(dim=="8×8d") |> pull(solution_num) |> sample(size=6) |> map(abstract_plot2) |> wrap_plots()
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.