第二章 二维图形生成技术
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
x 0 1 2 3 4
Line: P0(0, 0)-- P1(5, 2) 3 2 1 0 1 2 3 4 5
中点画线法(5/6)
d的初始值 Nhomakorabead0=F(X0+1,Y0+0.5) =F(X0,Y0)+a+0.5 =a+0.5b 用2d代替d后,d0=2a+b d的增量都是整数 只有整数运算,不含乘除法 可用硬件实现
float dx,dy,x,y,steps; int x1=0,y1=0,x2=200,y2=100,i; if(abs(x2-x1)>abs(y2-y1)) steps=(float)abs(x2-x1); else steps=(float)abs(y2-y1); dx=(x2-x1)/steps; dy=(y2-y1)/steps; x=(float)x1; y=(float)y1; for(i=1;i<=steps;i++) { pDC->SetPixel((int)(x+0.5),(int)(y+0.5),RGB(0,0,255)); x=x+dx; y=y+dy; }
因(X0,Y0)在直线上, 所以F(X0,Y0)=0
优点:
/* 算法2.2*/
中点画线法(6/6)
void Midpoint Line (int x0,int y0,int x1, int y1,int color) { int a, b, d1, d2, d, x, y; a=y0-y1, b=x1-x0, d=2*a+b; d1=2*a, d2=2* (a+b); x=x0, y=y0; drawpixel(x, y, color); while (x<x1) { if (d<0) {x++; y++; d+=d2; } else {x++; d+=d1;} drawpixel (x, y, color); } /* while */ } /* mid PointLine */
2.1 直线的生成算法
基本算法 数值微分(DDA)法 中点画线法 Bresenham算法
直线绘制基本算法
数学上的直线:没有宽度的、由无数个 点构成的集合。 直线的光栅化:在显示器所给定的有限 个像素矩阵中,确定最佳逼近于该直线 的一组像素。 对于水平线、垂直线和45°线,选择哪 些光栅元素是显而易见的,而对于其它 方向的直线,像素的选择较为困难。
第2章 二维图形生成技术
基本概念 基本图形的生成原理和算法 线的生成算法 直线的生成算法 圆的生成算法 区域的填充 文字的生成
光栅显示器上显示的图形,称之为光栅图形。 光栅显示器可以看作是一个象素矩阵,在光栅 显示器上显示的任何一个图形,实际上都是一 些具有一种或多种颜色和灰度象素的集合。由 于对一个具体的光栅显示器来说,象素个数是 有限的,象素的颜色和灰度等级也是有限的, 象素是有大小的,所以光栅图形只是近似的实 际图形。如何使光栅图形最完美地逼近实际图 形,便是光栅图形学要研究的内容。以后,我 们提到“显示器”时,如未特别声明,均指光 栅显示器。
d的增量为a
若d<0,中点M在直线下方,取右上方象素P2 (Xp+1,Yp+1)
再下一个象素的判别式为 M(xp+2,yp+1.5) : =F(Xp,Yp)+a+0.5b+a+b =d+a+b
P2 M P1
d’’=F((Xp+1)+1,(Yp+1)+0.5)= a(Xp+2)+b(Yp+1.5)+c
中点画线法( 7/7) 例2.2 :画直线段P0(0,0)--P 1(5,2)
a=y0-y1=-2, d1=2*a=-4, y 0 0 1 1 2 d 1 -3 3 -1 5
b=x1-x0=5, d=2*a+b=1 d2=2* (a+b)=6
3.编写自定义的成员函数ddaline()程序
void CDDALineView::ddaline(CDC* pDC, int x0, int y0, int x1, int y1, COLORREF color) { int length,i; float x,y,dx,dy; length=abs(x1-x0); if (abs(y1-y0)>length) length=abs(y1-y0); dx=(x1-x0)/length; dy=(y1-y0)/length; x=x0+0.5;y=y0+0.5; for (i=1;i<=length;i++) { pDC->SetPixel((int)x,(int)y,color); x=x+dx;y=y+dy; } }
像素的显示
函数 SetPixel(x,y,color); 其中, x和y为像素的位置坐标,color为像素的颜 色 作用:对显示设备的象素(x,y)进行写操作,既 让象素“发亮”,有时称绘制像素(x,y) 。 具体实现 pDC-> SetPixel(x,y,color); 其中color为绘制像素的颜色,形式为RGB(0,255,0)
k y / x ( y1 y0 ) /( x1 x0 )
b y0 k x0
从起点到终点,x每次增加(或减少)1,用直线方程计 算对应的y值,再用SetPixel(x, int(y+0.5),color)输出该像 素。 复杂度:乘法+加法+取整
直线绘制基本算法的不足
d的增量为a+b
中点画线法(7/7)
例2.2:画直线段P0(0,0)--P1(5,2)
a=y0-y1=-2, b=x1-x0=5, d1=a=-2, d2=a+b=3 y 0 0 1 1 2 d 0.5 -1.5 1.5 -0.5 2.5
if (d<0) else
d=a+0.5b=0.5
{x++; y++; d+=d2; } {x++; d+=d1;}
缺点:每步都需要一个浮点乘法运算和一个 四舍五入运算,所以效率太低。 由于一个图中可以包含成千上万条直线,所 以要求绘制算法应尽可能的快。
数值微分(DDA)法
给定两个端点P0(x0,y0)和P1(x1,y1),线段的斜率k和 截距b为:
若0<k<1, p0在左,p1在右, 画线过程从x的左端点x0开始,向x右端点步进,步长 =1(个像素),计算相应的y坐标:y=kx+b,取像素点 (x, round(y))作为当前点的坐标。 计算 yi+1= kxi+1+b=k(xi+ x)+b= kxi+b+kx = yi+kx 当x =1时 yi+1 = yi+k 即:当x每递增1,y递增k(即直线斜率)。
基本概念
多复杂的图形都是由基本图形组合而成的,学习基本图形的 生成算法是掌握计算机图形学的基础。 光栅化 确定最佳逼近图形的象素集合,并用指定的颜色和灰度设置 象素的过程称为图形的扫描转换或光栅化。对于一维图形, 在不考虑线宽时,用一个象素宽的直线或曲线来显示图形。 二维图形的光栅化必须确定区域对应的象素集,将各个象素 设置成指定的颜色和灰度,也称之为区域填充。任何图形光 栅化后,显示在屏幕上的一个窗口里,超出窗口的部分不予 显示。确定一个图形的哪些部分在窗口内,必须显示;哪些 部分落在窗口之外,不予显示,这需要对图形进行裁剪。裁 剪通常在扫描转换之前进行,从而可以对图形不可见部分不 必进行扫描转换。在光栅图形中,非水平和垂直的直线用象 素集合表示时,会呈锯齿状,这种现象称之为走样(aliasing); 用于减少或消除走样的技术称为反走样(antialiasing)。提高 显示器的空间分辨率可以减轻走样问题,但这是以提高设备 成本为代价的。实际上,当显示器象素可以用多亮度(或灰 度)显示时,可以通过调整图形上各象素的亮度来减轻走样 问题。
4.编写OnDraw()函数 void CDDALineView::OnDraw(CDC *pDC) { CDDALineDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here ddaline(pDC,100,100,400,100,RGB(255,0,0)); ddaline(pDC,400,100,400,400,RGB(0,255,0)); ddaline(pDC,400,400,100,400,RGB(0,0,255)); ddaline(pDC,100,400,100,100,RGB(255,255,0)); ddaline(pDC,100,100,400,400,RGB(255,0,255)); ddaline(pDC,100,400,400,100,RGB(0,255,255)); } 5.编译、调试和运行程序,查看程序结果。
DDA算法与基本算法的比较
DDA算法与基本算法相比,减少了浮点 乘法,提高了效率。 但是x与dx、y与dy用浮点数表示,每一 步要进行四舍五入后取整,不利于硬件 实现,因而效率仍有待提高。
中点画线法(1/6)
原理:
P2 Q M
假定直线斜率0<K<1,且已确 定点亮象素点P(X ,Y ),则 下一个与直线最接近的像素只 能是P1点或P2点。
P2 Q M
P=(xp,yp) P1
中点画线法(4/6)
分两种情形考虑再一下个象素的判定:
若d≥0,中点M在直线上方,取正右方象素P1 (Xp+1,Yp)
P2 M
P1
再下一个象素的判别式为 M(xp+2,yp+0.5): =F(Xp,Yp)+a+0.5b+a= d+a
d’=F((Xp+1)+1,Yp+0.5)=a(Xp+2)+b(Yp+0.5)+c
点在直线上面 点在直线上方 点在直线下方
P2 Q M
F x, y 0 F x, y 0 F x, y 0
P=(xp,yp) P1
中点画线法(3/6)
构造判别式: M(xp+1,yp+0.5) d=F(M)=F(xp+1,yp+0.5) =a(xp+1)+b(yp+0.5)+c =F(xp, yp)+a+0.5b= a+0.5b d>0,M在直线(Q点)上方,取右方P1; d<0,………………..下方,取右上方P2; d=0,选P1或P2均可,约定取P1; 能否采用增量算法呢?
沿着线段分布的象素应均匀; 不均匀的例子如下图所示,对同样长的 线段,如果进行图中的扫描转换,就会 因为斜率的不同,产生的象素个数不相 等,这样将导致象素亮度分布不均匀
直线绘制基本算法(续)
斜率截距直线方程: y kx b k表示斜率,b是y轴截距, 给定两个端点P0(x0,y0)和P1(x1,y1),线段的斜率k和 截距b为:
p p
设M为中点,Q为交点
现需确定下一个点亮的象素。
P=(xp,yp) P1
M在Q的下方—> P2离直线更近更近—>取P2 。 M在Q的上方—> P1离直线更近更近—>取P1 M与Q重合, P1、P2任取一点。 问题:如何判断M与Q点的关系?
中点画线法(2/6)
问题:判断距离理想直线最近的下一个象素点 已知:线段两端点(x0,y0),(x1,y1) 直线方程:F(x,y)=ax+by+c=0 a=y0-y1 如何判断M点在Q点上方还是下方? b=x1-x0 把M代入F(x,y),并检查其符号 c=x0y1-x1y0
k ( y1 y0 ) /( x1 x0 )
b y0 k x0
复杂度:加法+取整
DDA画线算法
实验步骤: 1.建立一个DDALine的工程文件; 2.添加ddaline()成员函数 方法:在工作区中选择CLASSVIEW类窗口,右 击CDDAlineView类,选择“add member function…”,定义如下的成员函数: void ddaline(CDC *pDC,int x0,int y0,int x1,int y1,COLORREF color);