Charachromism

“Chara” is intended to be short for “character” or “characteristics”. “Chromism” is a chemistry term that stands for change in color.

This was intended to be a simulation of an over-simplified version of my observations of human group behavior.
The color of each Dot represents its core personality. In addition, each also has its own set of characteristics that influence how the Dot approaches with and is influenced by other Dots.

The simulation is not working as I intend it to yet. There are a few characteristics that I haven’t implemented yet. This is a work in progress. I would like to put the Processing program on here, but it does not run when I upload it onto OpenProcessing and I do not know why.

ArrayList allFlocks;
ArrayList allDots;
int nDots;
 
void setup() {
  size(400, 400);
  colorMode(HSB, 100);
  noStroke();
 
  nDots = 50;
 
  allFlocks = new ArrayList();
 
  allDots = new ArrayList();
  for (int i=0; i1.0) {
      ithDot.shade+=(shadeDiff*ithDot.agreeableness/100.0);
    }
 
    if (iFlock.stdev>(40.0*ithDot.openness)) {
      iFlock.removeDot(ithDot);
      if (iFlock.flockSize()==0) {
        allFlocks.remove(iFlock);
      }
      Flock fnew = new Flock();
      fnew.addDot(ithDot);
      ithDot.flock = fnew;
    }
    else {
      for (int j=0; j ithDot.radius && dh group; //prioritized members of group this Dot associates with
  //The following are the Dot's characteristics
  float agreeableness; //probability of going w/ flow of group
  float extraversion; //probability of associating with other Dots
  float openness; //probability of being interested in a different color
  float spontaneity; //probability of randomly going off somewhere
   
  Flock flock;
 
  Dot (float x, float y, float s, float rad) {
    position = new PVector(x, y);
 
    float angle = random(TWO_PI);
    velocity = new PVector(cos(angle), sin(angle));
     
    acceleration = new PVector(0, 0);
 
    shade = s;
     
    radius = rad;
 
    maxspeed = 1.0;
    maxforce = 0.01;
 
    group = new ArrayList();
    flock = new Flock();
    flock.addDot(this);
 
    agreeableness = random(0, 1.0);
    extraversion = random(0, 1.0);
    openness = random(0, 1.0);
    spontaneity = random(0, 1.0);
     
//    println(str(shade)+"   "+str(openness));
  }
 
  float checkCompatibility (float s) {
    float lower = min(s, shade);
    float higher = max(s, shade);
    float shadeDist = min(higher-lower,(100-higher)+lower);
    float distRatio = abs(shadeDist)/100;
    return distRatio;
  }
   
  void updateFlock(Flock f) {
    flock = f;
  }
 
  void run(ArrayList dots) {
    flock(dots);
    update();
    handleBoundaries();
    render();
  }
 
  void handleBoundaries() {
    if (position.x > width+radius ) position.x -= width;
    if (position.x < 0-radius     ) position.x += width;
    if (position.y > height+radius) position.y -= height;
    if (position.y < 0-radius     ) position.y += height;
  }
 
  void applyForce (PVector force) {
    acceleration.add(force);
  }
 
  //From Flocking by Daniel Shiffman
  //http://processing.org/examples/flocking.html
  void flock(ArrayList dots) {
    PVector sep = separate(allDots);
    PVector ali = align(dots);
    PVector coh = cohesion(dots);
    sep.mult(1.5);
    coh.mult(1.0);
    ali.mult(1.0);
 
    applyForce(sep);
    applyForce(coh);
    applyForce(ali);
  }
 
  // Method to update position
  void update() {
    // Update velocity
    velocity.add(acceleration);
    // Limit speed
    velocity.limit(maxspeed);
    position.add(velocity);
    // Reset accelertion to 0 each cycle
    acceleration.mult(0);
  }
 
  // A method that calculates and applies a steering force towards a target
  // STEER = DESIRED MINUS VELOCITY
  PVector seek(PVector target) {
    PVector desired = PVector.sub(target, position);  // A vector pointing from the position to the target
    // Scale to maximum speed
    desired.normalize();
    desired.mult(maxspeed);
 
    // Steering = Desired minus Velocity
    PVector steer = PVector.sub(desired, velocity);
    steer.limit(maxforce);  // Limit to maximum steering force
    return steer;
  }
 
  // Separation
  // Method checks for nearby dots and steers away
  PVector separate (ArrayList dots) {
    float desiredseparation = 15.0f;
    PVector steer = new PVector(0, 0, 0);
    int count = 0;
    // For every dot in the system, check if it's too close
    for (Dot other : dots) {
      float d = PVector.dist(position, other.position);
      // If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
      if ((d > 0) && (d < desiredseparation)) {
        // Calculate vector pointing away from neighbor
        PVector diff = PVector.sub(position, other.position);
        diff.normalize();
        diff.div(d);        // Weight by distance
        steer.add(diff);
        count++;            // Keep track of how many
      }
    }
    // Average -- divide by how many
    if (count > 0) {
      steer.div((float)count);
    }
 
    // As long as the vector is greater than 0
    if (steer.mag() > 0) {
      // First two lines of code below could be condensed with new PVector setMag() method
      // Not using this method until Processing.js catches up
      // steer.setMag(maxspeed);
 
      // Implement Reynolds: Steering = Desired - Velocity
      steer.normalize();
      steer.mult(maxspeed);
      steer.sub(velocity);
      steer.limit(maxforce);
    }
    return steer;
  }
 
  // Alignment
  // For every nearby dot in the system, calculate the average velocity
  PVector align (ArrayList dots) {
    float neighbordist = 50;
    PVector sum = new PVector(0, 0);
    int count = 0;
    for (Dot other : dots) {
      float d = PVector.dist(position, other.position);
      if ((d > 0) && (d < neighbordist)) {
        sum.add(other.velocity);
        count++;
      }
    }
    if (count > 0) {
      sum.div((float)count);
      // First two lines of code below could be condensed with new PVector setMag() method
      // Not using this method until Processing.js catches up
      // sum.setMag(maxspeed);
 
      // Implement Reynolds: Steering = Desired - Velocity
      sum.normalize();
      sum.mult(maxspeed);
      PVector steer = PVector.sub(sum, velocity);
      steer.limit(maxforce);
      return steer;
    }
    else {
      return new PVector(0, 0);
    }
  }
 
  // Cohesion
  // For the average position (i.e. center) of all nearby dots, calculate steering vector towards that position
  PVector cohesion (ArrayList dots) {
    float neighbordist = 50;
    PVector sum = new PVector(0, 0);   // Start with empty vector to accumulate all positions
    int count = 0;
    for (Dot other : dots) {
      float d = PVector.dist(position, other.position);
      if ((d > 0) && (d < neighbordist)) {
        sum.add(other.position); // Add position
        count++;
      }
    }
    if (count > 0) {
      sum.div(count);
      return seek(sum);  // Steer towards the position
    }
    else {
      return new PVector(0, 0);
    }
  }
 
  void render() {
    fill(shade,100,100);
    ellipse(position.x, position.y, radius, radius);
  }
}
 
 
class Flock {
  ArrayList dots;
  float avgShade;
  float pcx;
  float pcy;
  float stdev;
   
  Flock() {
    dots = new ArrayList();
    avgShade = 0;
    pcx = 0;
    pcy = 0;
    stdev = 0;
    allFlocks.add(this);
  }
   
  void updateInfo(){
    float newx = 0;
    float newy = 0;
    int n = dots.size();
    float tempsum = 0;
    float totalShade = avgShade*n;
    for (Dot d: dots) {
      PVector pos = d.position;
      newx+=pos.x;
      newy+=pos.y;
       
      tempsum+=pow((totalShade-d.shade),2);
    }
     
    pcx = newx/dots.size();
    pcy = newy/dots.size();
     
    stdev = sqrt(tempsum/n);
  }
   
  void addDot(Dot d) {
    //Using previous numbers to calculate new avgs for runtime
    int n0 = dots.size();
    float totShade0 = avgShade*n0;
    int n = n0+1;
    float totShade = totShade0+d.shade;
    //Update the avg
    avgShade = totShade/n;
     
    d.updateFlock(this);
    dots.add(d);
  }
   
  void removeDot(Dot d) {
    //Using previous numbers to calculate new avgs for runtime
    int n0 = dots.size();
    float totShade0 = avgShade*n0;
    int n = n0-1;
    float totShade = totShade0-d.shade;
    //Update the avg
    avgShade = totShade/n;
     
    dots.remove(d);
  }
   
  int flockSize() {
    return dots.size();
  }
   
  void run() {
    for (Dot d: dots) {
      d.run(dots);
    }
  }
}

Comments are closed.