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> 
   
*/ 
 
// widthensions 
int num = 100; 
int time = 0; 
 
// display flag 
boolean showStructure = false; 
 
// object array 
Disc[] discs; 
 
 
// methods 
void setup() { 
  size(500, 500); 
  colorMode(RGB,255); 
  ellipseMode(CENTER_RADIUS); 
  background(0); 
  framerate(30); 
  
  // make 100 discs 
  discs = new Disc[num]; 
 
  // arrange linearly 
  for (int i=0;i<num;i++) { 
    float x = random(width); 
    float y = random(width); 
    float fy = 0; 
    float fx = random(-1.0,1.0); 
    float r = 20+random(20); 
    
    discs[i] = new Disc(i,x,y,fx,fy,r); 
  } 
} 
 
// main 
void loop() { 
  if (showStructure) { 
    background(0); 
    // render circles and intersections 
    for (int c=0;c<num;c++) { 
      discs[c].draw(); 
    } 
  } 
  // move discs 
  for (int c=0;c<num;c++) { 
    discs[c].move(); 
    discs[c].render(); 
  } 
  time++; 
} 
 
void keyReleased () { 
  if (key==' ') { 
    background(0); 
    if (showStructure) { 
      showStructure = false; 
    } else { 
      showStructure = true; 
    } 
  } 
} 
 
// translucent point 
void tpoint(int x1, int y1, int gc, float a) { 
  noStroke(); 
  fill(gc,a*255); 
  rect(x1,y1,1,1); 
} 
 
 
// disc object 
class Disc { 
  // index identifier 
  int id; 
  // position 
  float x,y; 
  // radius 
  float r, dr; 
  // velocity 
  float vx,vy; 
 
  // sand painters 
  int numsands = 1; 
  SandPainter[] sands = new SandPainter[numsands]; 
 
  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=1.0; 
    
    // create sand painters 
    for (int n=0;n<numsands;n++) { 
      sands[n] = new SandPainter(); 
    } 
  } 
 
  void draw() { 
    stroke(64); 
    noFill(); 
    ellipse(x,y,r,r); 
  } 
 
  void render() { 
    // find intersecting points with all ascending discs 
    for (int n=id+1;n<num;n++) { 
      // 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 circle intersection 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) 
 
          if (showStructure) { 
            stroke(255); 
            point(p3ax,p3ay); 
            point(p3bx,p3by); 
          } else { 
            tpoint(int(p3ax-1),int(p3ay),255,0.21); 
            tpoint(int(p3ax+1),int(p3ay),0,0.21); 
            tpoint(int(p3bx-1),int(p3by),255,0.21); 
            tpoint(int(p3ax+1),int(p3ay),0,0.21); 
          } 
          // draw sand painters 
          for (int s=0;s<numsands;s++) { 
            sands[s].render(p3ax,p3ay,p3bx,p3by); 
          } 
        } 
      } 
    } 
  } 
 
  void move() { 
    // move radius towards destination radius 
    if (r<dr) r+=0.02; 
    // add velocity to position 
    x+=vx; 
    y+=vy; 
    // bound check 
    if (x+r<0) { 
      x+=width+r+r; 
      y=random(width); 
    } 
    if (x-r>width) { 
      x-=width+r+r; 
      y=random(width); 
     } 
    if (y+r<0) { 
      y+=width+r+r; 
      x=random(width); 
    } 
    if (y-r>width) { 
      y-=width+r+r; 
      x=random(width); 
    } 
  } 
  
} 
 
// sandpainter object 
class SandPainter { 
 
  float p; 
  float g; 
  int c; 
 
  SandPainter() { 
    p = random(1.0); 
    c = int(random(256)); 
    g = random(0.01,0.1); 
  } 
 
  void render(float x, float y, float ox, float oy) { 
    // draw painting sweeps 
    tpoint(int(ox+(x-ox)*sin(p)),int(oy+(y-oy)*sin(p)),c,0.11); 
 
    g+=random(-0.050,0.050); 
    float maxg = 0.5; 
    if (g<-maxg) g=-maxg; 
    if (g>maxg) g=maxg; 
    p+=random(-0.050,0.050); 
    if (p<0) p=0; 
    if (p>1.0) p=1.0; 
 
    float w = g/10.0; 
    for (int i=0;i<11;i++) { 
      tpoint(int(ox+(x-ox)*sin(p + sin(i*w))),int(oy+(y-oy)*sin(p + sin(i*w))),c,0.1-i/110); 
      tpoint(int(ox+(x-ox)*sin(p - sin(i*w))),int(oy+(y-oy)*sin(p - sin(i*w))),c,0.1-i/110); 
    } 
  } 
}