计算机图形学 算法汇总(期末复习)

一、光栅图形扫描转换算法

1.扫描转换一个点

1.1.自动取整法

算法描述:直接取各个点坐标的整数部分。

算法举例:将点P(1.7,0.8)经过自动取整,转化为点(1,0)。

1.2.四舍五入法

算法描述:对点坐标的各个分量进行四舍五入

算法举例:将点P(1.7,0.8)经过四舍五入,转化为点(2,1)。

2.扫描转换一条直线

2.1.数值微分(DDA)算法

算法描述:

①判断直线的最大变化方向:首先计算出直线在X轴方向和Y轴方向各自变化量的绝对值,如果X轴方向变化量的绝对值更大则最大变化方向为X轴,反之最大变化方向为Y轴。
②判断在最大变化方向上两个点的坐标是否满足升序排列,如果不满足,则交换两个点;
③设两个点分别为A(x1,y1)和B(x2,y2),在两点位于主要变化方向上的两个坐标之间进入循环过程:每一次在最大变化方向上+1,而另一个方向上加上直线的斜率K(对最大变化方向为Y轴的情况,加上斜率的倒数1/K),并对求得的坐标点进行扫描转换(自动取整或四舍五入)。

2.2.中点画线算法

算法描述:

①判断直线的最大变化方向:首先计算出直线在X轴方向和Y轴方向各自变化量的绝对值,如果X轴方向变化量的绝对值更大则最大变化方向为X轴,反之最大变化方向为Y轴。
②判断在最大变化方向上两个点的坐标是否满足升序排列,如果不满足,则交换两个点;
③设两点分别为P1(x1,y1),P2(x2,y2),令a=y1-y2,b=x2-x1;
④分情况进行下列循环过程:
1.最大变化方向为X轴,斜率大于零:

int d = 2 * a + b;
int delta1 = 2 * a;
int delta2 = 2 * (a + b);
for (unsigned x = x1, y = y1; x <= x2; ++x)
{
	putpixel(x, y, BLUE);
	if (d >= 0)
	{
		d += delta1;
	}
	else
	{
		d += delta2;
		y++;
	}
}

2.最大变化方向为X轴,斜率小于零:

int d = 2 * a - b;
int delta1 = 2 * (a - b);
int delta2 = 2 * a;
for (unsigned x = x1, y = y1; x <= x2; ++x)
{
	putpixel(x, y, BLUE);
	if (d >= 0)
	{
		d += delta1;
		--y;
	}
	else
	{
		d += delta2;
	}
}

3.最大变化方向为Y轴,斜率大于零:

int d = a + 2 * b;
int delta1 = 2 * (a + b);
int delta2 = 2 * b;
for (unsigned y = y1, x = x1; y <= y2; ++y)
{
	putpixel(x, y, BLUE);
	if (d >= 0)
	{
		d += delta1;
		++x;
	}
	else
	{
		d += delta2;
	}
}

4.最大变化方向为Y轴,斜率小于零:

int d = 2 * b - a;
int delta1 = 2 * b;
int delta2 = 2 * (b - a);
for (unsigned y = y1, x = x1; y <= y2; ++y)
{
	putpixel(x, y, BLUE);
	if (d >= 0)
	{
		d += delta1;
	}
	else
	{
		d += delta2;
		x--;
	}
}

注:斜率为零的情况包含在④的1中,斜率不存在的情况包含在④的3中。

2.3.Bresenham算法

算法描述:
①判断直线的最大变化方向:首先计算出直线在X轴方向和Y轴方向各自变化量的绝对值,如果X轴方向变化量的绝对值更大则最大变化方向为X轴,反之最大变化方向为Y轴。
②判断在最大变化方向上两个点的坐标是否满足升序排列,如果不满足,则交换两个点;
③分情况在两点之间进行下列循环过程:(设dx=x2-x1,dy=y2-y1)
1.最大变化方向为X轴,斜率大于零:

int e = -dx;
for (; x <= x2; ++x)
{
	putpixel(x, y, YELLOW);
	e += 2 * dy;
	if (e > 0)
	{
		y++;
		e -= 2 * dx;
	}
}

2.最大变化方向为X轴,斜率小于零:

int e = dx;
for (; x <= x2; ++x)
{
    putpixel(x, y, YELLOW);
    e += 2 * dy;
    if (e <= 0)
	{
		y--;
		e += 2 * dx;
	}
}

3.最大变化方向为Y轴,斜率大于零:

int e = -dy;
for (; y <= y2; ++y)
{
	putpixel(x, y, YELLOW);
	e += 2 * dx;
	if (e > 0)
	{
		x++;
		e -= 2 * dy;
	}
}

4.最大变化方向为Y轴,斜率小于零:

int e = dy;
for (; y <= y2; ++y)
{
	putpixel(x, y, YELLOW);
	e += 2 * dx;
	if (e <= 0)
	{
		x--;
		e += 2 * dy;
	}
}

3.扫描转换一个圆

3.1.中点画圆算法

算法描述:(设圆心为(x0,y0))

①变量初始化:令d=1-r,x=0,y=r;
②按照d的正负进行如下的分情况循环(x大于等于y时结束):
作出八个顶点:
(x+x0,y+y0) (x+x0,-y+y0) (-x+x0,y+y0) (-x+x0,-y+y0)
(y+x0,x+y0) (y+x0,-x+y0) (-y+x0,x+y0) (-y+x0,-x+y0)

接着进行如下判定:

if (d < 0)
{
	d += (2 * x + 3);
	x++;
}
else if (d > 0)
{
	d += (2 * x - 2 * y + 5);
	x++;
	y--;
}

3.2.Bresenham画圆算法

算法描述:(设圆心为(x0,y0))

1.初始化x=0,y=r,flag=2-2r。
2.进入循环过程(当y<=0时算法终止):
作出四个顶点:
(x+x0,y+y0) (x+x0,-y+y0) (-x+x0,y+y0) (-x+x0,-y+y0)
确定下一步的绘图方向

if (flag < 0)
{
	int flag1 = 2 * (flag + y) - 1;
	if (flag1 <= 0)
		Direction = 1;
	else Direction = 2;
}
else if (flag > 0)
{
	int flag2 = 2 * (flag - x) - 1;
	if (flag2 <= 0)
		Direction = 2;
	else Direction = 3;
}
else if(flag==0)
{
	Direction = 2;
}

根据上述求出的作图方向进行分情况讨论:

if (Direction == 1)
{
	x++;
	flag += (2 * x + 1);
}
else if (Direction == 2)
{
	x++;
	y--;
	flag += (2 * x - 2 * y + 2);
}
else if (Direction == 3)
{
	y--;
	flag += (1 - 2 * y);
}

4.扫描转换一个椭圆(Bresenham算法)

算法描述:(设椭圆的圆心为(x0,y0),半长轴长为a,半短轴长为b)

1.求出P点坐标(a^2/sqrt(a×a+b×b))。
2.从(0,b)到P点部分:

int x = 0, y = b;
double d = b * b + (b - 0.25) * a * a;
for (; x < px; x++)
{
	putpixel(x + x0, y + y0, RED);
	putpixel(x + x0, -y + y0, RED);
	putpixed(-x + x0, y + y0, RED);
	putpixed(-x + x0, -y + y0, RED);
	if (d <= 0)
	{
		d += (2 * x + 3) * a * a;
	}
	else if (d > 0)
	{
		d += (2 * x + 3) * b * b + (2 - 2 * y) * a * a;
		y--;
	}
}

3.从P到(a,0)部分:

int x = px, y = py;
double d = b * b + (x + 0.5) * (x + 0.5) + a * a + (y - 1) * (y - 1) - a * a * b * b;
for (; y >= 0; y--)
{
    putpixel(x + x0, y + y0, RED);
	putpixel(x + x0, -y + y0, RED);
	putpixed(-x + x0, y + y0, RED);
	putpixed(-x + x0, -y + y0, RED);
	if (d <= 0)
	{
		d += (3 - 2 * y) * a * a + (2 * x + 2) * b * b;
		x++;
	}
	else if (d > 0)
	{
		d += (3 - 2 * y) * a * a;
	}
}

二.二维图形裁剪算法

1.直线段裁剪算法

1.1.Cohen-Suthurland裁剪算法

算法描述:

①求出线段两端点的区域码D3D2D1D0。一个点的区域码为:当点在裁剪窗口上方,则D3=1;当点在裁剪窗口下方,则D2=1;当点在裁剪窗口右边,则D1=1;当点在裁剪窗口左边,则D0=1。
②分情况讨论:
如果两个端点的区域码均为零则说明线段在窗口内,直接绘制即可;
如果两个端点的区域码进行按位与运算的结果不为零,则说明线段位于窗口外,不用绘制;
如果不满足上述两种情况则说明线段与窗口有交点,则需要求出线段与窗口的交点,以交点为分界点将线段分为两段,对两段线段分别递归使用该算法即可。
(求交点的方法:与左右边界的交点用y=y1+k*(x-x1),与上下边界的交点用x=x1+(y-y1)/k)

1.2.中点分割裁剪算法

算法描述:

①求出线段两端点的区域码D3D2D1D0。一个点的区域码为:当点在裁剪窗口上方,则D3=1;当点在裁剪窗口下方,则D2=1;当点在裁剪窗口右边,则D1=1;当点在裁剪窗口左边,则D0=1。
②分情况讨论:
如果两个端点的区域码均为零则说明线段在窗口内,直接绘制即可;
如果两个端点的区域码进行按位与运算的结果不为零,则说明线段位于窗口外,不用绘制;
如果不满足上述两种情况则说明线段与窗口有交点,则需要求出当前线段的中点,以中点为分界点将线段分为两段,对两段线段分别递归使用该算法即可。

1.3.Liang-Barsky裁剪算法

算法描述:

①初始化过程:
令p1=x1-x2,p2=x2-x1,p3=y1-y2,p4=y2-y1;q1=x1-xL,q2=xR-x1,q3=y1-yB,q4=yT-y1;
②判定过程:
如果x1=x2并且q1和q2中至少有一个小于零,则说明直线不在窗口内,无需绘制;
如果y1=y1并且q3和q4中至少有一个小于零,则说明直线不在窗口内,无需绘制;
③令uk=qk/pk(k=1,2,3,4),并定义Umax=max(0,uk|pk<0),Umin=min(1,uk|pk>0);
④如果Umax>Umin,则直线不在窗口内,无需绘制;否则说明直线与窗口相交,分别将Umax和Umin代入x=x1+(x2-x1)×u和y=y1+(y2-y1)×u即可求出两个交点的坐标。

2.多边形裁剪算法

2.1.Sutherland-Hodgman裁剪算法

算法描述:

①按照右下左上的顺序,每次选定窗口的一条边框及其延长线。原始队列就是按照顺时针方向的原始多边形顶点序列的顺时针排列。
②按照顺时针顺序遍历队列中的顶点:如果顶点在当前裁剪边的可见域中或裁剪边上,则将其放入队列中;如果顶点在可见域中或裁剪边上,并且与下一个顶点之间的线段与窗口所选择的边框或其延长线相交,则将交点加入队列中。
③四条边遍历完成后,从最后的顶点序列中找出所有交点,如果处在同一边框上的两个交点相邻,则需要去除这两个点之间的连边。将其它顶点按照顺序连接即可。

2.2.Weiler-Athurton算法

算法描述:

①首先选定多边形的一个顶点,按照顺时针顺序,找出多边形与裁剪窗口的所有交点,并对找到的交点进行分类:如果是从窗口外部走向窗口内部,则称为入点;如果是从窗口内部走向外部,则称为出点。
②再次从多边形的一个顶点开始对多边形进行顺时针行走,记录行走轨迹:如果行走过程中遇到出点,则沿着裁剪窗口按照顺时针方向走到下一个交点处,从下一个交点处开始继续沿着多边形行走。上述过程中获得的行走轨迹就是多边形的裁剪结果。

三.二三维图形的几何变换算法

1.二维图形的几何变换算法

1.1.二维平移变换

算法描述:

设X方向的平移距离为dx,Y方向的平移距离为dy,初始位置为(x,y)

x’=x+dx
y’=y+dy

1.2.二维比例变换

算法描述:

设参考点坐标为(x0,y0),X方向上的比例为Sx,Y方向上的比例为Sy,初始点位置为(x,y)

x’=x×Sx-x0×(Sx-1)
y’=y×Sy-y0×(Sy-1)

1.3.二维对称变换

算法描述:

设对称轴的方程为Ax+By+C=0,变换前点的坐标为(x0,y0)

x’=x0-2A×(Ax0+By0+C)/(A²+B²)
y’=y0-2B×(Ax0+By0+C)/(A²+B²)

1.4.二维旋转变换

算法描述:

设旋转中心为(x0,y0),旋转前的点为(x,y),旋转角度为a(以逆时针方向为正)
则有:
x’=(x-x0)*cos(a)-(y-y0)*sin(a)+x0
y’=(x-x0)*sin(a)+(y-y0)*cos(a)+y0

1.5.二维错切变换

算法描述:

设X方向上的错切系数为a,Y方向上的错切系数为b
x’=x+ay
y’=y+bx

2.三维图形的几何变换算法

2.1.三维平移变换

算法描述:

设X方向的平移距离为dx,Y方向的平移距离为dy,Z方向的平移距离为dz,初始位置为(x,y,z)

x’=x+dx
y’=y+dy
z’=z+dz

2.2.三维比例变换

算法描述:

设参考点坐标为(x0,y0,z0),X方向上的比例为Sx,Y方向上的比例为Sy,Z方向上的比例为Sz,初始点位置为(x,y,z)

x’=x×Sx-x0×(Sx-1)
y’=y×Sy-y0×(Sy-1)
z’=z×Sz-z0×(Sz-1)

2.3.三维旋转变换

算法描述:

设(vx,vy,vz)为旋转轴的单位向量,旋转前的点坐标为(x,y,z),旋转之后的点坐标为(x’,y’,z’),则有:
在这里插入图片描述

2.4.三维对称变换

算法描述:

设变换前的点坐标为(x0,y0,z0),变换后为(x,y,z),对称平面的方程为Ax+By+Cz+D=0,则有:
x=x0-2A×(Ax0+By0+Cz0+D)/(A²+B²+C²)
y=y0-2B×(Ax0+By0+Cz0+D)/(A²+B²+C²)
z=z0-2C×(Ax0+By0+Cz0+D)/(A²+B²+C²)

2.5.三维错切变换

算法描述:

设变换前的点坐标为(x0,y0,z0),变换后的点坐标为(x,y,z),则有:
x=x0+ay+bz
y=y0+cx+dz
z=z0+ex+fy
(其中的a,b,c,d,e,f都是错切系数)

四.三维图形的投影与消隐算法

1.平行投影

1.1.三视图

算法描述:

①主视图:令所有点的y值为零,所得到的二维图形就是主视图。变换矩阵如下:
在这里插入图片描述

②侧视图:令所有点的x值为零,将所得到的二维图形绕Z轴旋转90度,并将旋转后的图形移动一定距离。总体的变换矩阵如下:
在这里插入图片描述
③俯视图:令所有点的z值为零,将所得到的二维图形绕x轴旋转90度,并将旋转后的图形移动一定距离。总体的变换矩阵如下:

在这里插入图片描述

1.2.正轴测图

1.2.1.正等轴测图

算法描述:

正等轴测图的变换矩阵如下图所示:
在这里插入图片描述

1.2.2.正二轴测图

算法描述:

正二轴测图的变换矩阵如下图所示:
在这里插入图片描述

2.透视投影

2.1.单点透视投影

2.2.两点透视投影

2.3.三点透视投影

3.消隐算法

3.1.消除隐藏线算法

算法描述:

①根据三维物体的信息建立单链三表结构。单链三表结构介绍:面表中的每一个元素存储该面在环表中对应的起始下标和结束下标;环表中的每一个元素存储该面所有的顶点的编号(按照对外的一面的顺时针方向);点表存储每一个顶点的空间三维坐标(一个顶点可能被重复存储多次)。
②根据视轴,将三维物体的每一个顶点进行坐标变换得到投影点坐标。
③根据视轴,判定物体的每一个面的可见性,判定方法如下:对于一个对外的面的顶点的顺时针序列,按照逆时针方向找出相邻的三个顶点A(x1,y1,z1),B(x2,y2,z2),C(x3,y3,z3),计算外法线向量AB×BC=(y1z2-y2z1,z1x2-z2x1,x1y2-x2y1)。如果外法向量与视轴的点积大于零则该面可见,小于等于零则该面不可见。
④对于可见的面,绘制出其投影后的多边形边框。

3.2.交点检验算法

算法描述:

①从该点向下作一条与Z轴平行的射线。
②如果射线与平面图形的交点为偶数个则说明该点在多边形之外,如果交点个数为奇数个则说明该点在多边形之内。(如果射线刚好经过了多边形的顶点,则采用“左闭右开”的原则,即边在射线左边则不计数,边在射线的右边才计数)

3.3.夹角和检验算法(高效版本)

算法描述:

①将坐标系的坐标原点移动到被测点,此时多边形的每一个顶点相对于新的坐标原点,都有了新的象限。
②规定位于第一象限内的点角度为零,第二象限内的点角度为二分之派,第三象限内的点角度为派,第四象限内的点角度为负二分之派。
③将多边形所有顶点对应的角度进行求和,如果角度之和为0则说明该点在多边形之外,如果角度之和为二派则说明该点在多边形内部。

3.4.画家算法

算法描述:

当场景中有多个物体时,先画远处的物体,再画近处的物体,这样一来近处的物体就可以覆盖远处的物体。

3.5.Z缓冲区算法

算法描述:

①建立一个二维数组,用于存储屏幕上每一个像素的深度坐标,初始化每一个深度坐标为深度的最小值。初始化屏幕上每一个像素的颜色为背景色。
②逐一检验每一个多边形:如果当前多边形在该点的深度值大于该点当前的深度值,则将该点的深度值修改为该多边形在这一点的深度值,同时将该点的颜色改为该多边形在这一点的颜色。

五.曲线绘制算法

1.三次样条曲线绘制算法

算法描述:

三次样条曲线是由一段段短小的曲线进行光滑连接生成的,每一段曲线都是抛物线。第i段曲线的计算公式为:
Pi+1(t)=(-2t³+4t²-t)Pi+(12t³-410t²+1)Pi+1+(-12t³+8t²+t)Pi+2+(4t³-2t²)Pi+3
对于结尾处缺少的两条曲线,有两种添加辅助点的方法:
①添加两个辅助点P0=P1,Pn+1=Pn,这样可以得到一条不闭合的自由曲线;
②添加三个辅助点P0=Pn,Pn+1=P1和Pn+2=P2,由此可以得到一条闭合的曲线。

2.贝塞尔曲线绘制算法

算法描述:设有N个型值点,第i个型值点的坐标为(xi,yi)

①进入最外层循环,初始化t=0,从零开始自增(步长自行控制);
②以选定的t值,求出特征多边形上每两条相邻的的线段的t分割点,每一次都会使得特征多边形的边数减少1;
③当特征多边形只留下一条边时结束循环,求出来的等比例点就在贝塞尔曲线上。

3.B样条曲线绘制算法

算法描述:

根据下面的公式即可计算B样条曲线的函数表达式
在这里插入图片描述
在这里插入图片描述
也可以通过下面的公式进行递推:
在这里插入图片描述

  • 14
    点赞
  • 190
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计算机图形学中使用的椭圆算法主要包括中点椭圆算法和参数方程椭圆算法。根据您提供的引用内容,中点椭圆算法是一个常用的算法。 中点椭圆算法将椭圆分成两部分,并在第一象限中应用。该算法的基本思想是通过迭代计算来确定椭圆上的像素点。 首先,对于给定的椭圆参数(a, b),其中a是椭圆的长半轴,b是短半轴,我们需要确定椭圆的圆心坐标(xc, yc)。根据引用中的描述,我们可以将原点设置为(0, 0),然后将计算出的每个椭圆上的像素点(x, y)添加到屏幕位置上,即(xc + x, yc + y)。 其次,中点椭圆算法根据椭圆的斜率绝对值大小选择在x方向或y方向取单位步长。根据引用的描述,在斜率绝对值小于1的区域内,我们在x方向取单位步长。而在斜率绝对值大于1的区域内,我们在y方向取单位步长。 最后,根据引用的描述,在椭圆的上半部分椭圆弧中,法向量的y分量较大,即斜率绝对值小于1的区域;而在椭圆的下半部分椭圆弧中,法向量的x分量较大,即斜率绝对值大于1的区域。 综上所述,中点椭圆算法通过迭代计算每个椭圆上的像素点,并根据斜率绝对值大小确定在x方向或y方向取单位步长。这是计算机图形学中常用的椭圆算法之一。 : 引用内容描述了原点为(xc, yc)的椭圆上的像素点计算方法。 : 引用内容描述了椭圆上半部分和下半部分法向量的特点。 : 引用内容描述了中点椭圆算法将椭圆分成两部分,并在第一象限中应用的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值