S.E.P.
D.G.E.S.T.
D.I.T.D.
INSTITUTO TECNOLÓGICO SUPERIOR DE LIBRES Organismo Público Descentralizado del Gobierno del Estado de Puebla
INGENIERÍA EN SISTEMAS COMPUTACIONALES
“GRAFICACIÓN”
PRACTICA 3 “EJECUCIÓN DEL ALGORITMO DDA”
PRESENTA:
BONILLA GONZALEZ PABLO SÁNCHEZ BRISEÑO EVELIN ALEJANDRA LIBRES, PUEBLA, FEBRERO 2012
1.- Algoritmo de Línea DDA El analizador diferenciador digital (DDA - Digital Diferencial Analyzer) es un algoritmo de conversión de rastreo que se basa en el calculo ya sea de Dy o Dx por medio de ecuaciones. Se efectúa un muestreo de la línea en intervalos unitarios en una coordenada y se determina los valores enteros correspondientes mas próximos a la trayectoria de la línea para la otra coordenada. Tomemos una línea con pendiente positiva, si la pendiente | m | £ 1, se hace el muestreo en x en intervalos unitarios (Dx = 1 y Dy = m dado que m = Dy / Dx) y se calcula cada valor sucesivo de y como: yk+1 = yk+ m El subíndice toma valores enteros a partir de 1 y aumenta a razón de 1 hasta alcanzar el valor final. Ya que m puede ser cualquier numero real entre 0 y 1, los valores calculados de y deben redondearse al entero mas cercano. Para líneas con una pendiente | m | > 1, se revierten las funciones de x y y, o sea, se realiza un muestreo de y en intervalos unitarios (Dy = 1 y Dx = 1/m dado que m = Dy / Dx) y se calcula cada valor sucesivo de x como: xk+1 = xk+ 1/m Las ecuaciones anteriores se basan en la suposición de que las líneas deben procesarse del extremo izquierdo al derecho. Si este procesamiento se revierte, entonces Dx o Dy serian -1,yk+1 = yk - m o xk+1 = xk - 1/m(x I ,round(y I )) (xi ,y I ) (xi+1,round(y i+m)) (xi+1,y i+m) línea Deseada Dx Dy El procedimiento completo de dibujo seria el siguiente: void Line(Display* display, Window win, GC gc, int x0, int y0, int x1, int y1) { float x, y, xs, ys; int dx, dy, steps; dx = x1 - x0; dy = y1 - y0; /* se asigna el punto de donde se comenzara a dibujar la línea */ x = x0;
y = y0; /* verificar si la pendiente es mayor de x o y, para luego asignarla a steps */ if (abs(dx) > abs(dy)) steps = abs(dx); else steps = abs(dy); /* se divide por la pendiente mayor, para dar xs o ys igual a 1 (o -1) */Alfredo Weitzenfeld
Gráfica: Línea
3
if (steps == 0) { XDrawPoint(display,win,gc,round(x),round(y)); fprintf(stderr,”this line is a point”); return; } xs = dx/steps; ys = dy/steps; /* se cicla uno a la vez hasta llegar al numero de steps máximo */ for (i = 0; i <= steps; i++) { XDrawPoint(display,win,gc,round(x),round(y)); /* round(x) -> x+0.5 */ x = x + xs; y = y + ys; } } El problema con este algoritmo es que se debe redondear números flotantes a enteros y hacer operaciones sobre números flotantes, lo cual toma tiempo. Para líneas largas, la acumulación de errores de redondeo en adiciones sucesivas del incremento de punto flotante puede provocar que las posiciones del pixel calculadas se desvíen de la trayectoria real de la línea. Se puede mejorar el desempeño del algoritmo al separar los incrementos m y 1/m en partes enteras y fraccionarias, de forma que todos los cálculos se reduzcan a operaciones de enteros. [1]
2 INSTALACIÓN DE TAO FRAMEWORK Se copea el archivo Freeglut.dll de la carpeta lib del Tao Framework y se pega en C:\Windows\system. Posteriormente se ejecuta una aplicación en consola con el lenguaje C# de Visual Studio.Net y se agregan las referencia de las librería Tao.FreeGlut y Tao.OpenGl, como ultimo paso importamos las librerias a nuestro aplicación, como se muestra a continuacion: using Tao.FreeGlut; using Tao.OpenGl;
A continuación se muestra el código fuente de la aplicación trazando una línea Ejercicio 1 Línea Código: using using using using using using
System; System.Collections.Generic; System.Linq; System.Text; Tao.FreeGlut; Tao.OpenGl;
namespace ConsoleApplication1 { class Program { static double x1, y1, x2, y2; static void Main(string[] args) { Console.WriteLine("introduzca el valor de X1"); x1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de Y1"); y1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de X2"); x2 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de Y2"); y2 = Convert.ToDouble(Console.ReadLine()); Glut.glutInit();//funciones propias de opengl Glut.glutInitDisplayMode(Glut.GLUT_SINGLE | Glut.GLUT_RGB); Glut.glutInitWindowSize(640, 480);//creamos una ventana Glut.glutCreateWindow("**************Algoritmo DDA**************");//colocamos titulo a la ventana //llamamos a la funcion dda Glut.glutDisplayFunc(dda); Glut.glutMainLoop();
} public static void dda() { //componentes necesarios de opengl Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);//limpia el buffer de la pantall Gl.glColor3f(0.6F, 0.6F, 0.6F);//poner color a los pixeles Gl.glLoadIdentity();//''muy importante; Gl.glPointSize(2.0f);//medida de los puntos Gl.glBegin(Gl.GL_POINTS);//funcion para dibujar puntos //dibujando el plano float z = -1, w = 1, c = 0; for (int i = 0; i < 200; i++) { Gl.glColor3f(w, c, z); Gl.glVertex2d(z, 0); Gl.glVertex2d(0, w); z += .01f; w -= .01f; c += .1f; } Gl.glEnd();//termina funcion para dibujar puntos ///pasamos las Gl.glPointSize(5.0f);//sirve para el tama単o de los pixeles Gl.glColor3f(0.6f, 1.0f, 0.6f);//sirve para el color de los pixeles ddaDibujar(x1, y1, x2, y2); } public static void ddaDibujar(double x1, double y1, double x2, double y2) { double xinicial = x1, yinicial = y1, xfinal = x2, yfinal = y2, x, y; double deltax, deltay, xincremento, yincremento; double pasos; deltax = xfinal - xinicial; deltay = yfinal - yinicial; if (Math.Abs(deltax) > Math.Abs(deltay)) pasos = Math.Abs(deltax); else pasos = Math.Abs(deltay); xincremento = (deltax / pasos) / 10; yincremento = (deltay / pasos) / 10; x = xinicial; y = yinicial; Gl.glBegin(Gl.GL_POINTS); Gl.glVertex2d(x, y);//funcion que pinta un pixel en las coordenadas especificadas for (double k = .1; k <= pasos; k += .1) { x = (x + xincremento); y = (y + yincremento); Gl.glVertex2d(x, y); } Gl.glEnd(); //termina dda }
} }
La aplicaciĂłn debera quedar de la siguiente manera:
Figura 1. Pantalla para introducir coordenadas iniciales y finales para la lĂnea.
Figura 2. LĂnea dibujada en las coordenas respectivas.
Figura 3. Xinicial= -0.5, Yinicial=-0.7, Xfinal=.5, Yfinal=.7.
Figura 4. Xinicial= 0.3, Yinicial=0.3, Xfinal=1, Yfinal=1.
EJERCICIO 1 LINEA PUNTEADA: Realizar una aplicaci贸n que dibuje una l铆nea punteada con ayuda del algoritmo DDA en Visual Studio.net con el lenguaje C#. using using using using using using
System; System.Collections.Generic; System.Linq; System.Text; Tao.FreeGlut; Tao.OpenGl;
namespace ConsoleApplication1 { class Program { static double x1, y1, x2, y2; static void Main(string[] args) { Console.WriteLine("introduzca el valor de X1"); x1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de Y1"); y1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de X2"); x2 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de Y2"); y2 = Convert.ToDouble(Console.ReadLine()); Glut.glutInit();//funciones propias de opengl Glut.glutInitDisplayMode(Glut.GLUT_SINGLE | Glut.GLUT_RGB); Glut.glutInitWindowSize(640, 480);//creamos una ventana Glut.glutCreateWindow("**************Algoritmo DDA**************");//colocamos titulo a la ventana //llamamos a la funcion dda Glut.glutDisplayFunc(dda); Glut.glutMainLoop(); } public static void dda() { //componentes necesarios de opengl Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);//limpia el buffer de la pantall Gl.glColor3f(0.6F, 0.6F, 0.6F);//poner color a los pixeles Gl.glLoadIdentity();//''muy importante; Gl.glPointSize(2.0f);//medida de los puntos Gl.glBegin(Gl.GL_POINTS);//funcion para dibujar puntos //dibujando el plano float z = -1, w = 1, c = 0; for (int i = 0; i < 200; i++) { Gl.glColor3f(w, c, z); Gl.glVertex2d(z, 0); Gl.glVertex2d(0, w); z += .01f;
w -= .01f; c += .1f; } Gl.glEnd();//termina funcion para dibujar puntos ///pasamos las Gl.glPointSize(5.0f);//sirve para el tama単o de los pixeles Gl.glColor3f(0.6f, 1.0f, 0.6f);//sirve para el color de los pixeles ddaDibujar(x1, y1, x2, y2); } public static void ddaDibujar(double x1, double y1, double x2, double y2) { double xinicial = x1, yinicial = y1, xfinal = x2, yfinal = y2, x, y; double deltax, deltay, xincremento, yincremento; double pasos; deltax = xfinal - xinicial; deltay = yfinal - yinicial; if (Math.Abs(deltax) > Math.Abs(deltay)) pasos = Math.Abs(deltax); else pasos = Math.Abs(deltay); xincremento = (deltax / pasos) / 5; yincremento = (deltay / pasos) / 5; x = xinicial; y = yinicial; Gl.glBegin(Gl.GL_POINTS); Gl.glVertex2d(x, y);//funcion que pinta un pixel en las coordenadas especificadas for (double k = .1; k <= pasos; k += .1) { x = (x + xincremento); y = (y + yincremento); Gl.glVertex2d(x, y); } Gl.glEnd(); //termina dda } } }
Figura.5 Coordenadas para lĂnea punteada
Figura 6 LĂnea punteada
EJERCICIO 2 Realizar una aplicaci贸n que dibuje una l铆nea mas gruesa que la anterior con ayuda del algoritmo DDA en Visual Studio.net con el lenguaje C#. using using using using using using
System; System.Collections.Generic; System.Linq; System.Text; Tao.FreeGlut; Tao.OpenGl;
namespace ConsoleApplication1 { class Program { static double x1, y1, x2, y2; static void Main(string[] args) { Console.WriteLine("introduzca el valor de X1 x1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de Y1 y1 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de X2 x2 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("introduzca el valor de Y2 y2 = Convert.ToDouble(Console.ReadLine());
INICIAL"); INICIAL"); INICIAL"); INICIAL");
Glut.glutInit();//funciones propias de opengl Glut.glutInitDisplayMode(Glut.GLUT_SINGLE Glut.GLUT_RGB); Glut.glutInitWindowSize(1200, 780);//creamos una ventana Glut.glutCreateWindow("**************Algoritmo DDA con grosor mas grande **************");//colocamos titulo a la ventana //llamamos a la funcion dda Glut.glutDisplayFunc(dda); Glut.glutMainLoop(); } public static void dda() { //componentes necesarios de opengl Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);//limpia el buffer de la pantall Gl.glColor3f(0.3F, 0.3F, 0.3F);//poner color a los pixeles Gl.glLoadIdentity();//''muy importante; Gl.glPointSize(5.0f);//medida de los puntos Gl.glBegin(Gl.GL_POINTS);//funcion para dibujar puntos //dibujando el plano float z = -1, w = 1, c = 1; for (int i = 0; i < 200; i++) {
Gl.glColor3f(w, c, z); Gl.glVertex2d(z, 0); Gl.glVertex2d(0, w); z += .01f; w -= .01f; c += .1f; } Gl.glEnd();//termina funcion para dibujar puntos ///pasamos las Gl.glPointSize(5.0f);//sirve para el tama単o de los pixeles Gl.glColor3f(0.6f, 1.0f, 0.6f);//sirve para el color de los pixeles ddaDibujar(x1, y1, x2, y2); } public static void ddaDibujar(double x1, double y1, double x2, double y2) { double xinicial = x1, yinicial = y1, xfinal = x2, yfinal = y2, x, y; double deltax, deltay, xincremento, yincremento; double pasos; deltax = xfinal - xinicial; deltay = yfinal - yinicial; if (Math.Abs(deltax) > Math.Abs(deltay)) pasos = Math.Abs(deltax); else pasos = Math.Abs(deltay); xincremento = (deltax / pasos) /10; yincremento = (deltay / pasos) / 10; x = xinicial; y = yinicial; Gl.glBegin(Gl.GL_POINTS); Gl.glVertex2d(x, y);//funcion que pinta un pixel en las coordenadas especificadas for (double k = .1; k <= pasos; k += .1) { x = (x + xincremento); y = (y + yincremento); Gl.glVertex2d(x, y); } //Gl.glEnd(); //termina dda // ****************************************************** double p2; double p3; double p4; double p5; p2 = xinicial + .01; p4 = yinicial + .01; p5 = yfinal + .01; p3 = xfinal +.01;
deltax = (p3 - p2); deltay = (p5 - p4); if (Math.Abs(deltax) > Math.Abs(deltay)) pasos = Math.Abs(deltax); else pasos = Math.Abs(deltay); xincremento = (deltax / pasos) /10; yincremento = (deltay / pasos) / 10; x = p2+.1; y = p4; Gl.glBegin(Gl.GL_POINTS); Gl.glVertex2d(x, y);//funcion que pinta un pixel en las coordenadas especificadas for (double k = .1; k <= pasos; k += .1) { x = (x + xincremento); y = (y + yincremento); Gl.glVertex2d(x, y); } p2 = xinicial + .01; p4 = yinicial + .01; p5 = yfinal + .01; p3 = xfinal + .01; deltax = (p3 - p2); deltay = (p5 - p4); if (Math.Abs(deltax) > Math.Abs(deltay)) pasos = Math.Abs(deltax); else pasos = Math.Abs(deltay); xincremento = (deltax / pasos) / 10; yincremento = (deltay / pasos) / 10; x = p2 ; y = p4 + .1; Gl.glBegin(Gl.GL_POINTS); Gl.glVertex2d(x, y);//funcion que pinta un pixel en las coordenadas especificadas for (double k = .1; k <= pasos; k += .1) { x = (x + xincremento); y = (y + yincremento); Gl.glVertex2d(x, y); } Gl.glEnd(); //termina dda } } }
El programa compilado y ejecutado debera quedar de la siguiente manera:
Figura 7. Interfaz para introducir las coordenadas correspondientes.
Figura 8. Xinicial= 0.5, Yinicial=0.5, Xfinal=1, Yfinal=1.
Figura 9. Xinicial= 0.5, Yinicial=0.5, Xfinal=1, Yfinal=1.
Figura 10. Xinicial= - 0.9, Yinicial=- 0.8, Xfinal=8, Yfinal=9
FUENTES DE INFORMACIÓN 1.- Graficación, Departamento Académico de Computación Instituto Tecnológico Autónomo de México http://cannes.itam.mx/Alfredo/Espaniol/Cursos/Grafica/Linea.pdf 2.- OpenGL: CSGL y The Tao Framework en Csharp. Autor: Ing. Jesús Hernández León. Docente del Instituto Tecnológico Superior de Libres. Revisado en: http://opengl.blogspot.es
Sitios de trabajo en línea 1. Issuu. Sitio para la publicación de trabajos en línea. Vínculo: http://issuu.com/
2.- Hotmail. Sitio para enviar vinculo electrónicamente: http://www.hotmail.com/