Algoritmos para dibujo de líneas - LDC

Anuncio
Universidad Simón Bolívar
Computación gráfica I
Sep – Dic 2011
Algoritmos para
dibujo de líneas
Realizado por:
●
Natalya Blanco
●
Rubén Arévalo
Contenido
•
Líneas
•
Algoritmo DDA
•
Algoritmo Breseham
•
Algoritmo Xiaolin Wu o Antialiasing
Líneas
•
La Recta es una sucesión infinita o
continua de puntos
alineados en una
sola dirección.
•
Es una de las primitivas básicas en
Computación Gráfica
•
Viene dada por la ecuación Y=mX+b ,
donde m es la pendiente de la recta y b es
el corte con el eje Y.
•
B
A
Figura 1
Líneas
•
Para dibujar la recta hay que hallar todos los
puntos medios entre el inicial y el final.
•
El problema es que la ubicación de cada pixel se
representa con un entero y las posiciones
halladas mediante la ecuación son valores reales.
•
Por lo tanto, se necesitan formas eficientes de
dibujar la recta lo más parecida posible a la
realidad, a pesar de las limitaciones que las
pantallas de píxeles nos pongan.
Transformar primitivas en pixeles
Las coordenadas de los píxeles deben estar lo
más cerca posible de una
línea recta real
Un algoritmo debe cumplir con:
•
La secuencia de píxeles debe ser lo más recta
que se pueda.
•
Las líneas deben tener el mismo grosor e
intensidad sin importar el grado de inclinación
•
Las líneas deben dibujarse lo más rápido posible
Transformar línea a pixel
Figura 2 – Tomada de www2.dis.ulpgc.es/~ii-fgc/Tema%202%20-%20Primitivas%202D.pdf
Algoritmo Ineficiente
Algoritmo:
Se calcula m (pendiente)
Calculo de b (pto de corte en el eje Y)
Para x=x0 hasta x=xn
y = mx + b
Dibujar pixel (x,redondear(y))
Se necesita una multiplicación flotante, una
suma y un redondeo por cada paso
Analizador diferencial digital
Algoritmo DDA
Busca determinar los valores enteros correspondientes más
próximos a la trayectoria de la línea para la otra coordenada.
Para una pendiente positiva, |m| ≤ 1, se realiza el muestreo
de x en intervalos y se calcula el valor sucesivo de y con la
siguiente ecuación:
Yk+1 = Yk +m
El subíndice k crece con razón 1 hasta alcanzar el valor final,
y m toma valores entre 0 y 1 reales, los valores de y
calculados deben ser redondeados.
Si la pendiente es negativa, se utiliza un caso análogo con la
siguiente ecuación:
Xk+1 = Xk + 1/m
Algoritmo DDA
Pseudo Código
Función DDA_Line (int X0, y0, x1, y1)
Dx = x1 - x0
Dy = y1 – y0
Si |Dx| > |Dy| entonces
pasos = |Dx|
Si no
pasos = |Dy|
xinc = Dx / pasos
yinc = Dy / pasos
x = x0
y = y0
Dibujar Pixel (redondear(x), redondear(y))
Para k=1 hasta k = pasos
x = x + xinc
y = y + yinc
Dibujar Pixel (redondear(x), redondear(y))
Problemas DDA
•
Presenta errores de
acumulación
•
Redondeo lento
Mejora
Separar los incrementos m y 1/m en
parte entera y fraccionaria, para
reducir a operaciones de enteros
Código DDA - JAVA
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;
x = x0;
y = y0;
if (abs(dx) > abs(dy))
steps = abs(dx);
else
steps = abs(dy);
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;
for (i = 0; i <= steps; i++){
XdrawPoint(display,win,gc,round(x),round(y));
x = x + xs;
y = y + ys;
}
}
Tomado de: Alfredo Weitzenfeld – Gráfica la Línea. Recuperado de
http://www.docstoc.com/docs/273281/Graficos-Lineas-Circulos?term=linea-algoritmo-completo-bresenham#
Algoritmo Breseham
Calcula cuál de dos píxeles es el más cercano a la trayectoria de una
línea.
El pixel (Xk, Yk) se divide en (Xk+1, Yk) y (Xk+1, Yk+1) y hay que decidir
cuál pintar, cualculando la distancia vertical entre el centro de cada pixel y
la línea real.
Figura 3 – Tomada de www2.dis.ulpgc.es/~ii-fgc/Tema%202%20-%20Primitivas%202D.pdf
Algoritmo Bresenham
Pseudo Código
Función Bresenham (int X0, y0, x1, y1)
// para el caso 0 < m < 1, siendo x0 < x1
Dibujar Pixel (x0, y0)
Calculamos:
A=2∆y
B=2∆y-2∆x
Obtener el valor para p0 = 2∆y-∆x
Para cada Xk sobre la línea
si pk < 0
Dibujar Pixel (xk+1, yk)
pk+1 = pk + A
si pk > 0
Dibujar Pixel (xk+1, yk+1)
pk+1 = pk + B
• Si m > 1:
intercambiamos x e y
• Si m < 0:
el cambio es similar
Código Bresenham
public void Bresenham(Graphics g,int x0, int y0, int x1, int y1)
int x, y, dx, dy, p, incE, incNE, sx, sy;
dx = (x1 - x0);
dy = (y1 - y0);
/* Se determina el punto para comenzar, y para terminar */
if (dy < 0) {
dy = -dy;
Sy = -1;
} else
sy = 1;
if (dx < 0) {
dx = -dx;
Sx = -1;
} else
sx = 1;
x = x0;
y = y0;
g.drawLine( x0, y0, x0, y0);
Código Bresenham – Cont.
/* se itera hasta el final de la línea */
if(dx>dy){
p = 2*dy - dx;
incE = 2*dy;
incNE = 2*(dy-dx);
while (x != x1){
x = x + sx;
if (p < 0){
p = p + incE;
} else {
y = y + sy;
p = p + incNE;
}
g.drawLine( x0, y0, x0, y0);
}
}else{
p = 2*dx - dy;
incE = 2*dx;
incNE = 2*(dx-dy);
while (y != y1){
y = y + sy;
if (p < 0){
p = p + incE;
} else {
x = x + sx;
p = p + incNE;
}
g.drawLine( x0, y0, x0, y0);
}}}
Anti-Aliasing
Aliasing es la apariencia de ”escaleras” o ”escalones” que
se forman debido a la discretización de lo píxeles.
Propuesta Hardware:
- Mayor resolución
- Píxeles más pequeños
Figura 4 – tomada de www.cimat.mx/~cesteves/cursos/cg/pdf/Antialiasing.pdf
Algoritmo Xiaolin Wu
Mejora del algoritmo de Bresenham, para dibujar
rectas en dispositivos de gráficos rasterizados de
manera que se reduzca el aliasing.
Esta basado en dibujar parejas de píxeles a lo
largo del trazado de la línea con diferentes
intensidades, en función de la a la recta real.
Pseudo código Xiaolin Wu
función plot(x, y, c) es
Dibujar el pixel en (x, y) con brillo c (donde 0 ≤ c ≤ 1)
función ipart(x) es
Retornar parte entera de x
función redondear(x) es
Retornar ipart(x + 0.5)
función fpart(x) es
Retorna parte fraccional de x
función rfpart(x) es
Retorna 1 - fpart(x)
Pseudo código (Cont.)
función dibujarLinea(x1,y1,x2,y2) es
dx = x2 - x1
dy = y2 - y1
Si abs(dx) < abs(dy) entonces
intercambiar x1, y1
intercambiar x2, y2
intercambiar dx, dy
Si x2 < x1
intercambiar x1, x2
intercambiar y1, y2
gradiente = dy / dx
xend = redondear(x1)
yend = y1 + gradiente * (xend - x1)
xgap = rfpart(x1 + 0.5)
xpxl1 = xend
ypxl1 = ipart(yend)
dibujar(xpxl1, ypxl1, rfpart(yend) * xgap)
dibujar(xpxl1, ypxl1 + 1, fpart(yend) * xgap)
intery = yend + gradiente
Pseudo código – (Cont.)
xend = redondear(x2)
yend = y2 + gradiente * (xend - x2)
xgap = fpart(x2 + 0.5)
xpxl2 = xend
ypxl2 = ipart (yend)
dibujar (xpxl2, ypxl2, rfpart (yend) * xgap)
dibujar(xpxl2, ypxl2 + 1, fpart (yend) * xgap)
// ciclo principal
for x from xpxl1 + 1 to xpxl2 - 1 do
dibujar(x, ipart (intery), rfpart (intery))
dibujar(x, ipart (intery) + 1, fpart (intery))
intery = intery + gradiente
fin
Referencias
•
Tema 2 - Primitivas 2D. Recuperado Noviembre 8, 2011 de
www2.dis.ulpgc.es/~ii-fgc/Tema%202%20-%20Primitivas%202D.pdf
•
Algoritmo DDA Analizador Diferencial Digital. Recuperado
Noviembre 8, 2011 de http://maiki69.tripod.com/DDA.htm
•
Rosetta Code - Xiaolin Wu's Line Algorithm . Recuperado Noviembre
8,
2011
de
http://rosettacode.org/wiki/Xiaolin_Wu%27s_line_algorithm
•
Medellín Anaya, Héctor E. Algoritmo basado en la ecuación de la
recta.
Recuperado
Noviembre
8,
2011
de
http://galia.fc.uaslp.mx/~medellin/Applets/LineasRectas/Recta.htm
•
Algoritmo DDA . Recuperado Noviembre 8, 2011
http://sites.google.com/site/proyectosroboticos/algoritmo-dda
•
Gómez, Francisco (Febrero 16, 2011) - Una breve introducción a
Antialiasing.
Recuperado
Noviembre
8,
2011
de
www.cimat.mx/~cesteves/cursos/cg/pdf/Antialiasing.pdf
de
Descargar