I'm trying to animate a Fibonacci sequence in R, where both the squares and the spiral grow together. I have managed to create two separate animations:
Growing squares but no growing spiral: The squares appear one by one, but the spiral is static.
Growing spiral but no growing squares: The spiral grows, but the squares are static.
I want to combine both effects in a single animation, where each square appears with its corresponding arc in the spiral. Below are my attempts:
library(ggplot2)
library(gganimate)
# Define a function to generate Fibonacci numbers
fibonacci <- function(n) {
fib_seq <- numeric(n)
fib_seq[1] <- 1
fib_seq[2] <- 1
for (i in 3:n) {
fib_seq[i] <- fib_seq[i-1] + fib_seq[i-2]
}
return(fib_seq)
}
# Function to generate quarter circle arc data
quarter_circle_arc <- function(x, y, size, direction) {
theta <- seq(0, pi/2, length.out = 100)
if (direction == 1) {
# Bottom-left arc
data.frame(
x = x + size * (1 - cos(theta)),
y = y + size * (1 - sin(theta))
)
} else if (direction == 2) {
# Bottom-right arc
data.frame(
x = x + size * (sin(theta) - 1) + size,
y = y + size * (1 - cos(theta))
)
} else if (direction == 3) {
# Top-right arc
data.frame(
x = x + size * (cos(theta) - 1) + size,
y = y + size * (sin(theta) - 1) + size
)
} else if (direction == 0) {
# Top-left arc
data.frame(
x = x + size * (1 - sin(theta)),
y = y + size * (cos(theta) - 1) + size
)
}
}
# Generate the first 10 Fibonacci numbers
fib_seq <- fibonacci(10)
# Initialize the data frame for squares
squares <- data.frame(
x = numeric(10),
y = numeric(10),
size = fib_seq,
direction = numeric(10),
frame = 1:10
)
# Initialize the data frame for arcs
arcs <- data.frame(
x = numeric(0),
y = numeric(0),
frame = integer(0)
)
# Set the initial position and direction
x <- 0
y <- 0
direction <- 1
for (i in 1:10) {
if (direction == 1) {
y <- y - ifelse(x == 0, 0, fib_seq[i])
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 2) {
x <- x + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 3) {
x <- x - fib_seq[i-2]
y <- y + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 4) {
x <- x - fib_seq[i]
y <- y - fib_seq[i-2]
squares[i, "x"] <- x
squares[i, "y"] <- y
}
# Store the direction for the arcs
squares[i, "direction"] <- direction
# Generate the arc for the current square and append it to arcs data frame
new_arc <- quarter_circle_arc(
squares$x[i], squares$y[i], squares$size[i], direction = (i %% 4)
)
new_arc$frame <- i # Assign the frame for animation
arcs <- rbind(arcs, new_arc)
# Update the direction
direction <- (direction %% 4) + 1
}
# Create the base plot
p <- ggplot() +
coord_fixed(ratio = 1) +
theme_void()
# Plot squares and arcs with gradual appearance
p_anim <- p +
geom_rect(data = squares, aes(xmin = x, ymin = y, xmax = x + size, ymax = y + size, frame = frame),
fill = "white", color = "black") +
geom_path(data = arcs, aes(x = x, y = y, frame = frame), color = "black") +
transition_manual(frames = squares$frame, cumulative = TRUE) # Keep previous frames visible
# Render the animation
animate(p_anim, nframes = 100, fps = 10)
library(ggplot2)
library(gganimate)
# Define a function to generate Fibonacci numbers
fibonacci <- function(n) {
fib_seq <- numeric(n)
fib_seq[1] <- 1
fib_seq[2] <- 1
for (i in 3:n) {
fib_seq[i] <- fib_seq[i-1] + fib_seq[i-2]
}
return(fib_seq)
}
# Function to generate quarter circle arc data
quarter_circle_arc <- function(x, y, size, direction) {
theta <- seq(0, pi/2, length.out = 100)
if (direction == 1) {
# Bottom-left arc
data.frame(
x = x + size * (1 - cos(theta)),
y = y + size * (1 - sin(theta))
)
} else if (direction == 2) {
# Bottom-right arc
data.frame(
x = x + size * (sin(theta) - 1) + size,
y = y + size * (1 - cos(theta))
)
} else if (direction == 3) {
# Top-right arc
data.frame(
x = x + size * (cos(theta) - 1) + size,
y = y + size * (sin(theta) - 1) + size
)
} else if (direction == 0) {
# Top-left arc
data.frame(
x = x + size * (1 - sin(theta)),
y = y + size * (cos(theta) - 1) + size
)
}
}
# Generate the first 10 Fibonacci numbers
fib_seq <- fibonacci(10)
# Initialize the data frame for squares
squares <- data.frame(
x = numeric(10),
y = numeric(10),
size = fib_seq,
direction = numeric(10),
frame = 1:10
)
# Initialize the data frame for arcs
arcs <- data.frame(
x = numeric(0),
y = numeric(0),
frame = integer(0)
)
# Set the initial position and direction
x <- 0
y <- 0
direction <- 1
for (i in 1:10) {
if (direction == 1) {
y <- y - ifelse(x == 0, 0, fib_seq[i])
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 2) {
x <- x + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 3) {
x <- x - fib_seq[i-2]
y <- y + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 4) {
x <- x - fib_seq[i]
y <- y - fib_seq[i-2]
squares[i, "x"] <- x
squares[i, "y"] <- y
}
# Store the direction for the arcs
squares[i, "direction"] <- direction
# Generate the arc for the current square and append it to arcs data frame
new_arc <- quarter_circle_arc(
squares$x[i], squares$y[i], squares$size[i], direction = (i %% 4)
)
new_arc$frame <- i # Assign the frame for animation
arcs <- rbind(arcs, new_arc)
# Update the direction
direction <- (direction %% 4) + 1
}
# Create the base plot
p <- ggplot() +
coord_fixed(ratio = 1) +
theme_void()
# Plot squares with gradual appearance
for (i in 1:10) {
p <- p +
geom_rect(data = squares[1:i,], aes(xmin = x, ymin = y, xmax = x + size, ymax = y + size),
fill = "white", color = "black") +
geom_path(data = arcs[arcs$frame <= i,],
aes(x = x, y = y), color = "black")
}
# Animate the plot with growing spiral and preserving squares
p_anim <- p +
transition_reveal(arcs$frame) +
enter_fade() +
exit_fade()
# Render the animation
animate(p_anim, nframes = 100, fps = 10)
I want the squares to appear gradually along with the corresponding arcs forming a growing spiral. However, I haven't been able to achieve this.
library(ggplot2)
library(gganimate)
# Define a function to generate Fibonacci numbers
fibonacci <- function(n) {
fib_seq <- numeric(n)
fib_seq[1] <- 1
fib_seq[2] <- 1
for (i in 3:n) {
fib_seq[i] <- fib_seq[i-1] + fib_seq[i-2]
}
return(fib_seq)
}
# Function to generate quarter circle arc data
quarter_circle_arc <- function(x, y, size, direction) {
theta <- seq(0, pi/2, length.out = 100)
if (direction == 1) {
# Bottom-left arc
data.frame(
x = x + size * (1 - cos(theta)),
y = y + size * (1 - sin(theta))
)
} else if (direction == 2) {
# Bottom-right arc
data.frame(
x = x + size * (sin(theta) - 1) + size,
y = y + size * (1 - cos(theta))
)
} else if (direction == 3) {
# Top-right arc
data.frame(
x = x + size * (cos(theta) - 1) + size,
y = y + size * (sin(theta) - 1) + size
)
} else if (direction == 0) {
# Top-left arc
data.frame(
x = x + size * (1 - sin(theta)),
y = y + size * (cos(theta) - 1) + size
)
}
}
# Generate the first 10 Fibonacci numbers
fib_seq <- fibonacci(10)
# Initialize the data frame for squares
squares <- data.frame(
x = numeric(10),
y = numeric(10),
size = fib_seq,
direction = numeric(10),
frame = 1:10
)
# Initialize the data frame for arcs
arcs <- data.frame(
x = numeric(0),
y = numeric(0),
frame = integer(0)
)
# Set the initial position and direction
x <- 0
y <- 0
direction <- 1
for (i in 1:10) {
if (direction == 1) {
y <- y - ifelse(x == 0, 0, fib_seq[i])
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 2) {
x <- x + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 3) {
x <- x - fib_seq[i-2]
y <- y + fib_seq[i-1]
squares[i, "x"] <- x
squares[i, "y"] <- y
} else if (direction == 4) {
x <- x - fib_seq[i]
y <- y - fib_seq[i-2]
squares[i, "x"] <- x
squares[i, "y"] <- y
}
# Store the direction for the arcs
squares[i, "direction"] <- direction
# Generate the arc for the current square and append it to arcs data frame
new_arc <- quarter_circle_arc(
squares$x[i], squares$y[i], squares$size[i], direction = (i %% 4)
)
new_arc$frame <- i # Assign the frame for animation
arcs <- rbind(arcs, new_arc)
# Update the direction
direction <- (direction %% 4) + 1
}
# Create the base plot
p <- ggplot() +
coord_fixed(ratio = 1) +
theme_void()
p <- p +
geom_rect(
data = squares, aes(xmin = x, ymin = y, xmax = x + size, ymax = y + size),
fill = "white", color = "black"
) +
geom_path(
data = arcs,
aes(x = x, y = y), color = "black"
)
# Animate the plot with growing spiral and preserving squares
p_anim <- p +
transition_manual(frames = frame, cumulative = TRUE) + # Keep previous frames visible
enter_fade() +
exit_fade()
# Render the animation
animate(p_anim, nframes = 100, fps = 10)