Skip to content

Instantly share code, notes, and snippets.

@oliviergimenez
Created November 2, 2021 14:31
Show Gist options
  • Save oliviergimenez/df46af3883149666bfa203f1684fc054 to your computer and use it in GitHub Desktop.
Save oliviergimenez/df46af3883149666bfa203f1684fc054 to your computer and use it in GitHub Desktop.
Generative art à la Etienne Jacob with R
# 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
@oliviergimenez
Copy link
Author

oliviergimenez commented Nov 2, 2021

Animated gif from first tutorial
anim1

@oliviergimenez
Copy link
Author

Animated gif from second tutorial
anim2

@oliviergimenez
Copy link
Author

Animated gif from third tutorial
anim3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment