Skip to content

Instantly share code, notes, and snippets.

@expersso
Created July 28, 2016 08:44
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save expersso/944f3d4aad15f71b192fff254d4ac5b9 to your computer and use it in GitHub Desktop.
Save expersso/944f3d4aad15f71b192fff254d4ac5b9 to your computer and use it in GitHub Desktop.
Trigonometry with magick, gganimate, and purrr
## Purpose: illustrate use of magick, gganimate, and purrr
## Inspiration:
## https://rud.is/b/2016/07/27/u-s-drought-animations-with-the-witchs-brew-purrr-broom-magick/
## and subsequent discussion on magick vs gganimate:
## https://twitter.com/hrbrmstr/status/758304420224466944
library(purrr)
library(ggplot2)
library(gganimate)
library(animation)
library(magick)
# Sequence from 0 to 2pi (= radius of unit circle)
df <- data.frame(x = seq(0, 2 * pi, length.out = 100))
# Create breaks and breaks labels at fractional intervals of pi
breaks <- seq(0, 2, 0.5)
breaks_lbls <- sprintf("%s * pi", as.character(breaks)) %>%
map(~parse(text = .x)) %>%
lift(c)(.)
# Animated plot of sin(x) and cos(x) from 0 to 2pi
p_trig <- ggplot(df, aes(x = x, frame = x, cumulative = TRUE)) +
geom_line(aes(y = sin(x), color = "sin(x)")) +
geom_line(aes(y = cos(x), color = "cos(x)")) +
scale_x_continuous(breaks = breaks * pi,
labels = breaks_lbls,
expand = c(0, 0)) +
scale_y_continuous(expand = c(0, 0.01)) +
theme_light() +
theme(panel.grid.minor = element_blank()) +
labs(x = "\nx", y = "f(x)\n", color = NULL)
# Generate DF of XY-coordinates of a circle with a given radius and center
circle <- function(t, r = 1, center = c(0, 0)) {
x <- center[1] + r * cos(t)
y <- center[2] + r * sin(t)
data.frame(x, y, id = seq_along(t))
}
df_circle <- circle(df$x)
# Animated plot of unit circle, making a full revolution
p_unit_circle <- ggplot(df_circle, aes(x, y, yend = y, xend = x)) +
geom_hline(yintercept = 0, color = "grey80", linetype = "dashed") +
geom_vline(xintercept = 0, color = "grey80", linetype = "dashed") +
geom_path(color = "grey30") +
geom_segment(aes(x = 0, y = 0, frame = id), color = "grey80") +
geom_segment(aes(x = x, y = 0, frame = id, color = "sin(x)")) +
geom_segment(aes(x = 0, y = y, frame = id, color = "cos(x)")) +
scale_x_continuous(breaks = c(-1, 0, 1), expand = c(0, 0.01)) +
scale_y_continuous(breaks = c(-1, 0, 1), expand = c(0, 0.01)) +
coord_equal() +
theme_light() +
theme(panel.grid = element_blank(), legend.position = "none") +
labs(x = "\nx", y = "y\n")
# Save animated plots as GIFs
ani.options(ani.height = 130, interval = 0.001)
gg_animate(p_trig, "trig.gif", title_frame = FALSE, ani.width = 500)
gg_animate(p_unit_circle, "unit_circle.gif", title_frame = FALSE, ani.width = 130)
# Read the two plots and append together
map2(
"unit_circle.gif" %>% image_read() %>% as.list(),
"trig.gif" %>% image_read() %>% as.list(),
~image_append(c(.x, .y))
) %>%
lift(image_join)(.) %>%
image_write("result.gif")
# Remove intermediate files
c("trig.gif", "unit_circle.gif") %>% walk(unlink)
# Easier than doing it the old-fashioned way:
# shell(
# paste(
# "convert",
# "\\( unit_circle.gif -coalesce -append \\)",
# "\\( trig.gif -coalesce -append \\)",
# "+append -crop x130 -set delay 0.01 +repage result.gif"
# )
# )
@expersso
Copy link
Author

result

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