设M为中点,Q为交点现需确定下一个点亮的象素。
当M在Q的下方->P2离直线更近更近->取P2。
–M在Q的上方->P1离直线更近更近->取P1
–M与Q重合,P1、P2任取一点。
假设直线方程为:
ax+by+c=0
其中a=y0-y1,b=x1-x0,c=x0y1-x1y0
由常识知:
∴欲判断M点是在Q点上方还是在Q点下方,只需把M代入F(x,y),并检查它的符号。
(4)Bresenham画线算法
算法原理与推导过程:
在直线生成的算法中Bresenham算法是最有效的算法之一。
令k=Δy/Δx,就0≤k≤1的情况来说明Bresenham算法。
由DDA算法可知:
yi+1=yi+k
(1)
由于k不一定是整数,由此式求出的yi也不一定是整数,因此要用坐标为(xi,yir)的象素来表示直线上的点,其中yir表示最靠近yi的整数。
设图中xi列上已用(xi,yir)作为表示直线的点,又设B点是直线上的点,其坐标为(xi+1,yi+1),显然下一个表示直线的点(xi+1,yi+1,r)只能从图中的C或者D点中去选。
设A为CD边的中点。
若B在A点上面则应取D点作为(xi+1,yi+1,r),否则应取C点。
为能确定B在A点上面或下面,令
ε(xi+1)=yi+1-yir-0.5
(2)
若B在A的下面,则有ε(xi+1)<0,反之,则ε(xi+1)>0。
由图可知
yi+1,r=yir+1,若ε(xi+1)≥0(3)
yi+1,r=yir,若ε(xi+1)≤0
由式
(2)和式(3)可得到
ε(xi+2)=yi+2-yi+1,r-0.5
=yi+1+k-yi+1,r-0.5(4)
=yi+1-yir-0.5+k-1,当ε(xi+1)≥0
=yi+1-yir-0.5+k,当ε(xi+1)≤0
ε(xi+2)=ε(xi+1)+k-1,当ε(xi+1)≥0
ε(xi+2)=ε(xi+1)+k,当ε(xi+1)≤0
由式
(1)和式
(2)可得到
ε(x2)=k-0.5(5)
6.生成圆和椭圆的常用算法原理与推导过程
生成圆弧、椭圆弧的常用算法有:
(1)中点算法
利用圆的对称性,只须讨论1/8圆。
第二个8分圆P(Xp,Yp)
•P为当前点亮象素,那么,下一个点亮的象素可能是P1(Xp+1,Yp)或P2(Xp+1,Yp+1)。
•构造函数:
F(X,Y)=X2+Y2-R2;则
•F(X,Y)=0(X,Y)在圆上;
•F(X,Y)<0(X,Y)在圆内;
•F(X,Y)>0(X,Y)在圆外。
•设M为P1、P2间的中点,M=(Xp+1,Yp-0.5)
•有如下结论:
•F(M)<0->M在圆内->取P1
•F(M)>=0->M在圆外->取P2
•为此,可采用如下判别式:
•d=F(M)=F(xp+1,yp-0.5)=(xp+1)2+(yp-0.5)2-R2
•若d<0,则P1为下一个象素,那么再下一个象素的判别式为:
•d1=F(xp+2,yp-0.5)=(xp+2)2+(yp-0.5)2-R2=d+2xp+3即d的增量为2xp+3.
•若d>=0,则P2为下一个象素,那么再下一个象素的判别式为:
•d1=F(xp+2,yp-1.5)=(xp+2)2+(yp-1.5)2-R2=d+(2xp+3)+(-2yp+2)
•即d的增量为2(xp-yp)+5.
•d的初值:
d0=F(1,R-0.5)=1+(R-0.5)2-R2=1.25–R
•
(2)内接正多边形迫近法:
当一个正多边形的边数足够多时,该多边形可以和圆无限接近。
因此,在允许的误差范围内,可以用正多边形代替圆。
•设内接正n边形的顶点为Pi(xi,yi),Pi的幅角为i,每一条边对应的圆心角为a,则有xi=Rcosi,yi=Rsini
内接正n边形代替圆
计算多边形各顶点的递推公式
Xi+1Rcos(a+i)
=
Yi+1Rsin(a+i)
Xi+1cosa-sinaXi
=
Yi+1sinacosaYi
因为:
a是常数,sina,cosa只在开始时计算一次所以,一个顶点只需4次乘法,共4n次乘法,外加直线段的中点算法的计算量。
(3)等面积正多边形逼近法:
•当用内接正多边形逼近圆时,其面积要小于圆的面积;而当用圆的外切正多边形逼近圆时,其面积则要大于圆的面积。
为了使近似代替圆的正多边形和圆之间在面积上相等,只有使该正多边形和圆弧相交,称之为圆的等面积正多边形。
步骤:
●求多边形径长,从而求所有顶点坐标值
●由逼近误差值,确定边所对应的圆心角α
(4)生成圆弧的正负法
设圆的方程为F(x,y)=X2+Y2-R2=0;
假设求得Pi的坐标为(xi,yi);
则当Pi在圆内时->F(xi,yi)<0->向右->向圆外
Pi在圆外时->F(xi,yi)>0->向下->向圆内
即求得Pi点后选择下一个象素点Pi+1的规则为:
当F(xi,yi)≤0取xi+1=xi+1,yi+1=yi;
当F(xi,yi)>0取xi+1=xi,yi+1=yi-1;
这样用于表示圆弧的点均在圆弧附近,且使F(xi,yi)时正时负,故称正负法。
7.掌握几种线裁剪算法的原理及算法
流程
(1)直接求交算法
直线与窗口边都写成参数形式,
求参数值。
(2)Cohen-Sutherland裁剪
对于每条线段P1P2分为三种情况处理:
(1)若P1P2完全在窗口内,则显示该线段P1P2。
(2)若P1P2明显在窗口外,则丢弃该线段。
(3)若线段不满足
(1)或
(2)的条件,则在交点处把线段分为两段。
其中一段完全在窗口外,可弃之。
然后对另一段重复上述处理。
实现方法:
将窗口边线两边沿长,得到九个区域,每一个区域都用一个四位二进制数标识,直线的端点都按其所处区域赋予相应的区域码,用来标识出端点相对于裁剪矩形边界的位置。
•将区域码的各位从右到左编号,则坐标区域与各位的关系为:
上下右左
XXXX
任何位赋值为1,代表端点落在相应的位置上,否则该位为0。
若端点在剪取矩形内,区域码为0000。
如果端点落在矩形的左下角,则区域码为0101。
一旦给定所有的线段端点的区域码,就可以快速判断哪条直线完全在剪取窗口内,哪条直线完全在窗口外。
所以得到一个规律:
–若P1P2完全在窗口内code1=0,且code2=0,则“取”
–若P1P2明显在窗口外code1&code2≠0,则“弃”
–在交点处把线段分为两段。
其中一段完全在窗口外,可弃之。
然后对另一段重复上述处理。
如何判定应该与窗口的哪条边求交呢?
编码中对应位为1的边。
•计算线段P1(x1,y1)P2(x2,y2)与窗口边界的交点
if(LEFT&code!
=0)
{x=XL;y=y1+(y2-y1)*(XL-x1)/(x2-x1);}
elseif(RIGHT&code!
=0)
{x=XR;y=y1+(y2-y1)*(XR-x1)/(x2-x1);}
elseif(BOTTOM&code!
=0)
{y=YB;x=x1+(x2-x1)*(YB-y1)/(y2-y1);}
elseif(TOP&code!
=0)
{y=YT;x=x1+(x2-x1)*(YT-y1)/(y2-y1);}
具体算法见p201
(3)中点分割裁剪算法
基本思想:
从P0点出发找出离P0最近的可见点,和从P1点出发找出离P1最近的可见点。
这两个可见点的连线就是原线段的可见部分。
与Cohen-Sutherland算法一样首先对线段端点进行编码,并把线段与窗口的关系分为三种情况,对前两种情况,进行一样的处理;对于第三种情况,用中点分割的方法求出线段与窗口的交点。
A、B分别为距P0、P1最近的可见点,Pm为P0P1中点。
从P0出发找距离P0最近可见点采用中点分割方法
先求出P0P1的中点Pm,
若P0Pm不是显然不可见的,并且P0P1在窗口中有可见部分,则距P0最近的可见点一定落在P0Pm上,所以用P0Pm代替P0P1;
否则取PmP1代替P0P1。
再对新的P0P1求中点Pm。
重复上述过程,直到PmP1长度小于给定的控制常数为止,此时Pm收敛于交点。
从P1出发找距离P1最近可见点采用上面类似方法。
(4)梁友栋-Barsky算法
设要裁剪的线段是P0P1。
P0P1和窗口边界交于A,B,C,D四点,见图。
算法的基本思想是从A,B和P0三点中找出最靠近的P1点,图中要找的点是P0。
从C,D和P1中找出最靠近P0的点。
图中要找的点是C点。
那么P0C就是P0P1线段上的可见部分。
线段的参数表示:
x=x0+t△x
y=y0+t△y0<=t<=1
△x=x1-x0△y=y1-y0
窗口边界的四条边分为两类:
始边和终边。
求出P0P1与两条始边的交点参数t0,t1,令tl=max(t0,t1,0),则tL即为三者中离p1最近的点的参数
求出p0p1与两条终边的交点参数t2,t3,令tu=min(t2,t3,1),则tU即为三者中离p0最近的点的参数
若tu>tl,则可见线段区间[tl,tu]
始边和终边的确定及交点计算:
令QL=-△xDL=x0-xL
QR=△xDR=xR-x0
QB=-△yDB=y0-yB
QT=△yDT=yT-y0
交点为ti=Di/Qii=L,R,B,T
Qi<0ti为与始边交点参数
Qi>0ti为与终边交点参数
Qi=0Di<0时,线段不可见
Di>0时,分析另一D,
(5)参数化算法(Cyrus-Beck)见第四章课件
8.掌握多边形的逐边裁剪算法,双边裁剪算法的原理和算法流程。
9.分别写出(二维,三维)图形的平移、旋转、缩放、对称、错切及其组合的变换矩阵。
10.绕空间任意直线的旋转、对空间任意平面作对称变换等。
11.推导透视变换矩阵和各种投影(三视图、正轴测、和斜平行投影)的变换矩阵。
12.扫描线种子填充算法和扫描转换填充的扫描线算法原理及过程。
种子填充算法:
首先假定封闭轮廓线内某点是已知的,然后算法开始搜索与种子点相邻且位于轮廓线内的点。
如果相邻点不在轮廓线内,那么就达到轮廓线的边界;如果相邻点位于轮廓线之内,那么这一点就成为新的种子点,然后继续递归地搜索下去
扫描转换填充算法则是按扫描线的顺序确定某一点是否位于多边形或轮廓线范围内。
13.简述消隐算法的分类。
(1)画家算法
(2)Z-Buffer算法
(3)光线投射算法
(4)扫描线算法
14.简述点与多边形之间的包含性检验算法
15.简述深度缓存(Z-Buffer)算法及其特点。
特点:
简单、可靠,不需要对显示对象的面预先进行排序。
但要很大的Z缓冲器,显示对象的表面和像素对应的每一个点处都要计算它的Z值,所以工作量较大。
16.简述画家算法及其特点
整体排序
一维空间(数轴)上点的排序,二维平面上直线段的排序
17.简述扫描线算法及其特点
扫描线算法是多边形扫描转换的常用算法。
与逐点判断算法相比,扫描线算法充分利用了相邻象素之间的连贯性,避免了对象素的逐点判断和反复求交的运算,达到了减少了计算量和提高速度的目的。
开发和利用相邻象素之间的连贯性是光栅图形算法研究的重要内容。
扫描转换算法综合利用了区域的连贯性、扫描线连贯性和边的连贯性等三种形式的连贯性。
18.简述多面体消隐方法。
见课本135页,课件第八章
19.实体的定义,正则形体的性质及表面性质,基于边界面的正则集合算子(集合成员分类)
(1)实体的定义
b)具有一定的形状
c)具有封闭的边界(表面)
d)内部连通
e)占据有限的空间
f)经过运算后,仍然是有效的物体
(2)正则形体的性质及表面性质
(3)基于边界面的正则集合算子(集合成员分类)
正则集合运算的定义
正则并
正则交
正则差
任一实体S可以用它的边界bS和它的内部iS来表示,即
S=bS∪iS
由实体的定义可知,bS是封闭的,它将整个三维空间分成了三个区域:
S的内部iS,S的边界bS,S的外部eS。
边界bS与实体S是一一对应的。
确定了边界,也就唯一确定了一个实体。
因此,为了求实体A,B的正则集合运算结果Aop*B,只要求出其边界b(Aop*B)即可。
20.简述边界表示法,检验有效形体的准则(欧拉公式及附加条件,几何信息与拓扑信息
(1)边界表示(BR表示或BRep表示)
按照体-面-环-边-点的层次,详细记录了构成形体的所有几何元素的几何信息及其相互连接的拓扑关系。
边界表示的一个重要特点是在该表示法中,描述形体的信息包括几何信息(Geometry)和拓扑信息(Topology)两个方面。
拓扑信息描述形体上的顶点、边、面的连接关系,拓扑信息形成物体边界表示的“骨架”。
形体的几何信息犹如附着在“骨架”上的肌肉。
(2)欧拉运算是三维物体边界表示数据结构的生成操作。
运用欧拉运算,可以正确、有效构建三维物体边界表示中的所有拓扑元素和拓扑关系。
欧拉公式
V:
顶点数
E:
棱线数
F:
面数
凡是满足欧拉公式的形体
均称为欧拉形体
欧拉公式是简单多面体
的必要条件。
附加条件:
每边连接两个顶点
每条边只被两个面共享等来保证有效性
21.简述实体构造表示法(CSG)八叉树表示法
(1)CSG是通过对体素定义运算而得到新的形体的一种表示方法。
体素可以是立方体、圆柱、圆锥等,也可以是半空间,其运算为变换或正则集合运算并、交、差。
CSG表示可以看成是一棵有序的二叉树。
•其终端节点或是体素、或是形体变换参数。
•非终端结点或是正则的集合运算,或是变换(平移和/或旋转)操作,这种运算或变换只对其紧接着的子结点(子形体)起作用。
(2)8叉树的表示应用三维形体的分解,它对一个外接立方体的形体进行前后、左右、上下等部分8个小立方体,如果小立方体单元为满或为空,表示该立方体完全在形体中或完全不在形体中,则其停止分解;对部分形体占有的小立方体需进一步分解为8个子立方体,直至所有小立方体单元要么全部满,要么全部空,或已分解到规定的分解精度为止。
(见课件第十章)
几何信息:
用来表示形体的几何性质和度量关系。
拓扑信息:
用来表示形体之间的连接关系称为拓扑信息。
22.写出光线跟踪算法
i.模拟光线传播的递归计算过程
ii.递归终止条件
(1)光线不与场景中的任何物体相交
(2)被跟踪的光线达到了给定的层次
(3)被跟踪的光线对像素亮度的贡献小于给定的阈值
♦ColorTraceRay(start,direction,depth)
♦Vectorstart,direction;Intdepth;
♦{if(depth>MAX_DEPTH)color=black;
♦else{光线与物体求交,找出离start最近的交点;
♦if(无交点)color=背景色;
♦else{local_color=用局部光照模型计算出的交点处的光强;
♦计算反射方向;
♦Reflected_color=TraceRay(交点,反射方向,depth+1);
♦计算折射方向;
♦Transmitted_color=TraceRay(交点,折射方向,depth+1);
♦Color=local_color+Reflected_color*Kr+Transmitted_color*Kt;
♦}//endelse
♦}//endelse
♦returncolor;
♦}////endTraceRay