Created
March 8, 2018 20:27
-
-
Save mstrimas/ac50a38a7e656a2b3a173f3a6b31a760 to your computer and use it in GitHub Desktop.
Chaikin's corner cutting algorithm
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
library(tidyverse) | |
library(gganimate) | |
library(hrbrthemes) | |
# generate a jagged polygon | |
set.seed(1) | |
n <- 60 | |
theta <- (runif(n) + 1:n - 1) * 2 * pi / n | |
radius <- rgamma(n, shape = 3) | |
radius <- radius / max(radius) | |
xy <- cbind(cos(theta) * radius, sin(theta) * radius) | |
xy <- rbind(xy, xy[1, ]) | |
xy[, 1] <- xy[, 1] %>% {(. - min(.)) / (max(.) - min(.))} | |
xy[, 2] <- xy[, 2] %>% {(. - min(.)) / (max(.) - min(.))} | |
# function for a single chaikin iteration | |
chaikin <- function(x) { | |
n_pts <- nrow(x) | |
qr <- matrix(NA_real_, nrow = 2 * (n_pts - 1) + 1, ncol = 2) | |
qr[seq(1, nrow(qr) - 1, by = 2), ] <- 0.75 * x[-n_pts, ] + 0.25 * x[-1, ] | |
qr[seq(2, nrow(qr) - 1, by = 2), ] <- 0.75 * x[-1, ] + 0.25 * x[-n_pts, ] | |
qr[nrow(qr), ] <- qr[1, ] | |
qr | |
} | |
# iteratively apply chaikin, saving each step | |
xy_smoothed <- data.frame(xy) %>% | |
mutate(iteration = 0) %>% | |
select(iteration, x = X1, y = X2) | |
for (i in 1:4) { | |
xy <- chaikin(xy) | |
xy_smoothed <- data.frame(xy) %>% | |
mutate(iteration = i) %>% | |
select(iteration, x = X1, y = X2) %>% | |
rbind(xy_smoothed, .) | |
} | |
g <- ggplot(xy_smoothed, aes(x, y)) + | |
geom_polygon(data = filter(xy_smoothed, iteration == 0), fill = "grey40") + | |
geom_polygon(aes(frame = iteration), lwd = 1.5, color = "red", fill = NA) + | |
labs(x = NULL, y = NULL, | |
title = "Chaikin's corner cutting algorithm, iteration = ") + | |
theme_ipsum_rc() + | |
theme() | |
gganimate(g, "chaikin.gif") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment