Triangulo de Sierpinski           Por: Miguel Lou Moreno

Explicación del método

Partimos de un triangulo inicial

cs1.GIF (1709 bytes)

 Y en cada iteración eliminamos el triangulo que se forma entre la mitad de cada uno de los lados.

cs2.GIF (2076 bytes)

 De esta manera, de los 3 triángulos que tenemos ahora, a cada uno le eliminamos su triangulo central. Así hasta cansarnos

cs3.GIF (2673 bytes)

 Descripción del código:

 Lo he programado en C++ usando las librerias de OpenGL para representarlo

 Estructuras:

 typedef struct { //Para un punto en el espacio
      GLfloat x;
      GLfloat y;
      GLfloat z; //La coordenada z no se usa por que estamos en 2D
} punto;
 
typedef struct{ //Para un triangulo
      punto v[3];
}face;

 Variables globales:

 GLfloat lado=6.0f;           //Para la longitud del lado del triangulo
vector<face> Triangulos;    //Vector de triangulos
 

 Metodo para crear el triangulo inicial:

 void init(){
      face primera; //Primer triangulo
 
      //Damos las coordenadas de los 3 puntos en sentido contrario a las agujas del reloj
      primera.v[0].x=0.0f;
      primera.v[0].y=lado*sqrt(3.0f/4.0f);
      primera.v[0].z=0.0f;
 
      primera.v[1].x=-lado/2;
      primera.v[1].y=0.0f;
      primera.v[1].z=0.0f;
 
      primera.v[2].x=lado/2;
      primera.v[2].y=0.0f;
      primera.v[2].z=0.0f;
 
      Triangulos.push_back(primera);
}

 Para dibujar un triangulo:

void pintar1(face f){
      glBegin(GL_TRIANGLES);
            glVertex3f(f.v[0].x,f.v[0].y,f.v[0].z);
            glVertex3f(f.v[1].x,f.v[1].y,f.v[1].z);
            glVertex3f(f.v[2].x,f.v[2].y,f.v[2].z);
      glEnd();
}

 Metodo display:

 void Display (void) {
      glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      glClearDepth( 1.0f );
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
      // Se activa la matriz del modelador
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
 
      //Centramos el triangulo
      glTranslatef(0.0f,-(lado*sqrt(3.0f/4.0f))/3,-10.0f);
      glColor3f(1.0f,0.0f,0.0f); //Color rojo
 
      //Pintamos cada triangulo del vector
      for(int i=0; i<Triangulos.size();i++)
            pintar1(Triangulos[i]);
 
      glutSwapBuffers();
      glFlush();
}

 Metodo principal del programa:

 int main(int argc, char **argv) {
      glutInit(&argc, argv);
      glutInitWindowPosition(50,50);
      glutInitWindowSize (W_WIDTH, W_HEIGHT);
      glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);
      glutCreateWindow("Ventana con el Visual C++ y glut");
 
      //Funcion de dibujo
      glutDisplayFunc(Display);
 
      //Manejador de teclado
      glutKeyboardFunc(tecla);
 
      //Configuración de la matriz de proyeccion
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(-5.0f,5.0f,-5.0f,5.0f,-150.0,150.0f);
     
      init(); //Creamos el primer triangulo
 
      //Lazo principal
      glutMainLoop();
      return 0;
}

 Manejador de teclado:

 void tecla(unsigned char c, int x, int y) {
      switch (c) {
            case '+': //Hacer la siguiente iteración
                  hacerMas();
                  printf("Numero de triangulos: %d\n",Triangulos.size());
                  break;
            case '*': //Volver al triangulo inicial aumentando su tamaño
                  lado+=1.0;
                  Triangulos.clear();
                  init();
                  break;
            case 27:     // Se ha pulsado Esc.
                  exit(0); // Salimos del programa
                  break;
            default:
                  break;
      }
      glutPostRedisplay();
}

 

Método para llevar a cabo la siguiente iteración:

Este es el método mas interesante de todo este código.

Lo que hacemos es recorrer el vector de los triángulos existentes, y para cada uno de ellos, buscar los puntos medios de sus lados, y definir los 3 triángulos que lo sustituirán.

Los nuevos triángulos los guardamos en un vector a parte para no recorrerlos en la misma iteración en la que han sido creados. Finalmente devolvemos el vector con los nuevos triángulos.

 void hacerMas(){
      vector<face> aux; //Vector que devolveremos
      for(int j=0;j<Triangulos.size();j++){
            face leido=Triangulos[j];
            face nueva1,nueva2,nueva3; //Los 3 nuevos triangulos
 
            nueva1.v[0].x=leido.v[0].x;
            nueva1.v[0].y=leido.v[0].y;
            nueva1.v[0].z=0.0f;
 
            nueva1.v[1].x=(leido.v[0].x+leido.v[1].x)/2.0f;
            nueva1.v[1].y=(leido.v[0].y+leido.v[1].y)/2.0f;
            nueva1.v[1].z=0.0f;
 
            nueva1.v[2].x=(leido.v[0].x+leido.v[2].x)/2.0f;
            nueva1.v[2].y=(leido.v[0].y+leido.v[2].y)/2.0f;
            nueva1.v[2].z=0.0f;
 
            aux.push_back(nueva1);//Lo añadimos al vector
 
            nueva2.v[0].x=leido.v[1].x;
            nueva2.v[0].y=leido.v[1].y;
            nueva2.v[0].z=0.0f;
 
            nueva2.v[1].x=(leido.v[2].x+leido.v[1].x)/2.0f;
            nueva2.v[1].y=(leido.v[2].y+leido.v[1].y)/2.0f;
            nueva2.v[1].z=0.0f;
 
            nueva2.v[2].x=(leido.v[0].x+leido.v[1].x)/2.0f;
            nueva2.v[2].y=(leido.v[0].y+leido.v[1].y)/2.0f;
            nueva2.v[2].z=0.0f;
 
            aux.push_back(nueva2); //Lo añadimos al vector
 
            nueva3.v[0].x=leido.v[2].x;
            nueva3.v[0].y=leido.v[2].y;
            nueva3.v[0].z=0.0f;
 
            nueva3.v[1].x=(leido.v[0].x+leido.v[2].x)/2.0f;
            nueva3.v[1].y=(leido.v[0].y+leido.v[2].y)/2.0f;
            nueva3.v[1].z=0.0f;
 
            nueva3.v[2].x=(leido.v[1].x+leido.v[2].x)/2.0f;
            nueva3.v[2].y=(leido.v[1].y+leido.v[2].y)/2.0f;
            nueva3.v[2].z=0.0f;
 
            aux.push_back(nueva3); //Lo añadimos al vector
      }
      Triangulos.clear();//Eliminamos los antiguos
      Triangulos=aux;//Ponemos los nuevos
      aux.clear();
}

 

Dejá un comentario, sugerencia u opinión