With this variation, the fractal tree will combine the same functions as in earlier posts Fractal Tree 2 & Fractal Tree 3, meaning having the branch amounts, branch lengths and branch angles randomized but in a somewhat controlled manner.
While having this amount of controlled randomness added, the fractal coherence can be argued to only be used as a guiding function in order to create a more “realistic” looking tree system.
Most of the logic and functions used are already explained in more detail in previous posts, so this will be a more visual post ๐
private void RunScript(double startLength, double lengthRatio, double lengthTolerance, int maxBranchAmount, double branchAngle, double angleTolerance, int iterations, int branchSeed, int angleLengthSeed, ref object A)
{
Point3d startPoint = new Point3d(0, 0, 0);
Vector3d startVector = new Vector3d(0, 1, 0);
Vector3d z = new Vector3d(0, 0, 1);
Line first = new Line(startPoint, startVector, startLength);
int path = 0;
GH_Path firstPath = new GH_Path(path);
DataTree<Line> treeBranches = new DataTree<Line>();
treeBranches.Add(first, firstPath);
// branchAngles
List<double> angleList = new List<double>();
angleList.Add(branchAngle / -2.0);
DataTree<double> treeAngles = new DataTree<double>();
Random randomBranchAmount = new Random(branchSeed);
Random randomAngleLength = new Random(angleLengthSeed);
for(int i = 0;i < iterations;i++)
{
List<Line> branchList = treeBranches.Branch(treeBranches.BranchCount - 1);
path++;
GH_Path pth = new GH_Path(path);
foreach(Line branch in branchList)
{
int branchAmount = randomBranchAmount.Next(1, maxBranchAmount);
double angleIncrement = branchAngle / (branchAmount - 1);
for(int j = 0;j < branchAmount;j++)
{
double newAngle = angleIncrement + angleList[j];
if(j >= branchAmount - 1)
{
treeAngles.Add(branchAngle / -2.0, pth);
}
else
{
angleList.Add(newAngle);
treeAngles.Add(newAngle, pth);
}
List<double> angless = treeAngles.Branch(pth);
Line newBranchLeft = treeBranch(branch, angless[j], angleTolerance, lengthRatio, lengthTolerance, z, randomAngleLength);
treeBranches.Add(newBranchLeft, pth);
}
}
}
A = treeBranches;
}
// <Custom additional code>
Line treeBranch (Line Branch, double BranchAngle, double AngleTolerance, double LengthRatio, double LengthTolerance, Vector3d RotationAxis, Random random)
{
double rotation = RandomDoubleInRange(BranchAngle, AngleTolerance, random);
double radianRotation = RhinoMath.ToRadians(rotation);
Point3d endPoint = Branch.To;
Vector3d direction = Branch.To - Branch.From;
direction.Rotate(radianRotation, RotationAxis);
double length = Branch.Length * LengthRatio;
double branchLength = RandomDoubleInRange(length, LengthTolerance, random);
Line newBranch = new Line(endPoint, direction, branchLength);
return newBranch;
}
double RandomDoubleInRange (double OriginalValue, double Tolerance, Random random)
{
double tolerance = (OriginalValue * Tolerance) - OriginalValue;
double min = OriginalValue - tolerance;
double max = OriginalValue + tolerance;
var rDouble = random.NextDouble();
var rRangeDouble = rDouble * (max - min) + min;
return rRangeDouble;
}