Bir bitmapteki iki nokta arasında nasıl düz bir çizgi çizersiniz?


17

Yükseklik haritaları (bitmapler) ile oynuyorum, oyunumda kendiminkileri oluşturmaya çalışıyorum ve bunun için bazı temel çizim yöntemlerini uygulamam gerekiyor. Hızlı bir şekilde düz çizgiler çizmenin düşündüğüm kadar basit olmadığını fark ettim.

Noktalarınızın bir X veya Y koordinatını paylaşması veya mükemmel bir çapraz çizgi çizebilmeniz için hizalanması basittir. Ancak diğer tüm durumlarda daha hileli.

"Düz" bir çizgi olması için hangi piksellerin renklendirilmesi gerektiğini belirlemek için hangi algoritmayı kullanıyorsunuz?

Yanıtlar:



21

Bresenham'ın çizgi algoritması , bir çizgi segmentinin uygun bir görsel yaklaşımını elde etmek için bir ızgara ızgarasındaki hangi noktaların çizileceğini belirlemek için kullanılabilir.

Algoritma, başlangıç ​​noktasının sol üstte olduğu bir koordinat alanında başlangıç ​​noktası ve bitiş noktaları tarafından tanımlanan bir çizginin rasterleştirilmesini kapsar. Tamsayı koordinatlarının piksel merkezlerine eşlendiği varsayılır. Özellikle, algoritmanın temel formu dairenin sadece bir oktanını kapsar: çizginin artan X ve Y koordinatlarına sahip olduğu, ancak mutlak değeri 1'den küçük olan negatif bir eğimin olduğu diğer tüm oktanlar bunun basit dönüşümleri olarak türetilebilir. temel oktan.

Psuedocode'da bu temel form şöyle görünür:

void DrawLine(Point origin, Point endpoint, Bitmap surface) {
    deltaX = endpoint.X - origin.X
    deltaY = endpoint.Y - origin.Y
    error = 0

    // Note the below fails for completely vertical lines.
    deltaError = absoluteValue(deltaY / deltaX)

    Y = origin.Y
    for (X from origin.X to endpoint.X) {
        surface.PlotPixel(X, Y)
        error = error + deltaError 
        if (error >= 0.5) {
            ++Y;
            error -= 1.0
        }
    }
}

Rosetta Kodu web sitesinde bir çeşitli dillerde somut uygulamalar koleksiyonu bulunmaktadır .

Ayrıca , kenar yumuşatmaya izin veren Wu'nun çizgi algoritmasıyla da ilgilenebilirsiniz .


3
Kutudan çıkmayacağı için içerilen sözde kodu bağlamdan çıkarmamaları için yoldan geçenleri uyarmak istersiniz. Sadece belirli bir oktant için çalışır (cevabın geri kalanını okuyun). Kopyalamak / yapıştırmak için kod arıyorsanız, Rosetta Kodu web sitesine bağlantıyı deneyin.
congusbongus

1
Wu'nun çizgi algoritmasının c sürümünü kontrol etmek isteyen herkes için bunun eksik olduğu konusunda sizi uyarmak istiyorum. : _Dla_changebrightness olarak size onu değiştirmeniz gerekir parlaklığını değiştirmek zaman to->red = br * (float)from->red;bu aşağıdakine: to->red = (br * (float)from->red) + ((1-br) * (float) to->red);. Aynı şeyi sırayla yeşil ve mavi için yapın
Fredrik Boston Westman

2

İşte çizgi çizmenin son derece basit bir yolu. Fonksiyon, projelerde kullanılmak üzere kolayca değiştirilebilir.

void draw_line(float x0, float y0, const float& x1, const float& y1)
{
    float x{x1 - x0}, y{y1 - y0};
    const float max{std::max(std::fabs(x), std::fabs(y))};
    x /= max; y /= max;
    for (float n{0}; n < max; ++n)
    {
        // draw pixel at ( x0, y0 )
        x0 += x; y0 += y;
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.