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")