Algorithmic Structures

				
					

/*
       C
      / \
     /   \
    /     \
   /       \
B /---------\A
*/

import processing.svg.*;
import processing.pdf.*;

ArrayList<Triangle> 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;

void setup(){
  size(1000,1000);  
  background(255);
  noFill();
  triangles = new ArrayList<Triangle>();
  //beginRecord(PDF, "export"+id+"layer-1.pdf");       // start recording the export PDF
  //triangles.add(new Triangle(_m, _l, _a, _b, _c, mBC, nextRotationLeft));
  startPoint = new PVector(width/2, height/2);
  translate(startPoint.x, startPoint.y);                          // Translate to starting point
  line(-l,0,l,0);                                        // draw first hypotenuse
  iterate(l,g, 0, startPoint, 0);
  rotate(PI);
  iterate(l,g, 0, startPoint, 0);
  println(triangles.size());
}

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();
  }
}

void paint(PVector _m, PVector _a, PVector _b, PVector _c, float _l){
    stroke(100,0,0,80);                                      // Draw Circles for Orientation
      noFill();
      //fill(100,0,0,20);
      strokeWeight(1);
      ellipse(_m.x, _m.y, _l*2, _l*2);
      //strokeWeight(_l*_l/800);
      stroke(0);
      //fill(0);
      //fill(255,0,0);
      ellipse(_m.x, _m.y, 5,5);
      //fill(0,255,0);
      ellipse(_c.x,_c.y, 5,5);
      noFill();
                                                               // Draw Triangle, hypotenuse not needed
      line(_a.x, _a.y, _c.x, _c.y);
      line(_b.x, _b.y, _c.x, _c.y);
}

void keyPressed(){
  if (key == 'n'){
    background(255);
    triangles.clear();
    l = 150;//random(90,120);                                    // length of the first triangle
    int id = Math.round(random(10000));                    // random ID for the PDF export
    beginRecord(SVG, "export"+id+"layer-1.svg");       // start recording the export PDF
    translate(width/2, height/2);                          // Translate to starting point
    rotate(random(TWO_PI));
    line(-l,0,l,0);                                        // draw first hypotenuse
    iterate(l, g, 0, startPoint, 0);
    rotate(PI);
    iterate(l, g, 0, startPoint, 0);
    endRecord();
    
  }
  if (key == 'p'){
    //beginRecord(PDF, "export"+id+"layer-1.pdf");       // start recording the export PDF
    background(255);
    //translate(width/2, height/2);
    for(int i = 0; i < triangles.size(); i++){
      Triangle t = triangles.get(i);
      t.paint();
      //println(t.generation);
    }
    //endRecord();
  }
}
				
			
				
					class Triangle{
  PVector absolutePos, a, b, c;
  float l, r, angle, absoluteAngle;
  int generation;
  //Triangle (PVector _m, float _l, PVector _a, PVector _b, PVector _c, PVector _mBC, float _rotation) {
  Triangle (PVector _absolutePos, float _l, float _rotation, float _thisAlpha, int _generation, float _absoluteAngle) {
    absolutePos = _absolutePos;              // middle point of hypotenuse
    l = _l;              // length of base side (hypotenuse)
    r = _rotation;       // orientation of new triangle (based on kathede of parent)
    angle = _thisAlpha;      // angle to find new point C of new triangle
    generation = _generation;
    absoluteAngle = _absoluteAngle;
    
    a = new PVector(l, 0);
    b = new PVector(-l, 0);
    c = new PVector( + l*cos(angle),  + l * sin(angle));
  
  }
  
  void paint(){
     push();
       translate(absolutePos.x, absolutePos.y);
       rotate(absoluteAngle);
       println(absoluteAngle);
       //line(a.x, a.y, b.x, b.y);
       fill(255,0,0);
       ellipse(0, 0, 5,5);
       fill(0,255,0);
       ellipse(c.x,c.y,5,5);
       text(generation,0,0);
       line(a.x, a.y, c.x, c.y);
       line(b.x, b.y, c.x, c.y);
     pop();
  }
}