Blog hecho para la Materia de Graficacion de la carrera de ing. en sistemas computacionales del Instituto Tecnologico de la Laguna. Las publicaciones de este blog seran conforme vallamos avanzando en el curso, asi que se publicara codigo e imagenes para que sean de provecho para todos que quieran aprender.
domingo, 30 de octubre de 2011
Transformaciones bidimensionales
A la hora de graficar, el eje X se muestra como en plano cartesiano pero el eje Y esta invertido, lo cual quiere decir que conforme vaya aumentando el valor de Y este va hacie el fondo de la ventana.
A continuacion se muestra el codigo para invertir el eje Y, utilizando la clase VentanaPuerto, la cual tambien
no sirve a la hora de manejar las coordenadas mundiales y las coordenadas de los dispositivos.
class VentanaPuerto
{
private:
float xWmin, yWmin, xWmax, yWmax;
int xPvmin, yPvmin, xPvmax, yPvmax;
public:
void Ventana(float xW1, float yW1, float xW2, float yW2);
void Puerto_Vision(int xPv1, int yPv1, int xPv2, int yPv2);
void Mapeo(float x1, float y1, int *xt1, int *yt1, int L, int M);
};
void VentanaPuerto::Ventana(float xW1, float yW1, float xW2, float yW2)
{
xWmin = xW1; //0
yWmin = yW1; //0
xWmax = xW2; //500
yWmax = yW2; //500
}
void VentanaPuerto::Puerto_Vision(int xPv1, int yPv1, int xPv2, int yPv2)
{
xPvmin = xPv1;
yPvmin = yPv1;
xPvmax = xPv2;
yPvmax = yPv2;
}
void VentanaPuerto::Mapeo(float x1, float y1, int *xt1, int *yt1, int L, int M)
{
float sx, sy;
sx = (xPvmax - xPvmin) / (xWmax - yWmin);
sy = (yPvmax - yPvmin) / (yWmax - yWmin);
*xt1 = floor(sx * (x1 - xWmin) + xPvmin + L + 0.5);
*yt1 = floor(sy * (yWmin - y1) - yPvmin + M + 0.5);
}
void __fastcall TForm1::Button6Click(TObject *Sender)
{
int fig[4][2] = {{1, 1},
{3, 1},
{2, 3},
{1, 1}};
VentanaPuerto vp;
vp.Ventana(0, 0, 22, 28);
Canvas->Rectangle(100, 100, 321, 380);
vp.Puerto_Vision(100, 100, 321, 380);
int L = 0;
int M = 190 + 290;
int xx1, yy1, xx2, yy2;
vp.Mapeo(fig[0][0],fig[0][1], &xx1, &yy1, L, M);
Canvas->MoveTo(xx1, yy1);
for(int i = 1; i < 4; i++)
{
vp.Mapeo(fig[i][0], fig[i][1], &xx1, &yy1, L, M);
Canvas->LineTo(xx1, yy1);
}
}
domingo, 9 de octubre de 2011
Trazo de Espirales
Codigo para trazar espirales.
void TForm1::Espiral()
{
int xc = ClientWidth / 2, yc = ClientHeight / 2, radio = 5; // radio valor a cambiar
double dos_pi = M_PI * 2.0;
int cont = 0;
double dth, cth, sth, x, y, x_temp, xt, yt;
dth = dos_pi / (16 * radio); // cambiar 16 a 2 y 4
cth = cos(dth);
sth = sin(dth);
x = 0.0; y = radio;
xt = xc + x; yt = yc + y;
do
{
x_temp = x;
x = x * cth - y * sth;
y = y * cth + x_temp * sth;
if(x > 0)
x += 0.5;
else
x -= 0.5;
if(y > 0)
y += 0.5;
else
y -= 0.5;
Canvas->Pixels[floor(xt + 0.5)][floor(yt + 0.5)] = clRed;
linea_DDA(floor(xt + 0.5), floor(yt + 0.5), floor(xc + x + 0.5),
floor(yc + y + 0.5));
xt = xc + x;
yt = yc + y;
cont++;
Sleep(20);
}while(cont <= 350);
}
void TForm1::Espiral2()
{
int xc = ClientWidth / 2, yc = ClientHeight / 2;
float radio = 1.0; // valores a cambiar
double th, x, y, xt, yt;
th = 0.0; // valores a cambiar
x = radio * cos(th);
y = radio * sin(th);
xt = xc + x;
yt = yc + y;
while(radio < 250)
{
th += 0.1;
radio += 0.9;
x = radio * cos(th);
y = radio * sin(th);
g->linea_DDA(floor(xt + 0.5), floor(yt + 0.5), floor(xc + x + 0.5),
floor(yc + y + 0.5));
xt = xc + x;
yt = yc + y;
Sleep(5);
}
}
Trazo de Circunferencias
Los parametros basicos que definen una circunferencia son las coordenadas del centro (xc, yc) y el
radio. Podemos expresar la ecuacion de la circunferencia de varias formas.
Abajo el codigo para hacer un circulo mediante coordenadas polares, por segmentos e incrementos
de angulos.
void TForm1::Circ_Coord_Polares(int xc, int yc, int r)
{
float dt, ct, st, x, y, xtemp;
dt = 1.0 / r;
ct = cos(dt);
st = sin(dt);
x = 0;
y = r;
while(y >= x)
{
Canvas->Pixels[floor(xc + x)+ 0.5][floor(yc + y)+ 0.5] = clRed;
Canvas->Pixels[floor(xc - x)+ 0.5][floor(yc + y)+ 0.5] = clRed;
Canvas->Pixels[floor(xc + x)+ 0.5][floor(yc - y)+ 0.5] = clRed;
Canvas->Pixels[floor(xc - x)+ 0.5][floor(yc - y)+ 0.5] = clRed;
xtemp = x;
x = x * ct - y * st;
y = y * ct + xtemp * st;
}
}
void TForm1::Circulo_x_Segmentos(int xc, int yc, int radio)
{
double dos_pi = M_PI * 2;
double dth, ct, st, x, y, xtemp;
if(radio != 0)
{
dth = dos_pi / (16 * radio);
ct = cos(dth);
st = sin(dth);
x = 0;
y = radio;
for(int i = 0;i <=(16 * radio); i++)
{
xtemp = x;
x = x * ct + y *st;
y = y * ct - xtemp * st;
Canvas->Pixels[floor(x + xc + 0.5)][floor(y + yc + 0.5)] = clBlue;
}
}
}
void TForm1::Circulo_incremento_angulo(int xc, int yc, int radio)
{
int x, y;
for(int grados = 0; grados < 360; grados++)
{
x = xc + radio * cos (grados/180.0 * M_PI);
y = yc + radio * sin (grados/180.0 * M_PI);
Canvas->Pixels[x][y] = clBlack;
Sleep(30);
}
}
domingo, 2 de octubre de 2011
Algoritmo linea dda(algoritmo diferencial digital)
Este programa para trazar una linea recta basado en al algoritmo dda. Este, sirve para calcular posiciones de pixeles a lo largo de una linea recta. Abajo se encuentra el codigo de la aplicacion
de este algoritmo. Las lineas en el programa se pueden hacer con el click y arrastre del mouse o ya sea
insertando las coordenas manualmente.
class TForm1 : public TForm
{
__published: // IDE-managed Components
TPanel *Panel1;
TLabel *Label1;
TButton *Button1;
TEdit *Edit1;
TLabel *Label2;
TEdit *Edit2;
TLabel *Label3;
TEdit *Edit3;
TLabel *Label4;
TEdit *Edit4;
TPaintBox *PaintBox1;
TButton *Button2;
TComboBox *ComboBox1;
TLabel *Label5;
void __fastcall Button1Click(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall PaintBox1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y);
void __fastcall PaintBox1MouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
Graficos *g;
int x1, y1, x2, y2;
void linea_DDA(int x1, int y1, int x2, int y2);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
void TForm1::linea_DDA(int x1, int y1, int x2, int y2)
{
int dx, dy, steps, k;
float x_inc, y_inc, x, y;
dx = x2 - x1;
dy = y2 - y1;
if(abs(dx) > abs(dy))
{
steps = abs(dx);
}
else
{
steps = abs(dy);
}
x_inc = (float) dx / steps;
y_inc = (float) dy / steps;
x = x1;
y = y1;
//Putpixel(floor(x), floor(y), 1);
Form1->Canvas->Pixels[x][y] = clBlack;
for(k = 1; k < steps + 1 ; k++)
{
x = x + x_inc;
y = y + y_inc;
//Putpixel(x, y, 1);
PaintBox1->Canvas->Pixels[x][y] = clBlack;
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int x1 = Edit1->Text.ToInt();
int y1 = Edit2->Text.ToInt();
int x2 = Edit3->Text.ToInt();
int y2 = Edit4->Text.ToInt();
TColor color;
if(ComboBox1->Text == 'rojo')
{
color = color & 255;
}
g->linea_DDA(x1, y1, x2, y2, color);
//linea_DDA(x1, y1, x2, y2);
//int x1 = Edit1->Text.ToIntDef(10); por si el usuario no pone un valor en Edit
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
g = new Graficos(PaintBox1->Canvas);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
Edit1->Text = x1 = X;
Edit2->Text = y1 = Y;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::PaintBox1MouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
Edit3->Text = x2 = X;
Edit4->Text = y2 = Y;
g->linea_DDA(x1, y1, x2, y2);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Refresh(); //
}
//---------------------------------------------------------------------------
domingo, 25 de septiembre de 2011
Escena Fractal
En este fractal se utilzan 3 metodos para dibujarlo, los cuales en 2 de ellos se usa recursividad. Abajo el codigo. El fractal se puede generar mediante un timer (automaticamente) o con un boton. Usted elige.
class TForm1 : public TForm
{
__published: // IDE-managed Components
TPaintBox *PaintBox1;
TButton *Button1;
TTimer *Timer1;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Timer1Timer(TObject *Sender);
private: // User declarations
void subdivide(int first, int last, double std, double ratio);
void fractal(int y1, int y2, int maxlevel, double h, double scale);
void draw_fractal(void);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "EscenaFractal.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
const int MAXSIZE = 1000;
const int MAXLEVEL = 6;
double frct1[MAXSIZE];
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void TForm1::subdivide(int p1, int p2, double std, double ratio)
{
int midpnt;
double stdmid;
midpnt = (p1 + p2) / 2;
if(midpnt != p1 && midpnt != p2)
{
frct1[midpnt] = (frct1[p1] + frct1[p2]) / 2 +
(double)((random(16) - 8)) / 8.0 * std;
stdmid = std * ratio;
subdivide(p1, midpnt, stdmid, ratio);
subdivide(midpnt, p2, stdmid, ratio);
}
}
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);
frct1[first] = y1;
frct1[last] = y2;
ratio = 1.0 / pow(2.0,h);
std = scale * ratio;
subdivide(first, last, std, ratio);
}
void TForm1::draw_fractal(void)
{
int i, x, xinc, l;
//int cw = Form1->ClientWidth;
l = (int)pow(2.0, (double)MAXLEVEL);
xinc = ClientWidth / l * 3 / 2;
Form1->Canvas->MoveTo(0, 100);
for(i = 0, x = 0; i < l; i++, x +=xinc)
{
Form1->Canvas->LineTo(x, (int)frct1[i]);
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
randomize();
PaintBox1->Refresh();
PaintBox1->Canvas->Rectangle(0,0, PaintBox1->Width, PaintBox1->Height);
PaintBox1->Canvas->Brush->Color = clSkyBlue;
fractal(100,100, MAXLEVEL, 0.5, 50.0);
draw_fractal();
PaintBox1->Canvas->FloodFill(1,1, clBlack, fsBorder);
PaintBox1->Canvas->Brush->Color = clBlue; //(TColor);
fractal(170, 170, MAXLEVEL, 0.9, 30.0);
draw_fractal();
PaintBox1->Canvas->FloodFill(1, 240, clBlack, fsBorder);
PaintBox1->Canvas->Brush->Color = clYellow; //;(TColor)SUN;
PaintBox1->Canvas->Ellipse(250, 20, 290, 60);
PaintBox1->Canvas->FloodFill(270, 50, clBlack, fsBorder);
PaintBox1->Canvas->Brush->Color = clGreen;
PaintBox1->Canvas->FloodFill(270, 150, clBlack, fsBorder);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
randomize();
PaintBox1->Refresh();
PaintBox1->Canvas->Rectangle(0,0, PaintBox1->Width, PaintBox1->Height);
PaintBox1->Canvas->Brush->Color = clSkyBlue;
fractal(100,100, MAXLEVEL, 0.5, 50.0);
draw_fractal();
PaintBox1->Canvas->FloodFill(1,1, clBlack, fsBorder);
PaintBox1->Canvas->Brush->Color = clBlue; //(TColor);
fractal(170, 170, MAXLEVEL, 0.9, 30.0);
draw_fractal();
PaintBox1->Canvas->FloodFill(1, 240, clBlack, fsBorder);
PaintBox1->Canvas->Brush->Color = clYellow; //;(TColor)SUN;
PaintBox1->Canvas->Ellipse(250, 20, 290, 60);
PaintBox1->Canvas->FloodFill(270, 50, clBlack, fsBorder);
PaintBox1->Canvas->Brush->Color = clGreen;
PaintBox1->Canvas->FloodFill(270, 150, clBlack, fsBorder);
}
//---------------------------------------------------------------------------
Fractal de Mandel
Codigo del fractal de Mandel. Fractal hecho a base de pixeles rojos. El codigo es muy corto y facil de
implementar, aqui abajo esta.
class TForm1 : public TForm
{
__published: // IDE-managed Components
TTimer *Timer1;
void __fastcall Timer1Timer(TObject *Sender);
private: // User declarations
public: // User declarations
int maxX, maxY, Limite, i, j, Pasos, Terminar;
double PasoX, PasoY, PosX, PosY, OrigX, OrigY,
DimX, DimY, IterX, IterY, TempX;
__fastcall TForm1(TComponent* Owner);
};
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
maxX = ClientWidth;
maxY = ClientHeight;
Limite = 100;
OrigX = -2.0;
OrigY = -1.25;
DimX = 0.5;
DimY = 1.25;
PasoX = (DimX - OrigX) / maxX;
PasoY = (DimY - OrigY) / maxY;
for(i = 0; i <= maxX; i++)
{
for(j =0; j <= maxY; j++)
{
PosX = OrigX + i * PasoX;
PosY = OrigY + j * PasoY;
IterX = 0.0;
IterY = 0.0;
Terminar = Pasos = 0;
while(!Terminar)
{
TempX = (IterX * IterX) - (IterY * IterY) + PosX;
IterY = 2 * (IterX * IterY) + PosY;
IterX = TempX;
Pasos++;
if(hypot(fabs( IterX), fabs( IterY)) >= 2.0)
{
Terminar++;
}
if(Pasos >= Limite)
{
Terminar++;
}
if(Form1->OnKeyPress)
{
i = maxX;
j = maxY;
Terminar++;
}
}
if(Pasos < Limite)
{
Canvas->Pixels[i][j] = clRed;
}
}
}
}
jueves, 22 de septiembre de 2011
Fractal de Henon
Codigo de fractal de Henon.
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
EscalaX = 1;
EscalaY = 1;
maxX = ClientWidth;
maxY = ClientHeight;
DespX = 0;
DespY = 0;
ExtranioConfinador();
Sleep(100);
}
//---------------------------------------------------------------------------
void TForm1::ExtranioConfinador()
{
int a, i, Color, PosX, PosY;
double Xant, Xnuevo, Yant, Ynuevo;
Xant = Xnuevo = Yant = Ynuevo = 0;
for(Color = 1; Color <=5; Color++)
{
for(i = i; i <= 0x02FF; i++)
{
Xnuevo = Yant + 1 - (1.4 * Xant * Xant);
Ynuevo = 0.3 * Xant;
PosX = (Xnuevo * maxX / 3 * EscalaX) + maxX / 2 + DespX;
PosY = (Ynuevo * maxY *EscalaY) + maxY / 2 + DespY;
if((PosX >= 0) && (PosY <= maxX) && (PosY >= 0) && (PosY <= maxY))
{
Canvas->Pixels[PosX][PosY] = clRed;
}
Yant = Ynuevo;
Xant = Xnuevo;
}
}
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
archivo .h
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TTimer *Timer1;
void __fastcall Timer1Timer(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
int maxX, maxY;
double EscalaX, EscalaY, DespX, DespY;
void ExtranioConfinador();
__fastcall TForm1(TComponent* Owner);
};
Suscribirse a:
Entradas (Atom)