1 Primitivos gráficos - algoritmos Prof. Julio Arakaki 1 Algoritmos de reta Reta => infinitamente fina, ou seja, área = 0 Problemas para apresentação num monitor raster utilizando-se pixels: deve-se escolher quais pixels melhor representa a reta existem muitos algoritmos que possibilitam diferentes resultados 2
2 Algoritmo de reta equação reduzida Através da equação de reta: y = mx + b Problemas: for(int x = x_min; x <= x_max; x++) { int y = (int)round(m*x + b); desenharponto(x, y, cor); Linhas verticais. (m = ) Mais lento, pois para todo x tem-se: uma multiplicação em floating point uma adição em floating point uma chamada de função de arrendondamento ( round ) 3 Algoritmo de reta Digital Differential Analyser (DDA) Algoritmo simples e também não muito eficiente incremental Incrementa x de 1 ( x = 1) e atualiza y de acordo com: y 1 = mx 1 + b x 2 = x 1 + 1 y 2 = mx 2 + b = m(x 1 + 1) + b = (mx 1 + b) + m = y 1 + m Desenha o pixel (x, round(y)) em cada iteração 4
3 Algoritmo de reta Digital Differential Analyser (DDA) - exemplo reta: (2,2) (7,6) y = y + m m = 0.8 x = 1 x y Round(y) (7,7) 2.0 2.0 2 3.0 2.8 3 4.0 3.6 4 5.0 4.4 4 6.0 5.2 5 7.0 6.0 6 (0,0) desenharponto(x, round(y)); 5 Algoritmo de reta Digital Differential Analyser (DDA) float y; float m = (y2-y1)/(x2-x1); desenharponto(x1,y1, cor); y = y1; while( x1 < x2 ){ x1++; y += m; desenharponto(x1, ROUND(y), cor); x é um inteiro, mas y é floating point. custo: incremento, adição em floating point e chamada da função de arredondamento round(y) para cada valor de x. 6
4 Algoritmo de reta Digital Differential Analyser (DDA) void desenharretadda(int xa, int ya, int xa, int xb, int cor) { int dx = xb - xa, dy = yb - ya, steps, k; float xincr, yincr, x = xa, y = ya; if ( abs(dx)>abs(dy) ) steps = abs(dx); else steps = abs(dy); xincr = dx / (float) steps; yincr = dy / (float) steps; desenharponto( ROUND(x), ROUND(y), cor); for (k=0; k<steps; k++) { x += xincr; y += yincr; desenharponto( ROUND(x), ROUND(y), cor); 7 (Bresenham 1965) Mais eficiente que DDA. incremental e cálculo baseado em inteiros Em cada iteração determinamos se a linha intersecciona o próximo pixel acima ( above ) ou abaixo ( below ) da metade ( midpoint ) do valor de y. se acima então A: y i+1 = y i +1 caso contrário B: y i+1 = y i 8
5 Utiliza a forma implícita da equação de reta: ax i + by i + c = 0 : (x i, y i ) Na reta ax i + by i + c < 0 : (x i, y i ) Acima da reta ax i + by i + c > 0 : (x i, y i ) Abaixo da reta A cada iteração, verifica se o midpoint está acima ou abaixo da reta Examina-se o valor de: d i =a(x i + 1) + b(y i + ½) + c d i é uma variável de decisão no passo i 9 Se d i > 0 então escolhe-se o pixel A novo midpoint deverá ser checado: (x i + 2, y i + 3/2) : d i+1 = a(x i + 2) + b(y i + 3/2) + c = [a(x i + 1) + b(y i +1/2) + c] + a + b = = d i + a + b 10
6 Similarmente, se d i < 0 então escolhe-se o pixel B e o novo midpoint é: (x i + 2, y i + 1/2) : d i+1 = a(x i + 2) + b(y i + 1/2) + c = [a(x i + 1) + b(y i +1/2) + c] + a = d i + a Onde, para y=(dy/dx)*x + C temos: (dy/dx)*x y + C = 0 Multiplicando por dx todos os termos temos: a = dy = y end y start b = -dx = -(x end x start ) c = Cdx 11 No ponto inicial, a variável de decisão é calculada da seguinte forma: (x 1 +1, y 1 +1/2): d 1 = a(x 1 + 1) + b(y 1 + 1/2) + C = [ax 1 + by 1 + c] + a + b/2 = 0 + a + b/2 Uma parte fracionária é introduzida, b/2, mas pode se eliminar pois interessa-se somente o sinal de d - multiplicando por 2: d 1 = 2a + b, - ou seja, substituindo os valores de a e b: d i = 2 dy dx, 12
7 Cálculo do próximo valor de decisão Multiplicando por 2 e substituindo a e b : Para d i > 0 : d i+1 = d i + 2(a + b) = d i + 2(dy dx) Para d i < 0 : d i+1 = d i + 2a = d i + 2(dy) 13 dx = x2 x1; dy = y2 y1; d = 2*dy dx; inicialização x = x1; y = y1; while (x < x2) { if (d <= 0){ d = d + (2*dy); seleciona B x = x + 1; else { d = d + 2*(dy - dx); x = x + 1; seleciona A y = y + 1; desenharponto(x, y, cor); 14
8 Exemplo: Traçar a reta passando por: P1(2,2) e P2(7,6) dx = (7-2) = 5 dy = (6-2) = 4 Inicial: (d = 2*dy - dx) Ou seja, d = 3 se d > 0 (d = d + 2 * dy) ou seja, d = d - 2 se d < 0 (d = d + 2*(dy - dx)) ou seja, d = d + 8 15 reta: (2,2) (7,6) dx = 5 dy = 4 d = 3 if d>0 then d=d-2, y=y+1 if d<0 then d=d+8 x y d 7 (7,7) 2 2 3 6 3 3 1 5 4 4-1 4 5 4 7 3 6 5 5 2 7 6 3 1 (0,0) 1 2 3 4 5 6 7 16
9 Algoritmo de círculo Círculo com raio r e centro (x c, y c ) é definido parametricamente como: x = x c + rcosθ y = y c + rsenθ Variando θ de 0 até 2π plotando-se as coordenadas: Dificuldade para efetivamente controlar a dimensão do passo, para eliminar os espaços entre os pixels for(int theta = 0; theta <360; theta ++) { x = (int)round(xc + r*cos (theta)); y = (int)round(yc + r*sen (theta)); desenharponto(x, y, cor); 17 Algoritmo de círculo Equação do círculo: (x x c ) 2 + (y y c ) 2 r 2 = 0 (xc, yc): coordenada do centro R: raio do círculo Simétrico: necessário a determinação de apenas pixels de um octante 18
10 Algoritmo de círculo Midpoint algoritm void desenharpontossimetricos(int x, int y, int cor) { desenharponto(x, y, cor); desenharponto(y, x, cor); desenharponto(y, -x, cor); desenharponto(x, -y, cor); desenharponto(-x, -y, cor); desenharponto(-y, -x, cor); desenharponto(-y, x, cor); desenharponto(-x, y, cor); 19 Algoritmo de círculo Midpoint algoritm Forma implícita do círculo: (x x c ) 2 + (y y c ) 2 r 2 = 0 Utiliza um esquema similar ao algoritmo de reta ( midpoint ): A variável de decisão é calculada da seguinte forma: d i : < 0 se (x i, y i ) dentro do círculo = 0 se (x i, y i ) no círculo > 0 se (x i, y i ) fora do círculo 20
11 Algoritmo de círculo Midpoint algoritm Como na reta, determina-se o valor da variável de decisão pela substituição do midpoint do próximo pixel pela forma implícita do círculo: d i = (x i + 1) 2 + (y i 1/2) 2 - r 2 Se d i < 0 escolhe-se pixel A senão escolhe-se pixel B 21 Algoritmo de círculo Midpoint algoritm Semelhante ao algoritmo de reta, a escolha de A ou B pode ser utilizado para determinar o novo valor de d i+1 Se A for escolhido, então o próximo midpoint tem o seguinte variável de decisão: (x i + 2, y i 1/2) : d i+1 = (x i + 2) 2 + (y i 1/2) 2 r 2 = d i + 2x i + 3 Por outro lado, se B for escolhido, então a próxima variável de decisão é: (x i + 2, y i 3/2) : d i+1 = (x i + 2) 2 + (y i 3/2) 2 r 2 = d i + 2x i 2y i + 5 22
12 Algoritmo de círculo Midpoint algoritm Assumindo-se que o raio é um valor integral, então o primeiro pixel a ser desenhado é (0, r) e o valor inicial da variável de decisão é dado por: (1, r-1/2): d 0 = 1 + (r 2 r + 1/4) r 2 = 5/4 - r Neste caso o valor é fracionário, e todos os outros são inteiros. Pode-se arredondar para: d 0 = 1 - r 23 Algoritmo de círculo Midpoint algoritm d = 1-r; x = 0; inicialização y = r; while (x < y) { if (d < 0) { d = d + 2*x + 3; seleciona A x = x + 1; else{ d = d + 2*(x - y) + 5; x = x + 1; seleciona B y = y 1; desenharpontossimetricos(xc+x,yc+y) 24
13 Algoritmo de elipse Midpoint algoritm F x y b x a y a b 2 2 2 2 2 2 (, ) = + = 0 25 Algoritmo de elipse Midpoint algoritm 26
14 Algoritmo de elipse Midpoint algoritm 27 Anti-aliasing Técnica para minimizar o efeito de serrillamento ( aliasing ). 28
15 Anti-aliasing 29