【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();

}

本篇到此为止,希望各位大神指教,如有写的不好的地方,不喜勿喷

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