Fractal Tree 4

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 ๐Ÿ™‚

Fractal Tree variation
Fractal Tree variation
Fractal Tree variation
Fractal Tree variation
Fractal Tree variation
Fractal Tree variation
Fractal Tree variation
Fractal Tree variation
Grasshopper UI
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;
  }