Is my fractal optimized? Could it animate?

Hi,

Welcome to the forum! :wink:

If you check the definition of recursion on Wikipedia :

In computer science, recursion is a method of solving a problem where the solution depends on solutions to smaller instances of the same problem.

Recursion solves such recursive problems by using functions that call themselves from within their own code.

So your code doesn’t exactly use what we usually describe as recursion. You are manually running a for loop multiple times with different depth but that’s very tedious! :grinning:

Remember that programming is always trying to avoid repetition.

Let’s suppose I want to draw this shape :

fractal

As you can see, there’s a main circle then on each sides there’s 4 smaller circles that themselves have other smaller circles as well.

A naïve solution might be to implement it like this :

// Go to the center of the screen
translate(width / 2, height / 2);

noFill();

// The first radius
float r1 = 100;

// First circle
circle(0, 0, r1 * 2);

// Second radius
float r2 = r1 / 2;

// Second circles
circle(r1, 0, r2 * 2);
circle(-r1, 0, r2 * 2);
circle(0, r1, r2 * 2);
circle(0, -r1, r2 * 2);

// Third radius
float r3 = r2 / 2;

// Second circles
circle(r1 + r2, 0, r3 * 2);
circle(r1 - r2, 0, r3 * 2);
circle(r1, r2, r3 * 2);
circle(r1, -r2, r3 * 2);

circle(-r1 + r2, 0, r3 * 2);
circle(-r1 - r2, 0, r3 * 2);
circle(-r1, r2, r3 * 2);
circle(-r1, -r2, r3 * 2);

circle(0, r1 + r2, r3 * 2);
circle(0, r1 - r2, r3 * 2);
circle(r2, r1, r3 * 2);
circle(-r2, r1, r3 * 2);

circle(0, -r1 + r2, r3 * 2);
circle(0, -r1 - r2, r3 * 2);
circle(r2, -r1, r3 * 2);
circle(-r2, -r1, r3 * 2);

It gives exactly the same result but this is very tedious (and you’ll never want to do this by hand :yum: )

What we can extract from that is that each time we take position and a radius then we draw a circle. From that circle we do the same at each corners with circles that are half the size.

This is exactly what recursion is for : a function that calls itself :

void circles(float x, float y, float radius, int depth) {
  if (depth == 0) return;

  noFill();
  circle(x, y, radius * 2);

  float half = radius / 2;
  circles(x + radius, y, half, depth - 1);
  circles(x - radius, y, half, depth - 1);
  circles(x, y + radius, half, depth - 1);
  circles(x, y - radius, half, depth - 1);
}

If you wonder what the depth argument is for, ask you the question :

If a function calls itself over and over, it will be infinite (a calls b calls c calls d…). Therefore how can I stop it ?

We need what we call a base case, this is a case where we don’t need to do recursion : in this case when we reached the desired depth in the function call history (bc we are decreasing the depth parameter each time).

That’s why the statement :

if (depth == 0) return;

is really important because as soon as we reach the higher depth, we exit the function and don’t infinitely call the functions.

Now the power of this is that it’s less lines of code and easily procedural :

circles(width / 2, height / 2, 100, 4);
// or
circles(width / 2, height / 2, 100, 6);

fractal fractal8

This example was to show you how you can use recursion to easily implement algorithms that would be impossible to code by hand!

Also for performance, I think that you shouldn’t use PGraphics but directly draw the points using a recursive function!

Have fun :yum:

4 Likes