El algoritmo de línea de Bresenham es un algoritmo de dibujo de líneas que determina los puntos de una imagen rasterizada n -dimensional que deben seleccionarse para formar una aproximación cercana a una línea recta entre dos puntos . Se usa comúnmente para dibujar primitivas de línea en una imagen de mapa de bits (por ejemplo, en una pantalla de computadora ), ya que solo utiliza suma , resta y desplazamiento de bits, operaciones muy económicas en las arquitecturas de computadoras históricamente comunes. Es un algoritmo de error incremental y uno de los primeros algoritmos desarrollados en el campo de los gráficos por computadora . Una extensión del algoritmo original, llamada algoritmo de círculo de punto medio, puede usarse para dibujar círculos .
Si bien algoritmos como el de Wu también se utilizan con frecuencia en los gráficos modernos por computadora debido a su capacidad para aplicar suavizado de bordes (antialiasing) , el algoritmo de línea de Bresenham sigue siendo importante por su velocidad y simplicidad. Este algoritmo se utiliza en hardware como trazadores gráficos y en los chips gráficos de las tarjetas gráficas modernas . También se encuentra en muchas bibliotecas de software gráfico . Debido a su simplicidad, suele implementarse tanto en el firmware como en el hardware gráfico de las tarjetas gráficas modernas .
La denominación "Bresenham" se utiliza hoy en día para referirse a una familia de algoritmos que amplían o modifican el algoritmo original de Bresenham.
Historia
El algoritmo de línea de Bresenham lleva el nombre de Jack Elton Bresenham, quien lo desarrolló en 1962 en IBM . En 2001, Bresenham escribió: [ 1 ]
Trabajaba en el laboratorio de computación del centro de desarrollo de IBM en San José. Un trazador Calcomp estaba conectado a una IBM 1401 mediante la consola de la máquina de escribir 1407. El algoritmo se utilizaba en producción en el verano de 1962, posiblemente un mes antes. En aquella época, los programas se intercambiaban libremente entre empresas, así que Calcomp (Jim Newland y Calvin Hefte) tenía copias. Cuando regresé a Stanford en otoño de 1962, dejé una copia en la biblioteca del centro de computación de Stanford. Una descripción de la rutina de trazado de líneas fue aceptada para su presentación en la convención nacional de la ACM de 1963 en Denver, Colorado. Ese año no se publicaron las actas, solo la agenda de ponentes y temas en un número de Communications of the ACM. Después de mi presentación, una persona del IBM Systems Journal me preguntó si podían publicar el artículo. Acepté encantado y lo publicaron en 1965.
Método

Se aplicarán las siguientes convenciones:
- la esquina superior izquierda es (0,0) de tal manera que las coordenadas de píxeles aumentan en las direcciones derecha e inferior (por ejemplo, que el píxel en (7,4) está directamente encima del píxel en (7,5)), y
- Los centros de los píxeles tienen coordenadas enteras.
Los extremos de la línea son los píxeles enydonde la primera coordenada del par es la columna y la segunda es la fila.
El algoritmo se presentará inicialmente solo para el octante en el que el segmento va hacia abajo y hacia la derecha (y), y su proyección horizontales más largo que la proyección vertical(la línea tiene una pendiente positiva menor que 1). En este octante, para cada columna x entrey, hay exactamente una fila y (calculada por el algoritmo) que contiene un píxel de la línea, mientras que cada fila entreypuede contener múltiples píxeles rasterizados.
El algoritmo de Bresenham elige el entero y correspondiente al centro del píxel que está más cerca del y ideal (fraccional) para el mismo x ; en columnas sucesivas , y puede permanecer igual o aumentar en 1. La ecuación general de la línea que pasa por los puntos extremos viene dada por:
- .
Dado que conocemos la columna, x , la fila del píxel, y , se obtiene redondeando esta cantidad al entero más cercano:
- .
La pendientedepende únicamente de las coordenadas del punto final y puede precalcularse, y el valor ideal de y para sucesivos valores enteros de x puede calcularse a partir dey añadiendo repetidamente la pendiente.
En la práctica, el algoritmo no realiza un seguimiento de la coordenada y, que aumenta en m = ∆y/∆x cada vez que x aumenta en uno; mantiene un límite de error en cada etapa, que representa el negativo de la distancia desde (a) el punto donde la línea sale del píxel hasta (b) el borde superior del píxel. Este valor se establece primero en(debido al uso de las coordenadas del centro del píxel), y se incrementa en m cada vez que la coordenada x se incrementa en uno. Si el error se vuelve mayor que 0,5 , sabemos que la línea se ha movido un píxel hacia arriba, y que debemos incrementar nuestra coordenada y y reajustar el error para representar la distancia desde la parte superior del nuevo píxel, lo cual se hace restando uno al error. [ 2 ]
Derivación
Para derivar el algoritmo de Bresenham, se deben dar dos pasos: el primero es transformar la ecuación de una recta de la forma típica pendiente-ordenada al origen en una ecuación implícita con coeficientes enteros, y el segundo es usar esta nueva ecuación para trazar una línea basándose en la idea de acumulación de errores.
ecuación de línea


La forma pendiente-ordenada al origen de una recta se escribe como
dóndees la pendiente yes la intersección con el eje y . Porque esta es una función de solo, no puede representar una línea vertical. Por lo tanto, sería útil hacer que esta ecuación se escriba como una función de ambos.y, poder dibujar líneas en cualquier ángulo. El ángulo (o pendiente) de una línea se puede expresar como "elevación sobre desplazamiento horizontal", o. Luego, utilizando manipulación algebraica,
Si esta última ecuación es una función dey, se puede escribir como
donde las constantes son
La línea se define entonces para algunas constantes.,, yen cualquier lugar. Es decir, para cualquierno en la línea,. Esta forma involucra solo números enteros siyson números enteros, ya que las constantes,, yse definen como números enteros.
Como ejemplo, la líneaentonces esto podría escribirse comoEl punto (2,2) está en la línea
y el punto (2,3) no está en la línea
y tampoco lo es el punto (2,1)
Observe que los puntos (2,1) y (2,3) están en lados opuestos de la línea yse evalúa como positivo o negativo. Una línea divide un plano en dos mitades y el semiplano que tiene un valor negativoSe puede decir que una mitad es el semiplano negativo, y la otra mitad, el semiplano positivo. Esta observación es muy importante para el resto de la deducción.
Algoritmo
El punto de partida está en la línea
únicamente porque la línea está definida para comenzar y terminar en coordenadas enteras (aunque es totalmente razonable querer dibujar una línea con puntos finales no enteros).

Teniendo en cuenta que la pendiente es como máximo, ahora se plantea el problema de si el siguiente punto debería estar eno. Quizás intuitivamente, el punto debería elegirse en función de cuál esté más cerca de la línea enSi está más cerca del primero, entonces incluya el primer punto en la línea; si está más cerca del segundo, entonces incluya el segundo. Para responder a esto, evalúe la función de línea en el punto medio entre estos dos puntos:
Si el valor de esto es positivo, entonces la línea ideal está por debajo del punto medio y más cerca del punto candidato.; es decir, la coordenada y debería aumentar. De lo contrario, la línea ideal pasa por o por encima del punto medio, y la coordenada y debería permanecer igual; en cuyo caso el puntose elige. El valor de la función de línea en este punto medio es el único determinante de qué punto debe elegirse.
La imagen adjunta muestra el punto azul (2,2), elegido para estar sobre la línea junto con dos puntos candidatos en verde: (3,2) y (3,3). El punto negro (3, 2,5) es el punto medio entre los dos puntos candidatos.
Algoritmo para aritmética de enteros
Alternativamente, se puede usar la diferencia entre puntos en lugar de evaluar f(x,y) en los puntos medios. Este método alternativo permite realizar operaciones aritméticas solo con números enteros, lo cual generalmente es más rápido que usar aritmética de punto flotante . Para derivar el otro método, defina la diferencia de la siguiente manera:
Para la primera decisión, esta formulación es equivalente al método del punto medio ya queen el punto de partida. Simplificando esta expresión se obtiene:
Al igual que con el método del punto medio, sies positivo, entonces elige, de lo contrario, elige.
Sise elige, el cambio enserá:
Sise elige el cambio enserá:
Si el nuevo D es positivo entoncesse elige, de lo contrarioEsta decisión puede generalizarse acumulando el error en cada punto subsiguiente.

Ya se ha realizado toda la derivación del algoritmo. Un problema de rendimiento radica en el factor 1/2 del valor inicial de D. Dado que todo esto se refiere al signo de la diferencia acumulada, se puede multiplicar todo por 2 sin consecuencias.
Esto da como resultado un algoritmo que utiliza únicamente aritmética de enteros.
trazarLínea(x0, y0, x1, y1) dx = x1 - x0 dy = y1 - y0 D = 2*dy - dx y = y0 para x desde x0 hasta x1 trazar(x, y) si D > 0 y = y + 1 D = D + (2 * (dy - dx)) demás D = D + 2*dy fin si
Ejecutando este algoritmo paraDesde (0,1) hasta (6,4) se obtienen las siguientes diferencias con dx=6 y dy=3:
D=2*3-6=0 Recorrer en bucle desde 0 hasta 6 * x=0: plot(0, 1) , D≤0: D=0+6=6 * x=1: plot(1, 1) , D>0: D=6-12=-6, y=1+1=2, D=-6+6=0 * x=2: plot(2, 2) , D≤0: D=0+6=6 * x=3: plot(3, 2) , D>0: D=6-12=-6, y=2+1=3, D=-6+6=0 * x=4: plot(4, 3) , D≤0: D=0+6=6 * x=5: plot(5, 3) , D>0: D=6-12=-6, y=3+1=4, D=-6+6=0 * x=6: plot(6, 4) , D≤0: D=0+6=6
El resultado de esta gráfica se muestra a la derecha. La gráfica se puede visualizar trazando líneas en la intersección (círculos azules) o rellenando cuadrados de píxeles (cuadrados amarillos). En ambos casos, la gráfica es la misma.
Todos los casos
Sin embargo, como se mencionó anteriormente, esto solo funciona para el octante cero, es decir, líneas que comienzan en el origen con una pendiente entre 0 y 1 donde x aumenta exactamente en 1 por iteración e y aumenta en 0 o 1.
El algoritmo se puede extender para cubrir pendientes entre 0 y -1 comprobando si y necesita aumentar o disminuir (es decir, dy < 0).
plotLineLow(x0, y0, x1, y1) dx = x1 - x0 dy = y1 - y0 yi = 1 si dy < 0 yi = -1 dy = -dy fin si D = (2 * dy) - dx y = y0 para x desde x0 hasta x1 trazar(x, y) si D > 0 y = y + yi D = D + (2 * (dy - dx)) demás D = D + 2*dy fin si
Al intercambiar los ejes x e y, se puede escribir una implementación para pendientes pronunciadas positivas o negativas como:
plotLineHigh(x0, y0, x1, y1) dx = x1 - x0 dy = y1 - y0 xi = 1 si dx < 0 xi = -1 dx = -dx fin si D = (2 * dx) - dy x = x0 para y desde y0 hasta y1 trazar(x, y) si D > 0 x = x + xi D = D + (2 * (dx - dy)) demás D = D + 2*dx fin si
Una solución completa necesitaría detectar si x1 > x0 o y1 > y0 e invertir las coordenadas de entrada antes de dibujar, por lo tanto
trazarLínea(x0, y0, x1, y1) si abs(y1 - y0) < abs(x1 - x0) si x0 > x1 plotLineLow(x1, y1, x0, y0) demás plotLineLow(x0, y0, x1, y1) fin si si no si y0 > y1 plotLineHigh(x1, y1, x0, y0) demás plotLineHigh(x0, y0, x1, y1) fin si fin si
En las implementaciones de bajo nivel que acceden directamente a la memoria de vídeo, lo habitual es que los casos especiales de líneas verticales y horizontales se traten por separado, ya que pueden optimizarse en gran medida.
Algunas versiones utilizan los principios de Bresenham de error incremental entero para realizar todos los trazados de líneas octantes, equilibrando el error positivo y negativo entre las coordenadas x e y. [ 3 ]
trazarLínea(x0, y0, x1, y1) dx = abs(x1 - x0) sx = x0 < x1 ? 1 : -1 dy = -abs(y1 - y0) sy = y0 < y1 ? 1 : -1 error = dx + dy mientras que es cierto trazar(x0, y0) e2 = 2 * error si e2 >= dy si x0 == x1 salir error = error + dy x0 = x0 + sx fin si si e2 <= dx si y0 == y1 salir error = error + dx y0 = y0 + sy fin si fin mientras
Algoritmos similares
El algoritmo de Bresenham puede interpretarse como un analizador diferencial digital ligeramente modificado (utilizando 0,5 como umbral de error en lugar de 0, que es necesario para la rasterización de polígonos no superpuestos).
El principio de utilizar un error incremental en lugar de operaciones de división tiene otras aplicaciones en gráficos. Es posible utilizar esta técnica para calcular las coordenadas U,V durante el escaneo raster de polígonos con texturas mapeadas. [ 4 ] Los motores de renderizado de software de mapas de altura de vóxeles que se ven en algunos juegos de PC también utilizan este principio.
Bresenham también publicó un algoritmo computacional Run-Slice: mientras que el algoritmo Run-Length descrito anteriormente ejecuta el bucle en el eje principal, la variación Run-Slice lo hace en sentido contrario. [ 5 ] Este método ha sido representado en varias patentes estadounidenses:
- Patente estadounidense 5815163 , "Método y aparato para dibujar secciones transversales de líneas durante el cálculo".
- Patente estadounidense 5740345 , "Método y aparato para mostrar datos gráficos de computadora almacenados en un formato comprimido con un sistema eficiente de indexación de color".
- Patente estadounidense 5657435 , "Motor de dibujo de líneas de corte con capacidad de escalado no lineal".
- Patente estadounidense 5627957 , "Motor de corte en línea con capacidad de procesamiento mejorada".
- Patente estadounidense 5627956 , "Motor de estirado de línea de corte en carrera con capacidad de estiramiento".
- Patente estadounidense 5617524 , "Motor de dibujo de líneas de corte con capacidad de sombreado".
- Patente estadounidense 5611029 , "Motor de dibujo de líneas de corte con capacidades de sombreado no lineal".
- Patente estadounidense 5604852 , "Método y aparato para mostrar una curva paramétrica en una pantalla de vídeo".
- Patente estadounidense 5600769 , "Motor de dibujo de líneas de corte con técnicas de recorte mejoradas".
El algoritmo se ha ampliado a:
- Dibujar líneas de grosor arbitrario, un algoritmo creado por Alan Murphy en IBM. [ 6 ]
- Dibujar varios tipos de curvas (círculos, elipses, curvas cúbicas, cuadráticas y racionales de Bézier ) y líneas y curvas suavizadas; un conjunto de algoritmos de Alois Zingl. [ 3 ]
Véase también
- Analizador diferencial digital (algoritmo gráfico) , un método simple y general para rasterizar líneas y triángulos.
- El algoritmo de línea de Xiaolin Wu , un método igualmente rápido para dibujar líneas con suavizado de bordes.
- Algoritmo del círculo del punto medio , un algoritmo similar para dibujar círculos.
Notas
- ↑ Paul E. Black. Diccionario de algoritmos y estructuras de datos, NIST . https://xlinux.nist.gov/dads/HTML/bresenham.html
- ↑ Joy, Kenneth. "Algoritmo de Bresenham" (PDF) . Grupo de Investigación en Visualización y Gráficos, Departamento de Ciencias de la Computación, Universidad de California, Davis . Consultado el 20 de diciembre de 2016 .
- 1 2 Zingl, Alois (2016) [Publicado anteriormente en 2012]. Un algoritmo de rasterización para dibujar curvas (PDF) (Informe).Resumen y demostración en HTML: Zingl, Alois (2020) [Publicado anteriormente en 2012]. "La belleza del algoritmo de Bresenham" . zingl.github.io .
- ↑ US 5739818 , Spackman, John Neil, "Aparato y método para realizar interpolación con corrección de perspectiva en gráficos por computadora", publicado el 14 de abril de 1998, asignado a Canon KK
- ↑ "Edición especial del libro negro de programación gráfica de Michael Abrash: lo bueno, lo malo y lo segmentado" . www.phatcode.net . Consultado el 13 de febrero de 2024 .;
- ↑ "Algoritmo de la línea Bresenham modificado de Murphy" . homepages.enterprise.net . Consultado el 9 de junio de 2018 .('Engrosamiento de línea mediante modificación del algoritmo de Bresenham' en el Boletín de divulgación técnica de IBM, vol. 20, n.º 12, mayo de 1978, páginas 5358-5366).
Referencias
- Bresenham, JE (1965). «Algoritmo para el control informático de un trazador digital» (PDF) . IBM Systems Journal . 4 (1): 25–30 . doi : 10.1147/sj.41.0025 . Archivado del original (PDF) el 28 de mayo de 2008.
- "El algoritmo de trazado de líneas de Bresenham" , por Colin Flanagan
- Abrash, Michael (1997). El libro negro de programación gráfica de Michael Abrash . Albany, NY: Coriolis. pp. 654–678 . ISBN 978-1-57610-174-2.Una versión muy optimizada del algoritmo en C y lenguaje ensamblador para su uso en videojuegos, con detalles completos de su funcionamiento interno.
- Zingl, Alois (2016) [2012]. "Un algoritmo de rasterización para dibujar curvas" (PDF) .La belleza de los algoritmos de Bresenham
Lecturas adicionales
- Tesis de Patrick-Gillesbanda , que contiene una extensión del algoritmo de trazado de líneas de Bresenham para realizar la eliminación de líneas ocultas en 3D.
- También publicado en las actas de MICAD '87 sobre CAD/CAM y gráficos por computadora, página 591 - ISBN 2-86601-084-1.
- Engrosamiento de línea mediante modificación del algoritmo de Bresenham , AS Murphy, IBM Technical Disclosure Bulletin, vol. 20, n.º 12, mayo de 1978.
- Bresenham, Jack (febrero de 1977). "Un algoritmo lineal para la visualización digital incremental de arcos circulares". Communications of the ACM . 20 (2): 100– 106. doi : 10.1145/359423.359432 .– también Informe técnico 1964 27 de enero -11- Algoritmo de círculo TR-02-286 Laboratorio IBM San José
Enlaces externos
- Edición especial del libro negro sobre programación gráfica de Michael Abrash: Capítulo 35: Bresenham es rápido, y lo rápido es bueno.
- El algoritmo de trazado de líneas de Bresenham por Colin Flanagan
- Página del Instituto Nacional de Estándares y Tecnología sobre el algoritmo de Bresenham.
- Información sobre el trazador incremental Calcomp 563
- Algoritmo de Bresenham en varios lenguajes de programación
- La belleza del algoritmo de Bresenham : una implementación sencilla para trazar líneas, círculos, elipses y curvas de Bézier.
- Algoritmos de gráficos por computadora
- Geometría digital