You can download the RMarkdown source code for this page here.
Generate 200.000 points on a circle with normal-distributed angle
(al), so that a few more are on one side of the circle, and
a normal-distributed positive offset from the radius (dr)
to spread them out a bit.
n <- 200000
tibble(
dr = rnorm(n = n, sd=0.04, mean = 0) %>% abs,
al = rnorm(n = n, sd = 1.0, mean = 0)
) %>% mutate(
r = 1 + dr,
x = r * cos(al),
y = r * sin(al)
) -> pointsSet up a custom ggplot theme with no axes and a black background.
theme_void() %+replace% theme(
legend.position="none",
panel.background = element_rect(fill="black")
) -> thThen render as a scatter plot in white on a black background with low opacity.
points %>% ggplot(aes(x=x, y=y)) +
geom_point(alpha = 0.2, shape = ".", color = "white") +
coord_equal() +
xlim(-3, 3) +
ylim(-2, 2) +
thMake two subsets of the points: p1 with \(n = 40.000\) and p2 with \(n = 20000\)
p1 will remain unchanged and be rendered just as before.
p2 will be used for drawing outward pointing rays to give
that typical look of the sun’s corona during an eclipse.
Add an identifier to each point in p2, like the row
number. It doesn’t really matter what it is as long as it’s unique to
each point. We need that to control which points will be connected into
lines when rendering.
Also add new value \(c = 100\) to them. We’ll need that later.
points %>% slice_sample(n = 40000) -> p1
points %>% slice_sample(n = 20000) -> p2
p2 %>% mutate(
id = row_number(),
c = 100,
d = abs(rnorm(nrow(p2), mean = 0, sd = 0.07))
) -> p2Move the points from p2 all further outward in a loop.
Recalculate their X and Y coordinates as well and decrease \(c\) on each loop. Then merge the moved
copies and originals (p2) together with
bind_rows() into a new tibble (rays).
rays <- p2
steps <- 10
for (i in 1:steps) {
p2 %>% mutate(
r = r + d,
x = r * cos(al),
y = r * sin(al),
c = c - (100 / steps)
) -> p2
p2 %>% bind_rows(rays) -> rays
}Plot them again, but this time add a line graph
(geom_path) between each set of points that have the same
identifier \(i\) and set the opacity
(alpha) to the value of \(c\).
Set the opacity of the p1 points to a value much higher
than 100. We want them to be brighter than the rays. We also need to
control how the opacity (alpha) is handled for this with
scale_alpha_continuous.
This might take a little while to run …
ggplot() +
geom_path(data = rays,
aes(x = x, y = y, group = id, alpha = c),
color ="white", linewidth = 2) +
geom_point(data = p1,
aes(x = x, y = y, alpha = 800),
shape = ".",
color = "white") +
coord_equal() +
xlim(-4, 4) +
ylim(-4, 4) +
scale_alpha_continuous(range = c(0, 0.2)) +
th