• Options

Fractal Canopy

A fractal canopy is a fractal generated, by sequentially splitting and branching lines from existing lines.

At the end of each line, draw n new lines at certain angles.

There are a lot of parameters to vary here: the number of branches, the angle between them, the original width, as well as the decay of length and width...

When playing around with these you can get all kinds of interesting results. There are a few you can play around with in the presets above, like a shape that resembles 2d-broccoli, an H-Tree, or even a Sierpinski Triangle.

Many things in nature follow this pattern - like trees and plants, but also blood vessels or the patterns generated by an electric arc when it passes through materials (so-called Lichtenberg figures). Even some types of crystal growth resemble this structure.

The code used to generate this pattern looks like this:

function drawTree() {
  background(config.color);
  resetMatrix();
  translate(width / 2, height);
  branch(config.rootLength, config.rootWidth, 0);
}

const halfNumBranches = Math.floor(config.branches / 2)

function branch(len: number, weight: number, iteration: number) {
  // stop recursion if reached max depth
  if (iteration > config.maxIterations) {
    return;
  }
  strokeWeight(weight);
  stroke(
    // mapping stroke color based on iterations to different colors
    map(iteration, 0, 10, 100, 150),
    map(iteration, 0, 10, 100, 255),
    100
  );
  line(0, 0, 0, -len);
  translate(0, -len);

  // figure out angles 
  const evenBranches = config.branches % 2 === 0
  const midpoint = evenBranches
        ? halfNumBranches - 0.5
        : halfNumBranches;
        
  rotate(config.angle * midpoint);

  // loop over the amount of new branches
  for (let i = 0; i < config.branches; i++) {
    push();
    rotate(-config.angle * i);

    // then recurse, drawing a new branch into each direction
    branch(
      len * config.lengthDecay,
      weight * config.widthDecay,
      iteration + 1
    );
    pop();
  }
}