Drawing lines with Bresenham's Line Algorithm

前端 未结 3 1840
日久生厌
日久生厌 2021-01-04 23:00

My computer graphics homework is to implement OpenGL algorithms using only the ability to draw points.

So obviously I need to get drawLine() to work bef

3条回答
  •  独厮守ぢ
    2021-01-04 23:34

    I implemented the original Bresenham's algorithm in C++ and tried to optimize as much as I could (especially regarding removing the IF from the interior loop).

    It draws in a linear buffer instead of a surface, and for this matter, this implementation was almost as fast as EFLA (Extremely Fast Line Algorithm) (maybe 5% slower).

    #include 
    #include 
    using namespace std;
    
    vector buffer;
    
    int imageSide = 2048; // the width of the surface
    
    struct Point2Di
    {
        int x;
        int y;
        Point2Di(const int &x, const int &y): x(x), y(y){}
        Point2Di(){}
    
    };
    
    void drawLine(const Point2Di &p0, const Point2Di &p1)
    {
        int dx = p1.x - p0.x;
        int dy = p1.y - p0.y;
    
        int dLong = abs(dx);
        int dShort = abs(dy);
    
        int offsetLong = dx > 0 ? 1 : -1;
        int offsetShort = dy > 0 ? imageSide : -imageSide;
    
        if(dLong < dShort)
        {
            swap(dShort, dLong);
            swap(offsetShort, offsetLong);
        }
    
        int error = dLong/2;
        int index = p0.y*imageSide + p0.x;
        const int offset[] = {offsetLong, offsetLong + offsetShort};
        const int abs_d[]  = {dShort, dShort - dLong};
        for(int i = 0; i <= dLong; ++i)
        {
            buffer[index] = 255;  // or a call to your painting method
            const int errorIsTooBig = error >= dLong;
            index += offset[errorIsTooBig];
            error += abs_d[errorIsTooBig];
        }
    }
    

    The EFLA implementation that I am using is:

    void drawLine(Point2Di p0,  Point2Di p1)
    {
        bool yLonger=false;
        int shortLen=p1.y-p0.y;
        int longLen=p1.x-p0.x;
        if (abs(shortLen)>abs(longLen)) {
            swap(shortLen, longLen);
            yLonger=true;
        }
        int decInc = longLen==0 ?  decInc=0 : ((shortLen << 16) / longLen);
    
        if (yLonger) {
            p0.y*=imageSide;
            p1.y*=imageSide;
            if (longLen>0)
                for (int j=0x8000+(p0.x<<16);p0.y<=p1.y;p0.y+=imageSide, j+=decInc)
                    buffer[p0.y + (j >> 16)] = 255;  // or a call to your painting method
            else
                for (int j=0x8000+(p0.x<<16);p0.y>=p1.y;p0.y-=imageSide, j-=decInc)
                    buffer[p0.y + (j >> 16)] = 255;  // or a call to your painting method
        }
        else
        {
            if (longLen>0)
                for (int j=0x8000+(p0.y<<16);p0.x<=p1.x;++p0.x, j+=decInc)
                    buffer[(j >> 16) * imageSide + p0.x] = 255;  // or a call to your painting method
            else
                for (int j=0x8000+(p0.y<<16);p0.x>=p1.x;--p0.x, j-=decInc)
                    buffer[(j >> 16) * imageSide + p0.x] = 255;  // or a call to your painting method
        }
    }
    

提交回复
热议问题