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

}