Return to menu
/* 
   
   A surface filled with one hundred medium to small sized circles. 
   Each circle has a different size and direction, but moves at the same slow rate. 
   Display: 
   >>> A. The instantaneous intersections of the circles 
   B. The aggregate intersections of the circles 
 
   Implemented by J. Tarbell <http://levitated.net> 
   8 April 2004 
   Processing v.68 <http://processing.org> 
 
*/ 
 
int num = 100; 
int time = 0; 
 
// object array 
Disc[] discs; 
 
// initialization 
void setup() { 
  size(500, 500); 
  colorMode(RGB,255); 
  ellipseMode(CENTER_RADIUS); 
  background(0); 
  framerate(30); 
 
  // make some discs 
  discs = new Disc[num]; 
  
  // arrange in anti-collapsing circle 
  for (int i=0;i<num;i++) { 
    float fx = 0.4*width*cos(TWO_PI*i/num); 
    float fy = 0.4*width*sin(TWO_PI*i/num); 
    float x = random(width/2) + fx; 
    float y = random(width/2) + fy; 
    float r = 5+random(45); 
    int bt = 1; 
    if (random(100)<50) bt=-1; 
    discs[i] = new Disc(i,x,y,bt*fx/1000.0,bt*fy/1000.0,r); 
  } 
} 
 
// main 
void loop() { 
  background(0); 
  // move discs 
  for (int c=0;c<num;c++) { 
    discs[c].move(); 
    discs[c].render(); 
    discs[c].renderPxRiders(); 
  } 
  time++; 
} 
 
// disc object 
class Disc { 
  // index identifier 
  int id; 
  // position 
  float x,y; 
  // radius 
  float r, dr; 
  // velocity 
  float vx,vy; 
 
  //  pixel riders  
  int numr; 
  int maxr = 40; 
  PxRider[] pxRiders; 
 
  Disc(int Id, float X, float Y, float Vx, float Vy, float R) { 
    // construct 
    id=Id; 
    x=X; 
    y=Y; 
    vx=Vx; 
    vy=Vy; 
    dr=R; 
    r=0; 
    
    numr = int(R/1.62); 
    if (numr>maxr) numr=maxr; 
    
    // create pixel riders 
    pxRiders = new PxRider[maxr]; 
    for (int n=0;n<maxr;n++) { 
      pxRiders[n] = new PxRider(); 
    } 
  } 
 
  void draw() { 
    stroke(0,50); 
    noFill(); 
    ellipse(x,y,r,r); 
  } 
 
  void render() { 
    // find intersecting points with all ascending discs 
    for (int n=id+1;n<num;n++) { 
      if (n!=id) { 
      // find distance to other disc 
      float dx = discs[n].x-x; 
      float dy = discs[n].y-y; 
      float d = sqrt(dx*dx+dy*dy); 
      // intersection test 
      if (d<(discs[n].r+r)) { 
        // complete containment test 
        if (d>abs(discs[n].r-r)) { 
          // find solutions 
          float a = (r*r - discs[n].r*discs[n].r + d*d ) / (2*d); 
          
          float p2x = x + a*(discs[n].x - x)/d; 
          float p2y = y + a*(discs[n].y - y)/d; 
          
          float h = sqrt(r*r - a*a); 
          
          float p3ax = p2x + h*(discs[n].y - y)/d; 
          float p3ay = p2y - h*(discs[n].x - x)/d; 
          
          float p3bx = p2x - h*(discs[n].y - y)/d; 
          float p3by = p2y + h*(discs[n].x - x)/d; 
          
          // P3a and P3B may be identical - ignore this case (for now) 
          stroke(255); 
          point(p3ax,p3ay); 
          point(p3bx,p3by); 
        } 
      } 
      } 
    } 
  } 
 
  void move() { 
    // add velocity to position 
    x+=vx; 
    y+=vy; 
    // bound check 
    if (x+r<0) x+=width+r+r; 
    if (x-r>width) x-=width+r+r; 
    if (y+r<0) y+=width+r+r; 
    if (y-r>width) y-=width+r+r; 
 
    // increase to destination radius 
    if (r<dr) { 
      r+=0.1; 
    } 
  } 
  
  void renderPxRiders() { 
    for (int n=0;n<numr;n++) { 
      pxRiders[n].move(x,y,r); 
    } 
  } 
 
  // pixel rider object  
  class PxRider { 
    float t; 
    float vt; 
    int mycharge; 
    
    PxRider() { 
      t=random(TWO_PI); 
      vt=0.0; 
    } 
    
    void move(float x, float y, float r) { 
      // add velocity to theta 
      t=(t+vt+PI)%TWO_PI - PI; 
      
      vt+=random(-0.001,0.001); 
    
      // apply friction brakes 
      if (abs(vt)>0.02) vt*=0.9; 
 
      // draw      
      float px = x+r*cos(t); 
      float py = y+r*sin(t); 
      color c = get(int(px),int(py)); 
      if (brightness(c)>48) { 
        glowpoint(px,py); 
        mycharge = 164; 
      } else { 
        stroke(mycharge); 
        point(px,py); 
        mycharge*=0.98; 
      } 
 
    } 
  } 
} 
 
 
// methods 
void glowpoint(float px, float py) { 
  for (int i=-2;i<3;i++) { 
    for (int j=-2;j<3;j++) { 
      float a = 0.8 - i*i*0.1 - j*j*0.1; 
      tpoint(int(px+i),int(py+j),#FFFFFF,a); 
    } 
  } 
} 
 
void tpoint(int x1, int y1, color myc, float a) { 
  // place translucent point 
  int r, g, b; 
  color c; 
 
  c = get(x1, y1); 
 
  r = int(red(c) + (red(myc) - red(c)) * a); 
  g = int(green(c) +(green(myc) - green(c)) * a); 
  b = int(blue(c) + (blue(myc) - blue(c)) * a); 
  color nc = color(r, g, b); 
  stroke(nc); 
  point(x1,y1); 
}