Created
November 2, 2021 14:31
-
-
Save oliviergimenez/df46af3883149666bfa203f1684fc054 to your computer and use it in GitHub Desktop.
Generative art à la Etienne Jacob with R
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# some R code to mimic animated gifs created by Etienne Jacob | |
# @etiennejcb | |
# https://bleuje.github.io/tutorials/ | |
## load required packages | |
library(tidyverse) | |
theme_set(theme_void(base_size = 14)) | |
library(gganimate) | |
##-- first tutorial https://bleuje.github.io/tutorial1/ | |
# set up | |
numFrames <- 150 | |
frameCount <- 1:numFrames | |
width <- 400 | |
height <- 400 | |
t <- 1.0 * frameCount / numFrames | |
r <- 100 | |
x <- width / 2 + r * cos(2 * pi * t) | |
y <- height / 2 + r * sin(2 * pi * t) | |
# tibble of data | |
df <- tibble(t = t, | |
x = x, | |
y = y) | |
# static | |
df %>% | |
ggplot() + | |
aes(x = x, y = y) + | |
geom_point(show.legend = FALSE) + | |
lims(x = c(1,width), y = c(1,height)) | |
# animated | |
anim_point <- df %>% | |
ggplot() + | |
aes(x = x, y = y) + | |
geom_point(show.legend = FALSE, size = 4) + | |
lims(x = c(1,width), y = c(1,height)) + | |
labs(x = NULL, y = NULL) + | |
transition_reveal(frameCount) | |
# animate and save | |
animate(anim_point, nframes = numFrames, fps = 40) | |
anim_save('anim1.gif') | |
##-- second tutorial https://bleuje.github.io/tutorial2/ | |
# function to map value s from a range [a1,a2] to another [b1,b2] | |
map_range <- function(s, a1, a2, b1, b2){ | |
b1 + (s - a1) * (b2 - b1) / (a2 - a1) | |
} | |
# periodic function that controls the size of dots | |
periodic_function <- function(p){ | |
map_range(sin(2*pi*p),-1,1,2,8) | |
} | |
# compute distance between two points (x1,y1) and (x2,y2) | |
distance <- function(x1,y1,x2,y2){ | |
sqrt((x2 - x1)^2 + (y2 - y1)^2) | |
} | |
# radial offset function | |
offset <- function(x, y){ | |
0.01 * distance(x,y,width/2,height/2) | |
} | |
# set up | |
numFrames <- 60 | |
frameCount <- 1:numFrames | |
t <- 1.0 * frameCount/numFrames | |
width <- 500 | |
height <- 500 | |
m <- 40 | |
# get values | |
df <- matrix(NA, nrow = numFrames * m * m, ncol = 7) | |
index <- 1 | |
for(i in 1:m){ | |
for(j in 1:m){ | |
x <- map_range(i, 0, m - 1, 0, width) | |
y <- map_range(j, 0, m - 1, 0, height) | |
for (k in 1:numFrames){ | |
size <- periodic_function(t[k] - offset(x,y)) | |
df[index,1] <- i | |
df[index,2] <- j | |
df[index,3] <- k | |
df[index,4] <- t[k] | |
df[index,5] <- x | |
df[index,6] <- y | |
df[index,7] <- size | |
index <- index + 1 | |
} | |
} | |
} | |
# tibble of data | |
df <- as_tibble(df) | |
colnames(df) <- c("i", "j", "k", "t", "x", "y", "size") | |
# animated | |
anim_point <- df %>% | |
ggplot() + | |
aes(x = x, y = y) + | |
geom_point(show.legend = FALSE, aes(size = size)) + | |
lims(x = c(1,width), y = c(1,height)) + | |
labs(x = NULL, y = NULL) + | |
transition_reveal(k) | |
# animate and save | |
animate(anim_point, nframes = numFrames, fps = 20) | |
anim_save('anim2.gif') | |
##-- third tutorial https://bleuje.github.io/tutorial3/ | |
# to make some noise | |
library(ambient) # https://rdrr.io/cran/ambient/man/noise_simplex.html | |
# function to map value s from a range [a1,a2] to another [b1,b2] | |
map_range <- function(s, a1, a2, b1, b2){ | |
b1 + (s - a1) * (b2 - b1) / (a2 - a1) | |
} | |
# periodic function that controls the size of dots | |
periodic_function <- function(p, seed){ | |
radius <- 1.3 | |
1.0 * gen_simplex(seed + radius * cos(2*pi*p), | |
radius * sin(2*pi*p)) | |
} | |
# compute distance between two points (x1,y1) and (x2,y2) | |
distance <- function(x1,y1,x2,y2){ | |
sqrt((x2 - x1)^2 + (y2 - y1)^2) | |
} | |
# offset function | |
offset <- function(x, y){ | |
0.015 * distance(x,y,width/2,height/2) | |
} | |
numFrames <- 60 | |
frameCount <- 1:numFrames | |
t <- 1.0 * frameCount/numFrames | |
width <- 500 | |
height <- 500 | |
m <- 45 # should be 450 | |
margin <- 50 | |
df <- matrix(NA, nrow = numFrames * m * m, ncol = 8) | |
index <- 1 | |
for(i in 1:m){ | |
for(j in 1:m){ | |
x <- map_range(i, 0, m-1, margin, width-margin) | |
y <- map_range(j, 0, m-1, margin, height-margin) | |
for (k in 1:numFrames){ | |
dx <- 20 * periodic_function(t[k] - offset(x,y), 0) | |
dy <- 20 * periodic_function(t[k] - offset(x,y), 123) | |
df[index,1] <- i | |
df[index,2] <- j | |
df[index,3] <- k | |
df[index,4] <- t[k] | |
df[index,5] <- x | |
df[index,6] <- y | |
df[index,7] <- dx | |
df[index,8] <- dy | |
index <- index + 1 | |
} | |
} | |
} | |
# tibble of data | |
df <- as_tibble(df) | |
colnames(df) <- c("i", "j", "k", "t", "x", "y", "dx","dy") | |
# animated | |
anim_point <- df %>% | |
ggplot() + | |
aes(x = x + dx, y = y + dy) + | |
geom_point(show.legend = FALSE, size = 1.5, color = "white") + | |
lims(x = c(1,width), y = c(1,height)) + | |
theme(plot.background = element_rect(fill = "black")) + | |
transition_reveal(k) | |
# animate and save | |
animate(anim_point) | |
#animate(anim_point, nframes = numFrames, fps = 20) | |
anim_save('anim3.gif') | |
# definitely not what was expected | |
# probably due to ambient::gen_simplex() doing something different from the Processing function noise.eval | |
##-- fourth https://bleuje.github.io/tutorial4/ and fifth https://bleuje.github.io/tutorial5/ tutorials | |
##-- to come when time allows | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Animated gif from first tutorial
