Vous êtes sur la page 1sur 10

25.1.

Elipses
Aparte de las líneas, los círculos y las elipses son de los elementos gráficos
más comúnmente utilizados.

25.1.1. Algoritmo del punto medio para dibujar


círculos.
La misma lógica del algoritmo de Bresenham para dibujar líneas vista en el
capítulo 23.1.2. puede ser aplicada al círculo, que puede ser dibujado sin
trigonometría y sin multiplicaciones, por eso se le suele conocer como
algoritmo de Bresenham para dibujar círculos.
La ecuación de una circunferencia que tiene su centro en el punto (x 0, y0) y
de radio R es:
(x-x0)2 + (y-y0)2 = R2

Si suponemos que su centro es el origen de coordenadas, entonces la


fórmula queda así:
x2 + y2 = R2.

Las circunferencias son simétricas respecto de los ejes x, y de las líneas


y=x, y=-x. De modo que basta dibujar los puntos de la circunferencia en su
primer octante, el resto de puntos se calculan por simetría.

Fig. 25-01 - Octantes

En el primer octante la y cambia más rápidamente que la x, por lo que la


incrementaremos siempre y buscaremos el valor de la x a partir de ella.
Comenzaremos en el eje de las ordenadas en el sentido contrario a las
agujas del reloj, decrementando la x cuando toque y incrementado siempre
la y. Los puntos que dibujemos pueden cumplir o no la ecuación de la
circunferencia vista arriba, x2 + y2 = R2. En todo caso buscaremos el punto
que diste lo mínimo posible del valor teórico. Para ello definimos la función
del error cometido:
Ei = xi2 + yi2 - R2

Fig. 25-02 - Situación del punto respecto a la circunferencia

Partiendo de un punto (xi, yi) se trata de encontrar el valor del siguiente


punto (xi+1, yi+1). Ya hemos dicho que siempre yi+1 = yi + 1 en nuestro
primer octante. Tenemos que encontrar xi+1. Sólo hay dos posibilidades:
 xi+1 = xi

 xi+1 = xi-1

Cogeremos uno u otro en función del menor error que origine, da igual que
esté dentro o fuera de la circunferencia. Por tanto, para calcular qué error
es menor tendremos que elevarlo al cuadrado y compararlos.

1. (1) Supongamos que xi+1 = xi-1, entonces el error es:


[(xi-1)2 + (yi+1)2 - R2]2 = [xi2 - 2xi + 1 + yi2 + 2yi + 1 -
R2]2 = [xi2 + yi2 - R2 - 2xi + 2yi + 2]2 = [xi2 + yi2 - R2
+ 2yi + 1]2 + (1 - 2xi)2 + 2(1 - 2xi)(xi2 + yi2 - R2 +
2yi + 1).

2. (2) Supongamos que xi+1 = xi entonces el error


generado es:
[x + (yi+1) - R ] = [x + y + 2yi + 1 - R ] = [xi2
i
2 2 2 2
i
2
i
2 2 2

+ yi2 - R2 + 2yi + 1]2.

(1) < (2) <=> (1 - 2x i)2 + 2(1 - 2xi)(xi2 + yi2 - R2 + 2yi + 1) < 0
<=> (1 - 2xi)[(1 - 2xi) + 2(xi2 + yi2 - R2 + 2yi + 1)] < 0
<=> (1 - 2xi) + 2(xi2 + yi2 - R2 + 2yi + 1) > 0 si (1 - 2x i) < 0
<=> 2[(xi2 + yi2 - R2) + (2yi + 1)] + (1 - 2xi)> 0
Sean:
RE = xi2 + yi2 - R2
XChange = 1 - 2xi
YChange = 2yi + 1

Los valores iniciales serán X = R, Y = 0 y, por tanto, RE = 0, XChange = 1-


2R, YChange = 1.
Cómo cambian estas variables en función de su valor anterior cuando
cambien X e Y:
RE(i) = x i2 + yi2 - R2
YChange(i) = 2yi + 1
XChange(i) = 1 - 2xi

 Independientemente del valor de x i:


YChange(i+1) = 2(yi+1) + 1 = 2yi + 2 + 1 =
YChange(i) + 2. Siempre

 Si xi+1 = xi - 1 entonces:
 RE(i+1) = (xi+1)2 + (yi+1)2 - R2 = xi2 - 2xi + 1
+ yi2 + 2yi + 1 - R2= (xi2 + yi2 - R2 ) + (2yi +
1) + (1 - 2xi) = RE(i) + YChange(i) +
XChange(i)

 XChange(i+1) = 1 - 2(xi - 1) = 1 - 2xi + 2 =


XChange(i) + 2

 Si xi+1 = xi entonces:

 RE(i+1) = xi2 + (yi + 1)2 - R2 = xi2 + yi2 + 2yi


+ 1 - R2 = (xi2 + yi2 - R2 ) + (2yi + 1) = RE(i)
+ YChange(i)

 XChange(i+1) = 1 - 2xi = XChange(i)

Por lo tanto:
RE(i+1) = RE(i) + YChange(i) [+ XChange(i)]
YChange(i+1) = YChange(i) + 2 siempre
XChange(i+1) = XChange(i) [+ 2]

Donde lo que hay entre corchetes se da sólo en el caso en que x i+1 = xi - 1.


El pseudocódigo sería el siguiente:
; Valores iniciales
X = R
Y = 0
XChange = 1-2R
YChange = 1
RE = 0
while x <= y
DrawPoint(x,y) ; Para los 8 octantes
Temp = 2(RE+YChange)+XChange
Inc(Y)
RE += YChange
YChange += 2
if Temp > 0
inc(X)
RE += XChange
XChange += 2
endif
endwhile
25.1.2.Círculos y razón de aspecto
De la misma forma a como hemos visto en el capítulo anterior sobre cómo
afecta la razón de aspecto al visionado de un cuadrado, igual ocurre con los
círculos. Si dibujáramos un círculo tal cuál en la pantalla, su aspecto sería el
de una elipse debido a la razón de aspecto. Por tanto, la única forma de
dibujar circunferencias en la pantalla es dibujando elipses aplicándoles la
razón de aspecto.
Veamos a continuación, de forma esquemática, cuál sería la salida por
pantalla en modo 13h de una circunferencia matemática de radio 100
pixels:

Fig. 25-03 - Circunferencia teórica

Importante
Para observar mejor los ejemplos que vienen a continuación, mejor
ejecútense, para verlo con mayor claridad.
BcirCF BcirCN
BcirCM1 Resultado en pantalla
1 1
Código Código Código

[bin] [bin] [bin]

Source 25-01 - Circunferencia Bresenham


El código se ha preparado con recorte, como se puede ver. Además,
comprobaremos en la pantalla que la circunferencia teórica se asemeja más
a un huevo que a una circunferencia. Para evitar la razón de aspecto en el
dibujo de esta figura echaremos mano de las elipses que, debidamente
achatadas nos darán la impresión de circunferencias. Los programas recién
comentados han sido modificados para usar el código de las elipses:
BcirCM2 BcirCF2 BcirCN2 Resultado en pantalla
Código Código Código
[bin] [bin] [bin]
Source 25-02 - Circunferencia Bresenham con razón de aspecto
La figura de la izquierda es una circunferencia, la de la derecha arriba es un
círculo y la de abajo son circunferencias concéntricas.

25.1.3. Algoritmo para dibujar elipses


La elipse tiene simetría par e impar, es decir, podemos restringirnos al
cálculo de un cuadrante de una elipse para replicarla en el resto, esto
implica que tendremos que calcular los 90º del cuadrante y no sólo 45º
como ocurría en la circunferencia, debido al grado de crecimiento de las
variables x e y como ocurría con las líneas, habrá que diferenciar cada caso.
Recordemos que la circunferencia tiene simetría para cada octante.

25.1.3.1. Conversión de barrido de una elipse

Podemos usar la forma algebraica de una elipse para calcular las


coordenadas x e y para todos los puntos que representan una elipse dada.
La ecuación de una elipse es la siguiente:

Fig. 25-04 - Ecuación de la elipse

Esta ecuación describe una elipse centrada en (xc, yc) con los ejes mayor y
menor a y b paralelos a los ejes x e y. Sin embargo, el cálculo necesario
para dibujar elipses resolviendo esta ecuación es muy complejo. Las
operaciones de multiplicación, división y raíz cuadrada para determinar cada
una de las coordenadas consumen mucho tiempo.

25.1.3.2. Algoritmo incremental

Al igual que el algoritmo incremental que presentamos anteriormente para


dibujar circunferencias, no fue inventado por Bresenham, si bien, la técnica
usada es similar, por lo que también se le conoce por el algoritmo de
Bresenham. Después de dibujar un pixel, el algoritmo selecciona cuál es el
siguiente de sus vecinos que está más cerca de la elipse real.
Si suponemos que nuestra elipse está centrada en el origen de coordenadas
y los ejes mayor y menor coincidiendo con los ejes x e y, el algoritmo
resultante para dibujarla será mucho más sencillo.

Fig. 25-05 - Elipse de centro el origen

La ecuación de esta elipse centrada en el origen sería:


Fig. 25-06 - Ecuación de una elipse centrada en el origen

Multiplicando por a2b2 y pasando a un sólo lado:


b2x2 + a2y2 = a2b2.
(1) b2x2 + a2y2 - a2b2

El valor de esta ecuación para un punto P(x i, yi) nos dice dónde cae
respecto a la elipse.

 Si el valor es cero, el punto medio está en la


elipse.

 Si el valor es negativo, este punto estará dentro


de la elipse.

 Si el valor es positivo, este punto está fuera de la


elipse.

Realmente nos es indiferente la posición del punto respecto de la elipse, tan


sólo queremos minimizar la distancia. Por lo tanto definimos la función
error, que nos da la distancia del punto elegido a la elipse teórica:
(2) E(xi, yi) = | b2xi2 + a2yi2 - a2b2 |

En el primer cuadrante de la elipse, la tangente es siempre negativa. Si


empezamos en el x-eje y avanzamos en el sentido contrario a las agujas del
reloj, la pendiente es negativa y el valor absoluto muy grande, lo que
significa que la y-coordenada varía mucho más rápido que la x-coordenada.
Pero una vez que la pendiente alcanza el valor -1, es a la inversa y la x-
coordenada cambia más rápido que la y-coordenada. Por lo tanto tenemos
que calcular dos conjuntos de puntos para las dos tipologías que hemos
descrito. En el primer conjunto siempre incrementaremos la y-coordenada y
buscaremos cuándo decrementar la x-coordenada; mientras que en el
segundo siempre decrementaremos la x-coordenada y buscaremos cuándo
incrementar la y-coordenada. El valor que escojamos será aquel que
minimice la función error (2).
Veamos gráficamente lo que queremos decir para ambos conjuntos de
puntos:

Fig. 25-07 - Método del Punto Medio -tangente<-1

Fig. 25-08 - Método del Punto Medio - tangente>-1


En la ilustración superior vemos que el punto previo del que partimos,
dibujado en azul, es (xi-1,yi-1), mientras que siempre tenemos dos puntos
siguientes sobre los que elegir, A y B, dibujados en naranja. Por ejemplo,
para el primer conjunto de puntos, a partir de un punto (x i, yi) decidiremos
si xi+1 es xi o xi-1, para aquél que minimice el error provocado. Para ello
compararemos las funciones E(xi - 1, yi+1) con E(xi,yi+1). Obsérvese que en
este conjunto de puntos yi+1 = yi + 1 siempre.

 (3) E(xi - 1, yi + 1) = |b2(xi - 1)2 + a2(yi + 1)2 -


b2a2| = |b2xi2 - 2b2xi + b2 + a2yi2 + 2a2yi + a2 -
b2a2| = |b2xi2 + a2yi2 - b2a2 + b2(1-2xi) + a2(1 +
2yi)|

 (4) E(xi, yi + 1) = |b2xi2 + a2(yi + 1)2 - b2a2| = |


b2xi2 + a2yi2 + 2a2yi + a2 - b2a2| = |b2xi2 + a2yi2 -
b2a2 + a2(1 + 2yi)|

(3) < (4) <=> (3)2 < (4)2.

 (3)2 = [b2xi2 + a2yi2 - b2a2 + a2(1 + 2yi)]2 + [b2(1-


2xi)]2 + 2[b2(1-2xi)] [b2xi2 + a2yi2 - b2a2 + a2(1 +
2yi)]

 (4)2 = [b2xi2 + a2yi2 - b2a2 + a2(1 + 2yi)]2

(3)2 < (4)2 <=> [b2(1-2xi)] + 2[b2xi2 + a2yi2 - b2a2 + a2(1 + 2yi)] < 0.
Suponiendo que (1 - 2xi) > 0.
Entonces:

 Que sea menor que cero, significa que el punto x i


- 1 provoca el menor error.

 Si fuera positivo significaría que x i es la elección


correcta.

 Si fuera cero, podríamos escoger cualquiera de


los dos.
Definimos:
XChange = b2(1-2xi)
YChange = a2(1 + 2yi)
E = b2xi2 + a2yi2 - b2a2

Con lo que (3) < (4) <=> XChange + 2(E+YChange) < 0.


Además, decimos que partimos en el X-eje y nos movemos en el sentido
contrario a las agujas del reloj, por lo que los valores iniciales son:
X = a
Y = 0
XChange = b2(1-2a)
YChange = a2
E = 0

Estas tres variables pueden calcularse recursivamente.

 Si xi+1 = xi - 1

 XChange = b2(1 - 2(xi - 1)) = b2(1 - 2xi + 2)


= b2(1 - 2xi) + 2b2

 YChange = a2(1 + 2(yi + 1)) = a2(1 + 2yi +


2) = a2(1 + 2yi) + 2a2

 E = b2(xi - 1)2 + a2(yi + 1)2 - a2b2 = b2(xi2 -


2xi + 1) + a2(yi2 + 2yi + 1) -a2b2 = b2xi2 -
2b2xi + b2 + a2yi2 + 2a2yi + a2 - a2b2 = b2xi2 +
a2yi2 - a2b2 + b2(1 - 2xi) + a2(1 + 2yi)

Entonces:

 XChange(i+1) = XChange(i) + 2b2

 YChange(i+1) = YChange(i) + 2a2

 E(i+1) = E(i) + XChange(i) + YChange(i)

 Si xi+1 = xi

 XChange(i+1) = XChange(i)

 YChange(i+1) = YChange(i) + 2a2


 E = b2xi2 + a2(yi + 1)2 - a2b2 = b2xi2 + a2(yi2 +
2yi + 1) -a2b2 = b2xi2 + a2yi2 + 2a2yi + a2 -
a2b2 = b2xi2 + a2yi2 - a2b2 + a2(1 + 2yi).

Con lo que E(i+1) = E(i) + YChange(i)


Entonces
XChange(i+1) = XChange(i) [+ 2b2]
YChange(i+1) = YChange(i) + 2a2 siempre
E(i+1) = E(i) + YChange(i) [+ Xchange(i)]

Donde lo que hay entre corchetes se cumple sólo si xi+1 = xi - 1.


Por otro lado, podemos analizar la pendiente de la línea tangente a la elipse
diferenciando la y respecto de la x en la ecuación (1), nos queda:
2b2x + 2a2yy' = 0, despejando y':

El primer conjunto de puntos es aquel para el que y' < -1, es decir 2b 2x >
2a2y.
Si llamamos:
StopX(i) = 2b2xi,
StopY(i) = 2a2yi

Tenemos:
Si xi+1 = xi - 1, entonces:

 StopX(i+1) = 2b2(xi - 1) = 2b2xi - 2b2 = StopX(i)


- 2b2

 StopY(i+1) = StopY(i) + 2a2 siempre.

En resumen:
Si XChange + 2(E + YChange) < 0 entonces xi+1 = xi - 1.
XChange = b2(1-2xi)
YChange = a2(1+2yi)
E = b2xi2 + a2yi2 - a2b2
StopX = 2b2x
StopY = 2a2y

Cómo se calculan recursivamente:


XChange (i+1) = XChange(i) [+ 2b2]
Ychange (i+1) = YChange(i) + 2a2
E(i+1) = E(i) + YChange(i) [+ XChange(i)]
StopX (i+1) = StopX(i) [-2b2]
StopY (i+1) = StopY(i) + 2a2
Los valores iniciales son: X = a, Y = 0. Por lo tanto:
XChange = b2(1-2a)
YChange = a2
E = 0
StopX = 2b2a
StopY = 0

Esta estructura produciría un código con dos bucles, aunque existe un


algoritmo que recorre un solo bucle, que usamos.

25.1.4. Algoritmo para dibujar circunferencias y


círculos
Una vez que tenemos el algoritmo para dibujar elipses, escribir el de las
circunferencias es sencillo, pues ésta es una elipse usando la razón de
aspecto. Para dibujar el círculo, reusamos el código de la circunferencia,
sólo que dibujamos una línea horizontal entre cada par de puntos
encontrados en octantes paralelos.

25.1.5. Ejemplos
ElipCM1 ElipCF1 ElipCN1 Resultado en pantalla
Código Código Código

[bin] [bin] [bin]

Source 25-03 - Elipses Bresenham


Podemos observar en la ilustración una elipse azul, una circunferencia
verde, un círculo cián y un arco rojo.

Vous aimerez peut-être aussi