How do I draw an angled Line

Evelknet

I tried to do just draw some lines and shapes in a window with c (without a library which does it for me with one or two lines) to learn a bit. I can already draw horizontal and vertical lines and rectangles. Now, I want to draw angled lines. This is the entire code:

#include <windows.h>
#include <stdint.h>

typedef uint32_t u32;

int running = 1;
int width = 0;
int height = 0;
int rgb=0;

int pointA[]={100,100};
int pointB[]={200,100};

void* memory;
BITMAPINFO bitmap_info;

//Farben
u32 red = 0xFF0000;
u32 green = 0x00FF00;
u32 blue = 0x0000FF; 
u32 black = 0x000000;
u32 white = 0xFFFFFF;

int calculateCord(int x, int y){
    int memoryNumber=(height-y+1)*width-(width-x+1);
    return memoryNumber;
}

void setBackground(u32 color)
{
    u32 *pixel = (u32 *)memory; 
    for (int memoryNumber=0;memoryNumber<width*height;++memoryNumber)
    {
        *pixel++=color;
    }
}
void drawPixel(u32 color,int x,int y)
{
    u32 *pixel = (u32 *)memory;
    pixel += calculateCord(x,y);
    *pixel=color;

}
void drawLineHor(u32 color,int x,int y,int lineWidth,int direction)
{
    u32 *pixel=(u32 *)memory;
    pixel+=calculateCord(x,y);
    for(int a=0;a<lineWidth;a++)
    {
        if(direction ==0){
            *pixel++=color;
        }else{
            *pixel--=color;
        }
       
    }
}
void drawLineVert(u32 color,int x,int y,int lineHeight,int direction)
{
    u32 *pixel=(u32 *)memory;
    pixel+=calculateCord(x,y);
    *pixel=color;
    for(int b=0;b<lineHeight;b++)
    {
        *pixel=color;
        if(direction==0){
            pixel-= width;
        }else {
            pixel += width;
        }
         
    }
}
void drawLineDiagonal(u32 color,int x,int y,int distance,int direction)
{
    u32 *pixel=(u32 *)memory;
    pixel+=calculateCord(x,y);
    *pixel=color;
    for(int a=0;a<distance;a++){
        
        if (direction==0){
            *pixel++=color;
            pixel -= width;
        }else{
            *pixel--=color;
            pixel += width;
        }
    }
}
void drawLineAngle(u32 color,int x,int y,int targetX,int targetY)
{
    u32 *pixel=(u32 *)memory;
    pixel += calculateCord(x,y);
    *pixel=color;
    int difX=targetX-x+1;
    int difY=targetY-y+1;
    float ratioX= difX/difY;
    if(ratioX>=1){
        for (int b=0;b<difY;b++)
        {
            for(int a=0;a<=ratioX;a++)
            {
                *pixel++=color;
            }
            *pixel=color;
            pixel -= width;
        }
    }
}
void drawRect(u32 color,int x,int y,int rectWidth,int rectHeight)
{
    u32 *pixel=(u32 *)memory;
    pixel+=calculateCord(x,y);
    *pixel=color;
    for (int a=0;a<rectWidth;a++)
    {
        *pixel++=color;
    }
    for(int b=0;b<rectHeight;b++)
    {
        *pixel=color;
        pixel -= width;
    }
    for (int a=0;a<rectWidth;a++)
    {
        *pixel--=color;
    }
    for(int b=0;b<rectHeight;b++)
    {
        *pixel=color;
        pixel += width;
    }
}
void fillRect(u32 color,int x,int y,int rectWidth,int rectHeight)
{
    u32 *pixel=(u32 *)memory;
    pixel += calculateCord(x,y);
    *pixel=color;
    for(int b=0;b<rectHeight;b++)
    {
        for(int a=0;a<rectWidth;a++)
        {
            *pixel++=color;
        }
        pixel -= width+rectWidth;
        *pixel=color;
    }

}

LRESULT CALLBACK
WindowProc(HWND window, 
           UINT message, 
           WPARAM w_param, 
           LPARAM l_param)
{
    LRESULT result;
    switch(message)
    {
        case WM_CLOSE:
        {
            running = 0;
            printf("Ende");
        } break;
        default:
        {
            result = DefWindowProc(window,
                                   message, 
                                   w_param, 
                                   l_param);
        } break;
    }
    return result;
}

int WINAPI 
wWinMain(HINSTANCE instance, 
         HINSTANCE prev_instance, 
         PWSTR cmd_line, 
         int cmd_show)
{
    WNDCLASS window_class = {0};
    
    wchar_t class_name[] = L"GameWindowClass";
    
    window_class.lpfnWndProc = WindowProc;
    window_class.hInstance = instance;
    window_class.lpszClassName = class_name;
    
    RegisterClass(&window_class);
    
    HWND window = CreateWindowEx(0,
                                 class_name,
                                 L"Fenster",
                                 WS_OVERLAPPEDWINDOW|WS_VISIBLE,
                                 CW_USEDEFAULT,
                                 CW_USEDEFAULT,
                                 CW_USEDEFAULT,
                                 CW_USEDEFAULT,
                                 0,
                                 0,
                                 instance,
                                 0);
    
    RECT rect;
    GetClientRect(window, &rect);
    width = rect.right - rect.left;
    height = rect.bottom - rect.top;
    
    memory = VirtualAlloc(0,
                          width * height * 4,
                          MEM_RESERVE|MEM_COMMIT,
                          PAGE_READWRITE);

    setBackground(black);
    drawLineAngled(red,100,100,140,150);
    drawPixel(blue,140,150);
    drawPixel(green,100,100);


    bitmap_info.bmiHeader.biSize = sizeof(bitmap_info.bmiHeader);
    bitmap_info.bmiHeader.biWidth = width;
    bitmap_info.bmiHeader.biHeight = height;
    bitmap_info.bmiHeader.biPlanes = 1;
    bitmap_info.bmiHeader.biBitCount = 32;
    bitmap_info.bmiHeader.biCompression = BI_RGB;
    HDC hdc = GetDC(window);
    
    while(running)
    {
        MSG message;
        while(PeekMessage(&message, window, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&message);
            DispatchMessage(&message);
        }
        StretchDIBits(hdc,
                      0,
                      0,
                      width,
                      height,
                      0,
                      0,
                      width,
                      height,
                      memory,
                      &bitmap_info,
                      DIB_RGB_COLORS,
                      SRCCOPY);
    }
    return 0;
}

This is just the part of the angled line:

void drawLineAngled(u32 color,int x,int y,int targetX,int targetY)
{
    u32 *pixel=(u32 *)memory;
    pixel += calculateCord(x,y);
    *pixel=color;
    int difX=targetX-x+1;
    int difY=targetY-y+1;
    float ratioX= difX/difY;
    if(ratioX>=1){
        for (int b=0;b<difY;b++)
        {
            for(int a=0;a<=ratioX;a++)
            {
                *pixel++=color;
            }
            *pixel=color;
            pixel -= width;
        }
    }

When I execute it it draws an angled line but not to the point. The line ends a bit pixels right of the target point. I know that the code isn't the prettiest and there are some points to improve but I wanted to concentrate on this first.(Sorry for my English)

(Edit) Now i got this code wich works fine

void drawAngledLine(u32 color,int originX,int originY,int targetX,int targetY)
{
    int swap=0;
    if(originX > targetX || originY > targetY){
        int swapX=originX;
        originX=targetX;
        targetX=swapX;

        int swapY=originY;
        originY=targetY;
        targetY=swapY;

        swap=1;
    }

    const float m= (float)(targetY-originY)/ (float)(targetX-originX);
    const float b= originY-m*(float)originX;

    if(m<=1){
        for(int x=originX;x<targetX;x++)
        {
            float y=m*(float)x+b;
            y+=0.5;
            drawPixel(color,x,(int)y);
        }
    }else{
        const float w=(float)(targetX-originX)/(float)(targetY-originY);
        const float v=originX-w*(float)originY;

        for(int y=originY;y<targetY;y++)
        {
            float x=w*(float)y+v;
            x+=0.5;
            drawPixel(color,(int)x,y);
        }
    }
    if(swap=0){
        drawPixel(green,originX,originY);
        drawPixel(blue,targetX,targetY);
    }else{
        drawPixel(green,targetX,targetY);
        drawPixel(blue,targetX,targetY);
    }
}
jordanvrtanoski

You have problem with the remainder from the ratio devision in the following line for(int a=0;a<=ratioX;a++)

Though the ratioX is a float, the loop will work until the integer part of the number. Whatever remained from the difference of ratioX - (int)ratioX.

Solution is same as we had solved the leap year problem. We accumulate the extra 6h of the year's duration and we add one day on each 4 years. In a same manner, you need to accumulate this difference and add an extra pixel each time the accumulator passes 1 (and deduct 1 from the accumulator).

This will leave you with a problem with the last pixel. Sometimes, your line will be one pixel short, even with all of the compensations. So you might set the last pixel on the targetX,targetY explicitly.

Here is the example based on the code above:

void drawLineAngled(u32 color,int x,int y,int targetX,int targetY)
{
    u32 *pixel=(u32 *)memory;
    pixel += calculateCord(x,y);
    *pixel=color;
    int difX=targetX-x+1;
    int difY=targetY-y+1;
    float ratioX= difX/difY;
    const float remainderConst=ratioX-(int)ratioX;
    float remainder=0;
    if(ratioX>=1){
        for (int b=0;b<difY;b++)
        {
            for(int a=0;a<=ratioX;a++)
            {
                *pixel++=color;
            }
            // Add the pixel fraction that we had skipped in the loop
            remainder+=remainderConst;
            // If the skipped fractions accumulate to 1 or more, add a pixel
            if (remainder >= 1) {
                *pixel++=color;
                reminder--;
            }
            *pixel=color;
            pixel -= width;
        }
    }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How can I draw a right-angled triangle in Python/PsychoPy?

How do I draw a line on a Lazarus form?

How do I draw a line in Forth with OpenGL?

Basics of LiveCharts -- How do I draw a Line?

How do I remove the line if draw the new line

How do I use a function to draw a line in pyglet?

How do I draw a line along the center of the object

How do I draw an Ideal line between two headers?

How do I animate a line from my draw() function?

How do I draw a line over the Poisson curve?

How do I draw a line in CSS that starts wide and ends in a point

How do I draw a line connecting subplots in pyplot?

How do I draw a horizontal line between two circles with CSS?

How do I draw line from the outer most arc of the circle

How do I draw a vertical line from the middle of this button?

How do I get graphicsmagick to draw a line inside a BMP file?

python: how do I draw a line graph of the following function?

How to draw a rectangle with an angled corner in SVG

How to draw angled rectangle as background for ViewPager android

How to draw right angled triangle with python

How to calculate a point horizontaly projected to an angled line

How to draw a circle inside a right angled triangle in html page?

How to draw sharp curves and angled lines on Canvas in Android

How can I draw a line beside a boxplot

how can I draw a line with title in React?

How can I make angled table headers?

How do i get the graph to draw a line for constant 0 values using amcharts?

How do I draw a line in Visio 2010 without the end points jumping around?

How do I draw multiple lines in amcharts line graph using json?