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