Skip to content

Instantly share code, notes, and snippets.

@AdamSpannbauer
Last active July 24, 2018 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AdamSpannbauer/83d6d1446b9361a5e9928708aa9ebd4d to your computer and use it in GitHub Desktop.
Save AdamSpannbauer/83d6d1446b9361a5e9928708aa9ebd4d to your computer and use it in GitHub Desktop.
# Create/Draw a Binary Fractal Tree
library(ggplot2)
library(uuid)
options(stringsAsFactors = FALSE)
# create line segment from (0, 0) to (0, len) to be trunk of fractal tree
create_trunk = function(len = 1) {
end_point = c(0, len)
trunk_df = data.frame(x=c(0, 0),
y=end_point,
id=uuid::UUIDgenerate())
return(list(df=trunk_df, end_point=end_point))
}
# creates end point of line segment to satisfy length and
# angle inputs from given start coord
gen_end_point = function(xy, len = 5, theta = 45) {
dy = sin(theta) * len
dx = cos(theta) * len
newx = xy[1] + dx
newy = xy[2] + dy
return(c(newx, newy))
}
# create a single branch of fractal tree
# returns branch endpoint coords and a plotly line shape to represent branch
branch = function(xy, angle_in, delta_angle, len) {
end_point = gen_end_point(xy, len = len, theta = angle_in + delta_angle)
branch_df = as.data.frame(rbind(xy, end_point))
rownames(branch_df) = NULL
names(branch_df) = c('x', 'y')
branch_df$id = uuid::UUIDgenerate()
return(list(df=branch_df, end_point=end_point))
}
# helper function to aggregate branch objects into single branch object
collect_branches = function(branch1, branch2) {
return(list(df=rbind(branch1$df, branch2$df)))
}
# recursively create fractal tree branches
create_branches = function(xy,
angle_in = pi / 2,
delta_angle = pi / 8,
len = 1,
min_len = 0.01,
len_decay = 0.2) {
if (len < min_len) {
return(NULL)
} else {
branch_left = branch(xy, angle_in, delta_angle, len)
subranches_left = create_branches(branch_left$end_point,
angle_in = angle_in + delta_angle,
delta_angle = delta_angle,
len = len * len_decay,
min_len = min_len,
len_decay = len_decay)
branches_left = collect_branches(branch_left, subranches_left)
branch_right = branch(xy, angle_in, -delta_angle, len)
subranches_right = create_branches(branch_right$end_point,
angle_in = angle_in - delta_angle,
delta_angle = delta_angle,
len = len * len_decay,
min_len = min_len,
len_decay = len_decay)
branches_right = collect_branches(branch_right, subranches_right)
return(collect_branches(branches_left, branches_right))
}
}
# create and draw binary fractal tree
draw_fractal_tree = function(trunk_len=10,
delta_angle = pi / 8,
len_decay=0.7,
min_len=0.25) {
trunk = create_trunk(trunk_len)
branches = create_branches(trunk$end_point,
delta_angle =delta_angle,
len = trunk_len * len_decay,
min_len = min_len,
len_decay = len_decay)
tree = collect_branches(trunk, branches)$df
ggplot(tree, aes(x, y, group=id)) +
geom_point(size=.5, aes(color=x)) +
geom_line() +
scale_color_gradientn(colours = rainbow(5)) +
guides(color=FALSE) +
theme_void()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment