Skip to content

Instantly share code, notes, and snippets.

@dewittpe
Last active September 23, 2020 19:15
Show Gist options
  • Save dewittpe/785ee3a77f8b346ddf3a1911101921d5 to your computer and use it in GitHub Desktop.
Save dewittpe/785ee3a77f8b346ddf3a1911101921d5 to your computer and use it in GitHub Desktop.
inscribed circles and regular polygons
# objective - plot circles and polygons such that
# 0. A circle
# 1. An equilateral triangle such that the edges are tangent to the circle
# 2. A circle such that the vertices of the triangle are on the circumference
# 3. A square with edges tangent to the circle drown in step 2.
# 4. A circle with the vertices of the square on the circumference
# 5. A regular pentagon....
#
# A vertex of the regular polygons will all be co-linear. That is, with the
# initial circle centered at the Cartesian point (0, 0), then on vertex for each
# of the regular polygons will have an x-coordinate of 0.
library(ggplot2)
library(ggforce) # needed for geom_circle
# Radius given length of side:
# r = s / (2 * sin(pi / n))
# where s is the length of the side of regular polygon
# n is the number of sides
# Apothem (inradius)
# r = a / cos(pi / n)
# a is the apothem
# n is the number of sides
# Get the vertices of a regular polygon centered at the origin given the apothem
# and at least one vertex with x = 0 (one vertex if n is odd, two if n is even)
vertices <- function(apothem = NULL, radius = NULL, n = 3, rotate = 0) {
if (!xor(is.null(apothem), is.null(radius)) ) {
stop("apothem xor radius needs to be defined")
}
if (!is.null(apothem)) {
radius <- apothem / cos(pi / n)
} else {
apothem <- radius * cos(pi / n)
}
pts <- matrix(c(0, radius), ncol = 1)
theta <- seq(0, 2 * pi, length = n + 1)[-(n + 1)] + rotate
rtn <- do.call(rbind, lapply(theta, function(th) {data.frame(x = - radius * sin (th), y = radius * cos(th))}))
rtn$n <- n
rtn$apothem <- apothem
rtn$radius <- radius
rtn
}
vertices(radius = 2)
circles <- data.frame(x0 = 0, y0 = 0, r = 1)
polygons <- data.frame <- vertices(apothem = 1)
for(i in 2:30) {
circles <- rbind(circles, data.frame(x0 = 0, y0 = 0, r = tail(polygons$radius, 1)))
polygons <- rbind(polygons,
vertices(apothem = circles[i, "r"], n = tail(polygons$n, 1) + 1)
)
}
# build up layers
p1 <-
lapply(
1:nrow(circles),
function(i) {
eval(
substitute(
list(
geom_polygon(data = subset(polygons, n == nn), mapping = aes(x = x, y = y, group = n), fill = "black"),
geom_circle(data = subset(circles, r == rr), mapping = aes(x0 = x0, y0 = y0, r = r), fill = "white", color = NA)
)
,
list(nn = rev(unique(polygons$n))[i],
rr = rev(unique(circles$r))[i]))
)
})
g1 <-
ggplot() +
p1 +
coord_fixed() +
theme_no_axes() +
theme(legend.position = "none",
panel.background = element_rect(fill = "black"))
# Another way
circles <- data.frame(x0 = 0, y0 = 0, r = 1)
polygons <- vertices(radius = 1, n = 3, rotate = pi)
for(i in 2:10) {
circles <- rbind(circles, data.frame(x0 = 0, y0 = 0, r = tail(polygons$apothem, 1)))
polygons <- rbind(polygons, vertices(radius = circles[i, "r"], n = tail(polygons$n, 1) + 1, rotate = pi)
)
}
p2 <-
lapply(
1:nrow(circles),
function(i) {
eval(
substitute(
list(
geom_circle(data = subset(circles, r == rr), mapping = aes(x0 = x0, y0 = y0, r = r), fill = "white", color = NA),
geom_polygon(data = subset(polygons, n == nn), mapping = aes(x = x, y = y, group = n), fill = "black")
)
,
list(nn = unique(polygons$n)[i],
rr = unique(circles$r)[i]))
)
})
g2 <-
ggplot() +
p2 +
coord_fixed() +
theme_no_axes() +
theme(legend.position = "none",
panel.background = element_rect(fill = "black"))
g3 <-
ggplot() +
p1 + p2 +
coord_fixed() +
theme_no_axes() +
theme(legend.position = "none",
panel.background = element_rect(fill = "black"))
gridExtra::grid.arrange(g1, g2, g3, nrow = 1)
ggsave(filename = "g1.pdf", g1, width = 8, height = 8)
# end of file
Display the source blob
Display the rendered blob
Raw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment