Skip to content

Instantly share code, notes, and snippets.

@debruine
Created April 16, 2022 12:34
Show Gist options
  • Save debruine/ab0ca65fc15fdc8c03cbcab001d76f5c to your computer and use it in GitHub Desktop.
Save debruine/ab0ca65fc15fdc8c03cbcab001d76f5c to your computer and use it in GitHub Desktop.
Make a stained glass heart with ggplot
# inpired by https://github.com/IcaroBernardes/30DayChartChallenge/blob/master/2022/day10/day10.R
library(ggplot2)
library(dplyr)
library(sf)
library(ggforce) # for voroni tiles
seed <- 8675309
n_pts <- 150 ### Number of points to try to put inside the window
palette <- c(
"pink" = "#983E82",
"orange" = "#E2A458",
"yellow" = "#F5DC70",
"green" = "#59935B",
"blue" = "#467AAC",
"purple" = "#61589C"
)
# make heart frame
t <- seq(0, 2*pi, by=0.05) %>% c(0)
frame <- cbind(
16*sin(t)^3,
13*cos(t)-5*cos(2*t)-2*cos(3*t)-cos(4*t)
)
# convert to a polygon
frame_sf <- frame %>%
list() %>%
sf::st_polygon()
## Create random data points in frame bounds
set.seed(seed)
points <- tibble(
x = runif(n_pts, min = min(frame[,1]), max = max(frame[,1])),
y = runif(n_pts, min = min(frame[,2]), max = max(frame[,2]))
)
## Creates a new sf object to hold the created points
points_sf <- sf::st_as_sf(points, coords = c("x","y"))
## Keeps only the random points that are within the frame
contained <- sf::st_contains(frame_sf, points_sf)
points <- points %>% dplyr::slice(contained[[1]])
## Applies random colors and alphas to the remaining points
set.seed(seed)
points <- points %>%
mutate(
fill = sample(palette, nrow(.), T),
alpha = runif(nrow(.), min = 0.2, max = 0.9)
)
ggplot(points) +
geom_voronoi_tile(aes(x = x, y = y,
group = -1L,
fill = I(fill),
alpha = I(alpha)),
color = "black",
size = 1.5,
bound = frame) +
geom_sf(data = frame_sf,
size = 4,
color = "black",
fill = "transparent") +
theme_void()
ggsave("stained_glass_heart.png", width = 4, height = 4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment