31 de agosto de 2015

Algoritmo de Bresenham y Algoritmo DDA | DIBUJAR UNA LINEA C++

INTRODUCCIÓN



Dibujar una línea puede parecer poca cosa pero cuando pasamos esta misma acción a programación esto se complica aún más, las computadoras piensan diferente que nosotros, sus conceptos tienen que ser más específicos si queremos, por ejemplo, dibujar una línea; Todo aquello que los humanos hacen casi por instinto a una computadora se le tiene que describir de la forma mas exacta posible, un humano solo dibuja una línea en la forma en la que el quiere al arrastrar un lápiz de un punto a otro sobre una superficie se dibuja una línea sin mas, pero para poder hacer esto en una computadora tenemos que definir el punto exacto de partida, el punto de llegada, la pendiente, el color, el tamaño de la ventana donde se va a crear la línea, el color del fondo y tal vez otras cosas más que estoy olvidando en este momento, a lo que quiero llegar es que algo tan nimio como dibujar un línea o punto se puede convertir en una tarea mas laboriosa en una computadora. Existen multitud de herramientas que nos van ayudar a llevar a cabo esta y otras acciones de graficación en la computadora pero en esta ocasión nos vamos a enfocar en OpenGL, una serie de librearías que definen un API en varios lenguajes de programación y a su vez vamos a ver como utilizar ciertos algoritmos previamente desarrollados para dibujar una línea utilizando esta herramienta: el algoritmo de Bresenham y el algoritmo DDA.

DESARROLLO


OpenGL (Open Graphics Library) es una herramienta que se utiliza para definir una interfaz para aplicaciones creadas en múltiples lenguajes, pueden utilizarse gráficos en 2D o en 3D por lo cual las posibilidades son casi infinitas; La biblioteca de OpenGL contiene 250 funciones que van desde dibujar puntos, líneas, triángulos hasta figuras mas complejas en 3D. Esta herramienta fue creada por la empresa Silicon Graphics Inc. y desde su creación los usos que se le han encontrado son de los más variados, al no ser un software en si ni tampoco un lenguaje de programación le da una amplia compatibilidad con muchos otros lenguajes de programación.


Algoritmo DDA (Algoritmo Analizador Diferencial Digital): Se trata de un algoritmo capaz de dibujar líneas que se basa en el cálculo del incremento de una variable “X” o en el incremento de la variable “Y”, con el objetivo de obtener los valores enteros correspondientes más próximos a la trayectoria de la línea que da la otra coordenada; Se utilizan sobre todo para dibujar líneas, triángulos y polígonos.

 

 

 







Algoritmo de Bresenham: El algoritmo de Bresenham se utiliza para el rastreo de líneas,  mediante cálculos incrementales con número enteros que se pueden adaptan para dibujar cirulos o curvas. Los ejes verticales sirven para mostrar las  posiciones de rastreo mientras que los horizontales identifican columnas de pixel; El algoritmo está dado por:

ANEXOS

Ejemplo del Algoritmo de Bresenham en C++ (CodeBlocks)
#define BLACK 0
#include <C:\GLUT\include\GL\glut.h>
#include <stdio.h>
void draw_pixel(int ix, int iy, int value)
{  glBegin(GL_POINTS);
    glVertex2i( ix, iy);
  glEnd();}
bres(int x1,int y1,int x2,int y2)
{
  int dx, dy, i, e;
  int incx, incy, inc1, inc2;
  int x,y;
  dx = x2 - x1;
  dy = y2 - y1;
  if(dx < 0) dx = -dx;
  if(dy < 0) dy = -dy;
  incx = 1;
  if(x2 < x1) incx = -1;
  incy = 1;
  if(y2 < y1) incy = -1;
  x=x1;
  y=y1;
  if(dx > dy)
    {
      draw_pixel(x,y, BLACK);
      e = 2*dy - dx;
      inc1 = 2*( dy -dx);
      inc2 = 2*dy;
      for(i = 0; i < dx; i++)
      { if(e >= 0) {
            y += incy;
            e += inc1;
         }
         else e += inc2;
         x += incx;
         draw_pixel(x,y, BLACK);
      }}
   else
   { draw_pixel(x,y, BLACK);
      e = 2*dx - dy;
      inc1 = 2*( dx - dy);
      inc2 = 2*dx;
      for(i = 0; i < dy; i++)
      {if(e >= 0) {
           x += incx;
           e += inc1; }
        else e += inc2;
        y += incy;
        draw_pixel(x,y, BLACK);
    }} }
void display()
{glClear(GL_COLOR_BUFFER_BIT);
    bres(200, 200, 100, 100);
    glFlush();}
void myinit()
{
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glColor3f(1.0, 0.0, 0.0);
    glPointSize(1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 499.0, 0.0, 499.0);
}

void main(int argc, char** argv)
{
/*  Inicializacion GLUT estándar*/
    glutInit(&argc,argv);
    glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(500,500); /* ventana 500x500 pixeles */
    glutInitWindowPosition(0,0); /* coloca la ventana de despliegue en esq. sup. izq */
    glutCreateWindow("Bresenham's Algorithm"); /* título de la ventana*/
    glutDisplayFunc(display); /*llama a la funcion display cuando se abre la ventana */
    myinit(); /* fija o establece los atributos */
    glutMainLoop(); /* entra a un ciclo de evento */
}

Pantallas de Ejecución


Ejemplo Algoritmo DDA C++ (CodeBlocks):
#include <dos.h>
#include <stdio.h>
#include <graphics.h>
#include <math.h>
void DDA (int x1,int y1,int x2,int y2)
{
   float ax,ay,x,y,luz;
   int i;
   if(abs(x2-x1)>=abs(y2-y1))
   luz=abs(x2-x1);
   else
   luz=abs(y2-y1);
   ax=(x2-x1)/luz;
   ay=(y2-y1)/luz;
   x=(float)x1;
   y=(float)y1;
   i=1;
   while(i<=luz)
   {
        putpixel((319+floor(x)),(239-floor(y)),9);
        x=x+ax;
        y=y+ay;
        i=i+1;
   }}

Pantallas de Ejecución


CONCLUCION


Dibujar una línea conlleva mucho más lo que se puede percibir al inicio, hay tantas cosa que se deben de considerar para poder llevar esta tarea a cabo correctamente, a pesar de que al hacerlo por computadora parece más laborioso también es cierto que es mucho más preciso y exacto que hacerlo a mano alzada.  Aunque en un principio pareciera que el algoritmo de Bresenham y el algoritmo DDA hacen lo mismo la verdad es que son más diferentes de lo que cualquiera podría pensar, primeramente el algoritmo de Bresenham además de poder utilizarse para líneas rectas también parece ser capaz de generar líneas curvas, algo que el algoritmo DDA no parece ser capaz de hacer, por otro lado mientras que uno se enfoca en dibujar una línea lo más delgada posible el otro va más por generar líneas de forma más rápida.  Con todo esto en mente uno no puede sino solo ver las posibilidades que estas herramientas son capaces de ofrecer acompañados de las herramientas que la librería de OpenGL tiene también.


REFERENCIAS


Estructura de datos 0911005, Graficación.
21 de Febrero del 2012
http://graficaciondanielnavarroleanos.blogspot.mx/2012/02/algoritmo-dda-para-generacion-de-lineas.html
31 de agosto del 2015

Anónimo, Analizador Diferencial Digital (algoritmo gráfico)/ Wikipedia
4 de Junio del 2011
https://es.wikipedia.org/wiki/Analizador_Diferencial_Digital_(algoritmo_gr%C3%A1fico)
31 de agosto del 2015

Unklet0m, Algoritmo de Bresenham/Wikipedia
14 de Febrero del 2011
https://es.wikipedia.org/wiki/Algoritmo_de_Bresenham
31 de agosto del 2015

David Blanchard, ¿Qué es OpenGL?/ DAVID BLANCHARD SPACE
24 de Febrero del 2013
https://blanchardspace.wordpress.com/2013/02/24/que-es-opengl/
31 de agosto del 2015

Yan Sandoval Verjel, Primitivas Gráficas en OpenGL [Codigo en C++], (Linea DDA, Linea Bresenham, Circunferencia, etc)
25 de Septiembre del 2012
http://xcodigoinformatico.blogspot.mx/2012/09/primitivas-graficas-en-opengl-codigo-en.html
31 de agosto del 2015



No hay comentarios:

Publicar un comentario