Unlimited disk space/traffic/domains
1-click app installer, $9.99/month
Free Control Panel, full root access
Virtuozzo Containers, $25.00/month
Unlimited faxes, no fees
dedicated phone number
Reseller hosting services, domains,
vps, dedicated servers. Join free!
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:
Imagen extraida de www.matematicas.unal.edu.co
Lo he programado en C++ usando las
librerias de OpenGL para representarlo
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:
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);
}
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();
}
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:
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.
//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();
}
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:
Dejá un comentario, sugerencia u opinión