Bresenham'ın çizgi algoritması - Bresenham's line algorithm

Bresenham'ın çizgi algoritması a, çizgi çizimi algoritması bir noktaları tespit n boyutlu raster bir yakın bir yaklaşım oluşturmak amacıyla seçilmelidir iki nokta arasındaki düz çizgi . Standart bilgisayar mimarilerinde hepsi çok ucuz işlemler olan yalnızca tamsayı toplama, çıkarma ve bit kaydırma kullandığından, bir bitmap görüntüsünde (örneğin bir bilgisayar ekranında ) çizgi ilkelleri çizmek için yaygın olarak kullanılır . Bu bir olan artan hata algoritması . Bilgisayar grafikleri alanında geliştirilen en eski algoritmalardan biridir . Bir uzantı orijinal algoritmaya çiziminde kullanılabilir çevreler .

Wu'nun algoritması gibi algoritmalar , antialiasing'i destekleyebildikleri için modern bilgisayar grafiklerinde de sıklıkla kullanılırken , Bresenham'ın çizgi algoritmasının hızı ve basitliği, bunun hala önemli olduğu anlamına gelir. Algoritma, çiziciler gibi donanımlarda ve modern grafik kartlarının grafik yongalarında kullanılır . Ayrıca birçok yazılım grafik kitaplığında bulunabilir . Algoritma çok basit olduğu için, genellikle modern grafik kartlarının belleniminde veya grafik donanımında uygulanır .

"Bresenham" etiketi bugün Bresenham'ın orijinal algoritmasını genişleten veya değiştiren bir algoritma ailesi için kullanılmaktadır.

Tarih

Bresenham'ın çizgi algoritması, adını 1962'de IBM'de geliştiren Jack Elton Bresenham'dan almıştır . 2001 yılında Bresenham şunları yazdı:

IBM'in San Jose geliştirme laboratuvarındaki hesaplama laboratuvarında çalışıyordum. IBM 1401'e 1407 daktilo konsolu aracılığıyla bir Calcomp çizici bağlanmıştı . [Algoritma] 1962 yazında, muhtemelen bir ay kadar önce üretimdeydi. O günlerde programlar şirketler arasında serbestçe değiş tokuş edildi, bu nedenle Calcomp'un (Jim Newland ve Calvin Hefte) kopyaları vardı. 1962 sonbaharında Stanford'a döndüğümde, bir kopyasını Stanford bilgisayar merkezi kütüphanesine koydum. Çizgi çizme rutininin bir açıklaması, Denver, Colorado'daki 1963 ACM ulusal kongresinde sunulmak üzere kabul edildi . Hiçbir bildiri kitabının yayımlanmadığı, sadece konuşmacıların gündeminin ve ACM'nin İletişimleri'nin bir sayısında yer alan konuların yayınlandığı bir yıldı. IBM Systems Journal'dan bir kişi, sunumumu yaptıktan sonra makaleyi yayınlayıp yayınlamayacaklarını sordu. Memnuniyetle kabul ettim ve 1965'te bastılar.

Bresenham'ın algoritması, daireler, elipsler, kübik ve ikinci dereceden bezier eğrilerinin yanı sıra bunların yerel anti-aliased versiyonlarını üretecek şekilde genişletildi.

Yöntem

Bresenham'ın çizgi algoritmasının sonucunun çizimi. (0,0) ızgaranın sol üst köşesinde, (1,1) satırın sol üst ucunda ve (11, 5) satırın sağ alt ucundadır.

Aşağıdaki konvansiyonlar kullanılacaktır:

  • sol üst kısım (0,0)'dır, öyle ki piksel koordinatları sağ ve aşağı yönlerde artar (örn. (7,4)'deki piksel, (7,5)'daki pikselin hemen üzerindedir) ve
  • piksel merkezlerinin tamsayı koordinatları vardır.

Hattın bitiş noktaları olarak pikselleri ve kolon birinci çiftin koordine edilir ve ikinci satırdır.

Algoritma başlangıçta yalnızca segmentin aşağı ve sağa ( ve ) gittiği ve yatay projeksiyonunun dikey projeksiyondan daha uzun olduğu oktant için sunulacaktır (çizginin pozitif eğimi 1'den azdır). Bu oktanda, ve arasındaki her bir x sütunu için , çizginin bir pikselini içeren tam olarak bir y satırı (algoritma tarafından hesaplanmıştır) vardır ve aradaki ve arasındaki her satır birden fazla rasterleştirilmiş piksel içerebilir.

Bresenham'ın algoritması , aynı x için ideal (kesirli) y'ye en yakın piksel merkezine karşılık gelen y tamsayısını seçer ; ardışık sütunlarda y aynı kalabilir veya 1 artabilir. Uç noktalardan geçen doğrunun genel denklemi şu şekilde verilir:

.

x sütununu bildiğimiz için pikselin satırı y , bu miktar en yakın tam sayıya yuvarlanarak verilir:

.

Eğim yalnızca son nokta koordinatlarına bağlıdır ve önceden hesaplanabilir ve x'in ardışık tamsayı değerleri için ideal y , eğimden başlayarak ve eğimi tekrar tekrar ekleyerek hesaplanabilir .

Pratikte, algoritma , x'in her bir arttığında m = ∆y/∆x artan y koordinatını takip etmez ; (a) çizginin pikselden çıktığı nokta ile (b) pikselin üst kenarı arasındaki mesafenin negatifini temsil eden her aşamada bir hatayı bağlı tutar. Bu değer ilk olarak (pikselin merkez koordinatlarının kullanılması nedeniyle) olarak ayarlanır ve x koordinatı her bir artırıldığında m ile artırılır. Hata 0,5'ten büyük olursa, çizginin bir piksel yukarı hareket ettiğini ve y koordinatımızı artırmamız gerektiğini ve hatayı, yeni pikselin tepesinden olan mesafeyi temsil edecek şekilde yeniden ayarlamamız gerektiğini biliriz . hata.

türetme

Bresenham'ın algoritmasını türetmek için iki adım atılmalıdır. İlk adım, bir doğrunun denklemini tipik eğim-kesişim biçiminden farklı bir şeye dönüştürmektir; ve sonra bu yeni denklemi, hata birikimi fikrine dayalı bir çizgi çizmek için kullanmak.

çizgi denklemi

y=f(x)=.5x+1 veya f(x,y)=x-2y+2
Pozitif ve negatif yarım düzlemler

Bir doğrunun eğim-kesişim biçimi şu şekilde yazılır:

burada m eğim ve b y-kesişim noktasıdır. Bu sadece x'in bir fonksiyonudur ve bu denklemi hem x hem de y'nin bir fonksiyonu olarak yazmak faydalı olacaktır. Cebirsel manipülasyonu kullanma ve eğimin "koşu üzerinde yükselme" veya daha sonra olduğunun farkına varma

Bu son denklemin x ve y'nin bir fonksiyonu olmasına izin verilirse şöyle yazılabilir:

sabitler nerede

Çizgi daha sonra bazı A, B ve C sabitleri için herhangi bir yerde tanımlanır . Herhangi için değil on line sonra . Bu formla ilgili her şey, yalnızca x ve y tamsayılarsa tamsayıları içerir, çünkü sabitler zorunlu olarak tamsayılardır.

Örnek olarak, o zaman bu satır şu şekilde yazılabilir . (2,2) noktası doğru üzerindedir.

ve (2,3) noktası doğru üzerinde değil

ve nokta da (2,1) değil

(2,1) ve (2,3) noktalarının doğrunun zıt taraflarında olduğuna ve f(x,y)'nin pozitif veya negatif olarak değerlendirildiğine dikkat edin. Bir doğru, bir düzlemi yarıya böler ve eksi f(x,y) olan yarı-düzlem, negatif yarı-düzlem ve diğer yarısı, pozitif yarı-düzlem olarak adlandırılabilir. Bu gözlem, türetmenin geri kalanında çok önemlidir.

algoritma

Açıkçası, başlangıç ​​noktası çizgide

sadece çizgi tamsayı koordinatlarında başlayacak ve bitecek şekilde tanımlandığı için (tamsayı olmayan bitiş noktalarına sahip bir çizgi çizmek tamamen mantıklı olsa da).

Aday noktası (2,2) mavi ve iki aday noktası yeşil (3,2) ve (3,3)

Eğimin bire eşit veya daha küçük olduğunu akılda tutarak, sorun şimdi bir sonraki noktanın veya 'da mı olması gerektiği konusunda kendini gösteriyor . Belki de sezgisel olarak nokta, çizgiye hangisinin daha yakın olduğuna göre seçilmelidir . Birincisine daha yakınsa, o zaman ilk noktayı çizgiye, ikincisi ise ikincisini dahil edin. Bunu yanıtlamak için, bu iki nokta arasındaki orta noktada çizgi işlevini değerlendirin:

Bunun değeri pozitif ise ideal doğru orta noktanın altında ve aday noktaya daha yakındır ; aslında y koordinatı ilerlemiştir. Aksi takdirde ideal çizgi orta noktanın içinden veya üstünden geçer ve y koordinatı ilerlememiştir; bu durumda noktayı seçin . Bu gözlemi anlamak çok önemlidir! Bu orta noktadaki çizgi fonksiyonunun değeri, hangi noktanın seçilmesi gerektiğinin tek belirleyicisidir.

Yandaki resim, yeşil (3,2) ve (3,3) olarak iki aday noktası olan doğru üzerinde olmak üzere seçilen mavi noktayı (2,2) göstermektedir. Siyah nokta (3, 2.5), iki aday nokta arasındaki orta noktadır.

Tamsayı aritmetiği için algoritma

Alternatif olarak, orta noktalarda f(x,y)'yi değerlendirmek yerine noktalar arasındaki fark kullanılabilir. Bu alternatif yöntem, genellikle kayan nokta aritmetiği kullanmaktan daha hızlı olan yalnızca tamsayı aritmetiğine izin verir. Alternatif yöntemi türetmek için farkı aşağıdaki gibi tanımlayın:

İlk karar için bu formülasyon, başlangıç ​​noktasından itibaren orta nokta yöntemine eşdeğerdir . Bu ifadenin sadeleştirilmesi şunları sağlar:

Tıpkı orta nokta yönteminde olduğu gibi, eğer D pozitifse 'yi seçin , aksi halde 'yi seçin .

Eğer seçilirse seçilsin, D değişim olacak:

seçilirse , D'deki değişiklik şöyle olacaktır:

Yeni D pozitifse seçilir, aksi halde . Bu karar, sonraki her noktada hata toplanarak genelleştirilebilir.

Izgara çizgileri ve piksellerin bir çizimini gösteren (0,1) ile (6,4) arasındaki çizgiyi çizme

Algoritma için tüm türetme işlemleri yapılır. Bir performans sorunu, D'nin başlangıç ​​değerindeki 1/2 faktörüdür. Tüm bunlar, birikmiş farkın işaretiyle ilgili olduğundan, sonuç olmadan her şey 2 ile çarpılabilir.

Bu, yalnızca tamsayı aritmetiği kullanan bir algoritma ile sonuçlanır.

plotLine(x0, y0, x1, y1)
    dx = x1 - x0
    dy = y1 - y0
    D = 2*dy - dx
    y = y0

    for x from x0 to x1
        plot(x,y)
        if D > 0
            y = y + 1
            D = D - 2*dx
        end if
        D = D + 2*dy

Bu algoritmayı (0,1) ile (6,4) arasında çalıştırmak, dx=6 ve dy=3 ile aşağıdaki farklılıkları verir:

D=2*3-6=0
Loop from 0 to 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

Bu grafiğin sonucu sağda gösterilir. Çizim, çizgilerin kesiştiği noktada çizerek (mavi daireler) veya piksel kutularını doldurarak (sarı kareler) görüntülenebilir. Ne olursa olsun kurgu aynı.

Tüm vakalar

Bununla birlikte, yukarıda bahsedildiği gibi, bu yalnızca sıfır oktanı içindir , yani orijinde 0 ile 1 arasında bir eğimle başlayan, x'in yineleme başına tam olarak 1 arttığı ve y'nin 0 veya 1 arttığı çizgiler için geçerlidir.

Algoritma, y'nin artması veya azalması gerekip gerekmediği (yani dy < 0) kontrol edilerek 0 ile -1 arasındaki gradyanları kapsayacak şekilde genişletilebilir.

plotLineLow(x0, y0, x1, y1)
    dx = x1 - x0
    dy = y1 - y0
    yi = 1
    if dy < 0
        yi = -1
        dy = -dy
    end if
    D = (2 * dy) - dx
    y = y0

    for x from x0 to x1
        plot(x, y)
        if D > 0
            y = y + yi
            D = D + (2 * (dy - dx))
        else
            D = D + 2*dy
        end if

X ve y eksenini değiştirerek, pozitif veya negatif dik eğimler için bir uygulama şu şekilde yazılabilir:

plotLineHigh(x0, y0, x1, y1)
    dx = x1 - x0
    dy = y1 - y0
    xi = 1
    if dx < 0
        xi = -1
        dx = -dx
    end if
    D = (2 * dx) - dy
    x = x0

    for y from y0 to y1
        plot(x, y)
        if D > 0
            x = x + xi
            D = D + (2 * (dx - dy))
        else
            D = D + 2*dx
        end if

Eksiksiz bir çözümün x1 > x0 veya y1 > y0 olup olmadığını algılaması ve çizimden önce giriş koordinatlarını tersine çevirmesi gerekir, böylece

plotLine(x0, y0, x1, y1)
    if abs(y1 - y0) < abs(x1 - x0)
        if x0 > x1
            plotLineLow(x1, y1, x0, y0)
        else
            plotLineLow(x0, y0, x1, y1)
        end if
    else
        if y0 > y1
            plotLineHigh(x1, y1, x0, y0)
        else
            plotLineHigh(x0, y0, x1, y1)
        end if
    end if

Doğrudan video belleğine erişen düşük seviyeli uygulamalarda, dikey ve yatay çizgilerin özel durumlarının yüksek düzeyde optimize edilebildiklerinden ayrı olarak ele alınması tipik olacaktır.

Bazı sürümler, x ve y koordinatları arasındaki pozitif ve negatif hatayı dengeleyerek tüm oktant çizgi çizimlerini gerçekleştirmek için Bresenham'ın tamsayı artımlı hata ilkelerini kullanır. Siparişin mutlaka garanti edilmediğini unutmayın; başka bir deyişle, (x0, y0)'dan (x1, y1)'e veya (x1, y1)'den (x0, y0)'a doğru çizilebilir.

plotLine(int x0, int y0, int x1, int y1)
    dx =  abs(x1-x0);
    sx = x0<x1 ? 1 : -1;
    dy = -abs(y1-y0);
    sy = y0<y1 ? 1 : -1;
    err = dx+dy;  /* error value e_xy */
    while (true)   /* loop */
        plot(x0, y0);
        if (x0 == x1 && y0 == y1) break;
        e2 = 2*err;
        if (e2 >= dy) /* e_xy+e_x > 0 */
            err += dy;
            x0 += sx;
        end if
        if (e2 <= dx) /* e_xy+e_y < 0 */
            err += dx;
            y0 += sy;
        end if
    end while

benzer algoritmalar

Bresenham algoritması, biraz değiştirilmiş dijital diferansiyel analizör olarak yorumlanabilir (örtüşmeyen çokgen rasterleştirme için gerekli olan 0 yerine hata eşiği olarak 0,5 kullanılır).

Bölme işlemleri yerine artan bir hata kullanma ilkesi, grafiklerde başka uygulamalara sahiptir. Doku haritalı çokgenlerin raster taraması sırasında U,V koordinatlarını hesaplamak için bu tekniği kullanmak mümkündür . Voksel bazı PC oyunlarında görülen heightmap yazılım render motorları da bu ilkeyi kullandı.

Bresenham ayrıca bir Run-Slice (Run-Length'in aksine) hesaplama algoritmasını yayınladı. Bu yöntem bir dizi ABD patentinde temsil edilmiştir:

5.815.163 Hesaplama sırasında çizgi dilimleri çizmek için yöntem ve aparat
5.740.345 Etkin bir renk indeksleme sistemi ile sıkıştırılmış bir formatta saklanan bilgisayar grafik verilerinin görüntülenmesi için yöntem ve aparat
5.657.435 Doğrusal olmayan ölçekleme yetenekleriyle dilim çizgisi çizme motorunu çalıştırın
5.627.957 Gelişmiş işleme yetenekleriyle dilim çizgisi çizme motorunu çalıştırın
5.627.956 Uzatma özelliklerine sahip dilim çizgisi çizme motorunu çalıştırın
5,617,524 Gölgelendirme özelliklerine sahip dilim çizgisi çizme motorunu çalıştırın
5,611,029 Doğrusal olmayan gölgeleme yetenekleriyle dilim çizgisi çizme motorunu çalıştırın
5.604.852 Bir video ekranında bir parametrik eğrinin görüntülenmesi için yöntem ve aygıt
5.600.769 Gelişmiş kırpma teknikleriyle dilim çizgisi çizme motorunu çalıştırın

Kalın çizgileri işleyen algoritmanın bir uzantısı, IBM'de Alan Murphy tarafından oluşturuldu.

Ayrıca bakınız

Notlar

Referanslar

daha fazla okuma

yerine [ki] ACM 20 Dairesel Yaylar Şubat 1977 Haberleşme Artan Dijital Ekran Teknik Raporu 1964 Ocak-27 -11- Çember Algoritması TR-02-286 IBM San Jose Laboratuarı veya A Lineer Algoritma (2: daire uzatma kullanım için ):100-106 DOI:10.1145/359423.359432

Dış bağlantılar