비트 맵에서 두 점 사이에 직선을 어떻게 그리나요?


17

높이 맵 (비트 맵)을 가지고 놀면서 게임에서 내 자신의 것을 만들려고하는데 기본적인 그리기 방법을 구현해야합니다. 직선을 그리는 것이 생각만큼 기본적이지 않다는 것을 빨리 깨달았습니다.

점이 X 또는 Y 좌표를 공유하거나 완벽하게 대각선을 그릴 수 있도록 정렬되어 있으면 간단합니다. 그러나 다른 모든 경우에는 까다 롭습니다.

"직선"선이되기 위해 어떤 픽셀을 채색해야하는지 결정하기 위해 어떤 알고리즘을 사용합니까?

답변:



21

Bresenham의 선 알고리즘 을 사용하여 선 세그먼트의 적절한 시각적 근사를 달성하기 위해 래스터 그리드의 어떤 점을 그릴 지 결정할 수 있습니다.

이 알고리즘은 원점이 왼쪽 상단에있는 좌표 공간에서 원점과 끝점으로 정의 된 선의 래스터 화를 다룹니다. 정수 좌표는 픽셀 중심에 매핑되는 것으로 간주됩니다. 특히, 알고리즘의 기본 형태는 원의 한 옥탄트 만 다룹니다 : 선이 X와 Y 좌표를 증가 시키지만 절대 값이 1보다 작은 음의 기울기를 갖는 것입니다. 기본 옥탄트.

psuedocode에서이 기본 양식은 다음과 같습니다.

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 Code 웹 사이트에는 다양한 언어로 구현 된 구체적인 구현이 있습니다 .

앤티 앨리어싱을 허용하는 Wu의 라인 알고리즘에 관심이있을 수도 있습니다 .


3
포함 된 의사 코드를 컨텍스트에서 벗어나지 않도록 발신자에게 경고하고 싶을 때 상자에서 작동하지 않습니다. 특정 octant에 대해서만 작동합니다 (나머지 답변 읽기). 복사 / 붙여 넣을 코드를 찾고 있다면 Rosetta Code 웹 사이트 링크를 사용해보십시오.
congusbongus

1
Wu의 라인 알고리즘의 c 버전을 확인하려는 사람에게는 그것이 불완전하다는 것을 경고하고 싶습니다. _dla_changebrightness에서 밝기를 변경할 때 밝기를 to->red = br * (float)from->red;다음에서 다음 으로 변경해야합니다 to->red = (br * (float)from->red) + ((1-br) * (float) to->red);. 녹색과 파란색을 존중합니다
Fredrik Boston Westman

2

다음은 선을 그리는 매우 간단한 방법입니다. 이 기능은 프로젝트에서 사용하도록 쉽게 변경할 수 있습니다.

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;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.