4

我实现了我在网上找到的这个算法,它可以很好地绘制水平线和所有对角线的一半。但是当对角线通过“中途”标记变为垂直时,它不会更新 y 并且只会绘制斜率较小的线。它确实将它一直绘制到 x2,但绘制了一条倾斜到不同 y2 坐标的线。如果你尝试画一条垂直线,什么也画不出来。任何人都可以找到错误吗?

void init()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 500.0, 0.0, 500.0);
}

void midPoint(int x1, int y1, int x2, int y2)
{
    if (x1 > x2)
    {
        midPoint(x2, y2, x1, y1);
        return;
    }

    int slope;
    int dx, dy, d, x, y;

    dx = x2 - x1;
    dy = y2 - y1;
    d = dx - 2 * dy;
    y = y1;

    if (dy < 0) {
        slope = -1;
        dy = -dy;
    }
    else {
        slope = 1;
    }

    for (x = x1; x < x2; x++) {
        glBegin(GL_POINTS);
        glVertex2f(x, y);
        if (d <= 0) {
            d += 2 * dx - 2 * dy;
            y += slope;
        }
        else {
            d += -2 * dy;
        }
        glEnd();
    }

}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glColor3f(1.0, 0.0, 0.0);
    midPoint(10, 10, 110, 210);

    glColor3f(0.0, 1.0, 0.0);
    midPoint(10, 10, 210, 110);

    glColor3f(1.0, 1.0, 0.0);
    midPoint(210, 10, 10, 110);

    glFlush();
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(50, 50);
    glutInitWindowSize(500, 500);
    glutCreateWindow("Bresenham\'s midpoint line algorithm");
    init();
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;
}
4

3 回答 3

2

Bresenham 的线条绘制算法无法绘制垂直线。要绘制垂直线,请使用 DDA 线绘制算法。但 DDA 的问题在于,它并不准确。

于 2014-06-08T18:32:39.300 回答
0

按照维基百科的定义,实现看起来像:

void midPoint(int x1, int y1, int x2, int y2)
{
    bool steep = abs(y2 - y1) > abs(x2 - x1);
    if(steep) {
        // swap x1 and y1
        int tmp = x1;
        x1 = y1;
        y1 = tmp;
        // swap x2 and y2
        tmp = x2;
        x2 = y2;
        y2 = tmp;
    }
    if(x1 > x2) {
        // swap x1 and x2
        int tmp = x1;
        x1 = x2;
        x2 = tmp;
        // swap y1 and y2
        tmp = y1;
        y1 = y2;
        y2 = tmp;
    }

    int dx, dy, error, ystep, y;

    dx = x2 - x1;
    dy = abs(y2 - y1);
    error = dx / 2;
    y = y1;

    if(y1 < y2)
        ystep = 1;
    else
        ystep = -1;

    glBegin(GL_POINTS);
    for (x = x1; x <= x2; x++) {
        if(steep)
            glVertex2f(y, x);
        else
            glVertex2f(x, y);
        error -= dy;
        if (error < 0) {
            y += ystep;
            error += dx;
        }
    }
    glEnd();
}

(尚无法测试,但已针对 aschepler 的评论进行了修复)

于 2013-02-06T18:49:50.210 回答
0

我遇到了同样的问题,解决方案似乎很简单。while循环是正确渲染垂直线的关键。

下面的代码是来自我的 Java 图形项目的代码。z 坐标用于 z 缓冲区。

请注意,当采样沿 x 轴时,循环运行 dx 次,而当采样沿 y 轴时,循环运行 dy 次

display.setColor(Color.BLACK);
dx=x2-x1;
dy=y2-y1;

if(dx<0)
    xinc=-1;
else
    xinc=1;
if(dy<0)
    yinc=-1;
else
    yinc=1;
zinc=z2-z1;


dx=Math.abs(dx);dy=Math.abs(dy);
if(dx>dy){
    zinc/=dx;
    dy=dy<<1;
    p=dy-dx;
    y2=dx;
    dx=dx<<1;

    display.drawPixel(x1, y1, z1);
    for(j=0;j<y2;j++){
        z1+=zinc;
        if(p>=0){
            p-=dx;
            y1+=yinc;
        }
        x1+=xinc;
        p+=dy;
        display.drawPixel(x1, y1, z1);
    }


}
else{
    zinc/=dy;
    dx=dx<<1;
    p=dx-dy;
    x2=dy;
    dy=dy<<1;
    display.drawPixel(x1, y1, z1);
    for(j=0;j<x2;j++){
        z1+=zinc;
        if(p>=0){
            p-=dy;
            x1+=xinc;
        }
        y1+=yinc;
        p+=dx;
        //System.out.println("Pixel : "+x1+" ,"+y1);
        display.drawPixel(x1, y1, z1);
    }
}
于 2017-02-14T18:32:14.940 回答