You are on page 1of 51

GEOMETRÍA FRACTAL Página

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).

void BinaryTree(double level)


{
double n, h, r, x, x1, x2, y, y1, y2;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

// Se dibuja el tronco.
DrawLine(0.0, 0.0, 0.0, 0.0, -1.5, 0.0, red, green, blue);

// Se construye el árbol por niveles.


for (n = 0; n <= level - 1.0; n++) {

h = pow(2.0, (-1.0) * n + 1.0);

// Se dibujan las ramas de cada nivel.


for (r = 1.0; r <= pow(2.0, n); r++) {

x = -4.0 + (4.0 * r - 2.0) * h;


y = 2.0 - h;

x1 = (x - h);
x2 = (x + h);
y1 = (y + h / 2.0);
y2 = y;

// Rama vertical izquierda.


DrawLine(x1, y1, 0.0, x1, y2, 0.0, red, green, blue);

// Rama horizontal.
DrawLine(x1, y2, 0.0, x2, y2, 0.0, red, green, blue);

// Rama vertical derecha.


DrawLine(x2, y2, 0.0, x2, y1, 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
115

// ÁRBOL TERNARIO
// Parámetros: nivel de graficación (1 a 7).

void TernaryTree(double level)


{
double a, b, j, k, l, m, n, t[7];
double x, x1, y, y1;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

a = 0.45;
// Se construye el árbol por niveles.
for (m = 0.0; m <= level - 1.0; m++) {

// Se calculan todas las ramas de cada nivel.


for (n = 0.0; n <= pow(3.0, m) - 1.0; n++) {

// Se calcula cada punto de donde nacen tres ramas.


j = n;
for (l = 1.0; l <= m; l++) {
t[(int)l] = (int)j % 3;
j = floor(j / 3.0);
}

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);
}

// Se dibujan tres ramas.


// Primera rama.
x1 = x + pow(a, k);
DrawLine(x, y, 0.0, x1, y, 0.0, red, green, blue);

// 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).

void SierpinskiSieve(double level)


{
double a, m, n, p, q, k, t[7];
double x, y, x1, x2, y1, y2;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

a = sqrt(3.0);

// Se construye la criba.
for (m = 0.0; m <= level - 1.0; m++) {

// Se calculan los triángulos de cada nivel.


for (n = 0.0; n <= pow(3.0, m) - 1.0; n++) {
p = n;

for (q = 0.0; q <= m - 1.0; q++) {


t[(int)q] = (int)p % 3;
p = floor(p / 3.0);
}

x = 0.0;
y = 0.0;

// Se calculan las coordenadas de los vértices de un triángulo.


for (k = 0.0; k <= m - 1.0; k++) {
x = x + cos((4.0 * t[(int)k] + 1.0) * PI / 6.0) / pow(2.0, k);
y = y + sin((4.0 * t[(int)k] + 1.0) * PI / 6.0) / pow(2.0, k);
}
x1 = x + a / pow(2.0, m + 1.0);
x2 = x - a / pow(2.0, m + 1.0);
y1 = y - 1 / pow(2.0, m + 1.0);
y2 = y + 1 / pow(2.0, m);

// Se dibujan los lados del triángulo.


DrawLine(x1, y1, 0.0, x, y2, 0.0, red, green, blue);
DrawLine(x, y2, 0.0, x2, y1, 0.0, red, green, blue);
DrawLine(x2, y1, 0.0, x1, y1, 0.0, red, green, blue);
}
}

}
GEOMETRÍA FRACTAL Página
117

// PEINE DE CANTOR
// Parámetros: nivel de graficación (1 a 7).

void CantorComb(double level)


{
double a[256], b[256], base, h, i, j, k, p;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

for (i = 0; i < 256; i++) {


a[(int)i] = 0.0;
b[(int)i] = 0.0;
}
base = 5.0;
a[0] = 0.0;
a[1] = base;
h = 0.4;

// Se dibuja la base del peine.


DrawLine(-(base / 2.0), 0.0, 0.0, (base / 2.0), 0.0, 0.0, red, green, blue);
DrawLine(-(base / 2.0), -h, 0.0, (base / 2.0), -h, 0.0, red, green, blue);
DrawLine(-(base / 2.0), 0.0, 0.0, -(base / 2.0), -h, 0.0, red, green, blue);
DrawLine((base / 2.0), 0.0, 0.0, (base / 2.0), -h, 0.0, red, green, blue);

// Se construyen los dientes del peine.


for (p = 1.0; p <= level - 1.0; p++) {
// Se calculan los dientes de cada nivel.
for (i = 0.0; i <= pow(2.0, p) - 1.0; i++) {
b[(int)i] = a[(int)i] / 3.0;
b[(int)(i + pow(2.0, p))] = base - (base - a[(int)i]) / 3.0;
}
for (j = 1.0; j <= pow(2.0, (p + 1.0)) - 1.0; j++) a[(int)j] = b[(int)j];

// Se dibujan los dientes de cada nivel.


for (k = 0.0; k <= pow(2.0, (p + 1.0)) - 1.0; k += 2.0) {
DrawLine(a[(int)k] - (base / 2.0), (h * p), 0.0,
a[(int)k + 1] - (base / 2.0), (h * p), 0.0,
red, green, blue);
DrawLine(a[(int)k] - (base / 2.0), (h * p), 0.0,
a[(int)k] - (base / 2.0), (h * p - h), 0.0,
red, green, blue);
DrawLine(a[(int)k + 1] - (base / 2.0), (h * p), 0.0,
a[(int)k + 1] - (base / 2.0), (h * p - h), 0.0,
red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
118

// CURVA DE VON KOCH


// Parámetros: nivel de graficación (0 a 7).

void KochCurve(double level)


{
double t[10], h, k, m, n, s, x, y, xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

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;

// Se calculan las coordenadas del próximo punto.


x = x + cos(PI * s / 3.0) * h;
y = y + sin(PI * s / 3.0) * h;

// Se grafica un segmento hasta las coordenadass calculadas.


DrawLine(xprev, yprev, 0.0, x, y, 0.0, red, green, blue);
xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
119

// CRUZ DE VON KOCH – VERSIÓN 1


// Parámetros: nivel de graficación (0 a 6).

void KochCross1(double level)


{
double a[5] = {1.0, -1.0, -1.0, 1.0, 1.0};
double b[5] = {1.0, 1.0, -1.0, -1.0, 1.0};
double c[4] = {0.0, 0.3333, 0.5, 0.6667};
double d[4] = {0.0, 0.0, 0.2887, 0.0};
double a1, b1, i, j, k, m, m1, m2;
double n, u, v, x1, y1;
double x[5100], y[5100], xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

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;

// Se calculan las coordenadas de todos los puntos de la cruz.


for (i = 0.0; i <= (level - 1.0); i++) {

for (j = 0.0; j <= (pow(v, level) - 1.0); j += pow(v, level - i)) {

m1 = j + pow(v, level - i);


x1 = x[(int)m1] - x[(int)j];
y1 = y[(int)m1] - y[(int)j];

for (k = 1.0; k <= v - 1.0; k++) {

m2 = j + k * pow(v, level - i - 1.0);


x[(int)m2] = x1 * c[(int)k] - y1 * d[(int)k] + x[(int)j];
y[(int)m2] = y1 * c[(int)k] + x1 * d[(int)k] + y[(int)j];
}
}
}

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

for (n = 0.0; n <= pow(v, level); n++) {

x1 = a1 * x[(int)n] - b1 * y[(int)n] + a[(int)m];


y1 = b1 * x[(int)n] + a1 * y[(int)n] + b[(int)m];

// Se dibuja un segmento hasta el próximo punto.


DrawLine(xprev, yprev, 0.0, x1, y1, 0.0, red, green, blue);

xprev = x1;
yprev = y1;
}
}
}
GEOMETRÍA FRACTAL Página
121

// CRUZ DE VON KOCH – VERSIÓN 2


// Parámetros: nivel de graficación (0 a 6).

void CGFOpenGL::KochCross2(double level)


{
double a[4] = { 2.0, 2.0, 2.0, 2.0 };
double b[4] = { 0.0, PI / 2.0, PI, PI / -2.0 };
double c[4] = { 1.0, 1.0, 1.0, 1.0 };
double d[4] = { 0.0, PI / 3.0, PI / -3.0, 0.0 };
double e, f, i, j, k, m, n, s, t[6];
double u, v, x0, xm, xn, y0, ym, yn, xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

u = 4.0;
v = 4.0;
x0 = y0 = xm = ym = -1.0;
s = 0.0;

for (i = 0.0; i <= v - 1.0; i++) {


s += c[(int)i] * cos(d[(int)i]);
}

for (i = 0.0; i <= v - 1.0; i++) {


c[(int)i] /= s;
}

xprev = x0;
yprev = y0;

// Se construye cada lado de la cruz.


for (k = 0.0; k <= u - 1.0; k++) {

// Se calculan los segmentos que component un lado.


for (n = 0.0; n <= pow(v, level) - 1.0; n++) {

// Se calculan las coordenadas del próximo punto.


m = n;

for (j = 0.0; j <= level - 1.0; j++) {

t[(int)j] = (int)m % (int)v;


m = floor(m / v);
}

e = a[(int)k];
f = b[(int)k];
GEOMETRÍA FRACTAL Página
122

for (j = 0.0; j <= level - 1.0; j++) {

e *= c[(int)t[(int)j]];
f += d[(int)t[(int)j]];
}

xn = e * cos(f);
yn = e * sin(f);
xm += xn;
ym += yn;

// Se dibuja un segmento hasta el punto calculado.


DrawLine(xprev, yprev, 0.0, xm, ym, 0.0, red, green, blue);

xprev = xm;
yprev = ym;
}
}
}
GEOMETRÍA FRACTAL Página
123

// SALCHICHA DE MINKOWSKI
// Parámetros: nivel de graficación (0 a 4).

void MinkowskiSausage(double level)


{
double a[8] = {0.0, 1.0, 0.0, 3.0, 3.0, 0.0, 1.0, 0.0};
double h, k, p, m, n;
double s, t[4], x, y, xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

h = pow(4.0, (-1.0) * level);


x = -0.5;
y = 0.0;
xprev = x;
yprev = y;

// 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;
}

// Se calcula el próximo punto.


if (s == 0.0) x = x + h;
if (s == 1.0) y = y + h;
if (s == 2.0) x = x - h;
if (s == 3.0) y = y - h;

// Se dibuja un segmento hasta el punto calculado.


DrawLine(xprev, yprev, 0.0, x, y, 0.0, red, green, blue);

xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
124

// CURVA DE LEVY
// Parámetros: nivel de graficación (1 a 14).

void LevyCurve(double level)


{
double a, b, h, m, n, s;
double x, y, xprev, yprev, desp;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

h = pow(2.0, level / -2.0);


a = h * cos(level * PI / 4.0);
b = h * sin(level * PI / 4.0);
x = 1.0;
y = 1.0;
desp = 0.5;
xprev = x;
yprev = y;

// Se dibujan los dos primeros segmentos de la curva.


DrawLine(0.0 - desp, 0.0, 0.0, a - desp, (-1.0) * b, 0.0, red, green, blue);
DrawLine(a - desp, (-1.0) * b, 0.0, (a + b) - desp, (a - b), 0.0, red, green, blue);

// Se construye la curva.
for (n = 2.0; n <= (pow(2.0, level) - 1.0); n++) {

// Se calculan las coordenadas del próximo punto de la curva.


m = n;
s = 1.0;

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;

if (m_color == 3) GenColor(n, m_color, &red, &green, &blue);

// Se dibuja un segmento hasta el punto calculado.


DrawLine((a * xprev + b * yprev) - desp, (a * yprev - b * xprev), 0.0,
(a * x + b * y) - desp, (a * y - b * x), 0.0, red, green, blue);

xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
125

// CURVA DEL DRAGÓN


// Parámetros: ángulo entre segmentos (70 a 120); cantidad de segmentos.

void DragonCurve(double angle, double nsegments)


{
double ang, d, h, m, n, s;
static double x, y;
double xPrev, yPrev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

h = 0.5; // Longitud de segmento.


ang = PI - (angle * PI / 180.0);
s = 0.0;
x = 0.0;
y = 0.0;
xPrev = x;
yPrev = y;

// Se construye la curva.
for (n = 1.0; n <= nsegments; n++) {

// Se calculan las coordenadas del próximo punto.


m = n;
while ((int)m % 2 == 0) m = (int)m / 2;
d = ((int)m % 4 == 1) ? 1.0 : -1.0;
s += d;
x += h * cos(s * ang);
y += h * sin(s * ang);

// Se dibuja un segmento hasta el punto calculado.


DrawLine(xPrev, yPrev, 0.0, x, y, 0.0, red, green, blue);

xPrev = x;
yPrev = y;
}
}
GEOMETRÍA FRACTAL Página
126

// CURVA DEL DRAGÓN CON VÉRTICES REDONDEADOS


// Parámetros: cantidad de segmentos.

void DragonCurveRounded(double nsegments)


{
double d, dim, m, n, s, h;
double x1, y1, x2, y2;
static double xprev, yprev;
double xa, ya, xb, yb;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

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++) {

// Se calculan las coordenadas de los dos próximos puntos.


m = n;

while ((int)m % 2 == 0) m = (int)m / 2;


d = ((int)m % 4 == 1) ? 1.0 : -1.0;
s = (int)(s + d) % 4;

x2 = x1 + h * cos((s - dim / 2.0) * PI / 2.0);


y2 = y1 + h * sin((s - dim / 2.0) * PI / 2.0);
xa = (3.0 * x1 + x2) / 4.0;
ya = (3.0 * y1 + y2) / 4.0;
xb = (x1 + 3.0 * x2) / 4.0;
yb = (y1 + 3.0 * y2) / 4.0;

// Se dibujan los dos próximos segmentos.


DrawLine (xprev, yprev, 0.0, xa, ya, 0.0, red, green, blue);
DrawLine (xa, ya, 0.0, xb, yb, 0.0, red, green, blue);

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.

void ArquimedesSpiral(double def, double dist, double nsegments)


{
double de, di, b, n, x, y;
static double xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

de = def / 10.0;
di = dist / 100.0;
xprev = yprev = 0.0;

// Se construye la espiral.
for (n = 0.0; n <= nsegments; n += de) {

// Se calculan las coordenadas del próximo punto.


b = di * n;
x = b * cos(n);
y = b * sin(n);

// Se dibuja un segmento hasta el próximo punto.


DrawLine(xprev, yprev, 0.0, x, y, 0.0, red, green, blue);

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.

void LogarithmicSpiral(double def, double growth, double nsegments)


{
double de, gr, a, n, x, y, xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

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) {

// Se calculan las coordenadas del próximo punto.


a = exp(n * gr);
x = a * cos(n);
y = a * sin(n);

// Se dibuja un segmento hasta el próximo punto.


DrawLine(xprev, yprev, 0.0, x, y, 0.0, red, green, blue);

xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
129

// ESPIRAL ESFÉRICA O LOXODRÓMICA


// Parámetros: forma de la curva (1 a 10).

void SphericSpiral(double shape)


{
double a, c, n, p, q, s, t;
double x, y, z, xprev, yprev, zprev, u, v, uprev, vprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

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++) {

// Se calculan las coordenadas del próximo punto.


s = n * PI / 50.0;
t = atan(a * s);
x = cos(s) * cos(t);
z = sin(s) * cos(t);
y = (-1.0) * sin(t);

// Se proyecta el objeto 3D en un plano 2D.


u = p * (z - x);
v = c * y - q * (x + z);

// Se dibuja un segmento hasta el próximo punto.


// Si se construye una imagen 2D,
// se emplea la primera llamada a DrawLine( ).
// Si se construye una imagen 3D,
// se emplea la segunda llamada a DrawLine( ).
if (n > -600) {
// Dibujo 2D.
// DrawLine(uprev, vprev, 0.0, u, v, 0.0, red, green, blue);

// 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

// ÁRBOL BINARIO DE PITÁGORAS


// Parámetros: nivel de graficación (1 a 12).

void CGFOpenGL::PitagorasBinaryTree(double level)


{
double a[13], c, f, h, j, k, l, m, n;
double p1, p2, p3, p4, p5, p6, p7, p8;
double u, v, x, y;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

u = 1.0;
v = 1.0;
c = 1.0 / sqrt(2.0);
x = 0.0;
y = 0.0;

// Se construye cada nivel del árbol.


for (m = 0.0; m <= level; m++) {

// Se grafican los cuadrados de cada nivel.


for (n = pow(2.0, m); n <= pow(2.0, (m + 1.0)) - 1.0; n++) {

// Se calculan las coordenadas del próximo vértice.


l = n;
h = 1.0;
f = 0.0;
x = 0.0;
y = 0.0;

for (k = 0.0; k <= (m - 1.0); k++) {

a[(int)(m - k)] = (int)l % 2;


l = floor(l / 2.0);
}

for (j = 1.0; j <= m; j++) {

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));

// Se dibujan los lados de cada cuadrado.


p1 = (x - v);
p2 = (y - u);
p3 = (x + u);
p4 = (y - v);
p5 = (x + v);
p6 = (y + u);
p7 = (x - u);
p8 = (y + v);

DrawLine(p1, p2, 0.0, p3, p4, 0.0, red, green, blue);


DrawLine(p3, p4, 0.0, p5, p6, 0.0, red, green, blue);
DrawLine(p5, p6, 0.0, p7, p8, 0.0, red, green, blue);
DrawLine(p7, p8, 0.0, p1, p2, 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
132

// ÁRBOL DESNUDO DE PITÁGORAS


// Parámetros: nivel de graficación (1 a 12).

void PitagorasNakedTree(double level)


{
double a1, a2, b1, b2, c1, c2, d1, d2;
double c, f, j, m, s, u, v, xdesp, ydesp;
double p1, p2, p3, p4;
double x0, x1, xa, xb, xc, xd;
double y0, y1, ya, yb, yc, yd;
double x[16400], y[16400];
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

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);

// Se construye cada nivel del árbol.


for (m = 1.0; m <= level; m++) {

// Se dibujan las ramas de cada nivel.


for (j = 0.0; j <= pow(2.0, (m - 1.0)) - 1.0; j++) {

// Se calculan las coordenadas de cada par de ramas en “V”.


x0 = x[(int)(pow(2.0, m) + 2.0 * j)];
y0 = y[(int)(pow(2.0, m) + 2.0 * j)];
x1 = x[(int)(pow(2.0, m) + 2.0 * j + 1.0)];
y1 = y[(int)(pow(2.0, m) + 2.0 * j + 1.0)];

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;

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;

// Se dibuja el par de ramas en “V”.


p1 = (x0 + x1) / 2.0;
p2 = (y0 + y1) / 2.0;
p3 = (xa + xb) / 2.0;
p4 = (ya + yb) / 2.0;
DrawLine(p1-xdesp, p2-ydesp, 0.0, p3-xdesp, p4-ydesp, 0.0,
red, green, blue);
p3 = (xc + xd) / 2.0;
p4 = (yc + yd) / 2.0;
DrawLine(p1-xdesp, p2-ydesp, 0.0, p3-xdesp, p4-ydesp, 0.0,
red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
134

// ÁRBOL DESEQUILIBRADO DE PITÁGORAS


// Parámetros: nivel de graficación (1 a 12).

void PitagorasLopsidedTree(double level)


{
double a1, a2, b1, b2, c1, c2, d1, d2;
double c, f, j, m, s, u, v;
double x0, x1, xa, xb, xc, xd;
double y0, y1, ya, yb, yc, yd;
double x[16400], y[16400];
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

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;

// Se dibuja el cuadrado del tronco.


DrawLine(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, red, green, blue);
DrawLine(1.0, 0.0, 0.0, 1.0, -1.0, 0.0, red, green, blue);
DrawLine(1.0, -1.0, 0.0, 0.0, -1.0, 0.0, red, green, blue);
DrawLine(0.0, -1.0, 0.0, 0.0, 0.0, 0.0, red, green, blue);

// Se construye cada nivel del árbol.


for (m = 1.0; m <= level; m++) {

// Se construyen los cuadrados de cada nivel.


for (j = 0.0; j <= pow(2.0, (m - 1.0)) - 1.0; j++) {

// Se calculan las coordenadas de los vértices de cada cuadrado.


x0 = x[(int)(pow(2.0, m) + 2.0 * j)];
y0 = y[(int)(pow(2.0, m) + 2.0 * j)];
x1 = x[(int)(pow(2.0, m) + 2.0 * j + 1.0)];
y1 = y[(int)(pow(2.0, m) + 2.0 * j + 1.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;

// Se dibujan los lados de cada cuadrado.


DrawLine(x0, y0, 0.0, xa, ya, 0.0, red, green, blue);
DrawLine(xa, ya, 0.0, xb, yb, 0.0, red, green, blue);
DrawLine(xb, yb, 0.0, x1, y1, 0.0, red, green, blue);
DrawLine(x1, y1, 0.0, xd, yd, 0.0, red, green, blue);
DrawLine(xd, yd, 0.0, xc, yc, 0.0, red, green, blue);
DrawLine(xc, yc, 0.0, x0, y0, 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
136

// ÁRBOL DE PITÁGORAS CON PERTURBACIONES ALEATORIAS


// Parámetros: nivel de graficación (1 a 12); perturbación (0 a 10).

void PitagorasRandomTree(double level, double per)


{
double a1, a2, b1, b2, c1, c2, j, m, n, s, w, xdesp;
double u, u1[13], u2[13], v, v1[13], v2[13];
double x, x1[13], x2[13], x3, y, y1[13], y2[13], y3;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

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 dibuja la base del tronco.


DrawLine(-0.25, 0.0, 0.0, 0.25, 0.0, 0.0, red, green, blue);

// 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;
}

u1[(int)s - 1] = u2[(int)s - 1];


v1[(int)s - 1] = v2[(int)s - 1];
x1[(int)s - 1] = x2[(int)s - 1];
y1[(int)s - 1] = y2[(int)s - 1];
}

// Se dibujan todas las ramas de un camino.


for (j = s; j <= level; j++) {

// Se calculan las coordenadas de los puntos de las ramas.


u = u1[(int)j - 1];
v = v1[(int)j - 1];
x = x1[(int)j - 1];
y = y1[(int)j - 1];
x3 = u - x;
y3 = v - y;
u1[(int)j] = x + b1 * x3 - b2 * y3;
v1[(int)j] = y + b2 * x3 + b1 * y3;
x1[(int)j] = x + a1 * x3 - a2 * y3;
y1[(int)j] = y + a2 * x3 + a1 * y3;
x2[(int)j] = u1[(int)j];
y2[(int)j] = v1[(int)j];
u2[(int)j] = x + c1 * x3 - c2 * y3;
v2[(int)j] = y + c2 * x3 + c1 * y3;

// Se dibujan los segmentos de las ramas.


DrawLine(x - xdesp, y, 0.0, x1[(int)j] - xdesp, y1[(int)j],
0.0, red, green, blue);
DrawLine(u1[(int)j] - xdesp, v1[(int)j], 0.0,
x2[(int)j] - xdesp, y2[(int)j],0.0, red, green, blue);
DrawLine(u2[(int)j] - xdesp, v2[(int)j], 0.0,
u - xdesp, v, 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
138

// 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++) {

// Se calculan las coordenadas del próximo punto.


m = n;
b = n * a;
f = 0.0;

while (1) {
if ((int)m % (int)v != 0 || f >= (p - 1.0)) break;
f = f + 1.0;
m = floor(m / v);
}

x = x + pow(r, (p - f - 1.0)) * cos(b);


y = y + pow(r, (p - f - 1.0)) * sin(b);

// Se dibuja un segmento hasta el punto calculado.


DrawLine(xprev, yprev, 0.0, x, y, 0.0, red, green, blue);

xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
139

// POLVO FRACTAL – MÉTODO DE MONTE CARLO


// Parámetros: ninguno.

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;

// Se construye la nube de puntos.


for (n = 0.0; n <= 15000.0; n++) {

// Se calculan las coordenadas del próximo punto.


if (Random( ) < 0.5) {
z = x;
x = a * x - b * y;
y = b * z + a * y;
} else {
z = x;
x = c * x - d * y + 1.0 - c;
y = d * z + c * y - d;
}

// Se dibuja un punto en las coordenadas calculadas.


DrawPoint(x - xdesp, y, 0.0, red, green, blue);
}
}
GEOMETRÍA FRACTAL Página
140

// LÍNEA BROWNIANA
// Parámetros: incremento en la abscisa (1 a 30); amplitud máxima (1 a 20).

void BrownianLine(double inc, double amp)


{
double XMin = -2.0, XMax = 2.0;
double point, step, var;
double x, y, xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; //Color amarillo.

step = inc / 100.0;


var = amp / 10.0;

xprev = XMin;
yprev = 0.0;

// Se dibuja una línea horizontal central.


DrawLine(XMin, 0.0, 0.0, XMax, 0.0, 0.0, 100, 100, 100);

// Se generan segmentos aleatorios.


for (point = XMin; point <= XMax; point += step) {

// Se calculan las coordenadas del próximo punto.


// x de forma secuencial; y de forma aleatoria.
x = point;
y = Random( ) * var - var / 2.0;

// Se dibuja un segmento hasta el punto calculado.


DrawLine(xprev, yprev, 0.0, x, y, 0.0, red, green, blue);

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.

minX = XCenter - RANGE_X / 2.0 / zoom;


maxX = XCenter + RANGE_X / 2.0 / zoom;
minY = YCenter - RANGE_Y / 2.0 / zoom;
maxY = YCenter + RANGE_Y / 2.0 / zoom;
xrel = (maxX - minX) / RANGE_X;
yrel = (maxY - minY) / RANGE_Y;
stepx = 0.001 * xrel;
stepy = 0.001 * yrel;

// Se construye el modelo. Valores de la abscisa.


for (a = minX; a <= maxX; a+=stepx) {

y = 0.7;

// Se calculan 500 valores de y por cada valor de a.


// Sólo se dibujan los últimos (500 - est) puntos.
for (k = 1.0; k <= 500.0; k++) {

// Se calcula el valor de y.
y = a * y * (1.0 - y);

// Se dibuja un punto en las coordenadas (a, y).


if (k > est && y >= minY && y <= maxY)
DrawPoint(a / xrel - Xcenter * zoom,
y / yrel - Ycenter * zoom,
0.0, red, green, blue);
}
}
if (grid) SetGrid(0.17, 6.0, minX, maxX, minY, maxY);
}
GEOMETRÍA FRACTAL Página
142

// 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).

void MandelbrotSet(double nIter, double XCenter, double YCenter,


double zoom, bool grid)
{
double i, j, k, r;
double x, x1, y, y1;
double maxX; // Valor real extremo derecho.
double minX; // Valor real extremo izquierdo.
double maxY; // Valor imaginario extremo superior.
double minY; // Valor imaginario extremo inferior.
double stepx, stepy, xrel, yrel;
double RANGE_X = 4.0;
double RANGE_Y = 4.0;
unsigned int red, green, blue;

minX = XCenter - RANGE_X / 2.0 / zoom;


maxX = XCenter + RANGE_X / 2.0 / zoom;
minY = YCenter - RANGE_Y / 2.0 / zoom;
maxY = YCenter + RANGE_Y / 2.0 / zoom;
xrel = (maxX - minX) / RANGE_X;
yrel = (maxY - minY) / RANGE_Y;
stepx = 0.005 * xrel;
stepy = 0.005 * yrel;

// Valores del eje real.


for (i = minX; i <= maxX; i += stepx) {

// Valores del eje imaginario.


for (j = minY; j <= maxY; j += stepy) {

x = i;
y = j;

for (k = 0.0; k < nIter; k++) {

x1 = pow(x, 2.0) - pow(y, 2.0) + i;


y1 = 2.0 * x * y + j;
r = pow(x1, 2.0) + pow(y1, 2.0);

if (r > 4.0) break;


x = x1;
y = y1;
}
GEOMETRÍA FRACTAL Página
143

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);
}
}
}

if (grid) SetGrid(0.5, 8.0, minX, maxX, minY, maxY);


}
GEOMETRÍA FRACTAL Página
144

// 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).

void JuliaSet(double RealConst, double ImagConst, double nIter,


double XCenter, double YCenter, double zoom, bool grid)
{
double i, j, k;
double conX; // Constante real.
double conY; // Constante imaginaria.
double maxX; // Valor real extremo derecho.
double minX; // Valor real extremo izquierdo.
double maxY; // Valor imaginario extremo superior.
double minY; // Valor imaginario extremo inferior.
double x, y, xnew, ynew, xrel, yrel;
double stepx, stepy;
double RANGE_X = 4.0;
double RANGE_Y = 3.0;
unsigned int red, green, blue;

conX = RealConst; // Valor de referencia: -0.74


conY = ImagConst; // Valor de referencia: 0.1

minX = XCenter - RANGE_X / 2.0 / zoom;


maxX = XCenter + RANGE_X / 2.0 / zoom;
minY = YCenter - RANGE_Y / 2.0 / zoom;
maxY = YCenter + RANGE_Y / 2.0 / zoom;

xrel = (maxX - minX) / RANGE_X;


yrel = (maxY - minY) / RANGE_Y;
stepx = 0.005 * xrel;
stepy = 0.005 * yrel;

// Valores del eje real.


for (i = minX; i <= maxX; i += stepx) {

// Valores del eje imaginario.


for (j = minY; j <= maxY; j += stepy) {

x = i;
y = j;

xnew = 0.0;
ynew = 0.0;
GEOMETRÍA FRACTAL Página
145

// Iteración de cálculo para cada punto.


for(k = 0.0; k <= nIter; k++) {

// La función de Julia: Z = Z * Z + c
xnew = x * x - y * y + conX;
ynew = 2 * x * y + conY;
x = xnew;
y = ynew;

// Condición de interrupción cuando la iteración genera


// valores que tienden a infinito.
if ((x * x + y * y) > 4.0 ) break;
}

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);
}
}
}

if (grid) SetGrid(0.5, 8.0, minX, maxX, minY, maxY);


}
GEOMETRÍA FRACTAL Página
146

// ÓRBITAS DE UN SISTEMA DINÁMICO - VERSIÓN 1


// Parámetros: a (1.0 a 5.0); b (1.0 a 5.0); cantidad de puntos.

void DynamicSystem1(double a, double b, double npoints)


{
double j, w, x, y, z;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

b = b * -1.0;
x = 0.321;
y = 0.654;
w = a * x + b * (x - 1.0);

// Se construye la nube de puntos.


for (j = 0.0; j <= npoints; j++) {

// Se dibuja un punto en las coordenadas calculadas.


DrawPoint(x / 100.0, y / 100.0, 0.0, red, green, blue);

// Se calculan las coordenadas del próximo punto.


z = x;
x = y + w;
w = (x > 1.0) ? a * x + b * (x - 1.0) :
(x < -1.0) ? a * x + b * (x + 1.0) : a * x;
y = w - z;
}
}
GEOMETRÍA FRACTAL Página
147

// ÓRBITAS DE UN SISTEMA DINÁMICO – VERSIÓN 2


// Parámetros: a (1.0 a 50.0); b (1.0 a 50.0); cantidad de puntos.

void DynamicSystem2(double a, double b, double npoints)


{
double c, j, w, x, y, z;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

// Se convierte “a” al rango : 0.50 to 0.99


a = (100.0 - a) / 100.0;

// Se convierte “b” al rango: -0.01 to -0.50


b /= 100.0 * (-1.0);

c = 0.9995;
x = 4.0;
y = 1.0;
w = a * x;

// Se construye la nube de puntos.


for (j = 0.0; j <= npoints; j++) {

// Se dibuja un punto en las coordenadas calculadas.


DrawPoint(x, y, 0.0, red, green, blue);

// Se calculan las coordenadas del próximo punto.


z = x;
x = c * y + w;
w = (x > 0.0) ? a * x : b * x;
y = w - z;
}
}
GEOMETRÍA FRACTAL Página
148

// POLVO FRACTAL – MÉTODO DE RETROCESO


// Parámetros: nivel de graficación (1 a 15).

void FractalDust(double level)


{
double x1[16], x2[16], y1[16], y2[16];
double a, b, c, d, j, m, n, s, x, y;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

a = 0.5;
b = 0.5;
c = 0.5;
d = -0.5;
x1[0] = a;
y1[0] = b;
s = 1.0;

// Se construye la nube de puntos.


for (m = 0.0; m <= pow(2.0, (level - 1.0)) - 1.0; m++) {

if (m) {
s = level;
n = m;
while((int)n % 2 == 0) {
n = floor(n / 2.0);
s = s - 1.0;
}

x1[(int)s - 1] = x2[(int)s - 1];


y1[(int)s - 1] = y2[(int)s - 1];
}

for (j = s; j <= level; j++) {

// Se calculan las coordenadas de los próximos dos puntos.


x = x1[(int)j - 1];
y = y1[(int)j - 1];
x1[(int)j] = a * x - b * y;
y1[(int)j] = b * x + a * y;
x2[(int)j] = c * x - d * y + 1.0 - c;
y2[(int)j] = d * x + c * y - d;

// Se dibujan los dos puntos.


DrawPoint(x1[(int)j], y1[(int)j], 0.0, red, green, blue);
DrawPoint(x2[(int)j], y2[(int)j], 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
149

// POLVO FRACTAL DE TRIPLE ROTACIÓN


// Parámetros: nivel de graficación (1 a 10).

void TripleRotationDust(double level)


{
double x1[11], x2[11], x3[11], y1[11], y2[11], y3[11];
double a, b, g, h, j, m, n, s, t1, t2, x, y;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

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);

// Se construye la nube de puntos.


for (m = 0.0; m <= pow(3.0, (level - 1.0)) - 1.0; m++) {

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];
}

for (j = s; j <= level; j++) {


// Se calculan las coordenadas de los próximos tres puntos.
x = x1[(int)j - 1];
y = y1[(int)j - 1];
x1[(int)j] = a * x - b * y;
y1[(int)j] = b * x + a * y;
x2[(int)j] = a * x - b * y + 1.0 - a;
y2[(int)j] = b * x + a * y - b;
x3[(int)j] = a * x - b * y + g;
y3[(int)j] = b * x + a * y + h;
// Se dibujan los tres puntos.
DrawPoint(x1[(int)j], y1[(int)j], 0.0, red, green, blue);
DrawPoint(x2[(int)j], y2[(int)j], 0.0, red, green, blue);
DrawPoint(x3[(int)j], y3[(int)j], 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
150

// ÓRBITAS DEL SISTEMA CUADRÁTICO DE HENON


// Parámetros: forma de las órbitas (1 a 99); número de órbitas (1 a 500);
// cantidad de puntos por órbitas.

void HenonSystem(double a, double norbits, double npoints)


{
double b, k, n, x, y, z;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

a /= 100.0;

// Se construyen las órbitas.


for (k = 1.0; k <= norbits; k++) {

// Se calculan las coordenadas del punto inicial de la órbita.


x = Random( ) - 0.4;
y = Random( ) - 0.4;
b = sqrt(1.0 - pow(a, 2.0));

// Se dibuja la órbita. Cada órbita contiene (npoints) puntos.


for (n = 1.0; n <= npoints; n++) {

// Se dibuja un punto en las coordenadas calculadas.


DrawPoint(x, y, 0.0, red, green, blue);

// Se calculan las coordenadas del próximo punto.


z = x;
x = x * a - (y - pow(x, 2.0)) * b;
y = z * b + (y - pow(z, 2.0)) * a;

if ((abs((int)(x * 100.0)) + abs((int)(y * 100.0))) > 1000) break;


}
}
}
GEOMETRÍA FRACTAL Página
151

// ÓRBITAS DEL SISTEMA DE MIRA


// Parámetros: forma de la nube (1 a 99); cantidad de puntos.

void MiraSystem(double a, double npoints)


{
double b, c, d, e, n, x, x1, y, y1, z;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

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);
}

// Se calculan las coordenadas del próximo punto.


z = x;
x = b * y + d;
d = a * x + c * pow(x, 2.0) / (1.0 + pow(x, 2.0));
y = d - z;
}
}
GEOMETRÍA FRACTAL Página
152

// ATRACTOR DE LORENZ
// Parámetros: cantidad de puntos.

void LorenzAttractor(double npoints)


{
double a, b, c, dt, n;
double xa, ya, za, x, y, z, x1, y1, z1;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

dt = 0.03;
a = 5.0;
b = 15.0;
c = 1.0;
xa = 0.30;
ya = 0.15;
za = 0.02;

// Se construye la nube de puntos.


for (n = 0.0; n <= npoints; n++) {

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;

// Sólo para posicionar adecuadamente la nube en la pantalla.


x1 = x1 * 0.1 - 1.2;
y1 = y1 * 0.1 - 0.2;
z1 = z1 * 0.1;

// 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).

void EvolutiveCircle(double nsectors, double dist, double lsector)


{
double n, t, x, y, xprev, yprev;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

dist /= 100.0;
xprev = dist;
yprev = 0.0;

// Se construye el círculo.
for (n = 0.0; n <= nsectors; n++) {

// Se calculan las coordenadas del próximo punto.


t = lsector * PI * n / 80.0;
x = dist * (cos(t) + t * sin(t));
y = dist * (sin(t) - t * cos(t));

// Se dibuja un segmento hasta el punto calculado.


DrawLine(xprev, yprev, 0.0, x, y, 0.0, red, green, blue);

// Se dibuja una tangente desde el centro hasta el punto calculado.


DrawLine(dist * cos(t), dist * sin(t), 0.0, x, y, 0.0, red, green, blue);

xprev = x;
yprev = y;
}
}
GEOMETRÍA FRACTAL Página
154

// ÁRBOL DE MANDELBROT – MÉTODO DE RETROCESO


// Parámetros: nivel de graficación (1 a 12).

void MandelbrotTree(double level)


{
double a, b, a1, a2, b1, b2, c1, c2, d1, d2, e1, e2, f1, f2;
double h, j, m, n, p1, p2, p3, p4, r1, r2, s;
double u, u1[13], u2[13], u3, u4, v, v1[13], v2[13], v3, v4;
double x, x1[13], x2[13], x3, y, y1[13], y2[13], y3;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

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 dibuja la base del tronco.


DrawLine(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, red, green, blue);

// 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;

x1[(int)s - 1] = x2[(int)s - 1];


y1[(int)s - 1] = y2[(int)s - 1];
u1[(int)s - 1] = u2[(int)s - 1];
v1[(int)s - 1] = v2[(int)s - 1];
}
GEOMETRÍA FRACTAL Página
155

// Se dibujan todas las ramas de un camino.


for (j = s; j <= level; j++) {

// Se calculan las coordenadas de los puntos de las ramas.


x = x1[(int)j - 1];
y = y1[(int)j - 1];
u = u1[(int)j - 1];
v = v1[(int)j - 1];
x3 = u - x;
y3 = v - y;
x1[(int)j] = x + a1 * x3 - a2 * y3;
y1[(int)j] = y + a2 * x3 - a1 * y3;
u1[(int)j] = x + b1 * x3 - b2 * y3;
v1[(int)j] = y + b2 * x3 - b1 * y3;
x2[(int)j] = x + e1 * x3 - e2 * y3;
y2[(int)j] = y + e2 * x3 + e1 * y3;
u2[(int)j] = x + f1 * x3 - f2 * y3;
v2[(int)j] = y + f2 * x3 + f1 * y3;
u3 = x + c1 * x3 - c2 * y3;
v3 = y + c2 * x3 + c1 * y3;
u4 = x + d1 * x3 - d2 * y3;
v4 = y + d2 * x3 + d1 * y3;

if (j == s) {
h = a2; a2 = f2;
f2 = h; h = b2;
b2 = e2; e2 = h;
h = c2; c2 = d2;
d2 = h;
}

// Se dibujan los segmentos que componen las ramas.


p1 = x; p2 = y;
p3 = x1[(int)j]; p4 = y1[(int)j];
DrawLine(p1, p2, 0.0, p3, p4, 0.0, red, green, blue);
p1 = u1[(int)j]; p2 = v1[(int)j];
p3 = u3; p4 = v3;
DrawLine(p1, p2, 0.0, p3, p4, 0.0, red, green, blue);
p1 = u4; p2 = v4;
DrawLine(p1, p2, 0.0, p3, p4, 0.0, red, green, blue);
p3 = x2[(int)j]; p4 = y2[(int)j];
DrawLine(p1, p2, 0.0, p3, p4, 0.0, red, green, blue);
p1 = u2[(int)j]; p2 = v2[(int)j];
p3 = u; p4 = v;
DrawLine(p1, p2, 0.0, p3, p4, 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
156

// FRACTAL H – MÉTODO DE RETROCESO


// Parámetros: nivel de graficación (1 a 6).

void HFractalBacktracking(double level)


{
double a, b, c, j, m, n, s, x, y;
double x1[7], x2[7], x3[7], x4[7], xp, xq;
double y1[7], y2[7], y3[7], y4[7], yp, yq;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

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;
}

x1[(int)s - 1] = x2[(int)s - 1];


x2[(int)s - 1] = x3[(int)s - 1];
x3[(int)s - 1] = x4[(int)s - 1];
y1[(int)s - 1] = y2[(int)s - 1];
y2[(int)s - 1] = y3[(int)s - 1];
y3[(int)s - 1] = y4[(int)s - 1];
}

// Se dibujan las “H” que component un camino.


for (j = s; j <= level; j++) {

// Se calculan las coordenadas de los puntos de una “H”.


x = x1[(int)j - 1];
y = y1[(int)j - 1];
b = pow(a, j);
c = a * b * 1.5;
x1[(int)j] = x + b;
x2[(int)j] = x + b;
x3[(int)j] = x - b;
x4[(int)j] = x - b;
y1[(int)j] = y + c;
y2[(int)j] = y - c;
y3[(int)j] = y + c;
y4[(int)j] = y - c;
GEOMETRÍA FRACTAL Página
157

// Se dibujan los segmentos que component una “H”.


xp = (x - b);
yp = y;
xq = (x + b);
yq = y;
DrawLine(xp, yp, 0.0, xq, yq, 0.0, red, green, blue);
xp = x1[(int)j];
yp = y1[(int)j];
xq = x2[(int)j];
yq = y2[(int)j];
DrawLine(xp, yp, 0.0, xq, yq, 0.0, red, green, blue);
xp = x3[(int)j];
yp = y3[(int)j];
xq = x4[(int)j];
yq = y4[(int)j];
DrawLine(xp, yp, 0.0, xq, yq, 0.0, red, green, blue);
}
}
}
GEOMETRÍA FRACTAL Página
158

// FRACTAL H – CONSTRUCCIÓN POR NIVELES


// Parámetros: nivel de graficación (1 a 10).

void HFractalByLevels(double level)


{
double a, m, n, s, x1, x2, y1, y2;
double x[5200], y[5200];
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

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;

// Se dibujan todas las “H” de un nivel.


for (n = pow(2.0, m); n <= pow(2.0, (m + 1.0)) - 1.0; n++) {

// Se calculan las coordenadas de un segmento de la “H”.


if (s == 1.0) {
x[2 * (int)n] = x[(int)n];
y[2 * (int)n] = y[(int)n] + pow(a, m);
x[2 * (int)n + 1] = x[(int)n];
y[2 * (int)n + 1] = y[(int)n] - pow(a, m);
}
else {
x[2 * (int)n] = x[(int)n] + pow(a, m);
y[2 * (int)n] = y[(int)n];
x[2 * (int)n + 1] = x[(int)n] - pow(a, m);
y[2 * (int)n + 1] = y[(int)n];
}

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

// POLÍGONOS CONCÉNTRICOS EN ROTACIÓN


// Parámetros: número de lados (3 a 12); ángulo de rotación (1 a 50);
// número de polígonos (1 a 100).

void Polygons(double sides, double angle, double npolygons)


{
double a, b, k, l, m, n, t;
double x[13], x1, xprev, y[13], y1, yprev, z;
unsigned int red = 255, green = 255, blue = 0; // Color amarillo.

angle /= 100.0;
a = PI * (1.0 - 2.0 / sides);
b = sin(a) / (sin(angle) + sin(a + angle));

// Se calculan los vertices del polígono exterior.


for (k = 0.0; k <= sides; k++) {
t = (2.0 * k + 1.0) * PI / sides;
x[(int)k] = sin(t);
y[(int)k] = cos(t);
}

// Se dibujan los polígonos interiores.


for (n = 1.0; n <= npolygons; n++) {

x1 = x[0];
y1 = y[0];

// Vértice inicial del polígono.


xprev = x1;
yprev = y1;

// 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;
}

// Se calculan los vértices del próximo polígono, reducido y rotado.


for (m = 0.0; m <= sides; m++) {
z = x[(int)m];
x[(int)m] = (x[(int)m] * cos(angle) - y[(int)m] * sin(angle)) * b;
y[(int)m] = (z * sin(angle) + y[(int)m] * cos(angle)) * b;
}
}
}
GEOMETRÍA FRACTAL Página
160

// FUNCIONES AUXILIARES

// Función que dibuja un punto en el espacio.


// Parámetros: coordenada x; coordenada y; coordenada z;
// componente roja de color (0 a 255);
// componente verde de color (0 a 255);
// componente azul de color (0 a 255).

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();
}

// Función que dibuja una línea en el espacio.


// Parámetros: coordenada x inicial; coordenada y inicial; coordenada z inicial;
// coordenada x final; coordenada y final; coordenada z final;
// componente roja de color (0 a 255);
// componente verde de color (0 a 255);
// componente azul de color (0 a 255).

void DrawLine(double x1, double y1, double z1,


double x2, double y2, double z2, int red, int green, int blue)
{
glColor3ub(red,green,blue);
glBegin(GL_LINES);
glVertex3d(x1, y1, z1);
glVertex3d(x2, y2, z2);
glEnd();
}

// Función que dibuja una grilla en el plano (x, y).


// Parámetros: valor de la unidad; cantidad de divisiones;
// valor mínimo de x; valor máximo de x;
// valor mínimo de y; valor máximo de y.

void SetGrid(double unit, double ndivision,


double minx, double maxx, double miny, double maxy)
{
double start, end, i;
unsigned int red = 100, green = 100, blue = 100; // Color gris.

start = (-1) * ndivision * unit / 2.0;


end = ndivision * unit / 2.0;
GEOMETRÍA FRACTAL Página
161

for (i = 0.0; i <= ndivision; i++) {

// Se grafican las divisiones horizontales.


DrawLine(start + i * unit, start, 0.0, start + i * unit, end, 0.0,
red, green, blue);
// Se grafican las divisions verticals.
DrawLine(start, start + i * unit, 0.0, end, start + i * unit, 0.0,
red, green, blue);

// Se colocan las etiquetas sobre el eje de las abscisas.


glRasterPos2d(0.02 - ndivision / 2.0 * unit + i * unit, -0.08);
PrintTextBF("%.5f", minx + (maxx - minx) / ndivision * i);
// Se colocan las etiquetas sobre el eje de las ordenadas.
glRasterPos2d(0.02, 0.02 - ndivision / 2.0 * unit + i * unit);
PrintTextBF("%.5f", miny + (maxy - miny) / ndivision * i);
}
}

// Función que genera un número aleatorio entre 0 y 1.


// Parámetros: ninguno.

double Random(void)
{
// La función rand( ) original devuelve un valor entre 0 y 32767.
return rand( ) / 32767.0;
}

// Función que genera colores.


// Parámetros: valor de generación;
// variable para el componente rojo del color;
// variable para el componente verde del color;
// variable para el componente azul del color.

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;}
}

You might also like