计算机图形学(直线的扫描转换I)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2014-2015-1:CG:SCUEC
21
判别式的增量计算
di F (M ) F ( xi 1, yi 0.5) a( xi 1) b( yi 0.5) c 是xi, yi 的线性函数,因此可采用增量计算,提高运算效率 若di< 0,取右上方像素PT, 下一个像素应取哪个,应计 算如下的判别式
2014-2015-1:CG:SCUEC
5
生成直线算法的基本要求
给定一个写像素函数DrawPixel(x,y,color), 能不能直接用数学公式生成直线?
void DirectLine(int x0, int y0, int x1, int y1, int color) B(x1,y1) int x; float dx, dy, b, k; dx = x1-x0, dy=y1-y0; k=dy/dx, b=y0-k*x0; A(x0,y0) for (x=x0; xx1; x++) DrawPixel (x, int(k*x+b), color);
3
直线扫描转换的定义
在计算机显示器上画一条直线 和在纸上画一条直线有什么本 质的区别? 显示器是一个有限的像素矩阵 所画的直线是离散的像素集合 只有画水平线,垂直线,及正方 形对角线时,像素点集的位置 才是准确的
B(x2,y2)、
A(x1,y1)、
2014-2015-1:CG:SCUEC
Line: P0(0,0)-P1(5,2)
3
2
0
1
2
3
4
5
注:网格点表示象素
11
2014-2015-1:CG:SCUEC
DDA算法的分析
讨论: 根直接用数学公式画直线相比,算法效率有较大提高。 还是有可能造成隔行显示 y y
(xi+1,yi+1)
(xi+1,yi+1)
(xi百度文库yi)
(xi,yi) o
4
直线扫描转换的定义
在计算机显示器上画一条直线,只能在显示器 所给定的有限个像素组成的点阵中,选择能最 佳地逼近于该直线的一组像素,并对这些像素 按指定的属性进行写操作。这就是通常所说的 用显示器绘制直线,即直线的扫描转换。 直线扫描转换的主要工作:快速找出像素点阵 中距直线最近的网格点,用这些网格点对应的 像素表示该直线。
20
中点法的具体实现
di < 0,Q在M上方,取PT为 下一像素 di > 0,取PB为下一像素 di = 0,可在两个点中任取 一个,约定取下方的点PB
P=(x,y)
PT
Q M
PB
思考:这样做,每一个像素的计算量是多少? 答案:每一个像素的计算量是4个加法,两个乘 法。比DDA算还要坏,“山穷水尽疑无路了吗?”
yi+1 = yi + y t
(t 表示步长)
2014-2015-1:CG:SCUEC
9
生成直线的DDA算法
如果取 t=1/x,我们有: xi+1 = xi + 1 yi+1 = yi + k 即x方向每次增加1,y方向增加k(直线的斜率);
void DDALine1(int x0,int y0,int x1,int y1,int color) int x; float dx, dy, y, k; dx = x1-x0, dy=y1-y0; k=dy/dx, y=y0; for (x=x0; xx1, x++) drawpixel (x, int(y+0.5), color); y = y + k;
2014-2015-1:CG:SCUEC
10
DDA算法画线举例
例:用DDA法画线 P0 (0,0) P 1 (5,2) x 0 1 2 3 4 5 y+0.5 0.5 0.4+0.5 0.8+0.5 1.2+0.5 1.6+0.5 2.0+0.5 int(y+0.5) 0 0 1 1 2 2
1
dx = xe - xs; dy = ye - ys; if (fabs(dy) <= fabs(dx)) { //X方向长,|斜率|<=1 Length = abs(Round(xe)-Round(xs)); Flag = 1; //最大的插补长度和方向标记 ix = Round(xs); //初始X点 idx = sign(dx); //X方向单位增量 y = ys + dy / dx*((float)(ix)-xs); //初始Y点修正 dy = dy / fabs(dx); //Y方向增量(斜率) }
2014-2015-1:CG:SCUEC
6
生成直线算法的基本要求
数学公式生成直线的讨论: – 生成的直线可能不直 – 有可能产生隔行显示 – 算法复杂度高,运算速度慢 生成直线算法的基本要求 生成的直线要直 o
(xi,yi)
y
k>1
(xi+1,yi+1)
x
直线的端点要准确,保证绘制无定向性 直线的亮度、色泽要均匀,避免在视觉上造成一段亮 一段暗的感觉 画线的速度要尽可能的快
2014-2015-1:CG:SCUEC
22
判别式的增量计算
di F (M ) F ( xi 1, yi 0.5) a( xi 1) b( yi 0.5) c
若di≥0,取正右方像素PB, 下一个像素应取哪个,应 计算如下的判别式
P=(x,y) (xi,yi)
MT M
PT
P=(x,y) (xi,yi)
di 1 F ( M T ) F ( xi 2, yi 1.5) a( xi 2) b( yi 1.5) c a( xi 1) b( yi 0.5) c a b di a b
计算机图形学
第3章 基本光栅图形算法
本章内容
1 2 3
直线的扫描转换 圆的扫描转换 多边形的扫描转换
4
5
区域填充
字符的生成 光栅图形的反走样算法
2014-2015-1:CG:SCUEC
2
6
直线的扫描转换
直线扫描转换的定义 生成直线算法的基本要求 基本增量算法 中点法 Bresenham算法
2014-2015-1:CG:SCUEC
2014-2015-1:CG:SCUEC
13
DDA算法的进一步改进
讨论:如果直线段的两个端点不是整数怎么办?
2014-2015-1:CG:SCUEC
14
完整的DDA算法描述
void DDALine (float xs, float ys, float xe, float ye, int color) { int n, ix, iy, idx, idy ; int Flag; //插补方向标记 int Length; //插补长度 float x, y, dx, dy;
2014-2015-1:CG:SCUEC
18
生成直线的中点法
基本原理:
方便起见,假设直线斜小于1
设 P = (x, y)是直线上的一点(用Δ表 示),与(x, y)最近的像素为(xi, yi)(用 实心小圆点表示),则 下一个与直线最近的点只能是正右 方或右上方的点PB(xi+1,yi)和 PT(xi+1,yi+1)之一(用小空心圆表示)
2014-2015-1:CG:SCUEC
7
基本增量算法
问题
直接用直线方程y=kx+b来生成直线,之 所以算法复杂度高,是因为在迭代过程 中每次都要用到浮点数的乘法运算,那 是否可以去掉浮点数的乘法运算呢?
基本思想:如果在一个迭代算法中,每一步的x值和 y值都可以由前一步的的值加一个增量得到,那么这 种算法就称为增量算法。 最基本的增量算法是DDA算法 数值微分分析器(Digital Differential Analyzer) DDA算法的本质是用数值方法解直线的微分方程
xo
2014-2015-1:CG:SCUEC
x
12
DDA算法的改进
为了解决隔行显示的问题,分成两种情况考虑:首先 考虑直线斜率的绝对值小于1的情况,这时|x| ≥|y| > 0,我们取 t=1/|x|,DDA数值解的递推公式为:
xi+1 = xi + 1, yi+1 = yi + k 其次考虑直线斜率的绝对值大于1的情况,这时0<|x| ≤|y|,我们取 t=1/|y|,DDA数值解的递推公式为: xi+1 = xi + 1/k, yi+1 = yi + 1 综合起来, 取步长t = min{1/|x|,1/|y|}即根据斜率 k 的偏移程度,决定是以 x 为步进方向还是以 y 为步进 方向。然后在相应的步进方向上,步进变量每次增加 一个像素,而另一个相关坐标变量则为 yi+1 = yi + k (以 x 为步进变量为例xi+1 = xi+1)
di F (M ) F ( xi 1, yi 0.5) a( xi 1) b( yi 0.5) c
F(x, y) = 0, F(x, y) > 0, F(x, y) < 0, 分别表示点(x, y) 在直线上、直线上方和直线下方
2014-2015-1:CG:SCUEC
2014-2015-1:CG:SCUEC
8
生成直线的DDA算法
设直线的起点坐标为(x0 , y0),终点坐标为(x1 , y1), 令x = x1 – x0, y = y1 - y0,则直线微分方程为:
dx dy x, y dt dt
该方程的数值解的递推公式为
xi+1 = xi + x t
PT Q
M
P=(x,y)
(xi,yi)
PB
中点法每步迭代涉及 的像素和中点示意图
- 设M=(xi+1, yi+0.5),为PB与PT之中点,Q为理想直线与 x=xi+1垂线的交点。将Q与M的y坐标进行比较,当M在Q的下 方,则 PT 离直线近,下一个象素点应取PT;M在Q的上方, 则PB离直线更近,下一个象素点应取PT 。
2014-2015-1:CG:SCUEC
15
else { // Y方向长,|斜率|>1 Length = abs(Round(ye)-Round(ys)); Flag=0; iy = Round(ys); //初始Y点 idy = sign(dy); //Y方向单位增量 x= xs+dx/dy*((float)(iy)-ys); //初始X点修正 dx=dx/fabs(dy); //X方向增量(斜率的倒数) } if (Flag) { //X方向单位增量 for (n=0; n<= Length; n++) { //X方向插补过程 DrawPixel(ix, Round(y), color); ix+=idx; y+=dy; } //End of for } //End of if else { //Y方向斜率增量 for (n=0; n<= Length; n++) { //Y方向插补过程 DrawPixel (Round(x), iy, color); iy+=idy; x+=dx; } //End of for } //End of else } //Finish 2014-2015-1:CG:SCUEC
2014-2015-1:CG:SCUEC
19
中点法的具体实现
设直线的起点和终点分别为(xs, ys)和(xe, ye),直线 方程为: F ( x, y) ax by c 0 其中 a ys ye b xe xs c xs ye ys xe
要判断点M在直线上,上方还是下方可将M代入 下面的判别式判断其正负即可
16
首点校正对逼近的影响
2014-2015-1:CG:SCUEC
17
DDA算法优缺点
用DDA算法计算象素位置,可消除直线方程中的 乘法,在x和y方向使用合适的增量可逐步沿直线 推出各象素的位置,比直接画线算法快。 但算法中的斜率k与y坐标必须用浮点数表示,每 一步运算必须对y进行舍入取整,取整操作和浮点 运算释放耗时,并且算法中还存在除法运算,不 利于在硬件中实现。 思考:如何消除DDA算法中的除法运算? 如何消除DDA算法中的取整操作和浮点运算?
M
MB
di 1 F ( M B ) F ( xi 2, yi 0.5) a( xi 2) b( yi 0.5) c a( xi 1) b( yi 0.5) c a di a
21
判别式的增量计算
di F (M ) F ( xi 1, yi 0.5) a( xi 1) b( yi 0.5) c 是xi, yi 的线性函数,因此可采用增量计算,提高运算效率 若di< 0,取右上方像素PT, 下一个像素应取哪个,应计 算如下的判别式
2014-2015-1:CG:SCUEC
5
生成直线算法的基本要求
给定一个写像素函数DrawPixel(x,y,color), 能不能直接用数学公式生成直线?
void DirectLine(int x0, int y0, int x1, int y1, int color) B(x1,y1) int x; float dx, dy, b, k; dx = x1-x0, dy=y1-y0; k=dy/dx, b=y0-k*x0; A(x0,y0) for (x=x0; xx1; x++) DrawPixel (x, int(k*x+b), color);
3
直线扫描转换的定义
在计算机显示器上画一条直线 和在纸上画一条直线有什么本 质的区别? 显示器是一个有限的像素矩阵 所画的直线是离散的像素集合 只有画水平线,垂直线,及正方 形对角线时,像素点集的位置 才是准确的
B(x2,y2)、
A(x1,y1)、
2014-2015-1:CG:SCUEC
Line: P0(0,0)-P1(5,2)
3
2
0
1
2
3
4
5
注:网格点表示象素
11
2014-2015-1:CG:SCUEC
DDA算法的分析
讨论: 根直接用数学公式画直线相比,算法效率有较大提高。 还是有可能造成隔行显示 y y
(xi+1,yi+1)
(xi+1,yi+1)
(xi百度文库yi)
(xi,yi) o
4
直线扫描转换的定义
在计算机显示器上画一条直线,只能在显示器 所给定的有限个像素组成的点阵中,选择能最 佳地逼近于该直线的一组像素,并对这些像素 按指定的属性进行写操作。这就是通常所说的 用显示器绘制直线,即直线的扫描转换。 直线扫描转换的主要工作:快速找出像素点阵 中距直线最近的网格点,用这些网格点对应的 像素表示该直线。
20
中点法的具体实现
di < 0,Q在M上方,取PT为 下一像素 di > 0,取PB为下一像素 di = 0,可在两个点中任取 一个,约定取下方的点PB
P=(x,y)
PT
Q M
PB
思考:这样做,每一个像素的计算量是多少? 答案:每一个像素的计算量是4个加法,两个乘 法。比DDA算还要坏,“山穷水尽疑无路了吗?”
yi+1 = yi + y t
(t 表示步长)
2014-2015-1:CG:SCUEC
9
生成直线的DDA算法
如果取 t=1/x,我们有: xi+1 = xi + 1 yi+1 = yi + k 即x方向每次增加1,y方向增加k(直线的斜率);
void DDALine1(int x0,int y0,int x1,int y1,int color) int x; float dx, dy, y, k; dx = x1-x0, dy=y1-y0; k=dy/dx, y=y0; for (x=x0; xx1, x++) drawpixel (x, int(y+0.5), color); y = y + k;
2014-2015-1:CG:SCUEC
10
DDA算法画线举例
例:用DDA法画线 P0 (0,0) P 1 (5,2) x 0 1 2 3 4 5 y+0.5 0.5 0.4+0.5 0.8+0.5 1.2+0.5 1.6+0.5 2.0+0.5 int(y+0.5) 0 0 1 1 2 2
1
dx = xe - xs; dy = ye - ys; if (fabs(dy) <= fabs(dx)) { //X方向长,|斜率|<=1 Length = abs(Round(xe)-Round(xs)); Flag = 1; //最大的插补长度和方向标记 ix = Round(xs); //初始X点 idx = sign(dx); //X方向单位增量 y = ys + dy / dx*((float)(ix)-xs); //初始Y点修正 dy = dy / fabs(dx); //Y方向增量(斜率) }
2014-2015-1:CG:SCUEC
6
生成直线算法的基本要求
数学公式生成直线的讨论: – 生成的直线可能不直 – 有可能产生隔行显示 – 算法复杂度高,运算速度慢 生成直线算法的基本要求 生成的直线要直 o
(xi,yi)
y
k>1
(xi+1,yi+1)
x
直线的端点要准确,保证绘制无定向性 直线的亮度、色泽要均匀,避免在视觉上造成一段亮 一段暗的感觉 画线的速度要尽可能的快
2014-2015-1:CG:SCUEC
22
判别式的增量计算
di F (M ) F ( xi 1, yi 0.5) a( xi 1) b( yi 0.5) c
若di≥0,取正右方像素PB, 下一个像素应取哪个,应 计算如下的判别式
P=(x,y) (xi,yi)
MT M
PT
P=(x,y) (xi,yi)
di 1 F ( M T ) F ( xi 2, yi 1.5) a( xi 2) b( yi 1.5) c a( xi 1) b( yi 0.5) c a b di a b
计算机图形学
第3章 基本光栅图形算法
本章内容
1 2 3
直线的扫描转换 圆的扫描转换 多边形的扫描转换
4
5
区域填充
字符的生成 光栅图形的反走样算法
2014-2015-1:CG:SCUEC
2
6
直线的扫描转换
直线扫描转换的定义 生成直线算法的基本要求 基本增量算法 中点法 Bresenham算法
2014-2015-1:CG:SCUEC
2014-2015-1:CG:SCUEC
13
DDA算法的进一步改进
讨论:如果直线段的两个端点不是整数怎么办?
2014-2015-1:CG:SCUEC
14
完整的DDA算法描述
void DDALine (float xs, float ys, float xe, float ye, int color) { int n, ix, iy, idx, idy ; int Flag; //插补方向标记 int Length; //插补长度 float x, y, dx, dy;
2014-2015-1:CG:SCUEC
18
生成直线的中点法
基本原理:
方便起见,假设直线斜小于1
设 P = (x, y)是直线上的一点(用Δ表 示),与(x, y)最近的像素为(xi, yi)(用 实心小圆点表示),则 下一个与直线最近的点只能是正右 方或右上方的点PB(xi+1,yi)和 PT(xi+1,yi+1)之一(用小空心圆表示)
2014-2015-1:CG:SCUEC
7
基本增量算法
问题
直接用直线方程y=kx+b来生成直线,之 所以算法复杂度高,是因为在迭代过程 中每次都要用到浮点数的乘法运算,那 是否可以去掉浮点数的乘法运算呢?
基本思想:如果在一个迭代算法中,每一步的x值和 y值都可以由前一步的的值加一个增量得到,那么这 种算法就称为增量算法。 最基本的增量算法是DDA算法 数值微分分析器(Digital Differential Analyzer) DDA算法的本质是用数值方法解直线的微分方程
xo
2014-2015-1:CG:SCUEC
x
12
DDA算法的改进
为了解决隔行显示的问题,分成两种情况考虑:首先 考虑直线斜率的绝对值小于1的情况,这时|x| ≥|y| > 0,我们取 t=1/|x|,DDA数值解的递推公式为:
xi+1 = xi + 1, yi+1 = yi + k 其次考虑直线斜率的绝对值大于1的情况,这时0<|x| ≤|y|,我们取 t=1/|y|,DDA数值解的递推公式为: xi+1 = xi + 1/k, yi+1 = yi + 1 综合起来, 取步长t = min{1/|x|,1/|y|}即根据斜率 k 的偏移程度,决定是以 x 为步进方向还是以 y 为步进 方向。然后在相应的步进方向上,步进变量每次增加 一个像素,而另一个相关坐标变量则为 yi+1 = yi + k (以 x 为步进变量为例xi+1 = xi+1)
di F (M ) F ( xi 1, yi 0.5) a( xi 1) b( yi 0.5) c
F(x, y) = 0, F(x, y) > 0, F(x, y) < 0, 分别表示点(x, y) 在直线上、直线上方和直线下方
2014-2015-1:CG:SCUEC
2014-2015-1:CG:SCUEC
8
生成直线的DDA算法
设直线的起点坐标为(x0 , y0),终点坐标为(x1 , y1), 令x = x1 – x0, y = y1 - y0,则直线微分方程为:
dx dy x, y dt dt
该方程的数值解的递推公式为
xi+1 = xi + x t
PT Q
M
P=(x,y)
(xi,yi)
PB
中点法每步迭代涉及 的像素和中点示意图
- 设M=(xi+1, yi+0.5),为PB与PT之中点,Q为理想直线与 x=xi+1垂线的交点。将Q与M的y坐标进行比较,当M在Q的下 方,则 PT 离直线近,下一个象素点应取PT;M在Q的上方, 则PB离直线更近,下一个象素点应取PT 。
2014-2015-1:CG:SCUEC
15
else { // Y方向长,|斜率|>1 Length = abs(Round(ye)-Round(ys)); Flag=0; iy = Round(ys); //初始Y点 idy = sign(dy); //Y方向单位增量 x= xs+dx/dy*((float)(iy)-ys); //初始X点修正 dx=dx/fabs(dy); //X方向增量(斜率的倒数) } if (Flag) { //X方向单位增量 for (n=0; n<= Length; n++) { //X方向插补过程 DrawPixel(ix, Round(y), color); ix+=idx; y+=dy; } //End of for } //End of if else { //Y方向斜率增量 for (n=0; n<= Length; n++) { //Y方向插补过程 DrawPixel (Round(x), iy, color); iy+=idy; x+=dx; } //End of for } //End of else } //Finish 2014-2015-1:CG:SCUEC
2014-2015-1:CG:SCUEC
19
中点法的具体实现
设直线的起点和终点分别为(xs, ys)和(xe, ye),直线 方程为: F ( x, y) ax by c 0 其中 a ys ye b xe xs c xs ye ys xe
要判断点M在直线上,上方还是下方可将M代入 下面的判别式判断其正负即可
16
首点校正对逼近的影响
2014-2015-1:CG:SCUEC
17
DDA算法优缺点
用DDA算法计算象素位置,可消除直线方程中的 乘法,在x和y方向使用合适的增量可逐步沿直线 推出各象素的位置,比直接画线算法快。 但算法中的斜率k与y坐标必须用浮点数表示,每 一步运算必须对y进行舍入取整,取整操作和浮点 运算释放耗时,并且算法中还存在除法运算,不 利于在硬件中实现。 思考:如何消除DDA算法中的除法运算? 如何消除DDA算法中的取整操作和浮点运算?
M
MB
di 1 F ( M B ) F ( xi 2, yi 0.5) a( xi 2) b( yi 0.5) c a( xi 1) b( yi 0.5) c a di a