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