lunes, 1 de octubre de 2012

Introduccion a la computacion grafica


INTRODUCCIÓN A LA COMPUTACIÓN GRÁFICA
Los elementos de estudio de esta unidad que explicaremos serán los siguientes:

Puntos: Se especifican a partir de su localización y color. Su discretización es directa, como se mencionó con anterioridad.

Segmentos de recta: Son esenciales para la mayor parte de las entidades. Se especifican a partir de un par de puntos que representan sus extremos.

Circunferencias: En algunos casos representar entidades curvadas con segmentos poligonales puede ser inadecuado o costoso, por lo que en la prácticas las circunferencias o círculos se adoptan como primitivas. Se especifican con la posición de su centro y su radio.

Polígonos: Son indispensables para representar entidades sólidas. Se representan a partir de la secuencia de puntos que determina la poligonal de su perímetro.

Para el momento de escoger un método de discretización para una primitiva gráfica, es indispensable contar con criterios que permitan evaluar y comparar las ventajas y desventajas de las distintas alternativas.

Apariencia: Es la especificación más obvia, aunque no es fácil describirla en términos formales. Normalmente se espera que un segmento de recta tenga una “apariencia recta” más allá de que se hallan escogido los pixels matemáticamente más adecuados. Tampoco debe tener discontinuidades. Debe pasar por la discretización del primer y último punto del segmento. Debe ser uniforme, etc.

Simetría e invariancia geométrica: Esta especificación se refiere a que un método de discretización debe producir resultados equivalentes si se modifican algunas propiedades geométricas de la primitiva que se está discretizando. Por ejemplo, la discretización de un segmento no debe variar si dicho segmento se traslada a otra localización en el espacio, o si es rotado, etc.

Simplicidad y velocidad de cómputo: Como los métodos tradicionales de discretización de primitivas se desarrollaron hace tres décadas, en momentos en que las posibilidades del hardware y software eran muy limitadas, los resultados eran muy sensibles al uso de memoria u operaciones aritméticas complejas. Por lo tanto, los métodos tienden a no depender de estructuras complejas y a ser directamente implementables en hardware específico de baja complejidad.

METODOS DE DISCRETIZACIÓN
Los principales métodos para graficar las primitivas básicas mediante la discretización:

Evaluar su ecuación diferencial a diferencias finitas: Este método, denominado DDA (discrete diference analyzer) consiste en plantear la ecuación diferencial de la primitiva a discretizar, y luego evaluar dicha expresión a intervalos adecuados.

Análisis del error: Estos métodos fueron desarrollados por Bressenham y se basan en analizar, dado un pixel que pertenece a la discretización de la primitiva, cuál es el próximo pixel que minimiza una determinada expresión que evalúa el error que comete la discretización.

Con los cuales graficaremos la recta, el círculo, polígonos a continuación antes de eso una pequeña introducción a cada una de los gráficos

1.- Introducción a la primitiva línea
Es una primitiva gráfica que esta especificada por dos puntos: sus extremos.
Cuando hablamos de CG, lo que entendemos por linea es lo que en matemáticas entendemos por segmento.
También le podremos especificar algunas propiedades. Caracterización matemática En CG:
y = mx + b P1 = (x1; y1), P2 = (x2; y2)

SEGMENTO DE LA RECTA
El análisis de los métodos de discretización de rectas parte de considerar el comportamiento esperado en determinados casos particulares. Dichos casos surgen de suposiciones específicas que simplifican el problema, pero que al mismo tiempo se pueden generalizar a todos los demás casos por medio de simetrías. Dado un segmento de recta que va de (x0; y0) a (x1; y1), se supone que:
Ø   Dx = (x1 - x0) ³ 0
Ø   Dy = (y1 - y0) ³ 0, y
Ø   Dx ³ Dy.
Esto equivale a trabajar en el “octavo” del espacio de pantalla sombreado en la
Figura 28, donde el origen es el pixel que corresponde a la discretización del punto (x0;y0) y la zona sombreada a los lugares donde puede ubicarse el punto (x1;y1 ).

Segmento de la recta DDA
Como ya se mencionó, los métodos DDA evalúan la ecuación diferencial de la primitiva a intervalos finitos. En el caso particular de los segmentos de recta, la ecuación diferencial es:

El método busca encontrar una secuencia de n + 1 puntos tales que (x0;y0) = (x0;y0); (x1;y1 ); … (xn;yn) = (x1;y1 ). La discretización de cada uno de ellos son los pixeles de la discretización del segmento. Esta propiedad, si bien es trivial, es de gran importancia porque determina que la discretización de un segmento de recta es invariante frente a transformaciones afines. Esto significa que es equivalente transformar los extremos del segmento y discretizar el segmento transformado, o discretizar primero y transformar cada punto obtenido. Sin embargo, la primera alternativa es mucho más eficiente.

e determina la “frecuencia” de muestreo del segmento. Un valor muy pequeño determina que muchas muestras producirán puntos que serán discretizados al mismo pixel. Por el contrario, un valor muy grande determinaría que el segmento aparezca “punteado” en vez de ser continuo como corresponde. Un valor práctico es elegir Dx = 1 y por lo tanto n = Dx, es decir, la discretización tiene tantos pixeles como longitud tiene el segmento en la variable que más varía (más uno, dado que la secuencia tiene n + 1 puntos). Al mismo tiempo es fácil ver que
En la Figura es posible ver el resultado de discretizar un segmento particular por el método DDA. Obsérvese que los puntos extremos (x0; y0) a (x1;y1) son en efecto puntos y por lo tanto están ubicados en cualquier lugar dentro del pixel que corresponde a su discretización.


Un algoritmo sencillo escrito en lenguaje Java que computa la discretización de un segmento de recta por el método DDA se muestra en la Figura 30. Obsérvese que se computan las variables en punto flotantes, y que además se requiere una división en punto flotante que corresponde al cálculo de m.
Un pequeño paréntesis para explicar algunas sentencias que pueden causar dudas:

Ø  Sobre el parámetro Graphics g (línea 26), corresponde al contexto gráfico de la ventana (algo así como un lienzo) sobre el cual se dibuja.

Ø  La llamada al método setColor (línea 34) permite modificar el color actual con el cual se está dibujando, se toma el color como un objeto de tipo Color que puede ser de los preterminados de Java o creado a partir de los parámetros r, g, b. Esta llamada al método setColor permite modificar el color del “lápiz” que dibuja sobre el contexto gráfico.

Ø  Java no tiene una sentencia básica para dibujar puntos (pixeles), en este caso se utiliza la sentencia g.drawRect (línea 35) para dibujar un rectángulo con un ancho y alto de 0, que en su ejecución se traduce a pintar un único pixel ubicado en el punto enviado como parámetro.

Ø  En la misma sentencia g.drawRect (línea 35) se utiliza el “casting” a enteros para lograr la discretización de las coordenadas flotantes.

Algoritmo grafico de Primitiva línea por el método DDA

Segmento de recta por bresseham

En el algoritmo DDA para segmentos de recta es necesario computar sumas entre las variables en punto flotantes, y además se requiere una división en punto flotante para computar la pendiente. El mérito del algoritmo que vamos a presentar consiste en que todas las operaciones se realizan en aritmética entera por medio de operaciones sencillas, y por lo tanto, su ejecución es más rápida y económica, y es de fácil implementación con hardware específico.

El punto de partida del análisis es el siguiente. Si la discretización de los puntos extremos del segmento debe pertenecer a la discretización del segmento, entonces es conveniente efectuar la llamada al algoritmo luego de discretizar los extremos. Esto significa que (x0;y0) y (x1; y1 ),y por lo tanto Dx y Dy son enteros.

Luego, si p es un pixel que pertenece a la discretización del segmento, entonces en las condiciones particulares mencionadas, el próximo pixel solamente puede ser el ubicado a la derecha (E o “hacia el este”), o el ubicado en diagonal hacia la derecha y hacia abajo (D o “en diagonal”) como se muestra en la Figura.
De esta manera todas las operaciones se efectúan en aritmética entera, con su correspondiente agilización del tiempo de procesamiento.

La implementación del algoritmo de Bressenham para segmentos de recta se muestra en la Figura. Teniendo en cuenta que los productos por 2 en aritmética entera se efectúan con un desplazamiento a izquierda, es posible observar que el mismo utiliza operaciones elementales e implementables con hardware específico muy sencillo.

Algoritmo grafico de Primitiva línea por el método de bressenham
int dx = x1 - x0;
        int dy = y1 - y0;

         if (Math.abs(dx) > Math.abs(dy))
        {        
            float m = (float) dy / (float) dx;
            float b = y0 - m * x0;
            if(dx<0)
                dx =  -1;
            else
                dx =  1;
            while (x0 != x1)
            {
                x0 += dx;
                y0 = Math.round(m*x0 + b);
                g.drawLine( x0, y0, x0, y0);
            }
        } else
        if (dy != 0)
        {                             
            float m = (float) dx / (float) dy;     
            float b = x0 - m*y0;
            if(dy<0)
                dy =  -1;
            else
                dy =  1;
            while (y0 != y1)
            {
                y0 += dy;
                x0 = Math.round(m * y0 + b);
                g.drawLine( x0, y0, x0, y0);
            }
        }
EJERCICIO DE LA PRIMITIVA LINEA

2.- Discretización de circunferencias

Como en el caso de los segmentos de recta, en la discretización de circunferencias o círculos es posible trabajar un sólo segmento de la circunferencia y se obtienen las demás por simetría. Igualmente se dispone de algoritmos DDA y de Bressenham para el dibujo de circunferencias. En este aparte se mostrará una adaptación del algoritmo DDA a partir de la ecuación de la circunferencia, tomado de la página internet de Roberto Albornoz12.
Para poder realizar el dibujo de la circunferencia usaremos las ecuaciones de la circunferencia en coordenadas polares que son:
x = r * cosq
y = r *senq
Estas ecuaciones serán las que ocuparemos para calcular cada punto (x,y) del círculo, donde el r será obviamente el radio de círculo y q será el ángulo que forma el radio con la parte positiva del eje x. En forma gráfica sería así:
El ángulo deberá estar en radianes ya que las funciones de seno y coseno que incluye Java, trabajan con los ángulos en radianes. La fórmula para transformar grados a radianes es la siguiente:

Entonces para dibujar el círculo de un radio determinado, solamente tenemos que hacer un ciclo desde 0 hasta 360, pero con incrementos pequeños, calcular cada punto con las ecuaciones en coordenadas polares e ir dibujando cada punto. El ciclo en vez de ir de 0 a 360 (ángulos en grados) irá de 0 a 6.28 (360*3.14/180=6.28) ya que el ángulo debe estar en radianes.

Dibujar el círculo punto a punto es una tarea un poco lenta, debido a que se debe calcular en cada punto el seno y el coseno del ángulo, y estas funcionas son muy lentas. Para solucionar esto se pueden crear tablas predefinidas o precalculadas. En la siguiente figura se muestra el código en Java que permitiría dibujar el círculo en una ventana.

Algoritmo grafico de Primitiva de la circunferencia

3.- Discretización de polígonos
Introducción
Se considera un polígono una figura cerrada, formada a partir de varias líneas.
Para la discretización de polígonos se considerarán 2 tipos de polígonos: los irregulares y los regulares, en concordancia con lo mostrado por Steven R Davidson en su curso de gráficos disponible en internet.
Es una primitiva gráfica, que esta especificada por un conjunto ordenado de puntos.
Definición: (Poligonal)
Dada una secuencia finita de puntos en el plano
P = fP1; P2; : : : ; Png, una poligonal es la la unión de los segmentos de recta determinados por puntos consecutivos de P.

Existen dos tipos de polígonos:

Irregulares
La graficación de polígonos irregulares se realiza a partir de un conjunto de puntos que se unen secuencialmente, el polígono se cierra al unir el primer y último puntos. A continuación se muestra el código Java que dibujaría un polígono irregular a partir de un vector de elementos de tipo Punto y el correspondiente número de puntos.

Cabe recordar que en Java, al igual que en C, el índice de los vectores inicia en 0. Por tanto, la primera línea se dibuja desde el primer punto (índice 0) hasta el segundo punto (índice 1), continúa del segundo al tercero (índice 2), y así sucesivamente, hasta dibujar la línea del penúltimo punto (índice N-2) hasta el último punto del vector (índice N-1). Al finalizar el ciclo, dibuja la línea de cierre del polígono entre el último punto (índice N-1) y el primero (índice 0).

Algoritmo grafico de Primitiva de polígonos irregulares
Regulares
Un polígono regular se compone de aristas/lados de igual longitud. Esto implica que el ángulo entre cada arista contigua es el mismo. Si trazamos un segmento del centro a un vértice y otro segmento del centro a otro vértice contiguo, entonces el ángulo entre estos dos segmentos es un divisor de 2_ = 360°. En otras palabras, cada ángulo mencionado es inversamente proporcional a la cantidad de lados del polígono regular.

Podemos usar la siguiente fórmula:
a = 2π / N, donde a es el ángulo, y N es la cantidad de lados.
Crearemos polígonos regulares en base a una circunferencia que circunscribe nuestro polígono regular. Esto implica, que el centro de la circunferencia coincide con el centro geométrico de cualquier polígono regular. Para esto, necesitamos usar algunas funciones trigonométricas, junto con el ángulo ya calculado. El paso principal es averiguar la coordenada del siguiente vértice de nuestro polígono.
Usaremos las siguientes fórmulas:
x i = cx + r * cos( i*a )
y i = cy + r * sen( i*a )
Donde:
i = 0,1,2,...,N-1,
r es el radio de la circunferencia, y
c = (cx, cy) es la coordenada del centro geométrico de la circunferencia y del polígono.
Al agregar el centro a nuestra fórmula, conseguimos mover el centro geométrico del origen (0,0) al que nosotros deseemos. En la Figura se muestra el código que generaría los polígonos regulares.

Algoritmo grafico de Primitiva de polígonos regulares


Esto equivale a trabajar en el “octavo” del espacio de pantalla sombreado en la
Figura 28, donde el origen es el pixel que corresponde a la discretización del punto (x0;y0) y la zona sombreada a los lugares donde puede ubicarse el punto (x1;y1 ).

No hay comentarios:

Publicar un comentario