3
$\begingroup$

I am trying to draw an angled line in a raster grid.

The idea is to create a function that given a start point, a length and an angle, would give me the pixel positions that combined would give me a line at the specified angle, in a raster grid.

I tried to implement this in C++ but I seem to get some weird points...

The way I do it, is I compute the equation of the line, and thereby also the endpoint, and then use Bresenham's line algorithm to find the pixel positions that create the line between the start point and the end point.

Some of the points though, don't seem right. Some of the traversing points make no sense, or go to infinity. What is wrong with my implementation?

#include <iostream>
#include <math.h>
using namespace std;

int sign(double x ){ return (x > 0) ? 1 : ((x < 0) ? -1 : 0); }

std::pair<int,int> endpoint(double angle, int x1 , int y1, int lenght)
{

    if(angle == 90)
    {
        double y2 = y1+lenght;
        return std::make_pair(x1, -y2);
    }
    if(angle == 180)
    {
        double x2 = x1+lenght;
        return std::make_pair(-x2, y1);
    }
    if(angle == 270)
    {
        double y2 = y1+lenght;
        return std::make_pair(x1, y2);
    }


    double x2 = x1 + (lenght * cos(angle));
    double y2 = y1 + (lenght * sin(angle));
    return std::make_pair(x2,y2);
}


void bresenham(int x0, int y0, int x1, int y1)
{
    int dx = x1-x0;
    int dy = y1 - y0;
    if (abs(dx) > abs(dy))
    {
        // x-axis
        int j = y0;
        double e = dy - dx;

        for (int i = x0; i<x1; i++)
        {
            std::cout << "marked: " << i << ","<< j << std::endl;
            if( e >= 0)
            {
                j += 1;
                e -= dx;
            }
            e += dy;

        }
    }
    else if(abs(dx)<abs(dy))
    {
        // y-axis

        int j = x0;
        double e = dx - dy;

        for (int i = y0; i<y1; i++)
        {
            std::cout << "marked: " << j<< ","<< i << std::endl;
            if( e >= 0)
            {
                j += 1;
                e -= dy;
            }
            e += dx;

        }


    }

}


void line(int x0, int y0, int x1, int y1)
{

    if(x1 < x0)
    {
        swap(x1, x0);
    }

    if(y1 < y0)
    {
        swap(y1, y0);
    }


    int dx = x1-x0;
    int dy = y1-y0;
    double e = 0;
    if(dx == 0)
    {
        if (sign(dy) == -1)
        {
            cout << "new" << endl;
            for (int y = y0; y != y1; y--)
            {
                cout << "mark" << x1 << "," << y << endl;
            }

        }
        else
        {
            for (int y = y0; y != y1; y++)
            {
                cout << "mark" << x1 << "," << y << endl;
            }
        }
        return;
    }

    else if(dy == 0)
    {

        if (sign(dx) == -1)
        {
            cout << "new" << endl;

            for (int x = x0; x != x1; x--)
            {
                cout << "mark" << x << "," << y1 << endl;
            }

        }
        else
        {
            for (int y = y0; y != y1; y++)
            {
                cout << "mark" << x1 << "," << y << endl;
            }
        }
        return;
    }
    cout << "bressenham: " << endl;
    double de = abs(dy/dx);
    int y = y0;
    for (int x = x0; x != x1; x++)
    {
        cout << "mark: " << x << "," << y << endl;
        e = e + de;
        while (e >= 0.5)
        {
            cout << "mark: " << x << "," << y << endl;
            y = y + sign(y1-y0);
            e = e -1;
        }
    }


}

int main(int argc, const char * argv[])
{
    for (int angle = 0; angle < 180; angle++)
    {
        cout << "angle: " << angle << endl;
        pair<int, int> end = endpoint(angle, 3, 3, 20);
        cout << end.first << end.second << endl;
        line(3, 3, end.first, end.second);
        cout << end.first << end.second << endl;

    }
    return 0;
}
$\endgroup$
2

0

Browse other questions tagged or ask your own question.