Bresenham'ın çizgi algoritması

Tarihçe

Bresenham'ın çizgi algoritması, Amerikalı bilgisayar mühendisi Jack Bresenham tarafından, 1960'lı yıllarda IBM için doğrunun bilgisayar ekranına çizimi için geliştirilen bir algoritmadır.

Artıları

Bresenham Algoritmasi DDA'ya göre daha hızlıdır, çünkü DDA'nın aksine ondalıklı sayılarla (float) işlem yapılmaz. Bresenham algoritması tam sayılarla(int) toplama, çıkarma ve ikiyle çarpma işlemlerini içerir. İkiyle çarpma işlemi shift Operasyonu ile Assembler düzeyinde çok hızlı yapılabildiğinden, Bresenham algoritması oldukça verimli bir algoritmadır.

Genel Algoritma

Pseudo kod ile şu şekilde ifade edilir. Bu hali ondalıklı sayılarla işlem içerdiği için kullanılmaz.

 function line(x0, x1, y0, y1)
     int deltax := abs(x1 - x0)
     int deltay := abs(y1 - y0)
     real error := 0
     real deltaerr := deltay / deltax    // Assume deltax != 0 (line is not vertical)
     int y := y0
     for x from x0 to x1
         plot(x,y)
         error := error + deltaerr
         if error ≥ 0.5 then
             y := y + 1
             error := error - 1.0

Optimize Edilmiş Hali

Bu hali sadece tam sayılar kullandığı için oldukça verimlidir. Aşağıdaki hali algoritmanın anlaşılması için basitleştirilmiştir. aşağıdaki hali x-eksenin y-ekseninden daha hızlı arttığını (yani deltax'in deltay'den büyük olduğunu) ve x0'ın x1'den küçük olduğunu varsaymaktadır.

  function line(x0, y0, x1, y1)
      int deltax := abs(x1 - x0)
      int deltay := abs(y1 - y0)
      int error := 2 * deltay - deltax
      int xₖ := x0
      int yₖ := y0
      while xₖ < x1 
           xₖ₊₁ := xₖ + 1
           if error > 0
                yₖ₊₁ := yₖ + 1
                error := error + 2 * deltay - 2 * deltax
           else
                yₖ₊₁ := yₖ
                error := error + 2 * deltay
           xₖ := xₖ₊₁

Matematiksel İspatı

Bresenham algoritması verimliliğini, yavaş artan eksenin belirli bir kurala göre arttığını gözlemlemesine borçludur. Hızlı artan eksen her iterasyondan 1 piksel artarken, yavaş artan eksen bazen sabit kalıp, bazen bir piksel artar. Matematiksel olarak anlatmak istersek:
En son çizilen pikselin koordinatlarının (xₖ, yₖ) olduğunu ve y-ekseninin yavaş arttığını varsayalım. dₐₗₜ gerçek doğruyla yₖ arasındaki uzaklık olsun. düst gerçek doğruyla yₖ + 1 arasındaki uzaklık olsun.
Eğer (dₐₗₜ < düst) ise yₖ₊₁ := yₖ olmalıdır. Aksi halde yₖ₊₁ := yₖ + 1 olmalıdır.
y = mx + b doğrusu için

    dₐₗₜ = y - yₖ = m(xₖ + 1) + b - yₖ
    düst = yₖ + 1 - y = yₖ + 1 - m(xₖ + 1)

    m = (y1 - y0) / (x1 - x0) = deltay / deltax

    dₐₗₜ - düst = 2 * m * (xₖ + 1) - 2 * yₖ - 1
                = 2 * deltay * (xₖ + 1) / deltax - 2 * yₖ - 1
Bölüm halindeki deltax'den kurtulmak için bulduğumuz formülü deltax'le çarpalım ve pₖ olarak adlandıralım. pₖ değeri optimize edilmiş algoritmada error olarak isimlendirilmişti ama burada ardışık error değerlerini karıştırmamak için pₖ olarak adlandıracağız.

   pₖ = deltax * (dₐₗₜ - düst) = 2 * deltay * (xₖ + 1) - 2 * deltax * yₖ - deltax
Eğer pₖ pozitifse gerçek doğru üst piksele daha yakın olduğu için yₖ₊₁ = yₖ + 1, aksi halde yₖ₊₁ = yₖ olacaktır.

  pₖ₊₁ - pₖ = 2 * deltay * (xₖ₊₁ - xₖ) - 2 * deltax * (yₖ₊₁ - yₖ)
 
xₖ₊₁ = xₖ + 1 olduğundan

  pₖ₊₁ = pₖ + 2 * deltay - 2 * deltax * (yₖ₊₁ - yₖ)
Eğer pₖ pozitifse (yₖ₊₁ - yₖ) = 1; aksi halde (yₖ₊₁ - yₖ) = 0
Görüldüğü üzere error değeri (yani pₖ) pozitifse 2 * deltax kadar azaltılıyor ve yₖ değeri artırılıyor. Ayrıca error değeri, her adımda 2 * deltay kadar artırılmaktadır.