#### Fractal-like triangles process

The Processing sketch generates fractal shapes using a triangle and recursion. The main function is `iterate` which generates a new triangle based on a given triangle and calls itself for two new triangles (left and right). This is repeated until a certain condition is met (the length of the triangle’s side is smaller than 20). The final result is stored in an ArrayList of Triangles.

Start variables: l – length of the first triangle; startPoint – starting point for the first triangle

```				```

// ––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// A Processing sketch that generates fractal-like triangles.
//
//        C
//       / \
//      /   \
//     /     \
//    /       \
// B /---------\A
//
// Andreas Pirchner, 2020
// ––––––––––––––––––––––––––––––––––––––––––––––––––––––––

import processing.svg.*;  // import the library for SVG output
import processing.pdf.*;  // import the library for PDF output

ArrayList<Triangle> triangles;  // Create an ArrayList to store the triangles
float l = 150;  // length of the first triangle
int g = 1;  // variable to hold the generations of iterations
int id = Math.round(random(10000));  // random ID for the PDF export
PVector startPoint;  // Create a PVector to store the starting point

// The setup function is called once when the sketch starts
void setup(){
size(1000,1000);  // set the size of the window
background(255);  // set the background color to white
noFill();  // do not fill the shapes
triangles = new ArrayList<Triangle>();  // initialize the triangles ArrayList
//beginRecord(PDF, "export"+id+"layer-1.pdf");  // start recording the export PDF
startPoint = new PVector(width/2, height/2);  // set the starting point to the center of the window
translate(startPoint.x, startPoint.y);  // Translate to the starting point
line(-l,0,l,0);  // draw the first hypotenuse
iterate(l,g, 0, startPoint, 0);  // call the iterate function to start generating triangles
rotate(PI);  // rotate the entire sketch by 180 degrees
iterate(l,g, 0, startPoint, 0);  // call the iterate function again to generate more triangles
println(triangles.size());  // print the number of triangles generated
}

void draw(){
}

void iterate(float _l, int _g, float _angle, PVector _absolutePos, float _absoluteAngle){

float angle = -random(PI/16, PI*15/16);
//float angle = _angle;

//float angle = -PI/4; //random(PI);                     // The Angle for this iteration
// (how are the side lengths of this right angled triangle)
PVector _m = new PVector(0, 0);                        // Make Vektors for this iteration
PVector _a = new PVector(_l, 0);
PVector _b = new PVector(-_l, 0);
PVector _c = new PVector(_m.x + _l*cos(angle), _m.y + _l * sin(angle));

paint(_m, _a, _b, _c, _l);

PVector mAC = PVector.lerp(_a, _c, 0.5);                      // middle of side AC
PVector mBC = PVector.lerp(_b, _c, 0.5);                      // middle of side BC

float one = PI- PI/2 - angle/2;                               // calculate rotations of children triangles
float three = PI/2 - one;
float nextRotationLeft = three;                               // left child trianlge (hypotenuse: BC)
float nextRotationRight = (PI - PI/2 - (-angle/2));           // right child trianlge (hypotenuse: AC)

float _lBC = PVector.dist(_b, _c)/2;                          // length for left child
float _lAC = PVector.dist(_a, _c)/2;                          // length for right child

PVector nextAbsolutePos1 = PVector.add(_absolutePos, mBC); //mBC.rotate(nextRotationLeft));    // absolute pos of m of left child
PVector nextAbsolutePos2 = PVector.add(_absolutePos, mAC); //mAC.rotate(nextRotationRight));    // absolute pos of m of right child
float nextAbsoluteAngle1 = _absoluteAngle + nextRotationLeft; // absolute angle of left child
float nextAbsoluteAngle2 = _absoluteAngle + nextRotationRight;// absolute angle of right child

_g ++;

if (_lBC > 20){
//float nextAngle1 = -random(PI/16, PI*15/16);
float nextAngle1 = -PI/2;
triangles.add(new Triangle(nextAbsolutePos1, _lBC, nextRotationLeft, nextAngle1, _g, nextAbsoluteAngle1));
push();
translate(mBC.x, mBC.y);
rotate(nextRotationLeft);
iterate(_lBC, _g, nextAngle1, nextAbsolutePos1, nextAbsoluteAngle1);
pop();
}
if (_lAC > 20){
//float nextAngle2 = -random(PI/16, PI*15/16);
float nextAngle2 = -PI/2;
triangles.add(new Triangle(nextAbsolutePos2, _lAC, nextRotationRight, nextAngle2, _g, nextAbsoluteAngle2));
push();
translate(mAC.x, mAC.y);
rotate(nextRotationRight);
iterate(_lAC, _g, nextAngle2, nextAbsolutePos2, nextAbsoluteAngle2);
pop();
}
}

// Function to draw the triangle with given parameters
void paint(PVector _m, PVector _a, PVector _b, PVector _c, float _l) {
// Set the color and opacity for drawing the circles
stroke(100, 0, 0, 80); // Red color with 80% opacity

// Don't fill the circles with any color
noFill();

// Set the stroke weight (thickness) of the circles
strokeWeight(1);

// Draw the first circle with the given parameters
// The circle will have the same x and y position as _m and the diameter will be 2 times _l
ellipse(_m.x, _m.y, _l * 2, _l * 2);

// Set the color and opacity for the remaining circles
stroke(0); // Black color

// Draw the second circle with the same x and y position as _m
// The diameter of the circle is 5 pixels
ellipse(_m.x, _m.y, 5, 5);

// Draw the third circle with the given parameters
// The x and y position of the circle is _c and the diameter is 5 pixels
ellipse(_c.x, _c.y, 5, 5);

// Don't fill the triangle
noFill();

// Draw the first line from _a to _c
line(_a.x, _a.y, _c.x, _c.y);

// Draw the second line from _b to _c
line(_b.x, _b.y, _c.x, _c.y);
}
void keyPressed() {
// Check if the 'n' key is pressed
if (key == 'n') {
// Clear the background color to white
background(255);

// Clear the array of triangles
triangles.clear();

// Set the length of the first triangle
l = 150;

// Generate a random ID for the PDF export
int id = Math.round(random(10000));

// Start recording the first layer of the PDF export
beginRecord(SVG, "export" + id + "layer-1.svg");

// Translate the origin point to the center of the screen
translate(width / 2, height / 2);

// Rotate the screen by a random angle
rotate(random(TWO_PI));

// Draw the first hypotenuse with the given length
line(-l, 0, l, 0);

// Call the iterate function
iterate(l, g, 0, startPoint, 0);

// Rotate the screen by 180 degrees
rotate(PI);

// Call the iterate function again
iterate(l, g, 0, startPoint, 0);

// End recording the first layer of the PDF export
endRecord();
}

// Check if the 'p' key is pressed
if (key == 'p') {
// Clear the background color to white
background(255);

// Loop through the array of triangles
for (int i = 0; i < triangles.size(); i++) {
// Get the current triangle from the array
Triangle t = triangles.get(i);

// Call the paint function for the current triangle
t.paint();
}
//endRecord();
}
}
```
```
```				```
// ––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// Andreas Pirchner, 2021
// ––––––––––––––––––––––––––––––––––––––––––––––––––––––––

class Triangle{
// Three points defining the triangle
PVector absolutePos, a, b, c;

// Length of the base side of the triangle
float l;

// Rotation of the triangle
float r;

// Angle of the triangle
float angle;

// Absolute angle of the triangle
float absoluteAngle;

// Generation of the triangle
int generation;

// Constructor of the Triangle class
Triangle (PVector _absolutePos, float _l, float _rotation, float _thisAlpha, int _generation, float _absoluteAngle) {
// Initialize the absolute position of the triangle
absolutePos = _absolutePos;

// Initialize the length of the base side of the triangle
l = _l;

// Initialize the rotation of the triangle
r = _rotation;

// Initialize the angle of the triangle
angle = _thisAlpha;

// Initialize the generation of the triangle
generation = _generation;

// Initialize the absolute angle of the triangle
absoluteAngle = _absoluteAngle;

// Calculate the three points defining the triangle
a = new PVector(l, 0);
b = new PVector(-l, 0);
c = new PVector( + l*cos(angle),  + l * sin(angle));

}

// Function to paint the triangle on the screen
void paint(){
// store the current matrix position
push();
// Translate the triangle to its absolute position
translate(absolutePos.x, absolutePos.y);

// Rotate the triangle based on its absolute angle
rotate(absoluteAngle);

// Debugging information
println(absoluteAngle);

// Fill the center of the triangle with red color
fill(255,0,0);
ellipse(0, 0, 5,5);

// Fill point C of the triangle with green color
fill(0,255,0);
ellipse(c.x,c.y,5,5);

// Show the generation number of the triangle
text(generation,0,0);

// Draw the three sides of the triangle
line(a.x, a.y, c.x, c.y);
line(b.x, b.y, c.x, c.y);
// Restore the previous matrix position
pop();
}
}
```
```