class GrowTree{ float x,y; int direction, growthStep; LSystem lsystem; ParticleSystem treePhysics; Particle [] particle; Node [] node; //Attraction [] suck; boolean sucking = false; int drawStackSize = 0; float nodeVelocity = 4.0; GrowTree(float x, float y, int direction, String axiom, String [] ruleset, int iterations){ this.x = x; this.y = y; this.direction = direction; treePhysics = new ParticleSystem(0.0, 0.09); lsystem = new LSystem(axiom, ruleset); lsystem.iterate(iterations); makeTree(); } void draw(){ fill(20,255,0);//,100); stroke(0,200,0);//,200); for(int i = 0; i < drawStackSize; i++){ if(node[i].active){ if(node[i].parent != -1){ strokeWeight(node[i].size); line(particle[i].position().x(), particle[i].position().y(), particle[node[i].parent].position().x(), particle[node[i].parent].position().y()); } strokeWeight(1); ellipse(particle[i].position().x(), particle[i].position().y(), node[i].size*2, node[i].size*2); if(node[i].timer > -2){ node[i].timer--; } if(node[i].timer == 0){ growBurst(i); } } } /* if(particle[drawStackSize-1].velocity().x() < 0.01 && particle[drawStackSize-1].velocity().y() < 0.01 && !sucking && node[drawStackSize-1].timer < 0){ for(int i = 0; i < suck.length; i++){ suck[i].turnOn(); } } */ treePhysics.tick(); } //fires out more nodes from nodes that are "pregnant" (have children) void growBurst(int i){ if(node[i].child != null){ for(int j = 0; j < node[i].child.length; j++){ particle[node[i].child[j]].moveTo(particle[i].position().x(), particle[i].position().y(), 0.0); float xVel = cos(node[node[i].child[j]].angle) * nodeVelocity; float yVel = sin(node[node[i].child[j]].angle) * nodeVelocity; particle[node[i].child[j]].setVelocity(xVel, yVel, 0.0); node[node[i].child[j]].active = true; } } } //generates Nodes and Particles to grow the tree from LSystem class void makeTree(){ stroke(255); float angle = PI + HALF_PI; Vector drawStack = new Vector(0); Vector pushPop = new Vector(0); int pushPopDepth = 0; int parent = 0; drawStack.add(new Node(angle, 0.1, 6, -1)); drawStackSize++; for(int i = 0; i < lsystem.tree.length(); i++){ float angleStep = 0.3; switch(lsystem.tree.charAt(i)){ case 'F': drawStack.add(new Node(angle, 0.5 + random(pushPopDepth*0.2), 5 - constrain(pushPopDepth, 0, 4), parent)); drawStackSize++; parent = drawStackSize-1; break; case '+': angle += angleStep; break; case '-': angle -= angleStep; break; case '[': pushPop.add(new Node(angle, 0.5 + random(pushPopDepth*0.2), 5 - constrain(pushPopDepth, 0, 4), parent)); pushPopDepth++; break; case ']': Node temp = (Node)pushPop.remove(pushPopDepth-1); pushPopDepth--; angle = temp.angle; parent = temp.parent; break; } } particle = new Particle[drawStackSize]; node = new Node[drawStackSize]; node[0] = (Node)drawStack.get(0); node[0].active = true; particle[0] = treePhysics.makeParticle(1.0, x, y, 0.0); particle[0].makeFixed(); for(int i = 1; i < drawStackSize; i++){ node[i] = (Node)drawStack.get(i); if(node[node[i].parent].child != null){ node[node[i].parent].child = append(node[node[i].parent].child, i); } else{ node[node[i].parent].child = new int[1]; node[node[i].parent].child[0] = i; } particle[i] = treePhysics.makeParticle(node[i].weight, x, y, 0.0); } /* suck = new Attraction[drawStackSize-1]; for(int i = 1; i < drawStackSize; i++){ suck[i-1] = treePhysics.makeAttraction(particle[0], particle[i], 10000, 100.0); suck[i-1].turnOff(); } */ } } //information about how to draw the tree dynamically is stored in the Node object static class Node{ float angle, weight; int parent, timer, size; int [] child; boolean active; Node(float angle, float weight, int size, int parent){ this.angle = angle; this.parent = parent; this.weight = weight; this.size = size; timer = 5; active = false; } }