計算機輔助設計與圖形學——Bresenham直線算法的實現

Bresenham直線算法原理可以很容易的找到,在此不做介紹。在算法中要注意對直線進行分類,包括直線指向第幾象限以及斜率與正負1的大小比較。

判斷直線指向第幾象限:

  1. 直線指向第一象限:X方向的增量爲正,Y方向的增量爲正。
  2. 直線指向第二象限:X方向的增量爲負,Y方向的增量爲正。
  3. 直線指向第三象限:X方向的增量爲負,Y方向的增量爲負。
  4. 直線指向第四象限:X方向的增量爲正,Y方向的增量爲負。
斜率與正負1的大小:
若X方向增量的絕對值>Y方向增量的絕對值,則Bresenham算法每次迭代需要以x作爲自變量,來判斷y是否變化;
若X方向增量的絕對值<Y方向增量的絕對值,則Bresenham算法每次迭代需要以y作爲自變量,來判斷x是否變化。

以下是用C++語言在Qt中做的Bresenham算法生成直線的主要代碼,在此還需要注意的是不同的環境下的座標系統可能不同。Qt的座標系如圖所示:

    QPainter painter(this);
    painter.drawPixmap(0, 0, pix);

    QPen pen;
    pen.setColor(Qt::black); //設置畫筆的顏色
    painter.setPen(pen); //設置畫筆

    //Bresenham畫直線算法
    if(ButtonLineBool && flagLine)
    {
        QPainter pp(&pix);
        pp.setPen(pen);
        //pp.translate(firstPoint);
        qDebug() << firstPoint << secondPoint << endl;
        int x0 = firstPoint.x();
        int y0 = firstPoint.y(); //起點
        int x1 = secondPoint.x();
        int y1 = secondPoint.y(); //終點
        int deltaX = x1-x0, deltaY = y1-y0; // x、y方向上的增量
        int a = -deltaY, b = deltaX; //其直線方程爲 ax+by+c=0
        qDebug() << a << b << endl;

        int x = x0, y = y0; //初始點
        if( deltaX>=0 && deltaY>=0 ) //第一象限
        {
            if( qAbs(deltaX)>=qAbs(deltaY) ) //第一象限,斜率小於1時,x增量
            {
                int d = 2*a+b; //避免浮點運算
                while( x<=x1 )
                {
                    pp.drawPoint(x,y);
                    if( d<0 )
                    {
                        d += 2*(a+b);
                        y++;
                    }
                    else
                    {
                        d += 2*a;
                    }
                    x++;
                }
            }
            else  //第一象限,斜率大於1時,y增量
            {
                int d = a+2*b;
                while( y<=y1 )
                {
                    pp.drawPoint(x,y);
                    if( d<0 )
                    {
                        d += 2*b;
                    }
                    else
                    {
                        d += 2*(a+b);
                        x++;
                    }
                    y++;
                }
            }
        }

        else
        {
            if( deltaX>0 && deltaY<0 ) // 第四象限
            {
                if( qAbs(deltaX)>=qAbs(deltaY) ) //第四象限,斜率大於-1時,x增量
                {
                    int d = 2*a-b; //避免浮點運算
                    while( x<=x1 )
                    {
                        pp.drawPoint(x,y);
                        if( d<0 )
                        {
                            d += 2*a;
                        }
                        else
                        {
                            d += 2*(a-b);
                            y--;
                        }
                        x++;
                    }
                }
                else  //第四象限,斜率小於-1時,y增量
                {
                    int d = a-2*b;
                    while( y>=y1 )
                    {
                        pp.drawPoint(x,y);
                        if( d<0 )
                        {
                            d += 2*(a-b);
                            x++;
                        }
                        else
                        {
                            d -= 2*b;
                        }
                        y--;
                    }
                }
            }
            else
            {
                if( deltaX<0 && deltaY>0 ) // 第二象限
                {
                    if( qAbs(deltaX)>=qAbs(deltaY) ) //第二象限,斜率大於-1時,x增量
                    {
                        int d = -2*a+b; //避免浮點運算
                        while( x>=x1 )
                        {
                            pp.drawPoint(x,y);
                            if( d<0 )
                            {
                                d -= 2*a;
                            }
                            else
                            {
                                d += 2*(-a+b);
                                y++;
                            }
                            x--;
                        }
                    }
                    else  //第二象限,斜率小於-1時,y增量
                    {
                        int d = -a+2*b;
                        while( y<=y1 )
                        {
                            pp.drawPoint(x,y);
                            if( d<0 )
                            {
                                d += 2*(-a+b);
                                x--;
                            }
                            else
                            {
                                d += 2*b;
                            }
                            y++;
                        }
                    }
                }

                else  // 第三象限 deltaX<=0 && deltaY<=0
                {
                    if( qAbs(deltaX)>=qAbs(deltaY) ) //第三象限,x增量
                    {
                        int d = -2*a-b; //避免浮點運算
                        while( x>=x1 )
                        {
                            pp.drawPoint(x,y);
                            if( d<0 )
                            {
                                d -= 2*(a+b);
                                y--;
                            }
                            else
                            {
                                d -= 2*a;
                            }
                            x--;
                        }
                    }
                    else  //第三象限,y增量
                    {
                        int d = -a-2*b;
                        while( y>=y1 )
                        {
                            pp.drawPoint(x,y);
                            if( d<0 )
                            {
                                d -= 2*b;
                            }
                            else
                            {
                                d -= 2*(a+b);
                                x--;
                            }
                            y--;
                        }
                    }
                }
            }
        }

    }
    else
    {;}


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