Happy New Year

Just a ggplot2 decorated tree.
R
Author
Published

2025-01-06

Tree
library(ggplot2)

# Tree branches
tree_data <- data.frame(
  x = c(0, -1, 1, 0, -0.8, 0.8, 0, -0.6, 0.6), 
  y = c(0, -1, -1, 0.5, -0.45, -0.45, 1, 0.1, 0.1),
  group = rep(1:3, each = 3)
)

# Tree trunk
trunk_data <- data.frame(
  x = c(-0.2, 0.2, 0.2, -0.2),
  y = c(-1, -1, -1.4, -1.4)
)

# Star at the top
star_data <- data.frame(
  x = c(0, 0.05, 0.2, 0.08, 0.12, 0, -0.12, -0.08, -0.2, -0.05),
  y = c(1.35, 1.20, 1.20, 1.1, 0.95, 1.05, 0.95, 1.1, 1.2, 1.2)
)

# Decorations 
decorations_data <- data.frame(
  x = runif(100, -0.8, 0.8),  # Random x positions within the tree
  y = runif(100, -0.8, 1),    # Random y positions within the tree
  colors = sample(c("red", "darkblue", "purple", "gold", "deeppink"), 100, replace = TRUE)
)

# Check if a point is inside a triangle
point_in_triangle <- function(px, py, x1, y1, x2, y2, x3, y3) {
  denominator <- ((y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3))
  a <- ((y2 - y3)*(px - x3) + (x3 - x2)*(py - y3)) / denominator
  b <- ((y3 - y1)*(px - x3) + (x1 - x3)*(py - y3)) / denominator
  c <- 1 - a - b
  return(a >= 0 & b >= 0 & c >= 0)
}

# Filter decorations to fit in tree triangles
valid_points <- apply(decorations_data, 1, function(point) {
  x <- as.numeric(point['x'])
  y <- as.numeric(point['y'])
  inside_triangle1 <- point_in_triangle(x, y, 0, 0, -1, -1, 1, -1)
  inside_triangle2 <- point_in_triangle(x, y, 0, 0.5, -0.8, -0.45, 0.8, -0.45)
  inside_triangle3 <- point_in_triangle(x, y, 0, 1, -0.6, 0.1, 0.6, 0.1)
  return(inside_triangle1 | inside_triangle2 | inside_triangle3)
})

decorations_data <- decorations_data[valid_points, ]

# Plot the tree
ggplot() +
  geom_polygon(data = tree_data, aes(x, y, group = group), fill = "forestgreen", color = "black") +
  geom_polygon(data = trunk_data, aes(x, y), fill = "saddlebrown", color = "black") +
  geom_polygon(data = star_data, aes(x, y), fill = "gold", color = "black") +
  geom_point(data = decorations_data, aes(x, y, color = colors), size = 3) +
  scale_color_identity() +
  coord_fixed() +
  ggtitle("🎄 Happy New Year!") +
  theme_void() +
  theme(plot.title = element_text(hjust = 0.5)) +
  theme(legend.position="none")