Skip to content
Phyllotaxis flower/ Mandala art in R
Phyllotaxis: draw flowers using mathematics
📖 Background
Mathematics can describe many phenomena of the natural world. Excellent examples are the shape of snowflakes, the fractal geometry of Romanesco broccoli, and how self-similarity rules the growth of plants. In this competition, you will design floral patterns using scatter plots!
You don't need any mathematical background to participate in this competition, but if you want to know more about phyllotaxis, you can check out this article on Wikipedia.
# Load the ggplot2 package
library(ggplot2)
# Set plot images to a nice size
options(repr.plot.width = 6, repr.plot.height = 6)
# Number of points in the flower
points <- 500
# Define the golden angle
angle <- pi * (3 - sqrt(5)) # ~137.5 degrees
# Define the golden angle
angle <- pi * (3 - sqrt(5)) # ~137.5 degrees
# Generate data
t <- 1:points
theta <- t * angle
r <- sqrt(t) # Grow radius like a sunflower
# Convert polar to cartesian coordinates
x <- r * cos(theta)
y <- r * sin(theta)
# Create a data frame
df <- data.frame(x = x, y = y, t = t)
# Create flower plot
ggplot(df, aes(x = x, y = y, color = t)) +
geom_point(shape = 16, size = 2.5, alpha = 0.8) +
scale_color_viridis_c(option = "magma") + # Nice color gradient
theme_void() + # Removes axis, grid, etc.
theme(legend.position = "none") + # Hides legend
coord_equal() + # Keep aspect ratio
ggtitle("Phyllotaxis Flower in R")
# Multiple Phyllotaxis Flowers on one plot in R
# Load required libraries
library(ggplot2)
library(dplyr)
# Function to create one flower
generate_flower <- function(center_x, center_y, points = 300, size = 2, color_offset = 0) {
angle <- pi * (3 - sqrt(5)) # golden angle
t <- 1:points
r <- sqrt(t)
theta <- t * angle
x <- center_x + r * cos(theta)
y <- center_y + r * sin(theta)
data.frame(x = x, y = y, size = size, color = t + color_offset)
}
# Combine multiple flowers
set.seed(123)
flower_df <- bind_rows(
generate_flower(0, 0),
generate_flower(8, 3, size = 1.8, color_offset = 500),
generate_flower(-6, -5, size = 2.2, color_offset = 1000),
generate_flower(4, -7, size = 2, color_offset = 1500),
generate_flower(-8, 4, size = 2.5, color_offset = 2000)
)
# Plot the garden
ggplot(flower_df, aes(x = x, y = y, color = color)) +
geom_point(aes(size = size), alpha = 0.7, shape = 16) +
scale_color_viridis_c(option = "plasma") +
theme_void() +
theme(legend.position = "none") +
coord_equal() +
ggtitle("Phyllotaxis Flower Garden in R")
# Create an animation where the flower grows over time
#install.packages("gganimate")
#install.packages("gifski")
#install.packages("transformr") # Required by gganimate internally
#install.packages("magick")
# Load required packages
library(ggplot2)
library(gganimate)
library(gifski)
# Set parameters
points <- 300
angle <- pi * (3 - sqrt(5))
t <- 1:points
r <- sqrt(t)
theta <- t * angle
x <- r * cos(theta)
y <- r * sin(theta)
# Create data frame
df <- data.frame(x = x, y = y, t = t)
# Create the animated plot
p <- ggplot(df, aes(x = x, y = y)) +
geom_point(aes(size = t, color = t), alpha = 0.8) +
scale_color_viridis_c(option = "plasma") +
theme_void() +
coord_equal() +
transition_reveal(along = t) +
labs(title = "🌸 Blooming Flower Animation")
# Store the animation
flower_anim <- animate(p, fps = 20, duration = 5, width = 600, height = 600, renderer = gifski_renderer())
# Display the animation in DataCamp/interactive R
flower_anim
# Save the animation
anim_save("blooming_flower.gif", animation = flower_anim)
# Save the animation to a static file
ggplot(df, aes(x = x, y = y)) +
geom_point(aes(size = t, color = t), alpha = 0.8) +
scale_color_viridis_c(option = "plasma") +
theme_void() +
coord_equal() +
labs(title = "Static Flower Snapshot")
# Still WIP
library(ggplot2)
library(dplyr)
# Function to generate a single petal shape
generate_petal <- function(n = 100, scale = 1) {
t <- seq(0, pi, length.out = n)
x <- sin(t) * cos(t) * scale
y <- cos(t)^2 * scale
data.frame(x, y)
}
# Function to rotate and place petals in circular layout
create_layer <- function(petals = 16, scale = 1, radius = 1, layer_name = "") {
petal_list <- lapply(1:petals, function(i) {
angle <- 2 * pi * i / petals
petal <- generate_petal(scale = scale)
x_new <- petal$x * cos(angle) - petal$y * sin(angle)
y_new <- petal$x * sin(angle) + petal$y * cos(angle)
data.frame(
x = x_new + radius * cos(angle),
y = y_new + radius * sin(angle),
group = paste0(layer_name, "_", i),
layer = layer_name
)
})
bind_rows(petal_list)
}
# Create colored petal layers
layer1 <- create_layer(petals = 12, scale = 1.2, radius = 0, layer_name = "center")
layer2 <- create_layer(petals = 18, scale = 1.6, radius = 1.6, layer_name = "middle")
layer3 <- create_layer(petals = 24, scale = 1.9, radius = 3.3, layer_name = "outer")
mandala <- bind_rows(layer1, layer2, layer3)
# Create border rings (just points in circular shape)
circle_ring <- function(radius, points = 200, size = 1) {
theta <- seq(0, 2*pi, length.out = points)
data.frame(
x = radius * cos(theta),
y = radius * sin(theta),
size = size
)
}
ring1 <- circle_ring(radius = 0.3, size = 2)
ring2 <- circle_ring(radius = 2.8, size = 1.2)
ring3 <- circle_ring(radius = 4.8, size = 0.8)
rings <- bind_rows(ring1, ring2, ring3)
# Plot the mandala
ggplot() +
geom_polygon(data = mandala, aes(x, y, group = group, fill = layer),
color = "black", linewidth = 0.3, alpha = 0.9) +
scale_fill_manual(values = c("center" = "#FDAE61", "middle" = "#D53E4F", "outer" = "#5E4FA2")) +
geom_point(data = rings, aes(x, y, size = size), shape = 21, fill = "black", stroke = 0.2) +
geom_point(aes(x = 0, y = 0), shape = 21, size = 3, fill = "black") +
coord_equal() +
theme_void() +
theme(legend.position = "none") +
labs(title = "Colorful Mandala with Petals and Border Rings")