domingo, 13 de noviembre de 2011

Traslacion


                


Con las posiciones coordenadas expresadas de formas homogeneas las ecuaciones de transformacion
basucan pueden representarse como multiplicaciones de matrices de transformacion. Abajo se
encuentra el codigo de la clase Matrix el cual se utiliza para multiplicacion de matrices asi como tambien
el metodo traslacion para mover el triangulo sobre los ejes.

class Matrix
{
   int col, ren;
   float **Mat;

public:
   Matrix();
   Matrix(Matrix &);
   Matrix::Matrix(int nr,int nc, float valor);
   Matrix::Matrix(double nr,double nc, float m[][3]);
   ~Matrix();
   void SETM(int R, int C, float val){Mat[R][C]=val;}
   float GETM(int R, int C){return Mat[R][C];}
   int numCol(){return col;}
   int numRen(){return ren;}
   void Inicializa(int, int);
   Matrix &operator *=(Matrix &mat2);
   Matrix operator*(float);//Multiplicar por un escalar
   //Matrix & operator =(Matrix &mat2);
   Matrix &operator=(Matrix &m);
   Matrix & asignar(Matrix);
   Matrix & Identidad();

   //transformaciones
   Matrix & traslacion(Matrix,Matrix,int Tx ,int);
   Matrix & escalacion(Matrix,Matrix,float,float);
   Matrix & escalacion_puntof(Matrix,Matrix,float,float,int,int);
   Matrix & rotacion(Matrix,Matrix,float);
   Matrix & rotacion_pivote(Matrix,Matrix,float,float,float);
   Matrix & reflexion_con_X(Matrix,Matrix);
   Matrix & reflexion_con_Y(Matrix f,Matrix id);
   Matrix & reflexion_eje_coord(Matrix f,Matrix id);
   Matrix & reflexion_yigualx(Matrix f,Matrix id);
   Matrix & reflexion_yigualmenosx(Matrix f,Matrix id);
   Matrix & tijera_x(Matrix f, Matrix id, float Shx);
   Matrix & tijera_y(Matrix f, Matrix id, float Shy);
};

Matrix::Matrix()
{
   Mat = NULL;
}

/*
Matriz<T>::Matriz(const Matriz<T> &m)
{
  n_ren = m.n_ren;
  n_col = m.n_col;
  mat = new T*[n_ren];
  assert(mat);
  for(int i = 0; i < n_ren; i++)
  {
     mat[i] = new T[n_col];
     assert(mat[i]);
  }
  for( int i =0; i < n_ren; i++)
    for(int j = 0; j < n_col; j++)
        mat[i][j] = m.mat[i][j];
}
*/
Matrix::Matrix(Matrix &m)
{
   ren=m.numRen();
   col=m.numCol();
   Mat =new float*[ren];
   for(int i = 0; i < ren; i++)
  {
     Mat[i] = new float[col];
     assert(Mat[i]);
  }
   for(int i=0; i<ren; i++)
      for( int j=0; j<col; j++)
         Mat[i][j]=m.GETM(i,j);
}
Matrix::Matrix(int nr,int nc, float valor)
{
  ren = nr;
  col = nc;
  Mat = new float*[ren];
  assert(Mat);
  for(int i = 0; i < ren; i++)
  {
      Mat[i] = new float[col];
      assert(Mat[i]);
  }

  for(int i = 0; i < ren; i++)
    for(int j = 0; j < col; j++)
        Mat[i][j] = valor;
}



Matrix::Matrix(double nr,double nc, float m[][3])
{
  ren = nr;
  col = nc;
  Mat = new float*[ren];
  assert(Mat);
  for(int i = 0; i < ren; i++)
  {
      Mat[i] = new float[col];
      assert(Mat[i]);
  }
  for(int i = 0; i < ren; i++)
    for(int j = 0; j < col; j++)
        Mat[i][j] = m[i][j];
}

void Matrix::Inicializa(int R, int C)
{
   col=C;
   ren=R;
   Mat=new float *[ren];
   for(int i=0; i<ren; i++)
      Mat[i]=new float[col];
   for(int i=0; i<ren; i++)
      for(int j=0; j<col; j++)
         Mat[i][j]=0;
}

Matrix &Matrix::operator*=(Matrix &mat2)
{
   Matrix aux;
   aux.Inicializa(ren, mat2.numCol());


   for(int i=0; i<ren; i++)
   {
      for(int j=0; j<mat2.numCol(); j++)
      {
         float suma=0;
        // Mat[i][j]=0;
         for(int k=0; k<col; k++)
         {
           suma+=floor(Mat[i][k]*mat2.GETM(k,j)+0.5);
           aux.SETM(i,j,suma);
         }
         //aux.SETM(i,j,suma);
      }
   }
   asignar(aux);
   return *this;
}

Matrix Matrix::operator*(float val)
{
   Matrix temp;
   temp.Inicializa(ren,col);
   for(int i=0; i<ren;i++)
      for(int j=0; j<col; j++)
         temp.SETM(i,j,Mat[i][j]* val);
   return temp;
}


Matrix &Matrix::operator=(Matrix &m)
{
//eliminar el tamaño de la matriz destino
  for(int i= 0; i<ren;i++ )
     //Se borran los renglones de la matriz
       delete [] Mat[i];
  //Se borra el arreglo de punteros
  delete []Mat;
//Asignar los nuevos datos de la matriz que llego
  ren=m.numRen();
  col = m.numCol();
  Mat = new float*[ren];
  assert(Mat);
  for(int i = 0; i < ren; i++)
  {
     Mat[i] = new float[col];
     assert(Mat[i]);
  }
  for( int i =0; i < ren; i++)
    for(int j = 0; j < col; j++)
        Mat[i][j] = m.Mat[i][j];

  return *this;
}
/*Matrix &Matrix::operator =(Matrix &mat2)
{
    ren=mat2.numRen();
    col=mat2.numCol();
    for(int i=0;i<ren;i++)
       for(int j=0;j<col;j++)
          Mat[i][j]=mat2.GETM(i,j);
    return *this;
} */

Matrix &Matrix::asignar(Matrix m)
{
   for(int i=0;i<m.numRen();i++)
       for(int j=0;j<m.numCol();j++)
                Mat[i][j]=m.GETM(i,j);
   return *this;
}

Matrix::~Matrix()
{
  //Se libera la memoria
  for(int i= 0; i<ren;i++ )
     //Se borran los renglones de la matriz
       delete [] Mat[i];
  //Se borra el arreglo de punteros
  delete []Mat;

}

Matrix &Matrix::Identidad()
{
  for(int i=0; i < ren; i++)
    for( int j = 0; j < col; j++)
      if( i == j)
         Mat[i][i]= 1;
      else
         Mat[i][j]= 0;
  return *this;
}

//---------------TRANSFORMACIONES-----------------------------
Matrix & Matrix::traslacion(Matrix f,Matrix id,int tx,int ty)
{
   id.Identidad();
   id.SETM(2,0,tx);
   id.SETM(2,1,ty);
   f*=id;
   this->asignar(f);
   return *this;
}

Matrix & Matrix::escalacion(Matrix f,Matrix id,float sx,float sy)
{
   id.Identidad();

   id.SETM(0,0,sx);
   id.SETM(1,1,sy);

   f *= id;

   asignar(f);
   return *this;

}

Matrix & Matrix::escalacion_puntof(Matrix f,Matrix id, float sx, float sy, int tx ,int ty)
{
   id.Identidad();

   float res1 = -tx*(sx-1);
   float res2 = -ty*(sy-1);
   id.SETM(0,0,sx);
   id.SETM(1,1,sy);
   id.SETM(2,0,res1);
   id.SETM(2,1,res2);

   f*=id;

   asignar(f);
   return *this;
}

Matrix & Matrix::rotacion(Matrix f,Matrix id,float angulo)
{
   id.Identidad();
   float ang = angulo*M_PI/180.0;

   id.SETM(0,0,cos(ang));
   id.SETM(0,1,sin(ang));
   id.SETM(1,0,-sin(ang));
   id.SETM(1,1,cos(ang));

   f*=id;

   asignar(f);
   return *this;

}

Matrix &Matrix:: rotacion_pivote(Matrix f,Matrix id,float M,float N,float angulo)
{
   id.Identidad();
   float ang = angulo*M_PI/180.0;
   float r20= -M*(cos(ang)-1)+N*sin(ang);
   float r21= -N*(cos(ang)-1)-M*sin(ang);

   id.SETM(0,0,cos(ang));
   id.SETM(0,1,sin(ang));
   id.SETM(1,0,-sin(ang));
   id.SETM(1,1,cos(ang));
   id.SETM(2,0,r20);
   id.SETM(2,1,r21);
   
   f*=id;

   asignar(f);
   return *this;

}

Matrix & Matrix::reflexion_con_X(Matrix f,Matrix id)
{
   id.Identidad();
   id.SETM(1,1,-1);
   f*=id;
   asignar(f);
   return *this;
}

Matrix & Matrix::reflexion_con_Y(Matrix f,Matrix id)
{
   id.Identidad();
   id.SETM(0,0,-1);
   f*=id;
   asignar(f);
   return *this;
}

Matrix & Matrix::reflexion_eje_coord(Matrix f,Matrix id)
{
   id.Identidad();
   id.SETM(0,0,-1);
   id.SETM(1,1,-1);
   f*=id;
   asignar(f);
   return *this;
}

Matrix & Matrix::reflexion_yigualx(Matrix f,Matrix id)
{
   id.Identidad();
   id.SETM(0,1,1);
   id.SETM(1,0,1);
   id.SETM(0,0,0);
   id.SETM(1,1,0);
   f*=id;
   asignar(f);
   return *this;
}

Matrix & Matrix::reflexion_yigualmenosx(Matrix f,Matrix id)
{
   id.Identidad();
   id.SETM(0,1,-1);
   id.SETM(1,0,-1);
   id.SETM(0,0,0);
   id.SETM(1,1,0);
   f*=id;
   asignar(f);
   return *this;
}

Matrix & Matrix::tijera_x(Matrix f, Matrix id, float Shx)
{
   id.Identidad();
   id.SETM(1,0,Shx);

   f*=id;
   asignar(f);
   return *this;
}

Matrix & Matrix::tijera_y(Matrix f, Matrix id, float Shy)
{
   id.Identidad();
   id.SETM(0,1,Shy);

   f*=id;
   asignar(f);
   return *this;
}

void __fastcall TForm1::FormPaint(TObject *Sender)
{    
    // Linea horizontal
    Canvas->MoveTo(0, Form1->ClientHeight/2);
    Canvas->LineTo((Form1->Width - PageControl1->Width), Form1->ClientHeight/2);

    // Linea vertical
    Canvas->MoveTo((Form1->ClientWidth - PageControl1->Width)/2, 0);
    Canvas->LineTo((Form1->ClientWidth - PageControl1->Width)/2 , Form1->ClientHeight);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Form1->Refresh();
    int ancho = PageControl1->Width;
    int L = (Form1->ClientWidth-ancho)/2;
    int M = Form1->ClientHeight/2;

    Fig[0][0]= 10; Fig[0][1]= 10; Fig[0][2]= 1;
    Fig[1][0]= 30; Fig[1][1]= 10; Fig[1][2]= 1;
    Fig[2][0]= 10; Fig[2][1]= 30; Fig[2][2]= 1;
    Fig[3][0]= 10; Fig[3][1]= 10; Fig[3][2]= 1;

    for(int i = 0; i< 4; i++)
    {
      for(int j = 0; j < 3; j++)
      {
         FigAux[i][j] = Fig[i][j];
      }
    }

    UnidadII obj;

    obj.ventana((Form1->ClientWidth-ancho)/2,0,(Form1->ClientWidth-ancho),Form1->ClientHeight/2);
    obj.puerto((Form1->ClientWidth-ancho)/2,0,(Form1->ClientWidth-ancho),Form1->ClientHeight/2);

    int x,y;

    obj.mapeo(Fig[0][0], Fig[0][1], x, y, L, M);
    Canvas->MoveTo(x,y);

    for(int i=0; i< 4; i++)
    {
       obj.mapeo(Fig[i][0],Fig[i][1], x, y, L, M);
       Canvas->LineTo(x, y);
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
    Form1->Refresh();

    int ancho = PageControl1->Width;
    int tx = Edit1->Text.ToIntDef(0);
    int ty = Edit2->Text.ToIntDef(0);

    Matrix fig, tras, fres;

    fig.Inicializa(4, 3);
    tras.Inicializa(3, 3);
    fres.Inicializa(4, 3);

    for(int i =0; i < fig.numRen(); i++)
    {
       for(int j = 0; j < fig.numCol(); j++)
       {
          fig.SETM(i, j, Fig[i][j]);
       }
    }

   fres.traslacion(fig, tras, tx, ty);

   int L = (Form1->ClientWidth - ancho)/2;
   int M = Form1->ClientHeight/2;

   UnidadII obj;

    obj.ventana((Form1->ClientWidth-ancho)/2,0,(Form1->ClientWidth-ancho),Form1->ClientHeight/2);
    obj.puerto((Form1->ClientWidth-ancho)/2,0,(Form1->ClientWidth-ancho),Form1->ClientHeight/2);

    int x, y;

    obj.mapeo(fres.GETM(0,0), fres.GETM(0,1), x, y, L, M);
    PaintBox1->Canvas->MoveTo(x, y);

    for(int i =0; i < fres.numRen(); i++)
    {
       obj.mapeo(fres.GETM(i,0), fres.GETM(i,1), x, y, L, M);
       PaintBox1->Canvas->LineTo(x, y);
    }

    for(int i = 0; i < fres.numRen(); i++)  // pasar la figura resultante a la figura original
    {
       for(int j = 0; j <fres.numCol(); j++)
       {
          Fig[i][j]=fres.GETM(i,j);
       }
    }

}




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

Fractal del Dragon


En la imagen se ve el proceso que va tomando el codigo de este fractal. Abajo el codigo.



void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
        int i;
        Paso = 4096;
        Signo = -1;

        EjeX[1] = ClientWidth / 4;      //getmax
        EjeX[4097] = 3 * ClientWidth / 4;
        EjeY[1] = EjeY[4097] = 2 * ClientHeight / 3;
        randomize();

        Canvas->MoveTo(EjeX[1], EjeY[1]);
        Canvas->LineTo(EjeX[4097], EjeY[4097]);
       
        Sleep(1000);

        for(i = 1; i <= 13; i++)
        {
           //Repaint();
           Refresh();
           Canvas->TextOutA(5,5,"Curva fractal del dragon");
           GenerarDragon(TColor(RGB(random(256), 0 ,0)));
           Paso /= 2;
           Sleep(1000);
         
        }
        ///Sleep(10);
}
//---------------------------------------------------------------------------
 void TForm1::GenerarDragon(TColor color)
 {

        int i, j, dx, dy;
        j = Paso /2;

        Canvas->Pen->Color = color;
        Sleep(1000);

        for(i = 1; i <= 4096; i += Paso)
        {
            dx = EjeX[Paso + i] - EjeX[i];
            dy = EjeY[Paso + i] - EjeY[i];
           
            Signo *= -1;
            EjeX[i + j] = EjeX[i] + (dx + (dy * Signo)) / 2;
            EjeY[i + j] = EjeY[i] + (dy - (dx * Signo)) / 2;

            Canvas->MoveTo(EjeX[i], EjeY[i]);
            Canvas->LineTo(EjeX[i + j], EjeY[i + j]);

            Canvas->MoveTo(EjeX[i + j], EjeY[i + j]);
            Canvas->LineTo(EjeX[i + Paso], EjeY[i + Paso]);
            Sleep(100);
        }

 }
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
        Timer1->Enabled = false;      
}
//---------------------------------------------------------------------------




 abajo archivo .h

class TForm1 : public TForm
{
__published: // IDE-managed Components
        TTimer *Timer1;
        TButton *Button1;
        TButton *Button2;
        void __fastcall Timer1Timer(TObject *Sender);
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall Button2Click(TObject *Sender);
private:       // User declarations

void GenerarDragon(TColor color);
int EjeX[4098], EjeY[4098], Paso, Signo;

public: // User declarations

        __fastcall TForm1(TComponent* Owner);
};

domingo, 18 de septiembre de 2011

Fractal de Newton-Raphson





//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

//Fractal de Newton-Raphson

//#include <windows.h>

//--- Declaración de funciones del programa ------------------------------
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int );
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
void CrearPaleta(void);


//--- Declaración de variables del programa ------------------------------
char WindowName[]  = "Ventana de Windows";
char WindowTitle[] = "Fractal de Newton-Raphson";
BYTE ColorRGB[256][3];

void CrearPaleta(void)
{
int i;

for (i=0; i<256; i++)
{
if (i<64)
{
ColorRGB[i][0] = 192 + i;
ColorRGB[i][1] = 0;
ColorRGB[i][2] = 0;
}
else if ((i>63) && (i<128))
{
ColorRGB[i][0] = 0;
ColorRGB[i][1] = (192 + i)-64;
ColorRGB[i][2] = 0;
}
else if ((i>127)&&(i<192))
{
ColorRGB[i][0] = 0;
ColorRGB[i][1] = 0;
ColorRGB[i][2] = (192 + i)-128;
}
}
}


//=== Función principal WinMain() ========================================
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
   LPSTR lpCmdLine, int nCmdShow )
{
HWND hwnd;                              // handle a la ventana ppal.
MSG msg;                                // estructura de mensaje
WNDCLASSEX wcx;                         // estructura de la ventana

// Definimos la estructura de clase de ventana (campos):
wcx.cbSize = sizeof( WNDCLASSEX );      // tamaño de la estructura
wcx.style = CS_HREDRAW | CS_VREDRAW;    // valores más usuales
wcx.lpfnWndProc = WndProc;              // función de ventana (Wnd)
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;                     // informaciones extra
wcx.hInstance = hInstance;              // instancia actual

// icono, cursor, fondo e icono pequeño de la clase de ventana:
wcx.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH );
    wcx.hIconSm = LoadIcon(NULL, IDI_WINLOGO);

wcx.lpszMenuName = NULL;                // nombre del menú
wcx.lpszClassName = WindowName;         // nombre de la ventana

// Registramos la clase de ventana ya preparada:
if( !RegisterClassEx( &wcx ) )
return( FALSE );                    // en caso de error, salir

// Creamos la ventana con CreateWindowEx():
hwnd = CreateWindowEx(
WS_EX_OVERLAPPEDWINDOW,             // estilo extendido
WindowName,                         // nombre de la ventana
WindowTitle,                        // título de la ventana
WS_OVERLAPPEDWINDOW,                // estilo de ventana
CW_USEDEFAULT, CW_USEDEFAULT,       // Posición (x,y) en pantalla
400, 400,                           // ancho y alto de la ventana
NULL, NULL,                         // ventana padre e hija+menú
hInstance,                          // instancia actual
NULL                                // no hay más información
                );

// Comprobamos la creación de la ventana:
if( !hwnd )
return( FALSE );                    // en caso de error, salir

// Hacemos visible la ventana y la actualizamos:
ShowWindow( hwnd, nCmdShow );
UpdateWindow( hwnd );

// Bucle de mensajes, envía los mensajes hacia WndProc
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );           // convertimos el mensaje
DispatchMessage( &msg );            // devolvemos el control a w95
}

// devolvemos el valor recibido por PostQuitMessage().
return( msg.wParam );
}


//=== Función del procedimiento de ventana WndProc() =====================
LRESULT CALLBACK WndProc( HWND hwnd, UINT message,
 WPARAM wParam, LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
BYTE R, G, B;

double deltax, deltay, x, y, tmp, xx, yy, d;
float  xmin = -2.0, ymin=-2.0, xmax=2.0, ymax=2.0;
int maxiter = 2048;
int maxcol, maxrow;
int color, row, col, count;

  switch( message )
{
// mensaje producido en la creación de la ventana
case WM_CREATE:
  break;
        //dibuja el fractal de Newton-Raphson
case WM_PAINT:
CrearPaleta();
hdc = BeginPaint( hwnd, &ps );
GetClientRect(hwnd, &rect);

                                maxcol =  rect.right - rect.left ;
maxrow =  rect.bottom - rect.top;

deltax = (xmax - xmin)/maxcol;
deltay = (ymax - ymin)/maxrow;
for (col=0; col<=maxcol; col++)
{
for (row=0; row<=maxrow; row++)
{
x = xmin + col * deltax;
y = ymin + row * deltay;
count=0;
while (count<maxiter)
{
xx = x*x;
yy = y*y;
d = 3.0*((xx - yy)*(xx - yy) + 4.0*xx*yy);
if (d == 0.0)
d = 0.000001;
tmp=x;
x = (2.0/3.0)*x + (xx - yy)/d;
y = (2.0/3.0)*y - 2.0*tmp*y/d;
count+=1;
}
if (x>0.0)
color = count%64;
else
{
if ((x<-0.3) && (y>0.0))
color = (count%64) + 64;
else
color = (count%64) + 128;
}
   R=ColorRGB[color][0];
G=ColorRGB[color][1];
B=ColorRGB[color][2];
SetPixel(hdc, col, row, RGB(R,G,B));
}
}
EndPaint( hwnd, &ps );
break;

// mensaje producido al cerrar la ventana
case WM_DESTROY:
PostQuitMessage( 0 );
break;

// resto de mensajes, dar una respuesta estándar.
default:
return( DefWindowProc( hwnd, message, wParam, lParam ) );
}
return(0);
}

//=== Fin del archivo ====================================================---------------------------------------------------------------------

Como hacer zoom en una imagen bmp en c++


Codigo para hacer zoom en una imagen. El codigo es corto y facil. 




void __fastcall TForm1::Image1MouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
        x1 = X;         // coordenadas del click
        y1 = Y;        
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1MouseUp(TObject *Sender, TMouseButton Button,
      TShiftState Shift, int X, int Y)
{
         x2 = X;       // coordenadas cuando se suelta el click del mouse
         y2 = Y;

         TRect origen, destino;
         
         origen = Rect(x1, y1, x2, y2);  // area del rectangulo donde quiero hacer zoom

         destino = Rect(0, 0, Image2->Width, Image2->Height); // rectangulo donde se va a copiar

         Image2->Canvas->CopyRect(destino, Image1->Canvas, origen);  // zoom de la imagen
}
//---------------------------------------------------------------------------

domingo, 11 de septiembre de 2011

Manipulacion de pixeles en una imagen bmp


En este programa aprendimos como manejar la matriz de pixeles usando la mascara para el corrimiento de
los bits y asi poder cambiar el color de la imagen ya sea rojo, verde o azul. Tambien utilizamos la matriz
de pixeles para cambiar la posicion de la imagen. Abajo esta el codigo.


void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{

        TColor color;

        for(int y = 0; y < Image1->Height; y++)
        {
           for(int x = 0; x < Image1->Width; x++)
           {
              color = Image1->Canvas->Pixels[x][y];
              color = color & 255;

              Image2->Canvas->Pixels[x][y] = color;
           }
        }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BitBtn2Click(TObject *Sender)
{
        TColor color;
        int mascara = 255;

        mascara = mascara << 8;

        for(int y = 0; y < Image1->Height; y++)
        {
           for(int x = 0; x < Image1->Width; x++)
           {
              color = Image1->Canvas->Pixels[x][y];
              color = color + mascara;

              Image2->Canvas->Pixels[x][y] = color;
           }
        }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BitBtn3Click(TObject *Sender)
{
        TColor color;
        int mascara = 255;

        mascara = mascara << 16;

        for(int y = 0; y < Image1->Height; y++)
        {
           for(int x = 0; x < Image1->Width; x++)
           {
              color = Image1->Canvas->Pixels[x][y];
              color = color + mascara;

              Image2->Canvas->Pixels[x][y] = color;
           }
        }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        //Image3->Picture->LoadFromFile("santos laguna.bmp");
        //Image3->Height = Image2-> Width - 3;
        //Image3->Width = Image2-> Height - 3;
        TColor color;

        for(int x = 0; x < Image1->Width; x++)
        {
           for(int y = 0; y < Image1->Height; y++)
           {
             color = Image1->Canvas->Pixels[x][y];
             Image3->Canvas->Pixels[Image1->Width - x][y] = color;
           }
        }


}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
        TColor color;

        for(int x = 0; x < Image1->Width; x++)
        {
           for(int y = 0; y < Image1->Height; y++)
           {
             color = Image1->Canvas->Pixels[x][y];
             Image2->Canvas->Pixels[x][y] = color;
           }
        }

}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)
{
        TColor color;

        for(int x = 0; x < Image1->Width; x++)
        {
           for(int y = 0; y < Image1->Height; y++)
           {
             color = Image1->Canvas->Pixels[x][y];
             Image3->Canvas->Pixels[Image1->Width - x][Image1->Height - y] = color;
           }
        }
}
//---------------------------------------------------------------------------