计算机图形学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;
}效果图:

原文地址:https://www.cnblogs.com/sufferingStriver/p/8778266.html

时间: 2024-10-20 03:45:53

计算机图形学DDA画线法+中点画线法+Bresenham画线法的相关文章

计算机图形学中的中点画线,中点画圆,Bresenham画线与画圆算法

#include<iostream>#include<graphics.h>  // 这样引用 EasyX 图形库#include<conio.h>#include<time.h>#include<math.h>#include<stdlib.h>using namespace std; //Bresenham画线void Bresenham_line(int x0,int y0,int x1,int y1){ int x,y,dx,

计算机图形学-mac系统下Xcode中OpenGL开发环境配置。

mac系统下Xcode中OpenGL开发环境配置. 这学期有计算机图形学的课程,需要用到OpenGL,最近着手开始配置开发环境了,老师上课给的安装包都是基于windows系统的.网上也是windows上配置的教程比较多,Mac版的比较少.我综合了几个教程并自己总结,实践成功.特来分享配置过程.希望能帮到大家! 介绍 OpenGL(Open Graphics Library)是定义了一个跨编程语言,跨平台的编程接口规格的专业的图形程序接口.它用于三维图像(二维亦可),是一个功能强大,与硬件无关,调

中点画圆算法

[中点画圆算法] 此算是一种圆的光栅化算法.定义以下函数: 通过上述函数,可以得到点(x,y)与半径为r的圆的关系: 已知点(Xk,Yk),我们需要知道(Xk+1,Yk).(Xk+1,Yk-1)哪一个更接近圆.决策方程如下: 如果Pk小于0,那么中点位于圆内,扫描线Yk上的像素更接近于圆.否则,中点位于圆外,应该选择Yk - 1. 参考:<计算机图形学>3.9.2 中点画圆算法 中点画圆算法

图形学--(中点画线法+Bresenham画线算法)

编程环境:codeblocks+EGE库 用到的函数:putpixel(int x1,int y1,int color)  用某种颜色打亮一个坐标点. 这俩种算法都是用来在计算机上画一条直线的,那么我们为什么不直接用直线方程分别带点再打亮呢,这是因为,计算机中每个坐标点都是整数,而直线是由一个个像素点组合而成的,那么,直接将坐标点再进行四舍五入整数化就好了啊,的确,这是一种方法,但计算机中进行浮点数的四舍五入会使运算效率变差,因此真正画直线时是用到上边这俩种方法的. 1.中点画线法 只考虑当直线

扫描转换算法——DDA、中点画线画圆、椭圆

我的理解:在光栅图形学中,由于每一个点的表示都只能是整数值,所以光栅图形学实际只是对对实际图形的近似表示. 数值微分法(DDA):以下PPT截图来自北京化工大学李辉老师 代码实现: import matplotlib.pyplot as plt import matplotlib.patches as patches from pylab import * def init(ax): #将主标签设置为1的倍数 majorLocator = MultipleLocator(1); #设置主刻度标签

中点画线法画圆

中点画线法已经在画直线的时候详细讲过了,画圆时我们也可以用这种方法.画一个圆心为坐标原点的1/4圆,然后对其进行简单几何变换,平移对称,就可以得到任意圆. 类似的用中点画线法,从(0,r)点开始,每次要么向右走,要么向右下走,直到x==y,即到达四分之一圆处: (1)当d<0时,中点在圆内,则取正右方的点,(x+1,y+0.5),此时d=d+2*x+3; (2) 当d>=0时,中点在圆外,则取右下方的点,(x+1,y-1),此时d=d+2*(x-y)+5; (3) d0=1-r,即点(0,r)

计算机图形学(三种画线算法)

第二章:光栅图形学算法 1.光栅显示器:光栅扫描式图形显示器简称光栅显示器,是画点设备,可看作是一个点阵单元发生器,并可控制每个点阵单元的亮度 2.由来:随着光栅显示器的出现,为了在计算机上处理.显示图形,需要发展一套与之相适应的算法. 3.研究内容: 1>直线段的扫描转换算法 2>多边形的扫描转换与区域填充算法 3>裁剪算法 4>反走样算法 5>消隐算法 一.直线段的扫描转换算法 1.为了显示一条直线,就在光栅显示器上用离散的像素点逼近直线,所以我们就要知道这些像素点的坐标

计算机图形学(二)输出图元_6_OpenGL曲线函数_2_中点画圆算法

中点画圆算法 如同光栅画线算法,我们在每个步中以单位间隔取样并确定离指定圆最近的像素位置.对于给定半径r和屏幕中心(xc,yc),可以先使用算法计算圆心在坐标原点(0, 0)的圆的像素位置,然后通过将xc加到x且yc加到y.从而把计算出的每个位置(x,y)移动到其适当的屏幕位置.在第一象限中,圆弧段从x = 0到x = y,曲线的斜率从0变化到-1.0.因此,可以在该八分圆上的正x方向取单位步长,并使用决策参数来确定每一步两个可能的y位置中,哪一个更接近于圆的位置.然后,其他七个八分圆中的位置可

计算机图形学(三)_图元的属性_4_线的属性_3_画笔或画刷的选择

画笔或画刷的选择 在有些图形软件包中,尤其是绘画系统,可以直接选择不同的画笔和画刷类型.这种类型的选项包括形状.尺寸和画笔或画刷的图案.图4.7给出了一些可能的画笔和画刷形状.这些形状可以按像素位置的数值形式存储在一个像素模板中,然后再设置到线路径上.例如,矩形画笔可用图4.8给出的模板,通过将模板的中心(或一角)沿线路径移动而实现,如图4.9所示.为了避免在帧缓存中重复设置像素,可以简单地累计在模板的每个位置上生成的水平段,并沿每一条扫描线跟踪起始和终止的x位置. 通过改变模板的尺寸,使用画笔