Está en la página 1de 45

TEMA 2: Primitivas 2D

ndice
1. Algoritmos de Dibujo de Lneas
1. 2. 3. Algoritmo Bsico Incremental (DDA) Algoritmo de Bresenham Propiedades de las Lneas

2.

Algoritmos de Dibujo de Crcunferencias


1. 2. Algoritmo del Punto Medio Propiedades de las Lneas Curvas

3.

Algoritmos de Relleno
1. 2. Relleno de Polgonos por Scan-line Relleno por Inundacin

4. 5.

Generacin de Caracteres de Texto Tcnicas de Anti-aliasing


1. 2. 3. Super-sampling Area Sampling Anti-aliasing de contornos

Primitivas 2D
En los sistemas raster, las imgenes vienen definidas por la intensidad de sus pixels

aplicacin

controlador grfico

controlador de vdeo

Primitivas 2D
Los objetos presentes en la imagen se componen de primitivas simples (lneas, puntos) El sistema grfico dibuja estas primitivas transformndolos en pixels Rasterizacin

Fila i

0xFF 0xFF 0xFF 0x00 0x85 0x00 0xFF 0xFF

Memoria de vdeo

Los mtodos de conversin deben ser lo ms eficientes posible La primitiva Punto es la ms sencilla:
se coloca la intensidad deseada en la celda de memoria del frame buffer correspondiente Cuando el haz de electrones pase por esa lnea horizontal (scan-line), emitir al pasar por esa posicin

Dibujo de lneas rectas


Para dibujar lneas rectas, habr que calcular las posiciones intermedias entre los dos extremos Este problema no exista en las pantallas vectoriales o plotters Sin embargo, las posiciones de los pixels son valores enteros, y los puntos obtenidos de la ecuacin son reales existe un error (aliasing) A menor resolucin, mayor es el efecto

Es necesario disponer de mtodos para convertir primitivas en pixels de la forma ms eficiente posible

Consideraciones para el dibujo de rectas


Hay que calcular las coordenadas de los pixels que estn lo ms cerca posible de una lnea recta ideal, infinitamente delgada, superpuesta sobre la matriz de pixels. Las consideraciones que un buen algoritmo debe cumplir son:
la secuencia de pixels debe ser lo ms recta posible las lneas deben dibujarse con el mismo grosor e intensidad independientemente de su inclinacin las lneas deben dibujarse lo ms rpido posible

correcto

incorrecto

El algoritmo ms sencillo
La ecuacin de una recta es m es la pendiente b es el corte con el eje y
y0

y = mx + b
y1

P1

Calcular Calcular

m=

y y1 y 0 = x x1 x0

P0
x0 x1

b = y 0 mx0
No es muy eficiente Cada paso requiere una multiplicacin flotante, una suma y un redondeo

Para x=x0 hasta x=x1 y = mx + b Pintar Pixel (x, round(y))

Algoritmo Bsico Incremental (DDA)


Podemos eliminar la multiplicacin de la siguiente manera: Sabemos que yi = mxi + b Entonces yi+1 = mxi+1 + b = yi+1 = yi + m x Como x=1, llegamos a la frmula final yi+1 = yi + m

Cada pixel se calcula en funcin del anterior No hace falta calcular b Si m>1 falla pues quedan huecos Solucin: intercambiamos las variables x e y Sabemos que xi = (1/m) (yi b) . Entonces: xi+1 = (1/m)yi+1 - b/m = xi+1 = xi + y/m Como y=1, llegamos a la frmula final xi+1 = xi + 1/m

Algoritmo Bsico Incremental (DDA)


Funcion Linea_DDA (int x0, y0, x1, y1) dx = x1 x0 dy = y1 y0 Si abs(dx) > abs(dy) entonces steps = abs(dx) Si no steps = abs(dy) xinc = dx / steps yinc = dy / steps x = x0 y = y0 Pintar Pixel (round(x), round(y)) Para k=1 hasta k=steps x = x + xinc y = y + yinc Pintar Pixel (round(x), round(y)) Inconvenientes:
Existen errores de acumulacin El redondeo es muy lento

Algoritmo de Bresenham
Slo usa aritmtica entera Supongamos el caso 0 < m < 1 hay que decidir qu pixel dibujamos a continuacin, y slo hay dos candidatos! yk+1 yk xk xk+1 El algoritmo debe decidir cul de los dos pintar Partamos del pixel (xk, yk), y hay que decidir entre el pixel (xk+1, yk) o (xk+1, yk+1) Para ello calculemos la distancia vertical entre el centro de cada pixel y la lnea real y = m (xk + 1) + b yk+1

d2 d1

d2 = (yk + 1 y) = yk + 1 - m (xk+ 1) - b d1 = y yk = m (xk+ 1) + b - yk

yk

xk

xk+1

Algoritmo de Bresenham
La diferencia entre ambas constantes nos ayudar a decidir qu pixel pintar d1 d2 = 2m (xk + 1) 2yk + 2b 1 Multiplicando por x eliminamos el parmetro m, que no es entero pk = x (d1 d2) = 2 y xk 2 x yk + C, donde C = 2 y + x (2b 1)

Como x > 0, el signo de pk coincide con el de la diferencia (d1 d2), y por tanto: Si pk > 0 Si pk < 0 d1 > d2 d1 < d2 hay que pintar el pixel (xk+1, yk+1) hay que pintar el pixel (xk+1, yk)
yk+1 d2 d1

La gran ventaja es que puede calcularse pk+1 a partir del anterior pk, utilizando solamente aritmtica entera! pk+1 = = pk + 2 y 2 x (yk+1 yk) 0 1 dependiendo del signo de pk

yk xk xk+1

Algoritmo de Bresenham
Funcion Bresenham (int x0, y0, x1, y1) // slo para el caso 0 < m < 1, siendo x0 < x1

Pintar Pixel (x0, y0) Calcular las constantes A=2y, B=2y-2x Si m > 1, intercambiamos las variables x e y

Obtener el valor para p0 = 2y-x

Si m < 0, el cambio es similar

Para cada xk sobre la lnea si pk < 0 Pintar Pixel (xk+1, yk) pk+1 = pk + A si pk > 0 Pintar Pixel (xk+1, yk+1) pk+1 = pk + B

Ejemplo
P0 = (20, 10) P1 = (30, 18) x = 10 y = 8 p0 = 6 2y = 16 2y - 2x = -4

Direccionando el Frame Buffer


Para acceder al pixel (0,0) Para acceder al pixel (x,y) Para acceder al pixel (x+1,y) Para acceder al pixel (x+1,y+1) I(0,0) = FB[0] I(x,y) = FB[0] + y (xmax + 1) + x I(x+1,y) = I(x,y) + 1 I(x+1, y+1) = I(x,y) + xmax + 1
(0,0)

ymax

xmax Fila 0

(1,0) (2,0)

(xmax-1,0) (0,1) (0,2)

(0,0)

Fila 1

Si el punto (0,0) fuera la esquina superior izquierda, y la y creciera hacia abajo, habra que usar I(x, ymax-y) en lugar de I(x,y)

Frame Buffer

Problemas con la intensidad


El grosor de la lnea depende de la pendiente B Sin embargo, ambas usan el mismo nmero de pixels

Si I es la intensidad de cada pixel, la intensidad por unidad de longitud de A es I, pero la de B es I/V2 el ojo lo nota Solucin: Que la intensidad de los pixels dependa de la pendiente

Tipos de lnea
Existen varios tipos: continua, discontinua, con puntos Los procedimientos para dibujar estas lneas van mostrando secciones contiguas de pixels, y luego se van saltando otros Cmo se puede implementar esto? Las secciones de pixels se especifican mediante una mscara Ejemplo: 1111000 se pintan 4 pixels y se saltan 3 Al fijar el nmero de pixels, las longitudes son diferentes segn la direccin Solucin: ajustar el nmero de pixels dependiendo de la pendiente Otra forma para dibujar lneas discontinuas sera tratar cada tramo como una lnea individual

Grosor de lnea
Cmo podemos pintar lneas de grosor mayor que 1? Solucin: si la pendiente es menor que 1, para cada posicin de x pintamos una seccin vertical de pixels, tantos como ancho de lnea queramos, por igual a cada lado Si la pendiente es mayor que 1, se usan secciones horizontales

Hay que tener en cuenta que el ancho de las lneas horizontales y verticales ser V2 veces ms grueso que las diagonales

Problemas en las terminaciones


Existe un problema en los bordes finales de las lneas: son siempre horizontales o verticales! Tres soluciones diferentes:

Butt cap

Round cap

Projected cap

Otra forma para dibujar lneas gruesas es pintar el rectngulo relleno Tambin aparecen problemas al conectar lneas Tres soluciones diferentes: aparecen huecos en las uniones!

Miter join

Round join

Bend join

Dibujo de circunferencias
La ecuacin de un crculo de radio R centrado en (x0, y0) es (x-xc)2 + (y-yc)2 = R2 R Algoritmo de fuerza bruta: (xc,yc)

Para x=xc-R hasta x=xc+R

Calcular

y = y 0 R 2 ( x x0 ) 2

Pintar Pixel (x, round(y))

No es nada eficiente Cada paso requiere una raz cuadrada El espaciado entre pixels no es uniforme

Otra forma
Cmo solucionar lo de los agujeritos? Pasando a coordenadas polares El valor del incremento del ngulo t debe ser lo suficientemente pequeo para evitar los huecos Podemos reducir clculo aplicando simetras: t= R 2 3 1 t=3/2 4 Incluso el primer octante es simtrico al segundo a travs de la diagonal 2 1 Conclusin: dibujando slo el segundo octante, desde x=0 hasta x=y podemos pintar todo el crculo Problema: se necesitan races cuadradas y funciones trigonomtricas demasiado costoso x = xc + R cos t y = yc + R sin t

t=/2 (xc,yc)

t=0

Algoritmo del Punto Medio


Hay que determinar el pixel ms cercano a la circunferencia Consideremos el centro del crculo en (0,0) Comenzaremos en el punto (0,R) e iremos desde x=0 hasta x=y, donde la pendiente va de 0 a -1 Slo pintaremos el primer octante Sea la funcin: <0 f(x,y) = x2 + y2 R2 =0 >0 (x,y) est dentro (x,y) est sobre la circunferencia (x,y) est fuera

Este test lo ejecutaremos en los puntos medios entre los pixels que hay que decidir

Algoritmo del Punto Medio


Supongamos ya dibujado el pixel (xk, yk) pk = f (xk + 1, yk ) = (xk + 1)2 + (yk )2 R2 pk+1 = f (xk+1 + 1, yk+1 ) = (xk+1 + 1)2 + (yk+1 )2 R2

pk+1 = pk + 2xk+1 + 1 + (y2k+1y2k) (yk+1yk) 0 1 dependiendo del signo de pk Por lo tanto: Si pk < 0 Si pk > 0 pk+1 = pk + 2xk+1 + 1 hay que pintar el pixel (xk+1, yk) hay que pintar el pixel (xk+1, yk-1)

pk+1 = pk + 2xk+1 - 2yk+1 + 1

Empezamos en el punto (0, R). Cunto vale p0? p0 = f (1, R-1/2) = = 5/4 R no es entero!

Sin embargo, da igual. Podemos redondearlo, porque todos los incrementos son enteros, y slo queremos utilizar el signo de pk, y no su valor

Algoritmo del Punto Medio


Funcion PuntoMedio (int xc, yc, float R)

Pintar Pixel (0, R)

Calcular p0 = 5/4 R

// si R es entero, p0 = 1-r

Para cada xk si pk < 0 Pintar Pixel (xk+1, yk) pk+1 = pk + 2xk + 3 si pk > 0 Pintar Pixel (xk+1, yk-1) pk+1 = pk + 2xk 2yk + 5

Determinar por simetra los puntos de los otros 7 octantes

Pintar Pixel (x+xc, y+yc)

Ejemplo
R = 10 p0 = 9 (x0, y0) = (0, 10)

Tipos de lneas
Para dibujar lneas discontinuas usaremos mscaras como en las rectas Al copiar al resto de octantes hay que tener en cuenta la secuencia del interespaciado Las longitudes varan con la pendiente

Grosor de lnea
1. 2. 3. Existen 3 mtodos: Pintando secciones horizontales o verticales segn sea la pendiente mayor o menor que 1 Rellenar el espacio entre dos curvas paralelas, separadas por una distancia igual al ancho que queremos 1 1 1 Usar una brocha e irla moviendo a lo largo de la curva 1 1 1 1 1 1

Relleno de primitivas
Dada un rea cerrada, hay que ser capaz de rellenar los pixels interiores con un color determinado

Relleno de primitivas
Existe 2 categoras de mtodos

1.

Relleno por scan - line: fila a fila va trazando lneas de color entre aristas

2.

Relleno por inundacin: a partir de un punto central, se va expandiendo recursivamente hasta alcanzar el borde del objeto

Relleno por Scan-Line


Para cada scan-line que cruce el polgono se busca la interseccinentre la lnea de barrido y las aristas del polgono Dichas intersecciones se ordenan y se rellenan a pares El problema es existen problemas cuando se intersecta un vrtice

x0

x1

x2

x3

En la scan-line y apareceran 5 aristas intersectadas! Cmo lo solucionamos?

Relleno por Scan-Line


Solucin: contarlo slo una vez Pero entonces habra problemas en la scan-line y Solucin: contarlo slo una vez Pero entonces habra problemas en la scan-line y Cmo distinguir entre ambos casos? La diferencia de la lnea y es que las aristas estn al mismo lado de la scanline Cmo detectarlo? Mirando si los tres vrtices en cuestin son montonamente crecientes o decrecientes

Aceleracin del Scan-Line


En lugar de calcular para cada scan-line las intersecciones contodos las aristas del polgono, podemos ir aprovechando el clculo en cada scan-line anterior La pendiente de la arista es m = (yk+1 yk) / (xk+1 - xk) Como y = 1 entre cada scan-line: xk+1 = xk + 1/m

Para acelerar an ms podemos pasar a aritmtica entera: xk+1 = xk + x / y

Podemos ir incrementando el contador en x unidades en cada scan-line Cuando el contador supere y, restamos y y hacemos x++

Algoritmo optimizado para el relleno scan-line


Primero hay que crear una tabla de bordes (TB), para todas las aristas del polgono (exceptuando las horizontales) Cada arista viene representada por cuatro valores
Coordenada y del punto ms alto Coordenada x del punto ms bajo Inversa de la pendiente Puntero a otra arista en la misma scan-line

yt

xd

1/m

Se crea un vector vaco, con tantas posiciones como filas tenga la pantalla, y se coloca cada arista en la posicin de la scan-line del punto ms bajo

Algoritmo optimizado para el relleno scan-line


Comenzamos desde abajo, y vamos creando una lista de bordes activos (LBA), que contendrn en cada iteracin las aristas cruzadas por dicha scan-line

Funcion Scanline() Inicializar LBA vaca y crear TB Repetir hasta que LBA y TB vacas Mover de TB a LBA lados con ymin = y Ordenar LBA segn x Rellenar usando pares de x de LBA Eliminar lados de LBA con y = ymax Incrementar y a la siguiente scan-line Actualizar las x en LBA

Relleno por inundacin


Empieza en un punto interior y pinta hasta encontrar la frontera del objeto Partimos de un punto inicial (x,y), un color de relleno y un color de frontera El algoritmo va testeando los pixels vecinos a los ya pintados, viendo si son frontera o no No slo sirven para polgonos, sino para cualquier rea curva sobre una imagen en los programas de dibujo se usan

Algoritmo de relleno por inundacin


Hay dos formas de considerar los vecinos : 4 u 8 Dependiendo de qu esquema elijamos, el relleno ser diferente

Funcion Inundacin(x, y, col1, col2) El algoritmo se presta a un esquema recursivo muy simple color = LeerPixel (x,y) Si (color!=col1 && color!=col2) entonces PintaPixel (x,y,col1) Inundacin (x+1, y, col1, col2); Inundacin (x-1, y, col1, col2); Inundacin (x, y+1, col1, col2); Inundacin (x, y-1, col1, col2);

Algoritmo optimizado de relleno por inundacin


El algoritmo anterior necesita mucha memoria, y si el rea a rellenar es muy grande se desborda la pila Cmo podemos ahorrar memoria para poder rellenar reas de cualquier tamao?

La solucin consiste en no explorar todos los vecinos de cada pixel, sino slo a lo largo de un scan-line Rellenamos el span donde se encuentra el punto inicial Adems, guardamos las posiciones iniciales de todos los spans de las lneas horizontales contiguas al scan-line

Generacin de caracteres de texto


Las letras y nmeros pueden dibujarse en muchos estilos y tamaos Typeface: cada dseo diferente para una familia entera de caracteres (Courier, Helvetica, Arial) Existen dos formas de representacin:

Bitmap Fonts (usando una malla rectangular de pixels)


ms simples de definir y dibujar requieren mucho espacio de almacenamiento, porque cada variacin en tamaa o formato requiere un nuevo bitmap

Outline Fonts (usando una lista de segmentos rectos y curvos)


ahorran ms memoria los diferentes tamaos y formatos se crean fcilmente a partir de la forma original lleva ms tiempo procesarlas pueden pintarse huecas o rellenas Pueden pintarse en cualquier orientacin

Tcnicas anti-aliasing
Las primitivas construidas con los algoritmos raster tienen una apariencia de escalera, debido a la discretizacin en pixels Soluciones hardware:
mayor resolucin de las pantallas existe un lmite para que el Frame Buffer mantenga su refresco a 30 Hz pixels ms pequeos: existe un lmite en la precisin del haz de electrones

Imagen digitalizada

Super-sampling
Consiste en incrementar virtualmente la malla de pixels, engaando a Bresenham Una vez calculada la recta para los subpixels, determinamos el color del pixel real Cada pixel representa entonces un rea finita de la pantalla, y no un punto infinitesimal

Para dibujar una recta, contamos el nmero de subpixels que estn sobre la lnea La intensidad del pixel final ser proporcional al contador anterior Para mscaras 3x3 tendremos 3 posibles intensidades

33%

66%

66%

100%

33%

Bresenham en pixels

Bresenham en subpixels

Apariencia final

Super-sampling
Otra versin de super-sampling diferente consiste en considerar que las lneas tienen un grosor de 1 pixel son en realidad un rectngulo Lo que hacemos entonces es contar los subpixels que caen dentro del rectngulo Para mscaras 3x3 tendramos 9 intensidades diferentes Se requiere ms clculo que la versin anterior, pero el resultado es ms exacto

NOTA: Si el fondo de la imagen tiene color, debemos promediar entre ambos colores para determinar el valor del pixel

Area-sampling
La intensidad del pixel viene dada por el rea de interseccin entre cada pixel y el objeto que se va a dibujar Para estimar el rea sera muy costoso evaluar la integral Lo que hacemos es testear una malla de puntos interiores al pixel y calcular cuntos caen dentro del rectngulo mtodo de integracin de Montecarlo Si el fondo tambin tiene color, promediamos entre ambos como antes

90% de pixels dentro

90% de intensidad

Ejemplo de anti-aliasing de lneas

sin anti-aliasing

con anti-aliasing

Anti-aliasing de contornos
Cuando el aliasing se produce en un contorno que separa dos zonas de color diferente (aristas de un polgono relleno) aliasing de contornos La solucin consiste en incorporar las tcnicas anteriores a los algoritmos de scan-line Area-sampling: Segn el rea de polgono que caiga dentro de cada pixel de la frontera, determinamos el color final Super-sampling: Aadimos ms scan-lines en la imagen virtual que le pasamos al algoritmo de relleno decidimos el color de los pixels frontera en funcin de dnde acabe cada scan-line

rea-sampling

Super-sampling

Ejemplo de anti-aliasing de contornos

color =

A1 ( verde ) + A2 ( amarillo ) A1 + A2

A2 A1 color

También podría gustarte