计算机图形学DDA画线法+中点画线法+Bresenham画线法

Posted sufferingStriver

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机图形学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;
}
效果图:
技术分享图片
技术分享图片
技术分享图片
技术分享图片





以上是关于计算机图形学DDA画线法+中点画线法+Bresenham画线法的主要内容,如果未能解决你的问题,请参考以下文章

用C++如何实现bresenham画线算法?计算机图形学上面有个drawpixel的函数。不知道怎么用。

求计算机图形学中的直线绘制函数法、DDA算法、中点法和Bresenham算法的优缺点以及比较.

Bresenham画线算法

中点画线法画圆

计算机图形学第一次实验

计算机图形学之扫描转换直线-DDA,Bresenham,中点画线算法