(n)certainties

GSAPP-Fall 2011

(n)certainties header image 3

4_Terra(air)forma

/////////PARTICLE CLOUD SCRIPT/////////
import processing.pdf.*;

import processing.video.*;
import processing.opengl.*;
import processing.pdf.*;
import toxi.geom.*;
import toxi.processing.*;

PrintWriter output;

int nPoints = 5000; // points to draw

float complexity = 10; // wind complexity
float maxMass = .8; // max pollen mass
float timeSpeed = .03; // wind variation speed
float phase = TWO_PI; // separate u-noise from v-noise
float windSpeed = 10; // wind vector magnitude for debug
int step = 10; // spatial sampling rate for debug// distance between the wind vectors
float[] pollenMass;
float[][] points;

////////////////SETUP////////////////////
void setup() {

  size(900, 900, P2D);//P2D (Processing 2D) - Fast 2D renderer, best used with pixel data, but not as accurate as the JAVA2D default.
  // mm= new MovieMaker (this,width,height,"3W.mov",30,MovieMaker.MOTION_JPEG_B, MovieMaker.BEST);
  points = new float[nPoints][2];
  pollenMass = new float[nPoints];//maza gyris
  for (int i = 0; i < nPoints; i++) {//for each point
    points[i] = new float[] {
      random(0, width), random(0, height)
    };
    pollenMass[i] = random(0, maxMass);
  }

}

///////////////////DRAW////////////////////
void draw() {
  // mm.addFrame();
  float t = frameCount * timeSpeed;//defines the t
  background(0);

  float s = windSpeed;

  //wind lines
  for (int i = 0; i < width; i += step) {
    for (int j = 0; j < height; j += step) {
      float normx = map(i, 0, width, 0, 1);
      float normy = map(j, 0, height, 0, 1);
      float u = noise(t + phase, normx * complexity + phase, normy * complexity + phase);
      float v = noise(t - phase, normx * complexity - phase, normy * complexity + phase);
      pushMatrix(); //store the u,v in a matrix box
      translate(i, j);
      stroke(30);
      line(1, 1, lerp(-windSpeed, windSpeed, u), lerp(-windSpeed, windSpeed, v));//xaraktiristika wind grammis, x1,y1,x2,y2
      popMatrix();//takes the last stored item in the matrix box
    }
  }   

  //gia ta points: x,y
  fill(255,255,0,100);//xroma ellipses sto debugmode

  for (int i = 0; i < nPoints; i++) {
    float x = points[i][0];
    float y = points[i][1];
    float normx = norm(x, 0, width);//?normalizes the value of x between 0 and width
    float normy = norm(y, 0, height);//normalizes the value of y between 0 and height
    float u = noise(t + phase, normx * complexity + phase, normy * complexity + phase);
    float v = noise(t - phase, normx * complexity - phase, normy * complexity + phase);
    float speed = (1 + noise(t, u, v)) / pollenMass[i];
    x += lerp(-speed, speed, u);
    y += lerp(-speed, speed, v);

    //gia na mi feugoyn apo ti skini
    if (x < 0 || x > width || y < 0 || y > height) {
      x = random(0, width);
      y = random(0, height);
    }
    stroke(random(130, 200), random(128, 148), 48, random(150, 200));
    point(x,y);

    points[i][0] = x; //otan ta svino de kounietai tipota
    points[i][1] = y;
    if ((frameCount% 5) == 0 ){
       exportParticles();
    }else{
    }
  }
}

void exportParticles()
{
//  / open the text file
 output = createWriter("points" + frameCount  + ".txt");
//  //String[] lines = new String[points.length];
//  // loop through each agent and write to the file
 for (int i = 0; i < points.length; i++) {
//    // points[i] = new float[]{random(0, width), random(0, height)};
  output.println (points[i][0] + "," + points[i][1]+ "," + (frameCount));

 }

output.flush();
output.close();
}

/////////SINEWAVE ROBOT SCRIPT/////////
//Main Function//
import toxi.processing.*;
import toxi.geom.*;
import processing.video.*;

ArrayList population;
ArrayList attractFoodPop;

void setup(){
  colorMode(HSB, 160);
  smooth();
  size(975,563);

  population = new ArrayList();
  attractFoodPop = new ArrayList();

  for(int i = 0; i < 1000; i++){
    Vec3D p = new Vec3D(random(0,width),random(0,height),0);
    Vec3D v = new Vec3D(random(-1,1), random(-1,1), random(-1,1));
    agent a = new agent(p,v, random(3,4), random(0.1, 0.3));
    population.add(a);
  }

   for(int i = 0; i < 5; i++) {
     Vec3D p = new Vec3D(random(0,width),random(0,height),0);
     Vec3D v = new Vec3D(random(-1,1), random(-1,1), random(-1,1));
   attractFoodPop.add(new attractorFood(p,v,random(1,2), random(0.1, 0.3)));  // p, v, mv, mf

 }
}

void draw(){
  //mm.addFrame();
  background(0,0,0);

  for(int i = 0; i < population.size(); i++){
    agent a = (agent) population.get(i);
    a.update(attractFoodPop);
    a.render();
  }

  for(int i = 0; i < attractFoodPop.size(); i++) {
   attractorFood a = (attractorFood) attractFoodPop.get(i);
   a.update();
   a.render();
 }

//saveFrame("output/frames-####.png");

}

//Agent Class//
class agent{
 // states - global variables
 Vec3D pos;
 Vec3D vel;
 float scaleVel = 1;
 float maxVel;
 float maxForce;
 float Neighbors;

 // constructor
  agent(Vec3D p, Vec3D v, float mv, float mf){
    pos = p.copy();
    vel = v.copy();
    maxVel = mv;
    maxForce = mf;
  }

 // behaviors
  void update(ArrayList attPop){

    ////////////////////////////////////////////////////////////////////////////////////////////////
    this.attractorFood(attPop, 60);

    Vec3D acc = new Vec3D();

    // call the vector functions
    //this.attractorFood(attPop, 100);
    Vec3D ste = steer(new Vec3D(random(0,width),random(0,height),0));
    Vec3D ali = alignment(population, 30);
    Vec3D coh= cohesion (population, 30);
    Vec3D sep= separation  (population, 30);

    // weight or scale vectors
    ste.scaleSelf(2.0);//0
    ali.scaleSelf(2.0);//0
    coh.scaleSelf(2.0);//5
    sep.scaleSelf(2.0);//3

    /////////////////////////////////////////////////////////////////////////////////////////////
    //coh.scaleSelf(scaleCoh);//5

    // add vectors to acc
    acc.addSelf(ste);
    acc.addSelf(ali);
    acc.addSelf(coh);
    acc.addSelf(sep);

///////////////////////////////////////////////////////////////////////////////////////////////

    // vel = vel + acc

    vel.addSelf(acc);

    vel.scaleSelf(scaleVel); 

    vel.limit(maxVel);

    // pos = pos + vel
    pos.addSelf(vel);

  }

  void attractorFood(ArrayList attPop, float range) {
   float sumSin = 0;
   int count = 0;
   float minDist = 50000000;
    //loop thru all the attractors
   for(int i = 0; i < attPop.size(); i++) {
     attractorFood a = (attractorFood) attPop.get(i);
     //get the distance to the attractor
     float Attdist = a.pos.distanceTo(this.pos);
     if (Attdist<minDist){
       minDist = Attdist;

     }
     }

     //if distance < range of attractor
     if(minDist < range) {

       sumSin = sin(0.3*minDist);//sumSin = sumSin + (sin(0.06*Attdist))*(100/Attdist);
       }else{sumSin = 1;}

    scaleVel = sumSin; //scaleVel = 1/sumSin;

 }

  Vec3D steer(Vec3D target){
    // make a vector from the pos to the target:  vec = target - pos
    Vec3D vec = target.sub(pos);
    float d = vec.magnitude();
    if(d > 0){
      // normalize the vector - magnitude of 1
      vec.normalize();
      // scale to length of maxVel: vec = vec x maxVel
      vec.scaleSelf(maxVel);
      // subtract vel
      vec.subSelf(vel);
      // limit by maxForce
      vec.limit(maxForce);
    }else{
      vec = new Vec3D(); // 0,0,0
    }
    // return the vector
   return vec;
  }

  Vec3D alignment(ArrayList pop, float range){
    Vec3D sum = new Vec3D(); // 0,0,0
    int count = 0;
    // loop through each agent in pop
    for(int i = 0; i < pop.size(); i++){
      agent a = (agent) pop.get(i);
      // find the distance between the current agent and the other agent
      float d = pos.distanceTo(a.pos);
      // if distance < range
      if( (d < range) && (d > 0) ){ //(d>0)
        // sum = sum + other agents vel

        sum.addSelf(a.vel);
        // count = count + 1
        count++;
      }
    }
     // find the average: sum/count:  sum = sum x 1/count
     if(count > 0){
       sum.scaleSelf(1/(float)count);
       // limit the average vector to maxForce
       sum.limit(maxForce);
     }
     // return the limited vector
    return sum;
  }

Vec3D cohesion(ArrayList pop, float range){
    // make 0 vector sum, 0 int count
    Vec3D sum = new Vec3D();
    int count = 0;

    // loop through all agents
    for(int i = 0; i < pop.size(); i++){
      // get one agent out of the arraylist
      agent a = (agent) pop.get(i);
      // calculate distance from pos to the other agent pos
      float d = pos.distanceTo(a.pos);
      // if distance < range && other agent is not this agent
      if( (d < range) && (a != this) ){
        // add other agent pos to sum, add 1 to count: sum = sum + a.pos
        sum.addSelf(a.pos);
        count++;
      }
    }
    // find the average pos: sum/count: sum = sum x 1/count
    if(count > 0){
      sum.scaleSelf(1/(float)count); // sum is now the average pos
      // steer toward the average pos
      sum = steer(sum);
    }
    // return that vector
    return sum;
  }

  Vec3D separation(ArrayList pop, float range){
    // make 0 vector
    Vec3D sum = new Vec3D(0,0,0);
    // loop through each agent
    for(int i = 0; i < pop.size(); i++){
      // get an agent out of the arrayList
      agent a = (agent) pop.get(i);
      // calculate distance to the agent
      float d = pos.distanceTo(a.pos);
      // if distance is less than range
      if( (d < range) && ( a != this) ){
        // make a vector between the other agent and this agent

        Vec3D vec = pos.sub(a.pos);
        // scale vector by 1/distance
        vec.scaleSelf(1/d);
        // add the vector to sum
        sum.addSelf(vec);
      }
    }
    // limit to maxForce
    sum.limit(maxForce);
    // return vector
    return sum;
  }

   void render(){
     noStroke();
     fill(0,0,255,40);
     ellipse(pos.x, pos.y, 2, 2);
      // x, y, w, h
  }

}
//Attractor Class//

class attractorFood {
 Vec3D pos;
 Vec3D vel;
 float maxVel;
 float maxForce;
 float mag = 100;
 float range = 50;
 float Neighbors;

  attractorFood(Vec3D p, Vec3D v, float mv, float mf){
    pos = p.copy();
    vel = v.copy();
    maxVel = mv;
    maxForce = mf;
  }

 void update(){

   int Neighbors= getNeighbors(population, 30);
    println (Neighbors);

 Vec3D acc = new Vec3D();

    // call the vector functions
    Vec3D ste = steer(new Vec3D(random(0,width),random(0,height),0));  //steer(new Vec3D(mouseX,mouseY,0));
    Vec3D ali = alignment(attractFoodPop, 30);                          //steer(new Vec3D(random(0,width),random(0,height),0));
    Vec3D coh= cohesion (attractFoodPop, 30);
    Vec3D sep= separation  (attractFoodPop, 30);

    // weight or scale vectors
    ste.scaleSelf(.2);//0.1
    ali.scaleSelf(.2);//1.0
    coh.scaleSelf(.2);//2.0
    sep.scaleSelf(.2);//5.0

    // add vectors to acc
    acc.addSelf(ste);
    acc.addSelf(ali);

    acc.addSelf(coh);
    acc.addSelf(sep);

    // vel = vel + acc
    vel.addSelf(acc);

    vel.limit(maxVel);
    // pos = pos + vel
    pos.addSelf(vel);
    torusSpace();

  }

       int getNeighbors(ArrayList pop, float range){
    int count=0;
    for(int i = 0; i < pop.size(); i++){
      agent a = (agent) pop.get(i);
      float d = pos.distanceTo(a.pos);
      if( (d < range) && (d > 0) ) {
        count++;
      }
    }
    return count;
  }

  Vec3D steer(Vec3D target){
    // make a vector from the pos to the target:  vec = target - pos
    Vec3D vec = target.sub(pos);
    float d = vec.magnitude();
    if(d > 0){
      // normalize the vector - magnitude of 1
      vec.normalize();
      // scale to length of maxVel: vec = vec x maxVel
      vec.scaleSelf(maxVel);
      // subtract vel
      vec.subSelf(vel);
      // limit by maxForce
      vec.limit(maxForce);
    }else{
      vec = new Vec3D(); // 0,0,0
    }
    // return the vector
   return vec;
  }

  Vec3D alignment(ArrayList pop, float range){
    Vec3D sum = new Vec3D(); // 0,0,0
    int count = 0;
    // loop through each agent in pop
    for(int i = 0; i < attractFoodPop.size(); i++){
      attractorFood a = (attractorFood) pop.get(i);    ///attractorFood a = (attractorFood)
      // find the distance between the current agent and the other agent
      float d = pos.distanceTo(a.pos);
      // if distance < range
      if( (d < range) && (d > 0) ){ //(d>0)
        // sum = sum + other agents vel

        sum.addSelf(a.vel);
        // count = count + 1
        count++;
      }
    }
     // find the average: sum/count:  sum = sum x 1/count
     if(count > 0){
       sum.scaleSelf(1/(float)count);
       // limit the average vector to maxForce
       sum.limit(maxForce);
     }
     // return the limited vector
    return sum;
  }

Vec3D cohesion(ArrayList pop, float range){
    // make 0 vector sum, 0 int count
    Vec3D sum = new Vec3D();
    int count = 0;

    // loop through all agents
    for(int i = 0; i < attractFoodPop.size(); i++){
      // get one agent out of the arraylist
      attractorFood a = (attractorFood) pop.get(i);
      // calculate distance from pos to the other agent pos
      float d = pos.distanceTo(a.pos);
      // if distance < range && other agent is not this agent
      if( (d < range) && (d > 0) ){
        // add other agent pos to sum, add 1 to count: sum = sum + a.pos
        sum.addSelf(a.pos);
        count++;
      }
    }
    // find the average pos: sum/count: sum = sum x 1/count
    if(count > 0){
      sum.scaleSelf(1/(float)count); // sum is now the average pos
      // steer toward the average pos
      sum = steer(sum);
    }
    // return that vector
    return sum;
  }

  Vec3D separation(ArrayList pop, float range){
    // make 0 vector
    Vec3D sum = new Vec3D(0,0,0);
    // loop through each agent
    for(int i = 0; i < attractFoodPop.size(); i++){
      // get an agent out of the arrayList
      attractorFood a = (attractorFood) pop.get(i);
      // calculate distance to the agent
      float d = pos.distanceTo(a.pos);
      // if distance is less than range
      if( (d < range) && (d > 0) ){
        // make a vector between the other agent and this agent

        Vec3D vec = pos.sub(a.pos);
        // scale vector by 1/distance
        vec.scaleSelf(1/d);
        // add the vector to sum
        sum.addSelf(vec);
      }
    }
    // limit to maxForce
    sum.limit(maxForce);
    // return vector
    return sum;
  }  

    void torusSpace(){
    if(pos.x > width) pos.x = pos.x - width;
    if(pos.y > height) pos.y = pos.y - height;
    if(pos.x < 0) pos.x = pos.x + width;
    if(pos.y < 0) pos.y = pos.y + height;
  }

  void render() {
   noStroke();
   fill(25,100,255,70);
   ellipse(pos.x, pos.y, 7, 7);
 }
}