Need clarification on how this piece of found code is working (recursion)

Hello!

I am trying to understand how a sketch works that I saw on the openprocessing.org site by Naoto Hieda.

The use of “level” in this sketch, I am not fully understanding. And it’s probably a very simple oversight on my part but here is the line:

if (level == 0 || (random(1) < 0.5 && level < 5)) {

// level < 5?? Where is level being changed to test this criteria?

///////////////////////////////////////////////////////
FULL SKETCH BELOW :
///////////////////////////////////////////////////////

const W = 600;

function setup() {
	createCanvas(W, W);
	background(100);
}

function draw() {
	noLoop();

	div(0, 0, W, 0);
}

function div(x, y, w, level) {
	if (level == 0 || (random(1) < 0.5 && level < 5)) { // This is the line I'm stuck on, esp the end "level < 5"
		div(x, y, w / 2, level + 1);
		div(x + w / 2, y, w / 2, level + 1);
		div(x + w / 2, y + w / 2, w / 2, level + 1);
		div(x, y + w / 2, w / 2, level + 1);
	} else {
		// rect(x, y, w, w);
		if (random(1) < 0.5) {
			for (const r of [w / 3 * 4, w / 3 * 2]) {
				arc(x, y, r, r, 0, PI / 2)
				arc(x + w, y + w, r, r, PI, PI / 2 * 3)
			}
		} else {
			for (const r of [w / 3 * 4, w / 3 * 2]) {
				arc(x + w, y, r, r, PI / 2, PI)
				arc(x, y + w, r, r, PI / 2 * 3, PI * 2)
			}
		}
	}
}

Any clarification is most appreciated!
Thank you :slight_smile:

1 Like

It’s a recursive function: it’s calling itself.
Very strong, very interesting programming paradigm.

The new parameter for level is now level +1. That’s how it gets changed.

This measures the depth/ how many times the function called itself. The else part doesn‘t have a recursion so the recursion stops here. That’s important otherwise we have a stack overflow error.

3 Likes

Ah ha! That makes sense. Thank you!
:nerd_face:

1 Like

rewritten in processing (and simplified)

void setup() {
  size(600, 600);
  background(100);
  textAlign(CENTER, CENTER);
  noLoop();
}

void draw() {
  background(100);
  fourRectangles(0, 0, width, 0);
}

//----------------------------------------------------------------------

void fourRectangles(float x, float y, 
  float sizeRect, 
  int depth) {
  // When the depth is still smaller than our random border 
  if (depth < random(0, 8)) {
    // split the rect in four parts and call me again (recursion)
    sizeRect     = sizeRect/2; // the new rects have half the size
    int newLevel = depth+1;    // the new rects have a depth that's higher than the old by 1 
    // 4 parts / quadrants 
    fourRectangles(x, y, sizeRect, newLevel);// upper left rect (comment one line out to see the missing quadrant)
    fourRectangles(x + sizeRect, y, sizeRect, newLevel); // upper right rect 
    fourRectangles(x + sizeRect, y + sizeRect, sizeRect, newLevel); // lower right rect 
    fourRectangles(x, y + sizeRect, sizeRect, newLevel); // lower left rect
  } else {
    // else: End of recursion: draw ONE rect (using the current local values)
    fill(random(255), random(255), random(255));
    rect(x, y, sizeRect, sizeRect);
    if (depth<=5) {
      fill(0);
      text(depth, x+sizeRect/2, y+sizeRect/2);
    }//if
  }//else
}//func

//-----------------------------------------------------------------------------------------------
// Inputs

void keyPressed() {
  redraw();
}

void mousePressed() {
  redraw();
}
//

1 Like

This is tremendously helpful!! And makes recursion much more approachable to work with… THANK YOU and very much appreciated!!
:nerd_face:

1 Like

And you can redraw with mousepress now.

1 Like