< galactic.htm <body><style type="text/css"> div.bnu {font-size: 11px; line-height: 22px} .bnu a,.bnu a:hover{font:normal 11px Tahoma;text-decoration:none;color:black;padding:0px 5px} .bnu a:hover{color: #00F} div.ai{width: 240px;font:normal 12px Tahoma;padding:5px 0px 0px 0px;margin:0px;float:left;display: block;text-align:left} .ai p {padding:0px;margin:0px;font:normal 12px Tahoma;line-height:normal;text-decoration:none} .ai a,.ai a:hover{font:bold 12px Tahoma;text-decoration:underline;color:#00F} </style> <div id="0908800319" align="center"> <div style="text-align:center;width:765px;border:1px solid black;height:24px;overflow:hidden;background:white url(/icons/100ws/bg.gif) repeat-x" class="bnu"> <script language="JavaScript" src="/icons/100ws/sc.js"></script> <a href="http://www.100webspace.com"><img alt="webspace hosting" title="webspace hosting" src="/icons/100ws/fh.gif" border="0" height="24" width="172" align="left"/></a> <a href="http://www.resellerspanel.com">reseller hosting</a>| <a href="http://www.ipowerweb.com">web hosting</a>| <a href="http://www.lonex.com/blog/">blog</a>| <a href="http://www.lonex.com/forum/">forum</a>| <a href="http://www.idatingonline.com">dating</a>| <a href="http://www.fateback.com">free hosting</a>| <a href="http://www.openhost.us/">openhost</a>| <a href="http://www.100webspace.com/about_us/report_abuse.html" title="report abuse">report abuse</a> </div> <div style="width:750px; height: 60px"><div class="ai" style="margin-right:15px"><a href="http://www.UnityFax.com">Fax to Email</a><p>Unlimited Faxes, No Fees, Dedicated Phone Number</p></div><div style="display:block; float:right; cursor:pointer;" onClick="window.location.href='ht'+'tp:/'+'/ww'+'w.10'+'0we'+'bspa'+'ce.'+'co'+'m/'+'r/?'+'sr=1'+'00ws'"><img src="/icons/100ws/free_templates.gif" alt="Free Website Templates" onClick="window.location.href='ht'+'tp:/'+'/ww'+'w.10'+'0we'+'bspa'+'ce.'+'co'+'m/'+'r/?'+'sr=1'+'00ws'" /></div></div></div>.</body>

Curva de Von Koch          Por Miguel Lou Moreno

Explicación del método

Partimos de una linea inicial, la cual dividimos en 3 partes iguales. Dejamos las dos partes laterales como están y la central la convertimos en dos segmentos con la longitud de la parte inicial. A partir de ahí repetimos el mismo proceso una y otra vez para cada nuevo segmento como se muestra a continuación:

ck1.GIF (6962 bytes)

Imagen extraida de www.matematicas.unal.edu.co

Descripción del método

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 cada segmento
      punto p1;
      punto p2;
} linea;

  

Variables globales:

 
GLfloat lado=6.0f;              //Para la longitud del lado del triangulo
vector<linea> Segmentos;       //En este vector almacenamos todos los segmentos
bool dir=true;                  //Para indicar en qué dirección realizar los calculos
 
 

Metodo para crear el triangulo inicial:

void init(){
      linea primera;//La linea con la que trabajaremos
     
      /*Hacemos las lineas siguiendo el sentido contrario al de las agujas del reloj, ya que afecta a la dirección en la que crece el fractal.*/
      primera.p1.x=0.0f;
      primera.p1.y=lado*sqrt(3.0f/4.0f);
      primera.p1.z=0.0f;
      primera.p2.x=-lado/2;
      primera.p2.y=0.0f;
      primera.p2.z=0.0f;
      Segmentos.push_back(primera);
 
      primera.p1.x=-lado/2;
      primera.p1.y=0.0f;
      primera.p1.z=0.0f;
      primera.p2.x=lado/2;
      primera.p2.y=0.0f;
      primera.p2.z=0.0f;
      Segmentos.push_back(primera);
 
      primera.p1.x=lado/2;
      primera.p1.y=0.0f;
      primera.p1.z=0.0f;
      primera.p2.x=0.0f;
      primera.p2.y=lado*sqrt(3.0f/4.0f);
      primera.p2.z=0.0f;
      Segmentos.push_back(primera);
}
 
  

Para dibujar un segmento:

 void pintar1(linea l){
      glColor3f(0.0f,0.0f,1.0f); //Color azul
      glVertex3f(l.p1.x,l.p1.y,l.p1.z);
      glColor3f(0.0f,1.0f,0.0f); //Color rojo
      glVertex3f(l.p2.x,l.p2.y,l.p2.z);
}
 

 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);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
 
      //Ajustamos la visión
      glTranslatef(0.0f,-2.0f,-10.0f);
     
      glBegin(GL_LINES);
            for(int i=0; i<Segmentos.size();i++)
                  pintar1(Segmentos[i]);
      glEnd();
 
      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 los 3 primeros segmentos
 
      //Lazo principal
      glutMainLoop();
      return 0;
}
 
 

Manejador de teclado:

 void tecla(unsigned char c, int x, int y) {
      switch (c) {
            case '+':   
                  hacerMas();
                  printf("Numero de segmentos: %d\n",Segmentos.size());
                  break;
            case '*':
                  lado+=1.0;
                  Segmentos.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:

En esta función, lo que hacemos es recorrer la lista de segmentos existentes, y para cada uno de ellos hayamos los 3 nuevos puntos que harán que de un segmento, pasemos a tener 4 nuevos segmentos con la forma característica del fractal.

Cada segmento nuevo que obtenemos, lo almacenamos en una nueva lista de segmentos que al final del método sustituye a la lista que teníamos anteriormente.

Existe una variable llamada “dir” que es un booleano. La he puesto, porque nos permite jugar un poco con la dirección e que crece nuestro fractal. si hacia fuera o hacia adentro.

 void hacerMas(){
      //Nuevo vector de segmentos. Será el resultado final del metodo
      vector<linea> aux;
      //Vector de 4 segmentos para controlar los 4 nuevos
      linea lin[4];
      //Todos los puntos del segmento y algunos auxiliares
      punto A,B,C,D,E,F,EA,pEA;
      //Para el calculo de nuevos puntos
      GLfloat modulo,altura;
      //Ahora leemos cada linea
      for(int j=0;j<Segmentos.size();j++){
            linea leida=Segmentos[j];
            /*Al cambiar el orden de los puntos A y E, cambiamos la
            dirección de crecimiento. Estos dos puntos son los extremos
            del segmento principal.*/
            if(dir){
                  A=leida.p1;
                  E=leida.p2;
            }else{
                  A=leida.p2;
                  E=leida.p1;
            }
            //Calculo los puntos del segmento leido
            EA.x=A.x-E.x;
            EA.y=A.y-E.y;
            D.x=EA.x/3+E.x;
            D.y=EA.y/3+E.y;
            B.x=EA.x*2/3+E.x;
            B.y=EA.y*2/3+E.y;
            pEA.x=-EA.y;
            pEA.y=EA.x;
            modulo=sqrt(pEA.x*pEA.x+pEA.y*pEA.y);
            pEA.x/=modulo;
            pEA.y/=modulo;
            F.x=(A.x+E.x)/2;
            F.y=(A.y+E.y)/2;
            modulo=sqrt(EA.x*EA.x+EA.y*EA.y);
            altura=(modulo/6)*sqrt(3);
            C.x=altura*pEA.x+F.x;
            C.y=altura*pEA.y+F.y;
            //La z vale 0 porque estamos en 2D
            A.z=0.0f;
            B.z=0.0f;
            C.z=0.0f;
            D.z=0.0f;
            E.z=0.0f;
            lin[0].p1=A;
            lin[0].p2=B;
            aux.push_back(lin[0]);
            lin[1].p1=B;
            lin[1].p2=C;
            aux.push_back(lin[1]);
            lin[2].p1=C;
            lin[2].p2=D;
            aux.push_back(lin[2]);
            lin[3].p1=D;
            lin[3].p2=E;
            aux.push_back(lin[3]);
      }
      Segmentos.clear();
      Segmentos=aux;
      aux.clear();
}

 Resultado final:

ck2.GIF (15707 bytes)

 

Jugando con la dirección, podemos obtener todas las variantes.

Lo que he hecho en la siguiente imagen es que para cada iteración hacer que crezca en los 2 sentidos, obteniendo el copo de nieve:

ck3.GIF (44495 bytes)

 

 

Dejá un comentario, sugerencia u opinión