Recursive Tree without using rotate()

This might be a weird question :thinking:, but here goes:
Would it be possible to draw a Recursive Tree WITHOUT using rotate()?

I ask because I am preparing a couple of interactive projects where I use Processing to control a AxiDraw plotter in respons to users drawing on paper seen through top-dow web-camera + openCV. It seems like I might run into trouble with rotate(), since the AxiDraw needs specific coordinates to move to, and I cannot rotate the paper :upside_down_face:

Below is Shiffmans example of a recursive tree using rotate. Could it be done with PVectors instead?

float theta;   

void setup() {
  size(640, 360);
}

void draw() {
  background(0);
  frameRate(30);
  stroke(255);
  // Let's pick an angle 0 to 90 degrees based on the mouse position
  float a = (mouseX / (float) width) * 90f;
  // Convert it to radians
  theta = radians(a);
  // Start the tree from the bottom of the screen
  translate(width/2,height);
  // Draw a line 120 pixels
  line(0,0,0,-120);
  // Move to the end of that line
  translate(0,-120);
  // Start the recursive branching!
  branch(120);

}

void branch(float h) {
  // Each branch will be 2/3rds the size of the previous one
  h *= 0.66;
  
  // All recursive functions must have an exit condition!!!!
  // Here, ours is when the length of the branch is 2 pixels or less
  if (h > 2) {
    pushMatrix();    // Save the current state of transformation (i.e. where are we now)
    rotate(theta);   // Rotate by theta
    line(0, 0, 0, -h);  // Draw the branch
    translate(0, -h); // Move to the end of the branch
    branch(h);       // Ok, now call myself to draw two new branches!!
    popMatrix();     // Whenever we get back here, we "pop" in order to restore the previous matrix state
    
    // Repeat the same thing, only branch off to the "left" this time!
    pushMatrix();
    rotate(-theta);
    line(0, 0, 0, -h);
    translate(0, -h);
    branch(h);
    popMatrix();
  }
}
1 Like

That’s possible

Without being at a real computer:

get rid of rotate and calculate the new x,y using cos and sin.

probably pass the new x,y as a Parameter to the function

I attempted to do it with PVectors, but yeah perhaps it would be easier with just cos and sin? But I guess I should pass the angle to the function too or…?

PVector and cos go together well, you store the cos sin results in a PVector

Yeah, angle too I guess

Here is the recursive tree without using rotate hope it helps you with your own project.

float theta;   

void setup() {
  size(640, 360);
}

void draw() {
  background(0);
  frameRate(30);
  stroke(255);
  // Let's pick an angle 0 to 95 degrees based on the mouse position
  float a = (mouseX / (float) width) * 95f;
  // then cap it at 90 degrees
  a = min(a, 90); 
  // Convert it to radians
  theta = radians(a);
  // Start the tree from the bottom of the screen
  translate(width/2, height);
  // Draw a line 120 pixels
  line(0, 0, 0, -120);
  // Move to the end of that line
  translate(0, -120);
  // Start the recursive branching!
  branch(new PVector(0, 0), -PI/2, theta, 120);
}

void branch(PVector parent, float branch_angle, float delta_angle, float h) {  
  // Each branch will be 2/3rds the size of the previous one
  h *= 0.66;
  if (h > 2) {
    float ccw_angle, cw_angle, delta_x, delta_y;
    // Left branch
    // Counter-Clockwise branch
    pushMatrix();
    translate(parent.x, parent.y);
    ccw_angle = branch_angle - delta_angle;
    delta_x = h * cos(ccw_angle);
    delta_y = h * sin(ccw_angle);
    line(0, 0, delta_x, delta_y);
    popMatrix();
    branch(new PVector(parent.x + delta_x, parent.y + delta_y), ccw_angle, delta_angle, h);
    // Right branch
    // Clockwise branch
    pushMatrix();
    translate(parent.x, parent.y);
    cw_angle = branch_angle + delta_angle;
    delta_x = h * cos(cw_angle);
    delta_y = h * sin(cw_angle);
    line(0, 0, delta_x, delta_y);
    popMatrix();
    branch(new PVector(parent.x + delta_x, parent.y + delta_y), cw_angle, delta_angle, h);
  }
}

4 Likes

It is possible to remove all matrix operations from the recursive method and use absolute coordinates instead.
Replace the method with

void branch(PVector parent, float branch_angle, float delta_angle, float h) {  
  // Each branch will be 2/3rds the size of the previous one
  h *= 0.66;
  if (h > 2) {
    float ccw_angle, cw_angle, delta_x, delta_y;
    // Left branch
    // Counter-clockwise branch
    ccw_angle = branch_angle - delta_angle;
    delta_x = h * cos(ccw_angle);
    delta_y = h * sin(ccw_angle);
    line(parent.x, parent.y, parent.x + delta_x, parent.y + delta_y);
    branch(new PVector(parent.x + delta_x, parent.y + delta_y), ccw_angle, delta_angle, h);
    // Right branch
    // Clockwise branch
    cw_angle = branch_angle + delta_angle;
    delta_x = h * cos(cw_angle);
    delta_y = h * sin(cw_angle);
    line(parent.x, parent.y, parent.x + delta_x, parent.y + delta_y);
    branch(new PVector(parent.x + delta_x, parent.y + delta_y), cw_angle, delta_angle, h);
  }
}
2 Likes

Thanks so much @quark! This is perfect :star_struck:

1 Like