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

摘要:
=Y1){如果(d˂0)d+=d1;elsex+=cx,d+=d2;y+=cy;putfix;}}3。Bresenham算法DDA使得绘制直线的每个步骤只有一个加法。Bresenham算法提供了一种更通用的算法,增加了应用范围。该算法的思想是通过像素的每一行和每一列的中心构建一组虚拟网格线,按照线的起点到终点的顺序计算线和每条垂直网格线的交点,然后根据错误项的符号确定最靠近交点的列中的像素。

1.DDA算法

DDA(Digital Differential Analyer):数字微分法

DDA算法思想:增量思想

公式推导:

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

效率:采用了浮点加法和浮点显示是需要取整

代码:

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;
    }
}

2.中点画线法

采用了直线的一般式:Ax+By+C=0

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

当k在(0,1]中时,每次在x方向上加1,y方向上加1或不变:

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

当Q在M上方时,取Pu点;

当Q在M下方时,取Pd点。

接下来:

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

然后中点画线的计算:

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

di需要两个乘法和四个加法算,比DDA差的多,但是di可以用增量法求

当d<0时

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

当d>=0时

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

d的初始值d0:

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

中点算法计算为:

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

如果将d换成2d,就只有整数运算,优于DDA算法。

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

最终公式:

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

代码:

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);
        }
    }
}

3.Bresenham算法

DDA使画直线每步只有一个加法。

中点画线法使画直线每步只有一个整数加法。

Bresenham算法提供一个更一般的算法,使适用范围增大。

该算法的思想是通过各行、各列像素中心构造一组虚拟网格线,按照直线起点到终点的顺序,计算直线与各垂直网格线的交点,然后根据误差项的符号确定该列象素中与此交点最近的象素。

假设每次x+1,y的递增(减)量为0或1,它取决于实际直线与最近光栅网格点的距离,这个距离的最大误差为0.5。

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

误差项d的初值d 0=0,d=d+k,一旦d≥1,就把它减去1,保证d的相对性,且在0、1之间。

然后有下面计算公式:

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

怎么提升到整数算法?

答案是让e=d-0.5

e0=-0.5

每循环一次:e = e+k
if (e>0) then e = e-1

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

e+k这还是一个浮点加法

因为k=△y/△x

因为用误差项的符号,可以用e*2*△x来替换 e:

e0=-△x

每循环一次:e = e+2△y
if (e>0) then e = e-2△x

这已经变成为整数加法

算法步骤:

算法步骤为:
1.输入直线的两端点P 0(x 0,y 0)和P 1(x 1,y 1)。
2.计算初始值△x、△y、 e=-△x、x=x 0、y=y 0。
3.绘制点(x,y)。
4.e更新为 e+2△y,判断e的符号。若e>0,则(x,y)更新为
(x+1,y+1),同时将e更新为 e-2△x;否则(x,y)更新为
(x+1,y)。
5.当直线没有画完时,重复步骤3和4。否则结束。

代码:

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;
            }
        }
    }
}

免责声明:文章转载自《计算机图形学之扫描转换直线-DDA,Bresenham,中点画线算法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Excel 数据对比,窗口并列排序操作(xlw文件格式的由来)【成语】咸鱼翻身下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

opengl es 学习

http://blog.csdn.net/lpt19832003/archive/2010/03/03/5342070.aspx 1、学习网站 官方网站 http://www.khronos.org/opengles/ 最经典的Nehe 学习网站 http://nehe.gamedev.net/ 中文的Nehe 学习网站 http://www.owlei...

【Visual C++】游戏开发笔记之一——API函数、DirectX的关键系统

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。 http://blog.csdn.net/zhmxy555/article/details/7318264 作者:毛星云邮箱:happylifemxy@qq.com 在从第一节开始看这个笔记系列的话,大家会发现,一上来就开始讲DirectX相关的内容,但是写了几节之后,又开始讲...

计算机组成原理 — GPU 图形处理器

目录 文章目录 目录 显卡 GPU GPU 与深度学习 GPU 与 CPU 体系结构的区别 GPU 显存与 CPU 主存的区别 GPU 与 CPU 之间的数据交互方式 GPU 的体系结构 GPU 的工作原理 GPU 的关键参数 CUDA 编程模型 CUDA 的架构 CUDA 的核心概念 CUDA 的工作原理 云主机显卡的实现方式 虚拟显卡...

深入浅出计算机组成原理学习笔记:第三十一讲

一、引子 上一讲,我带你一起看了三维图形在计算机里的渲染过程。这个渲染过程,分成了顶点处理、图元处理、栅格化、片段处理,以及最后的像素操作。这一连串的过程, 也被称之为图形流水线或者渲染管线。 因为要实时计算渲染的像素特别地多,图形加速卡登上了历史的舞台。通过3dFx的Voodoo或者NVidia的TNT这样的图形加速卡,CPU就不需要再去处理一个个像素点...

Bresenham算法的实现思路

条件已知两个点的坐标p1(x0,y0),p2(x1,y1)要求画出这条直线 之后的e代表每次的误差积累,初始值为0,可以计算出斜率为k=dy/dx=(y0-y1)/(x0-x1) 1、x为阶跃步长(直线光栅化) 适用于0<k<1的情况 即x每次增加1,但是y的坐标根据其是靠近该点所处的单元格的距离来决定,如果离上边近则y加1,如果离下边近则还是...

OpenGL教程一

引自:https://blog.csdn.net/u013654125/article/details/73613644 GLEW, GLFW和GLM介绍 现在你有了工程,就让我们开始介绍下工程所用到的开源库和为啥需要这些。 The OpenGL Extension Wrangler (GLEW)是用来访问OpenGL 3.2 API函数的。不幸的是你不能...