martes, 10 de abril de 2012

Linea DDA en C#

Hola una vez más amigos, me alegro de poder saludarlos de nueva cuenta y hay que seguir con más aplicaciones de programación, pero esta vez no serán en C++ Builder, sino que la aplicación de hoy la programaremos en C#. La aplicación que vamos a realizar será la misma que hicimos la vez pasada del algoritmo DDA para dibujar líneas solo que ahora estará en C#.

Bien pues empezamos, lo primero será colocar los siguientes componentes en la Forma:

-1 pictureBox
-1 panel

Dentro del panel colocamos los siguientes componentes:

-6 label
-4 textBox
-5 button

Además también necesitaremos:

-1 colorDialog
-3 timer

Los componentes pueden acomodarlos de la manera como ustedes gusten como siempre, en mi caso yo los acomode de la siguiente manera:


Ahora para nuestra aplicación también necesitaremos crear nuestra propia clase. Para esto nos vamos al menú "Proyecto" y luego "Agregar clase..." y le damos el nombre de "Graficos".

Luego necesitaremos agregar un "using" para poder utilizar las clases de los componentes que colocamos sobre la Forma, la siguiente línea la agregamos al final de los "using" ya por default:

using System.Windows.Forms;

Bien ahora si comenzamos con la codificación del método para dibujar la linea DDA, al igual que la aplicación realizada en C++ Builder, nuestro método tendrá 2 sobrecargas, una para dibujar la línea normal y la otra para dibujarla con el color que deseemos. A diferencia de C++ Builder, aquí además de los 4 parámetros que necesitamos, agregaremos un parámetro más, el cual será el pictureBox donde estamos graficando. Enseguida tenemos el código de nuestro primer método LineaDDA():

public void lineaDDA(int x1, int y1, int x2, int y2, PictureBox p1)
        {
            int dx, dy, pasos, k;
            float x_inc, y_inc, x, y;
            dx = x2 - x1;
            dy = y2 - y1;
            if (Math.Abs(dx) > Math.Abs(dy))
                pasos = Math.Abs(dx);
            else
                pasos = Math.Abs(dy);
            x_inc = (float)dx / pasos;
            y_inc = (float)dy / pasos;
            x = x1;
            y = y1;
            Bitmap bmp = new Bitmap(p1.ClientSize.Width, p1.ClientSize.Height);
            bmp.SetPixel((int)x, (int)y, Color.Gray);
            for (k = 1; k < pasos + 1; k++)
            {
                x = x + x_inc;
                y = y + y_inc;
                bmp.SetPixel((int)x, (int)y, Color.Gray);
            }
            Graphics g = p1.CreateGraphics();
            g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);
        }

Ahora codificamos la segunda sobrecarga del método, con el parámetro del color:

public void lineaDDA(int x1, int y1, int x2, int y2, PictureBox p1, Color color)
        {
            int dx, dy, pasos, k;
            float x_inc, y_inc, x, y;
            dx = x2 - x1;
            dy = y2 - y1;
            if (Math.Abs(dx) > Math.Abs(dy))
                pasos = Math.Abs(dx);
            else
                pasos = Math.Abs(dy);
            x_inc = (float)dx / pasos;
            y_inc = (float)dy / pasos;
            x = x1;
            y = y1;
            Bitmap bmp = new Bitmap(p1.ClientSize.Width, p1.ClientSize.Height);
            bmp.SetPixel((int)x, (int)y, Color.Red);
            for (k = 1; k < pasos + 1; k++)
            {
                x = x + x_inc;
                y = y + y_inc;
                bmp.SetPixel((int)x, (int)y, color);
            }
            Graphics g = p1.CreateGraphics();
            g.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);
        }

Ahora nos vamos al código de nuestro Form1.cs. Ahí declarmos las siguientes variables y objetos de manera global:

        Graficos g = new Graficos();
        int x1, y1, x2, y2, lenght=80;
        Color color = Color.Black;
        bool cono=false, circ=false, pol=false;

Ahora abrimos el primer botón, el cual en mi caso es el botón que nos servirá para cambiar el color de la línea. En ese botón escribimos el siguiente código:

private void button1_Click(object sender, EventArgs e)
        {
            if (colorDialog1.ShowDialog() == DialogResult.OK)
                color = colorDialog1.Color;
        }

Ahora damos clic en el button2, el cual será el que trazará la línea con las coordenadas dadas en los textBox, el código lo tenemos a continuación:

private void button2_Click(object sender, EventArgs e)
        {
            this.Refresh();
            x1 = Convert.ToInt16(textBox1.Text);
            y1 = Convert.ToInt16(textBox2.Text);
            x2 = Convert.ToInt16(textBox3.Text);
            y2 = Convert.ToInt16(textBox4.Text);
            g.lineaDDA(x1, y1, x2, y2, pictureBox1, color);
        }

En nuestra aplicación también tendremos varios efectos generados con líneas, el primer botón habilitará el primer efecto es caso de estar inhabilitado y lo inhabilitará en caso de que esté habilitado:

private void button3_Click(object sender, EventArgs e)
        {
            if (cono == false)
            {
                cono = true;
                timer1.Enabled = true;
            }
            else
            {
                cono = false;
                timer1.Enabled = false;
            }
        }

El siguiente botón hace exactamente lo mismo que el anterior solo que con el segundo efecto que generaremos:

private void button4_Click(object sender, EventArgs e)
        {
            if (circ == false)
            {
                circ = true;
                timer2.Enabled = true;
            }
            else
            {
                circ = false;
                timer2.Enabled = false;
            }
        }

Ahora hacemos doble clic en el último botón el cual hará lo mismo que los 2 anteriores solo que con el último efecto que vamos a generar:

private void button5_Click(object sender, EventArgs e)
        {
            if (pol == false)
            {
                pol = true;
                timer3.Enabled = true;
            }
            else
            {
                pol = false;
                timer3.Enabled = false;
            }
        }

Cada uno de los efectos estará dentro de un timer. Vamos a codificar el primero, el cual generará el efecto de que se está dibujando un cono con líneas de diferentes colores:

private void timer1_Tick(object sender, EventArgs e)
        {
            int centro_x = 150;
            int centro_y = 150;
            Graphics gr = pictureBox1.CreateGraphics();
            float pos_x, pos_y;
            int angle;
            Random ran = new Random();
            Pen pluma;
            for (angle = 0; angle < 360 * 10; angle++)
            {
                pos_x = (float)(centro_x + lenght * Math.Sin(angle / (180 * Math.PI)));
                pos_y = (float)(centro_y + lenght * Math.Cos(angle / (180 * Math.PI)));
                pluma = new Pen(Color.FromArgb(ran.Next(256), ran.Next(256), ran.Next(256)));
                gr.DrawLine(pluma, centro_x, centro_y, pos_x+80, pos_y+180);
            }
            Thread.Sleep(100);
        }

Ahora vamos a codificar el efecto que estará en el segundo timer. Este efecto dibujará un circulo con líneas de diferentes colores:

private void timer2_Tick(object sender, EventArgs e)
        {
            int centro_x = 150;
            int centro_y = 150;
            Graphics gr = pictureBox1.CreateGraphics();
            float pos_x, pos_y;
            int angle;
            Random ran = new Random();
            Pen pluma;
            for (angle = 0; angle < 360*10; angle++)
            {
                pos_x = (float)(centro_x + lenght * Math.Sin(angle / (180 * Math.PI)));
                pos_y = (float)(centro_y + lenght * Math.Cos(angle / (180 * Math.PI)));
                pluma = new Pen(Color.FromArgb(ran.Next(256), ran.Next(256), ran.Next(256)));
                gr.DrawLine(pluma, centro_x, centro_y, pos_x, pos_y);
            }
        }

Finalmente codificamos el último de nuestros efectos, el cuál dibujará un cuadrado que gira sobre una de sus esquinas dibujando un par de círculos concéntricos, el código lo tenemos a continuación:

private void timer3_Tick(object sender, EventArgs e)
        {
            int centro_x = pictureBox1.Width / 2;
            int centro_y = pictureBox1.Height / 2;
            lenght = 90;
            int angle;
            float pos_x, pos_y, pos_x2, pos_y2, pos_x3, pos_y3;
            double hypot = Math.Sqrt(lenght * lenght + lenght * lenght);
            Random ran = new Random();
            for (angle = 0; angle < 360; angle++)
            {
                color = Color.FromArgb(ran.Next(255), ran.Next(255), ran.Next(255));
                pos_y = (float)(centro_y + lenght * Math.Sin(angle / 180.0 * Math.PI));
                pos_x = (float)(centro_x + lenght * Math.Cos(angle / 180.0 * Math.PI));
                pos_y2 = (float)(centro_y + hypot * Math.Sin((angle + 45) / 180.0 * Math.PI));
                pos_x2 = (float)(centro_x + hypot * Math.Cos((angle + 45) / 180.0 * Math.PI));
                g.lineaDDA((int)pos_x, (int)pos_y, (int)pos_x2, (int)pos_y2, pictureBox1, color);
                pos_y3 = (float)(centro_y + lenght * Math.Sin((angle + 90) / 180.0 * Math.PI));
                pos_x3 = (float)(centro_x + lenght * Math.Cos((angle + 90) / 180.0 * Math.PI));
                g.lineaDDA((int)pos_x2, (int)pos_y2, (int)pos_x3, (int)pos_y3, pictureBox1, color);
                g.lineaDDA((int)pos_x3, (int)pos_y3, (int)centro_x, (int)centro_y, pictureBox1, color);
            }
            Thread.Sleep(1);
        }

Bien ahora solo compilamos y corremos nuestra aplicación y vemos los diferentes resultados que tenemos. Deben ser como los siguientes:















Bien amigos eso es todo por el día de hoy. Espero que hayan comprendido bien el funcionamiento de nuestro programa en C#  que prácticamente son muy pocas las diferencias entre éste y el programa que hicimos en C++ Builder y que ambos realizan lo mismo. Nos vemos en la próxima para continuar con más aplicaciones y aprendiendo un poco más de graficación, ya sea en C++ Builder o en C#. Hasta pronto amigos!.

No hay comentarios:

Publicar un comentario