计算机图形学直线生成算法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2014-5-10
23
中点算法程序 MidPointLine(x0,y0,x1,y1,color) {int x0,y0,x1,y1,color; int a,b,d1,d2,x,y; a = y0-y1; b = x1 – x0; d = 2 * a +b; d1 = 2*a; d2 = 2*(a+b); x = x0; y = y0; SetPixel(x,y,color); while (x<x1) { if (d<0) { x++; y++; d +=d2;} else { x++; d +=d1;} SetPixel(x,y,color); } }
2014-5-10 25
画线Bresenham算法
Bresenham算法是计算机图形学领域使用最广泛的直 线扫描转换算法。该方法类似于中点法,由误差项符 号决定下一个象素取右边点还是右上点。 本算法由Bresenham在1965年提出该方法最初是为数 字绘图仪设计的,后来被广泛地应用于光栅图形显示 和数控(NC)加工 算法原理如下:过各行各列象素中心构造一组虚拟网 格线。按直线从起点到终点的顺序计算直线与各垂直 网格线的交点,然后确定该列象素中与此交点最近的 象素。该算法的巧妙之处在于采用增量计算,使得对 于每一列,只要检查一个误差项的符号,就可以确定 该列的所求象素。
2014-5-10
18
直线的正负划分性
点与直线的关系:on: F(x,y)=0; up: F(x, y)>0; down: F(x, y)<0;
2014-5-10
19
欲判断中M在Q点的上方还是下方,只要把M代 F(x,y),并判断它的符号。 构造判别式: d=F(M)=F(xp+1, yp+0.5) =a(xp+1)+b(yp+0.5)+c 当d<0,M在Q点下方,取P2为下一个象素; 当d>0,M在Q点上方,取P1为下一个象素; 当d=0,选P1或P2均可,约定取P1为下一个象 素
பைடு நூலகம்
2014-5-10
4
2 直线段的扫描转换
目标:求与直线段充分接近的像素集 像素间均匀网格 整型坐标系 两点假设
直线段的宽度为1 直线段的斜率:
m [1,1]
2014-5-10 5
基本图形点阵转换算法评价
所显示图形的精度 算法的时间和空间复杂性
两者冲突,权衡折衷
2014-5-10
6
描绘线条图形的要求
16
if (fabs(x2-x1)>=fabs(y2-y1)) length=fabs(x2-x1); else length=fabs(y2-y1);
deltx=(x2-x1)/length; delty=(y2-y1)/length;
2014-5-10
}
画线中点算法
目标:消除DDA算法中的浮点运算(浮点数取整
复杂度:加法+取整 程序
2014-5-10
9
DDA画线算法程序
void LineDDA(int x0,int y0,int x1,int y1,int color) /* 假定x0<x1,-1<=k<=1 */ { int x,y; float dx, dy, k; dx= float(x1-x0); dy= float(y1-y0); k=dy/dx; y=y0; for(x=x0; x<= x1, x++) { Setpixel(x, int(y+0.5), color); y+=k; } 2014-5-10 }
10
举例:用DDA方法扫描转换连接两点P0(0,0)和P1 (5,2)的直线段
X int(y+0.5) y+0.5 0 0 0 1 0 0.4+0.5 2 1 0.8+0.5 3 1 1.2+0.5 4 2 1.6+0.5
2014-5-10
11
特点1 注意上述分析的算法仅适用于|k| ≤1的情形。在这种 情况下,x每增加1, y最多增加1。当 |k| > 1时,必须 把x,y地位互换,y每增加1,x相应增加1/k。 特点2 在这个算法中,y与k必须用浮点数表示,而且每一步 都要对y进行四舍五入后取整。这使得它不利于硬件实 现
2014-5-10 24
举例 用中点画线方法扫描转换连接两点P0(0,0)和P1 (5,2)的直线段
a=y0-y1=-2; b=x1-x0=5; d0=2*a+b=1; d1=2*a=-4; d2=2*(a+b)=6 x y d 0 0 1 1 0 -3 d1 2 1 3 d2 3 1 -1 d1 4 2 5 d2 5 2 1
2014-5-10 15
DDA直线绘制的C++实现 void DDA直线绘制(HDC hdc) { int k; double x1=50,y1=50, x2=300,y2=350; double x,y,deltx,delty,length;
x=x1; y=y1; k=1; while(k<=length) { SetPixel(hdc,x,y, RGB(0,0,0)); x=x+deltx; y=y+delty; k=k+1; Sleep(50); }
第二讲 二维基本图形生成
所谓图元的生成,是指完成图元的参数表示形式(由图 形软件包的使用者指定)到点阵表示形式(光栅显示系 统刷新时所需的表示形式)的转换。通常也称扫描转换 图元
§1 §2 §3 §4 §5 简单的二维图形显示流程 直线段的扫描转换 圆弧的扫描转换 易画曲线的正负法 线画图元的属性控制
{( xi , yi ,r )}in0
8
yi,r round( yi ) (int)(yi 0.5)
2014-5-10
复杂度:乘法+加法+取整
DDA算法(增量算法) yi 1 m xi 1 B m ( xi 1) B m xi B m yi m
2014-5-10 26
工作原理:根据直线的斜率在x或y的方向每次都 只递增一个象素单位,另一个方向的增量为0或1
2014-5-10
27
设直线方程为y=kx+b,其中k=dy/dx。 假 设x列的象素已经确定为xi,其行坐标为yi。 那么下一个象素的列坐标为xi+1,而行坐 标要么不变为yi,要么递增1为yi+1。 是否增1取决于如图所示误差项d的值。因为 直线的起始点在象素中心,所以误差项d的 初值d0=0。X下标每增加1,d的值相应递 增直线的斜率值k,即d=d+k。 当d≥0.5时,直线与xi+1列垂直网格交点最 接近于当前象素(xi,yi)的右上方象素(xi +1,yi+1);而当d<0.5时,更接近于右 方象素(xi+1,yi)。
2014-5-10
12
改进算法(增量DDA)
增加斜率判断并改变循环参数
2014-5-10
13
DDA画线算法程序(改进)
void LineDDA(int x0,int y0,int x1,int y1,int color) { int x,y;float dx, dy,k,l,m; dx= float(x1-x0); dy= float(y1-y0); k=dy/dx; if abs(k)<1) { for(x=x0; x<= x1, x++) { Setpixel(x, int(y+0.5), color); y+=k; } } else { for(y=y0; y<= y1, y++) { Setpixel(int(x+0.5),y,color); x+=1/k; } } 问题: 如果x0> x1怎么办?
2014-5-10 30
举例:用Bresenham方法扫描转换连接两点 P0(0,0)和P1(5,2)的直线段。 xy e 0 0 -0.5 1 0 -0.1 0.3-1 2 1 -0.7 3 1 -0.3 0.1-1 4 2 -0.9 5 2 -0.5
2014-5-10 28
为方便计算,令e=d-0.5,e的初值为-0.5, 增量为k。当e≥0时,取当前象素(xi,yi) 的右上方象素(xi+1,yi+1);而当e<0 时,更接近于右方象素(xi+1,yi)。
2014-5-10
29
Bresenham画线算法程序 void Bresenhamline (int x0,int y0,int x1, int y1,int color) { int x, y, dx, dy; float k, e; dx = x1-x0; dy = y1- y0; k=dy/dx; e=-0.5; x=x0; y=y0; for (i=0; i<=dx; i++) { Putpixel (x, y, color); x=x+1; e=e+k; if (e>= 0) { y++, e=e-1;} } }
直线段要显得笔直 线段端点位置要准确 线段的亮度要均匀 转换算法速度要快
2014-5-10
7
DDA( digital differential analyzer)算法
条件:
, y1) 待扫描转换的直线段:P 0 ( x0, y0) P 1 ( x1
斜率:m y / x
2014-5-10 14
DDA直线生成算法的伪语言描述如下: begin if abs(x2﹣x1)≥abs(y2﹣y1) then lenght﹦abs(x2﹣x1) else lenght﹦abs(y2﹣y1) endif △x﹦(x2﹣x1)/lenght △y﹦(y2﹣y1)/lenght x﹦x1 y﹦y1 k﹦ 1 while(k≤lenght) putpixel(x,y) x﹦x﹢△x y﹦y﹢△y k﹦ k﹢ 1 endwhile end
x x1 x0, y y1 y0 直线方程:y m x B
直接求交算法:
划分区间[x0,x1]: x0 , x1 ,, xn , 其中xi 1 xi 1 计算纵坐标: yi m xi B 取整: {( x , y )}n
i i i 0
2014-5-10 20
问题:判断距直线最近的下一个象素点
构造判别式:d=F(M)=F(Xp+1,Yp+0.5) 由d>0,<0可判定下一个象素,
P2 P
P1
2014-5-10
21
要判定再下一个象素,分两种情形考虑:
1)若d≥0,取正右方象素P1,再下一个象素判定, 由: d1=F(Xp+2,Yp+0.5)=a(Xp+2)+b(Yp+0.5)+c=d+a , d的增量是a 2)若d<0,取右上方象素P2,再下一个象素, 由:d2=F(Xp+2,Yp+1.5)=d+a+b d的增量为a+b P2 P
运算,不利于硬件实现; DDA算法,效率低)
条件:
同DDA算法 斜 率:
m [0,1]
直线段的隐式方程((x0,y0)(x1,y1)两端点) F(x,y)=ax+by+c=0 式中 a=y0-y1,b=x1-x0,c=X0Y1-X1Y0
2014-5-10
17
画直线段的过程中,当前象素点为(xp, yp),一个象素点有 两种可选择点p1(xp+1, yp)或p2(xp+1, yp+1)。若M=(xp+1, yp+0.5)为p1与p2之中点,Q为理想直线与x=xp+1垂线的交 点。当M在Q的下方,则P2 应为下一个象素点;M在Q的上 方,应取P1 为下一点。就是中点画线法的基本原理。
2014-5-10
1
扫描转换直线段
• DDA算法 • 中点画线法 • Bresenham算法
圆弧、椭圆弧扫描转换
• 中点算法
• Bresenham算法 • 内接多边形迫近法* • 等面积多边形逼近法*
2014-5-10
2
1 简单的二维图形显示流程
2014-5-10
3
图形显示前需要:扫描转换+裁剪 ● 裁剪 ---〉扫描转换:最常用,节约计算时间。 ● 扫描转换 ---〉裁剪:算法简单; ● 扫描转换到画布 --〉位块拷贝:算法简单,但耗时耗 内存。常用于字符显示。
2014-5-10
P1
22
d的初始值 d0=F(X0+1,Y0+0.5)=F(X0,Y0)+a+0.5*b 因 (X0,Y0) 在 直 线 上 , F(X0 , Y0)=0, 所 以 , d0=a+0.5*b d的增量都是整数,只有初始值包含小数,可以 用2d代替d, 2a改写成a+a。 算法中只有整数变量,不含乘除法,可用硬件 实现。