Que onda chavos pues aquí nos encontramos de nueva cuenta para finalizar con este tema de los fractales, y como les había comentado en la ocasión pasada el fractal que nos falta es un fractal que genera un paisaje, dicho paisaje consta de montañas, el mar y el sol. Este fractal que vamos a programar se le conoce como escena fractal o fractal de Landscape.
Bien pues comenzamos ya con el final de este tema. Para empezar lo primero que haremos será cambiar el color de la Forma ya que dependiendo del color que le pongamos a la Forma es el color que van a tener las montañas de nuestra escena fractal, ustedes pueden elegir el color que mas les guste o que mas se acople al paisaje, yo en mi caso elegí el color gris para la Forma. Después todo lo que necesitamos es colocar un Timer sobre la Forma y terminamos con la parte gráfica, nuestra Forma debe de haber quedado de la siguiente manera:
Bueno ahora continuamos con la parte del código. Primero nos vamos al archivo H y en la parte de declaraciones privadas escribimos las siguientes variables:
private: // User declarations
int MAXSIZE,MAXLEVEL;
double frctl[1000];
int cw,ch,x1;
Ahora en la parte de declaraciones públicas escribimos las siguientes definiciones de los métodos que utilizaremos más adelante:
public: // User declarations
__fastcall TForm1(TComponent* Owner);
void TForm1::subdivide(int f1, int f2, double std, double ratio);
void TForm1::fractal(int y1, int y2, int maxlevel, double h, double scale);
void TForm1::draw_fractal(void);
Ahora nos regresamos a la Forma y abrimos el evento OnCreate de nuestra Forma y en él escribimos el siguiente código para darle valor a las variables apenas corra nuestra aplicación:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
x1=10;
MAXSIZE=1000;
MAXLEVEL=6;
cw=ClientWidth-10;
ch=ClientHeight-10;
this->DoubleBuffered = true;
}
//---------------------------------------------------------------------------
También escribimos en la línea final del código pasado la asignación de la propiedad DoubleBuffered en true, para con esto reducir el parpadeo que se genera al momento de repintar o refrescar la Forma.
Ahora vamos a codificar los métodos que utilizaremos para generar el fractal, el primero que codificaremos será el método llamado fractal():
void TForm1::fractal(int y1,int y2,int maxlevel,double h,double scale)
{
int first, last;
double ratio,std;
first=0;
last=(int)pow(2.0,(double)maxlevel);
frctl[first]=y1;
frctl[last]=y2;
ratio=1.0/pow(2.0,h);
std=scale*ratio;
subdivide(first,last,std,ratio);
}
//--------------------------------------------------------------------------------
Continuamos codificando los métodos ahora le toca el turno al método conocido como subdivide(), el código lo tenemos a continuación:
void TForm1::subdivide(int p1,int p2,double std,double ratio)
{
int midpnt;
double stdmid;
midpnt = (p1 + p2) / 2;
if(midpnt != p1 && midpnt != p2)
{
frctl[midpnt] = (frctl[p1] + frctl[p2]) / 2 + (double)((random(16)-8)) /8.0*std;
stdmid = std * ratio;
subdivide(p1,midpnt,stdmid,ratio);
subdivide(midpnt,p2,stdmid,ratio);
}
}
//-------------------------------------------------------------------------------
Para terminar de codificar los 3 métodos que vamos a utilizar codificamos el último de los métodos el cual lo hemos llamado draw_fractal():
void TForm1::draw_fractal()
{
int i,x,xinc,l;
l=(int)pow(2.0,(double)MAXLEVEL);
xinc = cw / l * 3 / 2;
this->Canvas->MoveTo(0,100);
for(i=0,x=0;i<l;i++,x+=xinc)
this->Canvas->LineTo(x,(int)frctl[i]);
}
//---------------------------------------------------------------------------------
Y con eso terminamos la parte de codificación de los métodos ya solo nos resta teclear el código que irá dentro del Timer y que es el que irá generando el efecto. En el código del Timer hemos agregado una variable x1 que se irá incrementando cada vez que se vuelva a ejecutar el Timer y así dar el efecto de que el sol está en movimiento. Además también hacemos uso de la función FloodFill(), la cual nos sirve para rellenar un área especifica que tenga un color, con otro color que nosotros hayamos especificado. Los parámetros de esta función consta de un par de coordenadas que estén dentro del área que deseamos colorear, el color que tiene el área que deseamos colorear, y el parámetro fsSurface que pintará el área completamente hasta encontrar otro color (si desean conocer más sobre esta función pueden colocar el cursor sobre la palabra FloodFill y oprimir la tecla F1 y se abrirá el menú de ayuda y ahí podrán leer más sobre el funcionamiento de ésta función). El código del Timer1 lo tenemos a continuación:
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
x1++;
this->Repaint();
randomize();
this->Canvas->Pen->Color=clBlack;
this->Canvas->Brush->Color=clSkyBlue;
fractal(100,100,MAXLEVEL,0.5,50.0);
draw_fractal();
this->Canvas->FloodFill(1,1,this->Color,fsSurface);
this->Canvas->Brush->Color=clTeal;
fractal(170,170,MAXLEVEL,0.9,30.0);
draw_fractal();
this->Canvas->FloodFill(1,ch-1,this->Color,fsSurface);
this->Canvas->Brush->Color=clYellow;
this->Canvas->Ellipse(10+x1,10,80+x1,80);
this->Canvas->FloodFill(cw,50,this->Color,fsSurface);
}
//---------------------------------------------------------------------------
Y pues eso es todo chavos ya solo queda compilar y ejecutar nuestra aplicación y automáticamente comenzará a generar el efecto debido a que el código lo escribimos en un Timer. El efecto de nuestra escena fractal debería de ser como lo que tenemos a continuación:
Y con este último fractal podemos dar por terminado este tema de los fractales. Si quieren pueden seguir buscando y en internet encontrarán muchísimos ejemplos más sobre fractales y si quieren seguir practicando pues pueden programarlos en C++ Builder. Bien pues gracias por haberme acompañado y nos vemos en la próxima ocasión para seguir realizando más aplicaciones de C++ pero ahora con un tema diferente. Hasta pronto amigos!.
No hay comentarios:
Publicar un comentario