【Computer Graphics】2.直線生成算法(中點畫線 算法)

在介紹中點畫線算法之前,我們先來看一個概念,增量算法

何爲增量算法?

增量算法就是在一個迭代算法中,如果每一步,x,y值都是用前一步的值加上一個增量來獲得。。。。則稱增量算法。。DDA就是一個增量算法。

下面我們來講增量算法,先看一張圖(ps:自己畫的,各位大神手下留情)

這裏寫圖片描述

假設直線斜率 0<=k<=1,且已經確定點亮的像素點P(Xp,Yp),則下一個點與直線最接近的像素只能是P1或者P2,即P點的正右方或者右上角的點。。設M爲P1P2的中點,Q爲與直線相交的點。。。現在我們需要確定下一個點亮的元素。。。只要判斷直線離P1更近還是離P2更近,那麼,當直線的交點Q與中點M進行比較即可,當Q在M的上方,則取P2,Q在M的下方則取P1。。。。那麼最後的問題歸結在了M在直線的上方還是下方還是在直線上

高中數學中,我們學過,直線的表達式 F(x,y) = ax+by+c,那麼我們把M的數值代入到直線表達式中即可,

當 F(x,y) = 0 ,點在直線上,任意取P1或者P2都可以
當 F(x,y) >0 ,點在直線上方,取P1,P1座標爲(Xp+1,Yp)
當 F(x,y) < 0 ,點在直線下方,取P2,P2座標爲(Xp+1,Yp+1)

我們只需要判斷符號,就可以判斷下一個點是P1還是P2

那麼我們是否可以用增量算法來判斷下一個點是否可以由上一個點表示呢?

構造判別式:
M點和Q點重合。。。
d 0= F(Xp+1,Yp+0.5) = a(Xp+1)+b(Yp+0.5)+C
=aXp+a+bYp+0.5b+C
=F(Xp,Yp)+a+0.5b
我們只需要判斷d>0還是d<0,那麼我們可以將d擴大兩倍,可以避開小數,變成整數,這樣的話:
d 0= 2a+b

當d>0 時,F(M)>0
F(M)=a(Xp+1)+bYp+C = aXp+a+bYp+C = F(Xp,Yp)+a
因爲P點已經是點亮的點,也就是在直線上
所以我們可以代入: d =d0+2a
增量爲2a

當d<0時,F(M)<0
F(M) = a(Xp+1)+b(Yp+1)+C = F(Xp,Yp)+a+b
同上面 d = d0+2a+2b
增量爲 2a+2b

上述過程爲0<=k<=1,同理我們得到其他斜率的增量

這裏寫圖片描述

下面來看效果:

這裏寫圖片描述

貼出代碼,在OpenGL中實現:

#include <GL\glut.h>
#include <cstdio>


GLint _x0,_y0,_x1,_y1;
void Init()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(-100, 100, -100, 100);
}

// 0≤k≤1
void MidpointLine1()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0f, 0.0f, 0.0f);
    GLint a, b, d, d1, d2, x, y;
    a = _y0 - _y1;
    b = _x1 - _x0;
    d = 2 * a + b;
    d1 = 2 * a;
    d2 = 2 * (a + b);
    x = _x0;
    y = _y0;
    glBegin(GL_POINTS);
    glVertex2i(x, y);
    glEnd();
    while (x < _x1)
    {
        if (d > 0)
        {
            x++;
            d += d1;
        }

        else
        {
            x++;
            y++;
            d += d2;
        }

        glBegin(GL_POINTS);
        glVertex2i(x, y);
        glEnd();

    }
    glFlush();
}

//-1≤k≤0
void MidpointLine2()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0f, 0.0f, 0.0f);
    GLint a, b, d, d1, d2, x, y;
    a = _y0 - _y1;
    b = _x1 - _x0;
    d = 2 * a - b;
    d2 = 2 * a;
    d1 = 2 * (a - b);
    x = _x0;
    y = _y0;

    glBegin(GL_POINTS);
    glVertex2i(x, y);
    glEnd();

    while (x < _x1)
    {
        if (d > 0)
        {
            x++;
            y--;
            d += d1;
        }

        else
        {
            x++;            
            d += d2;
        }

        glBegin(GL_POINTS);
        glVertex2i(x, y);
        glEnd();

    }
    glFlush();
}

//k>1  
void MidpointLine3()
{   
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0f, 0.0f, 0.0f);
    GLint a, b, d1, d2, d, x, y;
    a = _y0 - _y1;
    b = _x1 - _x0;
    d = a + 2 * b;
    d1 = 2 * (a + b);
    d2 = 2 * b;
    x = _x0;
    y = _y0;

    while (y<_y1)
    {
        if (d<0)
        {
            y++;
            d += d2;
        }
        else
        {
            y++;
            x++;
            d += d1;
        }
        glBegin(GL_POINTS);
        glVertex2i(x, y);
        glEnd();

    }
    glFlush();
}

//k<1  
void MidpointLine4()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0f, 0.0f, 0.0f);
    GLint a, b, d1, d2, d, x, y;
    a = _y0 - _y1;
    b = _x1 - _x0;
    d = a - 2 * b;
    d1 = -2 * b;
    d2 = 2 * (a - b);
    x = _x0;
    y = _y0;

    glBegin(GL_POINTS);
    glVertex2i(x, y);
    glEnd();

    while (y<_y1)
    {
        if (d<0)
        {
            x++;
            y--;
            d += d2;
        }
        else
        {
            y--;
            d += d1;
        }
        glBegin(GL_POINTS);
        glVertex2i(x, y);
        glEnd();

    }
    glFlush();
}


void main(int argc, char** argv)
{   
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(50, 100);
    glutInitWindowSize(500, 500);
    glutCreateWindow("MidpointLine");
    Init();

    scanf_s("%d%d%d%d", &_x0, &_y0, &_x1, &_y1);

    GLfloat k = GLfloat(_y1 - _y0) / GLfloat(_x1 - _x0);

    if(k>=0 && k<=1)
        glutDisplayFunc(MidpointLine1);
    else if(k>=-1 && k<=0)
        glutDisplayFunc(MidpointLine2);
    else if(k>1)
        glutDisplayFunc(MidpointLine3);
    else
        glutDisplayFunc(MidpointLine4); 
    glutMainLoop();

}

本篇到此爲止,希望各位大神指教,如有寫的不好的地方,不喜勿噴

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章