計算機圖形學DDA畫線法+中點畫線法+Bresenham畫線法


#include <cstdio>
#include <cstring>
#include <conio.h>
#include <graphics.h>
void line1(){
    line(100, 100, 200, 400);
    line(100, 400, 200, 100);
    line(0, 200, 300, 300);
    line(0, 300, 300, 200);
}

void lineDDA(int x0, int y0, int x1, int y1, int color){
    int x;
    float dy, dx, y, m;
    dx = x1 - x0;
    dy = y1 - y0;
    m = dy / dx;
    y = y0;
    for (x = x0; x <= x1; x++){
        putpixel(x, (int)(y + 0.5), color);
        y += m;
    }
}

void lineDDA(){
    lineDDA(100, 100, 200, 400, RED);
    lineDDA(100, 400, 200, 100, RED);
    lineDDA(0, 200, 300, 300, RED);
    lineDDA(0, 300, 300, 200, RED);
}

void lineMidPoint(int x0, int y0, int x1, int y1, int color){
    int x = x0, y = y0;
    int a = y0 - y1, b = x1 - x0;
    int cx = (b >= 0 ? 1 : (b = -b, -1));
    int cy = (a <= 0 ? 1 : (a = -a, -1));

    putpixel(x, y, color);

    int d, d1, d2;
    if (-a <= b)     // 斜率絕對值 <= 1  
    {
        d = 2 * a + b;
        d1 = 2 * a;
        d2 = 2 * (a + b);
        while (x != x1)
        {
            if (d < 0)
                y += cy, d += d2;
            else
                d += d1;
            x += cx;
            putpixel(x, y, color);
        }
    }
    else                // 斜率絕對值 > 1  
    {
        d = 2 * b + a;
        d1 = 2 * b;
        d2 = 2 * (a + b);
        while (y != y1)
        {
            if (d < 0)
                d += d1;
            else
                x += cx, d += d2;
            y += cy;
            putpixel(x, y, color);
        }
    }
}

void lineMidPoint(){
    lineMidPoint(100, 100, 200, 400, GREEN);
    lineMidPoint(100, 400, 200, 100, GREEN);
    lineMidPoint(0, 200, 300, 300, GREEN);
    lineMidPoint(0, 300, 300, 200, GREEN);
}

void lineBresenham(int x0, int y0, int x1, int y1, int color)
{
    int dx = x1 - x0;
    int dy = y1 - y0;
    int ux = dx >0 ? 1 : -1;//x伸展方向  
    int uy = dy >0 ? 1 : -1;//y伸展方向  
    int dx2 = dx << 1;//x偏移量乘2  
    int dy2 = dy << 1;//y偏移量乘2  
    if (abs(dx)>abs(dy))
    {//以x為增量方向計算  
        int e = -dx; //e = -0.5 * 2 * dx,把e 用2 * dx* e替換  
        int x = x0;
        int y = y0;//起點y坐標  
        for (x = x0; x < x1; x += ux)
        {
            putpixel(x, y, color);
            e = e + dy2;//來自 2*e*dx= 2*e*dx + 2dy  (原來是 e = e + k)  
            if (e > 0)//e是整數且大於0時表示要取右上的點(否則是右下的點)   
            {
                y += uy;
                e = e - dx2;//2*e*dx = 2*e*dx - 2*dx  (原來是 e = e -1)  
            }
        }
    }
    else
    {//以y為增量方向計算  
        int e = -dy; //e = -0.5 * 2 * dy,把e 用2 * dy* e替換  
        int x = x0;
        int y = y0;
        for (y = y0; y < y1; y += uy)
        {
            putpixel(x, y, color);
            e = e + dx2;//來自 2*e*dy= 2*e*dy + 2dy  (原來是 e = e + k)  
            if (e > 0)//e是整數且大於0時表示要取右上的點(否則是右下的點)   
            {
                x += ux;
                e = e - dy2;//2*e*dy = 2*e*dy - 2*dy  (原來是 e = e -1)  
            }
        }
    }
}

void lineBresenham1(int x0, int y0, int x1, int y1, long color)
{
    int dx = abs(x1 - x0);
    int dy = abs(y1 - y0);
    int x = x0;
    int y = y0;
    int stepX = 1;
    int stepY = 1;
    if (x0 > x1)  //從右向左畫  
        stepX = -1;
    if (y0 > y1)
        stepY = -1;

    if (dx > dy)  //沿着最長的那個軸前進  
    {
        int e = dy * 2 - dx;
        for (int i = 0; i <= dx; i++)
        {
            putpixel(x, y, color);
            x += stepX;
            e += dy;
            if (e >= 0)
            {
                y += stepY;
                e -= dx;
            }
        }
    }
    else
    {
        int e = 2 * dx - dy;
        for (int i = 0; i <= dy; i++)
        {
            putpixel(x, y, color);
            y += stepY;
            e += dx;
            if (e >= 0)
            {
                x += stepX;
                e -= dy;
            }
        }
    }
}

void lineBresenham(){
    lineBresenham1(100, 100, 200, 400, YELLOW);
    lineBresenham1(100, 400, 200, 100, YELLOW);
    lineBresenham1(0, 200, 300, 300, YELLOW);
    lineBresenham1(0, 300, 300, 200, YELLOW);
}




void showWord(int code){
    outtextxy(200, 30, "單擊右鍵退出");
    switch (code){
    case 1://原畫
        outtextxy(200, 10, "easyX系統畫線算法");
        break;
    case 2://DDA算法
        outtextxy(200, 10, "DDA算法");
        break;
    case 3://中點畫線算法
        outtextxy(200, 10, "中點畫線算法");
        break;
    case 4://Bresenham算法
        outtextxy(200, 10, "Bresenham算法");
        break;
    default:
        line1();
        break;
    }
}

void drawLine(int code){
    switch (code){
    case 1://原畫
        line1();
        break;
    case 2://DDA算法
        lineDDA();
        break;
    case 3://中點畫線算法
        lineMidPoint();
        break;
    case 4://Bresenham算法
        lineBresenham();
        break;
    default:
        line1();
        break;
    }
}

void drawLine(int x0,int y0,int x1,int y1,int code){
    showWord(code);
    switch (code){
    case 1://原畫
        line(x0,y0,x1,y1);
        break;
    case 2://DDA算法
        lineDDA(x0, y0, x1, y1,WHITE);
        break;
    case 3://中點畫線算法
        lineMidPoint(x0, y0, x1, y1, WHITE);
        break;
    case 4://Bresenham算法
        lineBresenham1(x0, y0, x1, y1, WHITE);
        break;
    default:
        line1();
        break;
    }
}


void showWORDXY(int x, int y, int showX, int showY,int flag){
    char dintX[5] = { 0 };
    char dintY[5] = { 0 };
    _itoa_s(showX, dintX, 10);//把整數showX轉成字符串dintX
    _itoa_s(showY, dintY, 10);//把整數showY轉成字符串dintY
    char str1[100] = "第一個點的坐標:(";//此時數組沒有定義長度   元素的個數應該為strlen +1  因為字符串末尾有 '\0'結束 
    char str2[100] = "第二個點的坐標:(";
    if (flag == 1){
        // _countof(dintX)能夠獲取到數組中元素的個數 含‘\0’
        strcat_s(str1, strlen(str1) + strlen(dintX)+1, dintX);
        strcat_s(str1, strlen(str1) + strlen(",")+1, ",");
        strcat_s(str1, strlen(str1) + strlen(dintY)+1, dintY);
        strcat_s(str1, strlen(str1) + strlen(")")+1, ")");
        outtextxy(x, y, str1);
    }
    else if (flag == 2){
        strcat_s(str2, strlen(str2) + strlen(dintX)+1, dintX);
        strcat_s(str2, strlen(str2) + strlen(",")+1, ",");
        strcat_s(str2, strlen(str2) + strlen(dintY)+1, dintY);
        strcat_s(str2, strlen(str2) + strlen(")")+1, ")");
        outtextxy(x, y, str2);
    }
}

//調用easyX
void easyX(int code){
    initgraph(640, 480);       //初始化
    showWord(code);
    MOUSEMSG m; // 定義鼠標消息
    int n=0;//讀取兩個點
    int exit = false;
    int x0=0, y0=0,x1=0,y1=0;
    while (n<2 && !exit)
    {
        m = GetMouseMsg();
        switch (m.uMsg)
        {
        case WM_RBUTTONDOWN:
            outtextxy(200, 300, "再次點擊鍵退出");
            exit = true;
            break;    // 按鼠標右鍵退出程序
        }
        while (m.uMsg != WM_LBUTTONDOWN){
            m = GetMouseMsg();
            switch (m.uMsg)
            {
            case WM_RBUTTONDOWN:
                outtextxy(200, 300, "再次點擊鍵退出");
                exit = true;
                break;    // 按鼠標右鍵退出程序
            }

        }
        while (m.uMsg != WM_LBUTTONUP){
            m = GetMouseMsg();

            cleardevice();
            showWord(code);
            if (n == 0){
                showWORDXY(200, 430, x0, y0,1);
                x0 = m.x;
                y0 = m.y;
            }
            else{
                showWORDXY(200, 430, x0, y0, 1);
                showWORDXY(200, 450, x1, y1, 2);
                x1 = m.x;
                y1 = m.y;
            }
        }
        n++;
        if (n == 2){
            //畫線
            drawLine(x0, y0, x1, y1, code);
            //重置
            n = 0;
        }
    }
    //_getch();                  //等待用戶操作
    closegraph();             //關閉圖形
}

int main(){
    int n = 1;
    printf("請選擇畫線算法畫線:\n");
    printf("1.easyX系統畫線函數.\n");
    printf("2.DDA畫線算法函數.\n");
    printf("3.中點畫線算法函數.\n");
    printf("4.Bresenham畫線算法函數.\n");
    printf("0.退出.\n");
    while (n != 0){
        scanf_s("%d", &n);
        if (n == 0){
            exit(0);
        }
        easyX(n);
    }
    return 0;
}
效果圖:




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM