直线的绘制(光栅化)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
则di的计算仅包括整数运算,其符号与(d1-d2)的符号相同,可以作为判别 式。下一点的选取规则; 当di<0时,直线上理想位置与像素(xi+1,yi)更接近,应取右方像素; 当di>0时,像素(xi+1,yi+1)与直线上理想位置更接近; 当di=0时,两个像素与直线上理想位置一样接近,可约定取(xi+1,yi +1)。
b y0 k x0
从起点到终点,x每次增加(或减少)1,用直线方程计 算对应的y值,再用SetPixel(x, int(y+0.5),color)输出该 像素。上述方法称为直线绘制基本算法。复杂度:乘 法+加法+取整
缺点:每步都需要一个浮点乘法运算和一个四舍五 入运算,所以效率太低。由于一个图中可以包含成 千上万条直线,所以要求绘制算法应尽可能的快。
设Δy=y1-y0, Δx=x1-x0,则k=Δy/Δx,代入上式,得; x(d1 d 2 ) 2yxi 2y 2bx 2 yi x x
2yxi 2 yi x c
c 2y x(2b 1) 是常量,与像素位置无关。令
di x( d1 d 2 )
DDA算法与基本算法相比,减少了浮点乘法,提高了 效率。但是x与dx、y与dy用浮点数表示,每一步要 进行四舍五入后取整,不利于硬件实现,因而效率 仍有待提高。
Bresenham算法 Bresenham算法1965年提出,基本原理是:借助于一个误差量 (直线与当前实际绘制像素点的距离),来确定下一个像素点的 位置。算法的巧妙之处在于采用增量计算,使得对于每一列, 只要检查误差量的符号,就可以确定该下一列的像素位置。 如图3-3所示,对于直线斜率k在0~1之间的情况,从给定线段 的左端点P0(x0, y0)开始,逐步处理每个后续列(x位置),并在扫 描线y值最接近线段的像素上绘出一点。 假设当前直线上的像素坐标 为(xi, yi),那么下一步需要 在列xi+1上确定扫描线y的 值。y值要么不变,要么递 增1,可通过比较d1和d2来 决定。
2.验证你所创建的类:在你的视区类的 OnDraw函数中,创建CLine类的若干对象, 并利用不同的方法绘制所创建的直线对象。
x
y
图3-1 DDA算法基本原理
复杂度:加法+取整
上述采用的增量计算方法称为数值微分算法(Digital Differential Analyzer,简称DDA)。数值微分法的本质, 是用数值方法解微分方程,通过同时对x和y各增加一 个小增量,计算下一步的x、y值。
注意: x, y的选择.
void DDALine(int x0,int y0,int x1,int y1,int color) int i; float dx, dy, length,x,y; if (fabs(x1-x0)>=fabs(y1-y0)) length=fabs(x1-x0); else length=fabs(y1-y0); dx = (x1-x0)/length; dy=(y1-y0)/length; i=1;x= x0;y= y0; while(i<=length) { SetPixel (int(x+0.5), int(y+0.5), color); x=x+dx; y=y+dy; i++;
此时参数c已经消去,且xi+1=xi+1,得:
如果选择右上方像素,即:yi1 yi 1,则: 如果选择右方像素,即:
di1 di 2 y 2 x ( yi1 yi )
di1 di 2y 2x
yi1 yi
,则:
di1 di 2y
对于每个整数x,从线段的坐标端点开始,循环的进行误差量的 计算。在起始像素(x0,y0)的参数d0为:
d0 2y x
以下是当0<k<1时的Bresenham画线算法程序: void Bresenham_Line (int x0,int y0,int x1, int y1,int color) { int dx,dy, det1,det2, i,x,y,e; dx=x1-x0; dy=y1-y0; det1=2*dy; det2=2*(dy-dx) ; x=x0;y=y0; e=2*dy-dx; for (i=0; i<=dx; i++) { SetPixel (x, y, color); x++; if (e>=0){ y++; e+=det2;} else e+=det1; } }
数值微分(DDA)法
给定直线段的两个端点P0(x0,y0)和 P1(x1,y1),直线方程:
y kx b
画线过程从x的左端点x0开始,向x右端点步进,x+=x,计算相应 的y坐标: y=kx+b,取像素点 (round(x), round(y)) 作为当前点的坐 标。
设第i个点(xi,yi), yi= kxi+b
实验二
1.创建一个类CLine, 成员变量包括: CPoint m_StartPoint; CPoint m_EndPoint; COLORREF m_Color; 均设置为私有成员变量。 成员函数(均为公有)包括: 构造函数: CLine (CPoint start, CPoint end, COLORREF color); 获取属性的函数: Get(CPoint &start, CPoint &end, COLORREF &color); 设置属性的函数: Set(CPoint start, CPoint end, COLORREF color); 直接利用MFC中的画线函数绘制该直线段的函数: void Draw(CDC *pDC); 利用DDA 算法绘制该直线段的函数: void DrawWithDDA (CDC *pDC); 利用Bresenham绘制该直线段的函数: void DrawWithBresenham(CDC *pDC);
第i+1个点(xi+1,yi+1), 令xi+1= xi+ x, 则yi+1=k(xi+ x)+b=yi+kx = yi+y, y= kx 当x =1时 yi+1 = yi+k
( i+1,int( i+1+0.5))
ቤተ መጻሕፍቲ ባይዱ
x
y
( i, i)
x y
( i+1, i+1)
x
y
( i,int( i+0.5))
光栅化和扫描转换是光栅图形学的基本问题,其算 法的好坏对系统的效率有直接的关系。
3.2 线的生成算法
3.2.1 直线的生成算法
• 问题所在:
• 在数学上,直线是连续的,由无数个点构成的集 合。x,y坐标均为实数。 • 但在显示器上,只能用有限的像素表示,像素的 坐标是整数值。 • 因此,绘制时,需要将直线段离散化为有限的像 素,这些像素应该尽可能地连续、尽量避免出现锯齿, 并最佳逼近于给定的直线段。此外,绘制直线是非常 基本的绘图操作,一个图中往往包括成千上万条直线, 所以,算法应该尽可能地快。
第3章 基本光栅图形生成技术
3.1 本章的主要内容
本章介绍基本二维图形的绘制,包括直线、圆弧、 椭圆弧的生成,多边形的填充以及更一般区域的填充。 显示器是由离散像素组成的矩阵,在绘制具有连 续性质的直线、曲线或区域等基本图形时,需要确定 最佳逼近它们的像素,这个过程称为光栅化。当光栅 化按照扫描线的顺序进行时,它被称为扫描转换。
Yi +1 y
d2 d1
yi
xi xi+1 图3-3 根据误差量来确定理想的像素点
判别式(误差参数):
d1 y yi (k(xi 1) b) yi
d 2 ( yi 1) y yi 1 (k(xi 1) b)
d1 d 2 2[k ( xi 1) b] 2 yi 1 2kxi 2k 2b 2 yi 1
判别式(误差参数)的递推计算:
di x(d1 d 2 ) 2 y xi 2 x yi c
对于k+1步,误差参数为:
di1 2 y xi1 2 x yi1 c di1 di 2 y ( xi1 xi ) 2 x ( yi1 yi )
对于水平线、垂直线和45°线,选择哪些光栅元素是显而 易见的,而对于其它方向的直线,像素的选择较为困难。
直线绘制基本算法 给定直线段的两个端点P0(x0,y0)和 P1(x1,y1),斜率截距直线方程:
k y / x ( y1 y0 ) /( x1 x0 )
y kx b
b y0 k x0
从起点到终点,x每次增加(或减少)1,用直线方程计 算对应的y值,再用SetPixel(x, int(y+0.5),color)输出该 像素。上述方法称为直线绘制基本算法。复杂度:乘 法+加法+取整
缺点:每步都需要一个浮点乘法运算和一个四舍五 入运算,所以效率太低。由于一个图中可以包含成 千上万条直线,所以要求绘制算法应尽可能的快。
设Δy=y1-y0, Δx=x1-x0,则k=Δy/Δx,代入上式,得; x(d1 d 2 ) 2yxi 2y 2bx 2 yi x x
2yxi 2 yi x c
c 2y x(2b 1) 是常量,与像素位置无关。令
di x( d1 d 2 )
DDA算法与基本算法相比,减少了浮点乘法,提高了 效率。但是x与dx、y与dy用浮点数表示,每一步要 进行四舍五入后取整,不利于硬件实现,因而效率 仍有待提高。
Bresenham算法 Bresenham算法1965年提出,基本原理是:借助于一个误差量 (直线与当前实际绘制像素点的距离),来确定下一个像素点的 位置。算法的巧妙之处在于采用增量计算,使得对于每一列, 只要检查误差量的符号,就可以确定该下一列的像素位置。 如图3-3所示,对于直线斜率k在0~1之间的情况,从给定线段 的左端点P0(x0, y0)开始,逐步处理每个后续列(x位置),并在扫 描线y值最接近线段的像素上绘出一点。 假设当前直线上的像素坐标 为(xi, yi),那么下一步需要 在列xi+1上确定扫描线y的 值。y值要么不变,要么递 增1,可通过比较d1和d2来 决定。
2.验证你所创建的类:在你的视区类的 OnDraw函数中,创建CLine类的若干对象, 并利用不同的方法绘制所创建的直线对象。
x
y
图3-1 DDA算法基本原理
复杂度:加法+取整
上述采用的增量计算方法称为数值微分算法(Digital Differential Analyzer,简称DDA)。数值微分法的本质, 是用数值方法解微分方程,通过同时对x和y各增加一 个小增量,计算下一步的x、y值。
注意: x, y的选择.
void DDALine(int x0,int y0,int x1,int y1,int color) int i; float dx, dy, length,x,y; if (fabs(x1-x0)>=fabs(y1-y0)) length=fabs(x1-x0); else length=fabs(y1-y0); dx = (x1-x0)/length; dy=(y1-y0)/length; i=1;x= x0;y= y0; while(i<=length) { SetPixel (int(x+0.5), int(y+0.5), color); x=x+dx; y=y+dy; i++;
此时参数c已经消去,且xi+1=xi+1,得:
如果选择右上方像素,即:yi1 yi 1,则: 如果选择右方像素,即:
di1 di 2 y 2 x ( yi1 yi )
di1 di 2y 2x
yi1 yi
,则:
di1 di 2y
对于每个整数x,从线段的坐标端点开始,循环的进行误差量的 计算。在起始像素(x0,y0)的参数d0为:
d0 2y x
以下是当0<k<1时的Bresenham画线算法程序: void Bresenham_Line (int x0,int y0,int x1, int y1,int color) { int dx,dy, det1,det2, i,x,y,e; dx=x1-x0; dy=y1-y0; det1=2*dy; det2=2*(dy-dx) ; x=x0;y=y0; e=2*dy-dx; for (i=0; i<=dx; i++) { SetPixel (x, y, color); x++; if (e>=0){ y++; e+=det2;} else e+=det1; } }
数值微分(DDA)法
给定直线段的两个端点P0(x0,y0)和 P1(x1,y1),直线方程:
y kx b
画线过程从x的左端点x0开始,向x右端点步进,x+=x,计算相应 的y坐标: y=kx+b,取像素点 (round(x), round(y)) 作为当前点的坐 标。
设第i个点(xi,yi), yi= kxi+b
实验二
1.创建一个类CLine, 成员变量包括: CPoint m_StartPoint; CPoint m_EndPoint; COLORREF m_Color; 均设置为私有成员变量。 成员函数(均为公有)包括: 构造函数: CLine (CPoint start, CPoint end, COLORREF color); 获取属性的函数: Get(CPoint &start, CPoint &end, COLORREF &color); 设置属性的函数: Set(CPoint start, CPoint end, COLORREF color); 直接利用MFC中的画线函数绘制该直线段的函数: void Draw(CDC *pDC); 利用DDA 算法绘制该直线段的函数: void DrawWithDDA (CDC *pDC); 利用Bresenham绘制该直线段的函数: void DrawWithBresenham(CDC *pDC);
第i+1个点(xi+1,yi+1), 令xi+1= xi+ x, 则yi+1=k(xi+ x)+b=yi+kx = yi+y, y= kx 当x =1时 yi+1 = yi+k
( i+1,int( i+1+0.5))
ቤተ መጻሕፍቲ ባይዱ
x
y
( i, i)
x y
( i+1, i+1)
x
y
( i,int( i+0.5))
光栅化和扫描转换是光栅图形学的基本问题,其算 法的好坏对系统的效率有直接的关系。
3.2 线的生成算法
3.2.1 直线的生成算法
• 问题所在:
• 在数学上,直线是连续的,由无数个点构成的集 合。x,y坐标均为实数。 • 但在显示器上,只能用有限的像素表示,像素的 坐标是整数值。 • 因此,绘制时,需要将直线段离散化为有限的像 素,这些像素应该尽可能地连续、尽量避免出现锯齿, 并最佳逼近于给定的直线段。此外,绘制直线是非常 基本的绘图操作,一个图中往往包括成千上万条直线, 所以,算法应该尽可能地快。
第3章 基本光栅图形生成技术
3.1 本章的主要内容
本章介绍基本二维图形的绘制,包括直线、圆弧、 椭圆弧的生成,多边形的填充以及更一般区域的填充。 显示器是由离散像素组成的矩阵,在绘制具有连 续性质的直线、曲线或区域等基本图形时,需要确定 最佳逼近它们的像素,这个过程称为光栅化。当光栅 化按照扫描线的顺序进行时,它被称为扫描转换。
Yi +1 y
d2 d1
yi
xi xi+1 图3-3 根据误差量来确定理想的像素点
判别式(误差参数):
d1 y yi (k(xi 1) b) yi
d 2 ( yi 1) y yi 1 (k(xi 1) b)
d1 d 2 2[k ( xi 1) b] 2 yi 1 2kxi 2k 2b 2 yi 1
判别式(误差参数)的递推计算:
di x(d1 d 2 ) 2 y xi 2 x yi c
对于k+1步,误差参数为:
di1 2 y xi1 2 x yi1 c di1 di 2 y ( xi1 xi ) 2 x ( yi1 yi )
对于水平线、垂直线和45°线,选择哪些光栅元素是显而 易见的,而对于其它方向的直线,像素的选择较为困难。
直线绘制基本算法 给定直线段的两个端点P0(x0,y0)和 P1(x1,y1),斜率截距直线方程:
k y / x ( y1 y0 ) /( x1 x0 )
y kx b