Return to menu
/* 
   
   Structure 3 
   
   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 Casey Reas <http://groupc.net> 
   8 March 2004 
   C++ / OpenGL 
 
   Writing this program in C++ required three files: 
   s3_A.cpp     The controller file, opens/updates the window 
   Circle.cpp   Defines the behavior for the circles 
   Circle.h     Skematic information about the circles 
 
*/ 
 
 
 
#include <GL/glut.h> 
#include <stdlib.h> 
#include <math.h> 
#include "Circle.h" 
 
static GLfloat spin = 0.0; 
static GLint once = 1; 
 
static int width; 
static int height; 
 
Circle *circles[numCircle]; 
 
void display(void) 
{ 
   if(once == 1) { 
     glClear(GL_COLOR_BUFFER_BIT); 
     once = 0; 
   } 
   
   for(int i=0; i<numCircle; i++) { 
     circles[i]->update(); 
     circles[i]->move(); 
   } 
 
   glutSwapBuffers(); 
   glutPostRedisplay(); 
} 
 
GLfloat random() { 
  return (GLfloat) ((float)(rand() >> 0) / 16384.0) - 1.0; 
} 
 
void init(void)  
{ 
   glEnable (GL_BLEND); 
   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
   glClearColor (1.0, 1.0, 1.0, 1.0); 
   glShadeModel (GL_FLAT); 
   
   width = 1024; 
   height = 786; 
   
   for (int i=0; i<numCircle; i++) { 
     circles[i] = new Circle(random()*512, random()*384, 
                            (random() + 1) * 60, 
                             random()*0.25, random()*0.25, i, circles); 
   } 
} 
 
void reshape(int w, int h) 
{ 
   glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
   glMatrixMode(GL_PROJECTION); 
   glLoadIdentity(); 
   gluOrtho2D(-512.0, 512.0, -384.0, 384.0); 
   glMatrixMode(GL_MODELVIEW); 
   glLoadIdentity(); 
   glClear(GL_COLOR_BUFFER_BIT); 
} 
 
void mouse(int button, int state, int x, int y)  
{ 
   switch (button) { 
      case GLUT_LEFT_BUTTON: 
         break; 
      case GLUT_MIDDLE_BUTTON: 
      case GLUT_RIGHT_BUTTON: 
         break; 
      default: 
         break; 
   } 
} 
 
void keyboard(unsigned char c, int x, int y) { 
  if(c == 'q' || c == 'Q') { 
    exit(0); 
  } 
} 
   
/* 
 *  Request double buffer display mode. 
 *  Register mouse input callback functions 
 */ 
int main(int argc, char** argv) 
{ 
   glutInit(&argc, argv); 
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); 
   glutCreateWindow("Structure3"); 
   glutFullScreen(); 
   init (); 
   glutDisplayFunc(display); 
   glutReshapeFunc(reshape); 
   glutMouseFunc(mouse); 
   glutKeyboardFunc(keyboard); 
   glutMainLoop(); 
   return 0;   /* ANSI C requires main to return int. */ 
} 
 
 
 
#include "Circle.h" 
 
Circle::Circle(float px, float py, float pr, float psp, float pysp, int pid, Circle *circles[numCircle]) 
{ 
    others = circles; 
    
    x = px; 
    y = py; 
    r = pr; 
    r2 = r*r; 
    id = pid; 
    sp = psp; 
    ysp = pysp; 
} 
 
void Circle::update() 
{ 
  for(int i=0; i<numCircle; i++) { 
    if(i != id) { 
      intersect( others[id], others[i] ); 
    } 
  } 
} 
 
 
void Circle::move() 
{ 
  x += sp; 
  y += ysp; 
  
  if(sp > 0) { 
    if(x > width/2+r) { 
      x = -width/2-r; 
    }   
  } else { 
    if(x < -width/2-r) { 
      x = width/2+r; 
    } 
  } 
  
  if(ysp < 0) { 
    if(y < -height/2-r) { 
      y = height/2+r; 
    } 
  } else { 
    if(y > height/2+r) { 
      y = -height/2-r; 
    } 
  } 
} 
 
void Circle::intersect(Circle *cA, Circle *cB) 
{ 
  float dx = cA->x - cB->x; 
  float dy = cA->y - cB->y; 
  float d2 = dx*dx + dy*dy; 
  float d = sqrt( d2 ); 
 
  if ( d>cA->r+cB->r || d<abs(cA->r-cB->r) ) return; // no solution 
 
  float a = (cA->r2 - cB->r2 + d2) / (2*d); 
  float h = sqrt( cA->r2 - a*a ); 
  float x2 = cA->x + a*(cB->x - cA->x)/d; 
  float y2 = cA->y + a*(cB->y - cA->y)/d; 
 
  float paX = x2 + h*(cB->y - cA->y)/d; 
  float paY = y2 - h*(cB->x - cA->x)/d; 
  float pbX = x2 - h*(cB->y - cA->y)/d; 
  float pbY = y2 + h*(cB->x - cA->x)/d; 
 
  float dist = distance(paX, paY, pbX, pbY) *2 / 255.0f; 
  glColor4f(dist, dist, dist, 0.05f); 
  glBegin(GL_LINES); 
  glVertex2f(paX, paY); 
  glVertex2f(pbX, pbY); 
  glEnd(); 
} 
 
float Circle::distance(float x1, float y1, float x2, float y2) { 
	return sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)); 
} 
 
 
 
#include "math.h" 
#include <GL/glut.h> 
 
#ifndef _Circle_H_ 
#define _Circle_H_ 
 
#define PI 3.14159265358979323846 
#define TWO_PI 6.28318530717958647693 
#define numCircle 100 
 
class Circle 
{ 
public: 
  
  float x, y, r, r2, sp, ysp; 
  int id; 
 
  Circle **others; 
 
  Circle(); 
  Circle(float, float, float, float, float, int, Circle *[numCircle]); 
  void update(); 
  void move(); 
  void intersect(Circle *, Circle *); 
  float distance(float, float, float, float); 
 
}; 
 
#endif