Implementacion con opengl de la visualizacion de grafos, donde los vertices son resortes uniendo los nodos, y los nodos se rechazan entre ellos, y existe una fuerza en el origen que los acerca a todos.
Makefile para compilarlo:
INCLUDE = -I/usr/include/
LIBDIR = -L/usr/X11R6/lib
CC = gcc
CCFLAGS = -g ${INCLUDE}
LIBRARY = -lX11 -lXi -lXmu -lglut -lGL -lGLU -lm
all :ejemplo1.o
${CC} ${CCFLAGS} -o ejemplo1 ejemplo1.o ${LIBDIR} ${LIBRARY}
clean :
rm -rf ejemplo1 ejemplo1.o
typedef struct _point{
float x,y,z;
} point;
typedef struct _force{
float fx,fy,fz;
} force;
typedef struct _sisi{
point p;
force f;
} sisi;
typedef struct _grafo{
int nnodos;
sisi nodos[100];
int enlaces[100][100];
point max,min;
} grafo;
float angulo=0.0;
grafo grafo_global;
void calcularfuerzas(grafo *g){
int i,j;
float distancia;
for (i=0;i<g->nnodos;i++){
g->nodos[i].f.fx = 0.0f;
g->nodos[i].f.fy = 0.0f;
g->nodos[i].f.fz = 0.0f;
for (j=0;j<g->nnodos;j++){
if (i!=j && g->enlaces[i][j]==1){
distancia = sqrt(powf(g->nodos[i].p.x - g->nodos[j].p.x,2.0f) + powf(g->nodos[i].p.y - g->nodos[j].p.y,2.0f) + powf(g->nodos[i].p.z - g->nodos[j].p.z,2.0f));
if ( distancia > 0.001f ){
g->nodos[i].f.fx += (g->nodos[i].p.x - g->nodos[j].p.x) / powf(distancia,3.0f);
g->nodos[i].f.fy += (g->nodos[i].p.y - g->nodos[j].p.y) / powf(distancia,3.0f);
g->nodos[i].f.fz += (g->nodos[i].p.z - g->nodos[j].p.z) / powf(distancia,3.0f);
}
}
}
// Nene
distancia = sqrt(powf(g->nodos[i].p.x,2.0f)+powf(g->nodos[i].p.y,2.0f)+powf(g->nodos[i].p.z,2.0f));
if (distancia>(float)g->nnodos){
g->nodos[i].f.fx -= g->nnodos*g->nodos[i].p.x/powf(distancia,3.0f);
g->nodos[i].f.fy -= g->nnodos*g->nodos[i].p.y/powf(distancia,3.0f);
g->nodos[i].f.fz -= g->nnodos*g->nodos[i].p.z/powf(distancia,3.0f);
}
}
grafo_global.max.x=-1000;
grafo_global.max.y=-1000;
grafo_global.max.z=-1000;
grafo_global.min.x=1000;
grafo_global.min.y=1000;
grafo_global.min.z=1000;
for (i=0;i<g->nnodos;i++){
// Movimiento
g->nodos[i].p.x+=g->nodos[i].f.fx;
g->nodos[i].p.y+=g->nodos[i].f.fy;
g->nodos[i].p.z+=g->nodos[i].f.fz;
if (grafo_global.max.x<grafo_global.nodos[i].p.x)
grafo_global.max.x=grafo_global.nodos[i].p.x;
if (grafo_global.max.y<grafo_global.nodos[i].p.y)
grafo_global.max.y=grafo_global.nodos[i].p.y;
if (grafo_global.max.z<grafo_global.nodos[i].p.z)
grafo_global.max.z=grafo_global.nodos[i].p.z;
if (grafo_global.min.x>grafo_global.nodos[i].p.x)
grafo_global.min.x=grafo_global.nodos[i].p.x;
if (grafo_global.min.y>grafo_global.nodos[i].p.y)
grafo_global.min.y=grafo_global.nodos[i].p.y;
if (grafo_global.min.z>grafo_global.nodos[i].p.z)
grafo_global.min.z=grafo_global.nodos[i].p.z;
}
}
void init_grafo(void){
int i,j;
grafo_global.nnodos=30;
for (i=0;i<grafo_global.nnodos;i++){
for (j=0;j<grafo_global.nnodos;j++){
grafo_global.enlaces[i][j]=1;
}
grafo_global.nodos[i].p.x=rand()%10;
grafo_global.nodos[i].p.y=rand()%10;
grafo_global.nodos[i].p.z=rand()%10;
}
// grafo_global.enlaces[0][1]=0;
// grafo_global.enlaces[1][0]=0;
grafo_global.nodos[0].p.x=5;
grafo_global.nodos[0].p.y=1;
grafo_global.nodos[0].p.z=5;
grafo_global.nodos[1].p.x=2;
grafo_global.nodos[1].p.y=2;
grafo_global.nodos[1].p.z=2;
grafo_global.nodos[2].p.x=2;
grafo_global.nodos[2].p.y=2;
grafo_global.nodos[2].p.z=3;
grafo_global.nodos[3].p.x=3;
grafo_global.nodos[3].p.y=6;
grafo_global.nodos[3].p.z=6;
grafo_global.nodos[4].p.x=5;
grafo_global.nodos[4].p.y=-5;
grafo_global.nodos[4].p.z=5;
grafo_global.nodos[5].p.x=-2;
grafo_global.nodos[5].p.y=2;
grafo_global.nodos[5].p.z=2;
grafo_global.nodos[6].p.x=2;
grafo_global.nodos[6].p.y=2;
grafo_global.nodos[6].p.z=-3;
grafo_global.nodos[7].p.x=3;
grafo_global.nodos[7].p.y=8;
grafo_global.nodos[7].p.z=6;
grafo_global.max.x=grafo_global.nodos[0].p.x;
grafo_global.max.y=grafo_global.nodos[0].p.y;
grafo_global.max.z=grafo_global.nodos[0].p.z;
grafo_global.min.x=grafo_global.nodos[0].p.x;
grafo_global.min.y=grafo_global.nodos[0].p.y;
grafo_global.min.z=grafo_global.nodos[0].p.z;
}
void init(void)
{
glClearColor (1.0, 1.0, 1.0, 0.0);
glShadeModel (GL_FLAT);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (0, 0, 0);
glLoadIdentity();
gluLookAt (0.0, 0.0, 15.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glRotatef(angulo,0,1.0,0);
float dx,dy,dz;
dx = grafo_global.max.x - grafo_global.min.x;
dy = grafo_global.max.y - grafo_global.min.y;
dz = grafo_global.max.z - grafo_global.min.z;
// glutWireCube (1.0);
// glScalef (10.0/dx, 10.0/dy, 10.0/dz);
if (dx>dy && dx >dz){
glScalef(10.0/dx,10.0/dx,10.0/dx);
glutWireCube (dx);
// glTranslatef(dx/2.0f,dx/2.0f,dx/2.0f);
} else if (dy>dx && dy >dz){
glScalef(10.0/dy,10.0/dy,10.0/dy);
glutWireCube (dy);
// glTranslatef(dy/2.0f,dy/2.0f,dy/2.0f);
} else if (dz>dx && dz >dy){
glScalef(10.0/dz,10.0/dz,10.0/dz);
glutWireCube (dz);
// glTranslatef(dz/2.0f,dz/2.0f,dz/2.0f);
}
int cont,cont2;
for (cont=0;cont<grafo_global.nnodos;cont++){
glPushMatrix();
glTranslatef(grafo_global.nodos[cont].p.x, grafo_global.nodos[cont].p.y, grafo_global.nodos[cont].p.z);
glutSolidSphere(.2, 32, 32);
glPopMatrix();
for (cont2=cont;cont2<grafo_global.nnodos;cont2++){
if (grafo_global.enlaces[cont][cont2]){
glBegin(GL_LINES);
glVertex3f(grafo_global.nodos[cont].p.x,grafo_global.nodos[cont].p.y,grafo_global.nodos[cont].p.z);
glVertex3f(grafo_global.nodos[cont2].p.x,grafo_global.nodos[cont2].p.y,grafo_global.nodos[cont2].p.z);
glEnd();
}
}
}
glFlush ();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 25.0);
glMatrixMode (GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}
void idle(void){
static int timelast=0;
int time;
time = glutGet(GLUT_ELAPSED_TIME);
if (time-timelast>10){
timelast=time;
if (angulo<360){
angulo+=0.1;
} else {
angulo=0.0;
}
}
calcularfuerzas(&grafo_global);
glutPostRedisplay();
}
int main(int argc, char** argv)
{
/*
* Inicializando OpenGL
* */
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutIdleFunc(idle);
/*
* Inicializando Entrada del Grafo
* */
init_grafo();
/*
* Entrando en el ciclo
* */
glutMainLoop();
return 0;
}