Described here is a primitive, fractal method of generating trees using Mathematica and Python. Python code parallels the Mathematica code and outputs a Mathematica graphics object. Trees like this:
The algorithm is quite simple:
- Draw a line segment of [somewhat] random length at a [somewhat] random angle.
- Decide if the tree is going to bifurcate at this point -- i.e. pick random integer between 1 and 2.
- Call the the same routine which performed both of the above for each of new branches (either 1 or 2).
- Repeat until the desired depth is achieved.
Most who implement this algorithm are disappointed because the trees do not look realistic:
The inevitable zig-zag fest is due to a subtle yet physically important detail: the angle of the branch is not a mere random number, it is a random deviation from the branch upon which it grows. The angle is given by:
not by:
This correction alone turns what wouldn't even pass for drunken lighting into tree-looking objects. Variation of length and thickness of the branches play an important role as well.
branches[x0_, y0_, maximumDepth_, maximumNfurcation_, maximumDeviation_, initialLean_] := Module[{
x = x0, y = y0,
depth = maximumDepth,
Nfurcation = maximumNfurcation,
deviation = maximumDeviation,
lean = initialLean,
angle, nfurcation, r, x1, y1
},
If[depth > 0,
(* Play around with these two to attain the desired tree structure *)
(* Angle of the branch *)
angle = lean + deviation*Random[Real, {-.5, .5}];
(* Length of the branch *)
r = Sqrt[depth]*Random[Real, {.5, 1}];
(* Number of branches *)
nfurcation = RandomInteger[{1, Nfurcation}];
(* Self-explanatory *)
x1 = x + r Sin[angle];
y1 = y + r Cos[angle];
Append[
Table[
branches[
(* New initial coordinates *)
x1, y1,
(* Decremented depth *)
depth - 1,
(* Still the same maximum number of branches at each split *)
Nfurcation,
(* Still the same maximum deviation of each new branch *)
deviation,
(* Angle of the current branch is the initial lean of the next branch *)
angle
],
{nfurcation}
],
Graphics[
{
(* Play around with this *)
Thickness[depth/300.],
CapForm["Round"],
Line[{{x, y}, {x1, y1}}]
}
]
] // Flatten,
{}
]
];
To run/view:
Show[
branches[
(* Initial coordinates *)
0, 0,
(* Depth *)
11,
(* Maximum number of branches at each split *)
2,
(* Deviation range, [-45˚, 45˚], of every new branch *)
90 \[Degree],
(* Initial lean angle *)
0
],
PlotRange -> All,
AspectRatio -> 1
]
or, for a sampling of trees:
Table[
Show[
branches[0, 0, 11, 2, 90 \[Degree], 0],
PlotRange -> All,
AspectRatio -> 1
],
{9}
]
Modify the source code and pipe the output into an nb file:
python trees.py > tree.nb