Professional Documents
Culture Documents
111
CÓDIGOS FUENTE
GEOMETRÍA FRACTAL Página
112
GEOMETRÍA FRACTAL Página
113
INTRODUCCIÓN
La aplicación que genera los fractales fue desarrollada en Microsoft Visual C++ 6.0,
empleando la librería gráfica OpenGL, y el entorno MFC (Microsoft Foundation
Classes) vinculado en forma estática.
Todos los códigos fuente que producen los fractales se presentan como
funciones, cuyos argumentos son los parámetros necesarios para la graficación. Estos
procedimientos son invocados dentro de un entorno OpenGL, donde el contexto de
renderizado fue resuelto con el código correspondiente, así como el manejo de las
operaciones de traslación, escalado y rotación.
Dentro de estas funciones, se hace referencia a otras, como las que grafican
líneas o puntos, cuyo sencillo código, empleando las primitivas de OpenGL, se presenta
al final de este capítulo.
El código fuente completo de la aplicación se encuentra en el CD que acompaña
a la presente publicación.
GEOMETRÍA FRACTAL Página
114
// ÁRBOL BINARIO
// Parámetros: nivel de graficación (de 1 a 10).
// Se dibuja el tronco.
DrawLine(0.0, 0.0, 0.0, 0.0, -1.5, 0.0, red, green, blue);
x1 = (x - h);
x2 = (x + h);
y1 = (y + h / 2.0);
y2 = y;
// Rama horizontal.
DrawLine(x1, y2, 0.0, x2, y2, 0.0, red, green, blue);
// ÁRBOL TERNARIO
// Parámetros: nivel de graficación (1 a 7).
a = 0.45;
// Se construye el árbol por niveles.
for (m = 0.0; m <= level - 1.0; m++) {
x = y = 0.0;
for (k = 1.0; k <= m; k++) {
b = (2.0 * t[(int)k] * PI) / 3.0;
x += cos(b) * pow(a, k);
y += sin(b) * pow(a, k);
}
// Segunda rama.
x1 = x - 0.5 * pow(a, k);
y1 = y + sqrt(3.0) / 2.0 * pow(a, k);
DrawLine(x, y, 0.0, x1, y1, 0.0, red, green, blue);
// Tercera rama.
y1 = y - sqrt(3.0) / 2.0 * pow(a, k);
DrawLine(x, y, 0.0, x1, y1, 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
116
// CRIBA DE SIERPINSKI
// Parámetros: nivel de graficación (1 a 8).
a = sqrt(3.0);
// Se construye la criba.
for (m = 0.0; m <= level - 1.0; m++) {
x = 0.0;
y = 0.0;
}
GEOMETRÍA FRACTAL Página
117
// PEINE DE CANTOR
// Parámetros: nivel de graficación (1 a 7).
x = -0.5;
y = 0.0;
xprev = -0.5;
yprev = 0.0;
h = pow(3.0, -1.0 * level);
// Se construye la curva.
for (n = 0.0; n <= pow(4.0, level) - 1.0; n++) {
m = n;
for (k = 0.0; k <= level - 1.0; k++) {
t[(int)k] = (int)m % 4;
m = floor(m / 4.0);
}
s = 0.0;
for (k = 0.0; k <= level - 1.0; k++)
s = s + (int)(t[(int)k] + 1) % 3 - 1;
u = 4.0;
v = 4.0;
x[0] = y[0] = 0.0;
x[(int)pow(v, level)] = 1.0;
y[(int)pow(v, level)] = 0.0;
xprev = a[0];
yprev = b[0];
// Se dibuja la cruz.
for (m = 0.0; m <= u - 1.0; m++) {
a1 = a[(int)m + 1] - a[(int)m];
b1 = b[(int)m + 1] - b[(int)m];
GEOMETRÍA FRACTAL Página
120
xprev = x1;
yprev = y1;
}
}
}
GEOMETRÍA FRACTAL Página
121
u = 4.0;
v = 4.0;
x0 = y0 = xm = ym = -1.0;
s = 0.0;
xprev = x0;
yprev = y0;
e = a[(int)k];
f = b[(int)k];
GEOMETRÍA FRACTAL Página
122
e *= c[(int)t[(int)j]];
f += d[(int)t[(int)j]];
}
xn = e * cos(f);
yn = e * sin(f);
xm += xn;
ym += yn;
xprev = xm;
yprev = ym;
}
}
}
GEOMETRÍA FRACTAL Página
123
// SALCHICHA DE MINKOWSKI
// Parámetros: nivel de graficación (0 a 4).
// Se construye la gráfica.
for (n = 0.0; n <= pow(8.0, level) - 1.0; n++) {
m = n;
for (p = 0.0; p <= level - 1.0; p++) {
t[(int)p] = (int)m % 8;
m = floor(m / 8.0);
}
s = 0.0;
for (k = 0.0; k <= level - 1.0; k++) {
s = s + a[(int)t[(int)k]];
s = (int)s % 4;
}
xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
124
// CURVA DE LEVY
// Parámetros: nivel de graficación (1 a 14).
// Se construye la curva.
for (n = 2.0; n <= (pow(2.0, level) - 1.0); n++) {
do {
if ((int)m % 2 == 1) s = s + 1;
m = floor(m / 2.0);
} while (m > 1.0);
if ((int)s % 4 == 0) x = x + 1;
if ((int)s % 4 == 1) y = y + 1;
if ((int)s % 4 == 2) x = x - 1;
if ((int)s % 4 == 3) y = y - 1;
xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
125
// Se construye la curva.
for (n = 1.0; n <= nsegments; n++) {
xPrev = x;
yPrev = y;
}
}
GEOMETRÍA FRACTAL Página
126
dim = 2.0;
h = pow(2.0, dim / -2.0); // Longitud de segmento.
x1 = h * cos(dim * PI / 4.0);
y1 = (-1.0) * h * sin(dim * PI / 4.0);
s = 0.0;
xprev = x1;
yprev = y1;
// Se construye la curva.
for (n = 1.0; n <= nsegments; n++) {
x1 = x2;
y1 = y2;
xprev = xb;
yprev = yb;
}
}
GEOMETRÍA FRACTAL Página
127
// ESPIRAL DE ARQUÍMEDES
// Parámetros: definición de la curva (1 a 100) ; distancia entre espiras (1 a 100);
// longitud de la curva.
de = def / 10.0;
di = dist / 100.0;
xprev = yprev = 0.0;
// Se construye la espiral.
for (n = 0.0; n <= nsegments; n += de) {
xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
128
// ESPIRAL LOGARÍTMICA
// Parámetros: definición de la curva (1 a 5); tasa de crecimiento (1 a 10);
// longitud de la curva.
gr = growth / 100.0;
de = def / 10.0;
xprev = 1.0;
yprev = 0.0;
// Se construye la espiral.
for (n = 0.0; n <= nsegments; n += de) {
xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
129
a = shape / 10.0;
c = 0.9;
p = 1 / sqrt(2.0);
q = p * sqrt(1.0 - c * c);
xprev = 0.0; yprev = 0.0;
// Se construye la espiral.
for (n = -600.0; n <= 600.0; n++) {
// Dibujo 3D.
DrawLine(xprev, yprev, zprev, x, y, z, red, green, blue);
}
uprev = u;
vprev = v;
xprev = x;
yprev = y;
zprev = z;
}
}
GEOMETRÍA FRACTAL Página
130
u = 1.0;
v = 1.0;
c = 1.0 / sqrt(2.0);
x = 0.0;
y = 0.0;
if (a[(int)j] == 0.0) {
x = x - h * (cos(f) + 2.0 * sin(f));
y = y + h * (2.0 * cos(f) - sin(f));
f = f + PI / 4.0;
h = c * h;
} else {
x = x + h * (cos(f) - 2.0 * sin(f));
y = y + h * (2.0 * cos(f) + sin(f));
f = f - PI / 4.0;
h = c * h;
}
}
GEOMETRÍA FRACTAL Página
131
u = h * (cos(f) + sin(f));
v = h * (cos(f) - sin(f));
f = PI / 4.0;
c = cos(f);
s = sin(f);
a1 = (-1.0) * c * s;
a2 = pow(c, 2.0);
b1 = a1 + a2;
b2 = (-1.0) * a1 + a2;
c1 = b2;
c2 = 1.0 - b1;
d1 = 1.0 - a1;
d2 = 1.0 - a2;
x[2] = 0.0;
y[2] = 0.0;
x[3] = 1.0;
y[3] = 0.0;
xdesp = 0.5;
ydesp = 1.0;
// Se dibuja el tronco.
DrawLine(0.0, -1.0, 0.0, 0.0, -2.0, 0.0, red, green, blue);
u = x1 - x0;
v = y1 - y0;
GEOMETRÍA FRACTAL Página
133
xa = x0 + a1 * u - a2 * v;
ya = y0 + a2 * u + a1 * v;
xb = x0 + b1 * u - b2 * v;
yb = y0 + b2 * u + b1 * v;
xc = x0 + c1 * u - c2 * v;
yc = y0 + c2 * u + c1 * v;
xd = x0 + d1 * u - d2 * v;
yd = y0 + d2 * u + d1 * v;
f = PI / 3.0;
c = cos(f);
s = sin(f);
a1 = (-1.0) * c * s;
a2 = pow(c, 2.0);
b1 = a1 + a2;
b2 = (-1.0) * a1 + a2;
c1 = b2;
c2 = 1.0 - b1;
d1 = 1.0 - a1;
d2 = 1.0 - a2;
x[2] = 0.0;
y[2] = 0.0;
x[3] = 1.0;
y[3] = 0.0;
u = x1 - x0;
v = y1 - y0;
GEOMETRÍA FRACTAL Página
135
xa = x0 + a1 * u - a2 * v;
ya = y0 + a2 * u + a1 * v;
xb = x0 + b1 * u - b2 * v;
yb = y0 + b2 * u + b1 * v;
xc = x0 + c1 * u - c2 * v;
yc = y0 + c2 * u + c1 * v;
xd = x0 + d1 * u - d2 * v;
yd = y0 + d2 * u + d1 * v;
x[(int)(pow(2.0, (m + 1.0)) + 4.0 * j)] = xa;
y[(int)(pow(2.0, (m + 1.0)) + 4.0 * j)] = ya;
x[(int)(pow(2.0, (m + 1.0)) + 4.0 * j + 1.0)] = xb;
y[(int)(pow(2.0, (m + 1.0)) + 4.0 * j + 1.0)] = yb;
x[(int)(pow(2.0, (m + 1.0)) + 4.0 * j + 2.0)] = xc;
y[(int)(pow(2.0, (m + 1.0)) + 4.0 * j + 2.0)] = yc;
x[(int)(pow(2.0, (m + 1.0)) + 4.0 * j + 3.0)] = xd;
y[(int)(pow(2.0, (m + 1.0)) + 4.0 * j + 3.0)] = yd;
per /= 10.0;
w = 0.15;
a1 = 0.0;
a2 = 3.0;
b1 = 0.5;
b2 = 3.5;
c1 = 1.0;
c2 = 3.0;
x1[0] = 0.0;
y1[0] = 0.0;
u1[0] = 0.5;
v1[0] = 0.0;
s = 1.0;
xdesp = 0.25;
// Se construye el árbol.
for (m = 0.0; m <= pow(2.0, level - 1.0) - 1.0; m++) {
if (m == 0.0) {
a2 = a2 * (1.0 + w * Random( ) * per);
c2 = c2 * (1.0 + w * Random( ) * per);
b2 = (a2 + c2) / 2.0 + 0.5;
}
if (m != 0.0) {
s = level;
n = m;
if (s < 8.0) {
a2 = a2 * (1.0 + w * Random( ) * per);
c2 = c2 * (1.0 + w * Random( ) * per);
b2 = (a2 + c2) / 2.0 + 0.5;
}
GEOMETRÍA FRACTAL Página
137
while ((int)n % 2 == 0) {
n = floor(n / 2.0);
s = s - 1.0;
}
// FRACTAL ESTRELLA
// Parámetros: ninguno.
void StarFractal(void)
{
double a, b, f, m, n, p, r, v;
double x, y, xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.
a = 144.0 * PI / 180.0;
p = 5.0;
r = 0.35;
v = 4.0;
x = -0.5;
y = -0.05;
xprev = -0.5;
yprev = -0.05;
// Se construye la estrella.
for (n = 0.0; n <= (v + 1.0) * pow(v, (p - 1.0)) - 1.0; n++) {
while (1) {
if ((int)m % (int)v != 0 || f >= (p - 1.0)) break;
f = f + 1.0;
m = floor(m / v);
}
xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
139
void MontecarloDust(void)
{
double a, b, c, d, n, r, x, y, z, xdesp;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.
r = 0.6;
a = r * cos(2.0 * PI / 3.0);
b = r * sin(2.0 * PI / 3.0);
c = r * cos(2.0 * PI / 3.0);
d = (-1.0) * r * sin(2.0 * PI / 3.0);
x = a;
y = b;
xdesp = 0.5;
// LÍNEA BROWNIANA
// Parámetros: incremento en la abscisa (1 a 30); amplitud máxima (1 a 20).
xprev = XMin;
yprev = 0.0;
xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
141
// MODELO DE VERHULST
// Parámetros: nivel de estabilización (0 a 450);
// coordenada x del centro de la gráfica (2.9 a 3.0);
// coordenada y del centro de la gráfica (0,0 a 1,0);
// factor de escala (1 a 14 aproximadamente);
// grilla (verdadero o falso).
void Verhulst(double est, double XCenter, double YCenter, double zoom, bool grid)
{
double a, k, y;
double maxX; // Valor x extremo derecho.
double minX; // Valor x extremo izquierdo.
double maxY; // Valor y extremo superior.
double minY; // Valor y extremo inferior.
double stepx, stepy, xrel, yrel;
double RANGE_X = 1.1;
double RANGE_Y = 1.0;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.
y = 0.7;
// Se calcula el valor de y.
y = a * y * (1.0 - y);
// CONJUNTO DE MANDELBROT
// Parámetros: número de iteraciones por punto (1 a 100);
// coordenada x del centro de la gráfica (-2.0 a 2.0);
// coordenada y del centro de la gráfica (-2,0 a 2,0);
// factor de escala (1 a 14 aproximadamente);
// grilla (verdadero o falso).
x = i;
y = j;
if (k >= nIter)
// Se dibuja un punto negro.
DrawPoint(i / xrel - XCenter * zoom,
j / yrel - YCenter * zoom, 0.0, 0, 0, 0);
else {
// Se dibuja un punto de color.
GenColor(k, &red, &green, &blue);
DrawPoint(i / xrel - XCenter * zoom,
j / yrel – Ycenter * zoom, 0.0,
red, green, blue);
}
}
}
// CONJUNTO DE JULIA
// Parámetros: constante real (-1.0 a 1.0); constante imaginaria (-1.0 a 1.0);
// número de iteraciones por punto (1 a 100);
// coordenada x del centro de la gráfica (-2.0 a 2.0);
// coordenada y del centro de la gráfica (-2,0 a 2,0);
// factor de escala (1 a 14 aproximadamente);
// grilla (verdadero o falso).
x = i;
y = j;
xnew = 0.0;
ynew = 0.0;
GEOMETRÍA FRACTAL Página
145
// La función de Julia: Z = Z * Z + c
xnew = x * x - y * y + conX;
ynew = 2 * x * y + conY;
x = xnew;
y = ynew;
if (k >= nIter) {
// Se dibuja un punto negro.
DrawPoint(i / xrel – XCenter * zoom,
j / yrel – YCenter * zoom, 0.0, 0, 0, 0);
} else {
// Se dibuja un punto de color.
GenColor(k, &red, &green, &blue);
DrawPoint(i / xrel – XCenter * zoom,
j / yrel – YCenter * zoom, 0.0, red, green, blue);
}
}
}
b = b * -1.0;
x = 0.321;
y = 0.654;
w = a * x + b * (x - 1.0);
c = 0.9995;
x = 4.0;
y = 1.0;
w = a * x;
a = 0.5;
b = 0.5;
c = 0.5;
d = -0.5;
x1[0] = a;
y1[0] = b;
s = 1.0;
if (m) {
s = level;
n = m;
while((int)n % 2 == 0) {
n = floor(n / 2.0);
s = s - 1.0;
}
a = 0.43; b = 0.30;
t1 = 0.5; t2 = 0.866;
x1[0] = 0.0; y1[0] = 0.0;
s = 1.0;
g = t1 * (1.0 - a) + t2 * b;
h = (-1.0) * t1 * b + t2 * (1.0 - a);
if (m) {
s = level;
n = m;
while((int)n % 3 == 0) {
n = floor(n / 3.0);
s = s - 1.0;
}
x1[(int)s - 1] = x2[(int)s - 1];
y1[(int)s - 1] = y2[(int)s - 1];
x2[(int)s - 1] = x3[(int)s - 1];
y2[(int)s - 1] = y3[(int)s - 1];
}
a /= 100.0;
a /= 100.0;
b = 0.9998;
c = 2.0 - 2.0 * a;
x = 0.0;
y = 12.35;
d = a * x + c * pow(x, 2.0) / (1.0 + pow(x, 2.0));
e = 2.0;
// Se construye la nube.
for (n = 0.0; n <= npoints; n++) {
x1 = x / 10.0;
y1 = y / 10.0;
if (n > 100.0) {
// Se dibuja un punto en las coordenadas calculadas.
DrawPoint(x1, y1, 0.0, red, green, blue);
}
// ATRACTOR DE LORENZ
// Parámetros: cantidad de puntos.
dt = 0.03;
a = 5.0;
b = 15.0;
c = 1.0;
xa = 0.30;
ya = 0.15;
za = 0.02;
x = xa;
y = ya;
z = za;
x1 = x - c * x * dt + z * y * dt;
y1 = y + b * z * dt - y * dt - x * z * dt;
z1 = z - a * z * dt + a * y * dt;
xa = x1;
ya = y1;
za = z1;
// Se dibuja un punto.
DrawPoint(x1, y1, z1, red, green, blue);
}
}
GEOMETRÍA FRACTAL Página
153
// CÍRCULO EVOLUTIVO
// Parámetros: número de sectores (10 a 500); distancia entre espiras (1 a 10);
// longitud de sector (1 a 5).
dist /= 100.0;
xprev = dist;
yprev = 0.0;
// Se construye el círculo.
for (n = 0.0; n <= nsectors; n++) {
xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
154
a = 3.98; b = 4.38;
a1 = 0.0; a2 = a;
r1 = 0.62; r2 = 0.67;
b1 = 0.0; b2 = a + r1;
c1 = 0.5; c2 = b2;
e1 = 1.0; e2 = b + r2;
f1 = 1.0; f2 = b;
d1 = 0.5; d2 = e2;
s = 1.0;
x1[0] = 0.0; y1[0] = 0.0;
u1[0] = 1.0; v1[0] = 0.0;
// Se construye el árbol.
for (m = 0.0; m <= pow(2.0, (level - 1.0)) - 1.0; m++) {
if (m) {
n = m;
s = level;
while((int)n % 2 == 0) {
n = floor(n / 2.0);
s -= 1.0;
}
h = a2; a2 = f2;
f2 = h; h = b2;
b2 = e2; e2 = h;
h = c2; c2 = d2;
d2 = h;
if (j == s) {
h = a2; a2 = f2;
f2 = h; h = b2;
b2 = e2; e2 = h;
h = c2; c2 = d2;
d2 = h;
}
a = 0.5; s = 1.0;
x1[0] = 0.0; y1[0] = 0.0;
// Se construye el fractal.
for (m = 0.0; m <= pow(4.0, (level - 1.0)) - 1.0; m++) {
if (m) {
n = m;
s = level;
while((int)n % 4 == 0) {
n = floor(n / 4.0);
s -= 1.0;
}
a = sqrt(0.5);
x[1] = 1.0;
y[1] = 1.0;
// Se construye el fractal.
for (m = 0.0; m <= level; m++) {
s = (int)m % 2;
x1 = x[2 * (int)n];
y1 = y[2 * (int)n];
x2 = x[2 * (int)n + 1];
y2 = y[2 * (int)n + 1];
// Se dibuja el segmento.
DrawLine(x1, y1, 0.0, x2, y2, 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
159
angle /= 100.0;
a = PI * (1.0 - 2.0 / sides);
b = sin(a) / (sin(angle) + sin(a + angle));
x1 = x[0];
y1 = y[0];
// Se construye el polígono.
for (l = 1.0; l <= sides; l++) {
x1 = x[(int)l];
y1 = y[(int)l];
// Se dibuja un segmento hasta el próximo vértice.
DrawLine(xprev, yprev, 0.0, x1, y1, 0.0, red, green, blue);
xprev = x1;
yprev = y1;
}
// FUNCIONES AUXILIARES
void DrawPoint(double x, double y, double z, int red, int green, int blue)
{
glColor3ub(red,green,blue);
glBegin(GL_POINTS);
glVertex3d(x, y, z);
glEnd();
}
double Random(void)
{
// La función rand( ) original devuelve un valor entre 0 y 32767.
return rand( ) / 32767.0;
}
void GenColor(double gen, unsigned int *red, unsigned int *green, unsigned int *blue)
{
if ((int)gen % 11 == 0) {*red = 255; *green = 0 ; *blue = 0 ; return;}
if ((int)gen % 10 == 0) {*red = 255; *green = 70 ; *blue = 0 ; return;}
if ((int)gen % 9 == 0) {*red = 255; *green = 170; *blue = 0 ; return;}
if ((int)gen % 8 == 0) {*red = 255; *green = 255; *blue = 0 ; return;}
if ((int)gen % 7 == 0) {*red = 0 ; *green = 255; *blue = 0 ; return;}
if ((int)gen % 6 == 0) {*red = 0 ; *green = 255; *blue = 255; return;}
if ((int)gen % 5 == 0) {*red = 0 ; *green = 150; *blue = 255; return;}
if ((int)gen % 4 == 0) {*red = 0 ; *green = 0 ; *blue = 255; return;}
if ((int)gen % 3 == 0) {*red = 150; *green = 0 ; *blue = 255; return;}
if ((int)gen % 2 == 0) {*red = 255; *green = 0 ; *blue = 255; return;}
if ((int)gen % 1 == 0) {*red = 255; *green = 0 ; *blue = 100; return;}
}