Lesson 1 概论
1.计算机图形学(Computer Graphics)定义
利用计算机研究图形的表示,生成,处理、显示的学科。
2.计算机图形特点
图形广义与抽象定义的结合,其“逼真模拟”是相对概念
可以采用数学表示方法表示,可以在计算机内表示存储,可以在图形输出设备上显示
包括数学方法所描述的几何信息,还有颜色,材质等非几何信息
3.图形与图像
图形:矢量表示——存储生成图形锁需坐标、形状等几何、非几何数据的集合。反应图形内部联系,存储空间小
图像:点阵表示——存储图各像素点颜色值,存储空间大,放大虚化
扫描转换:点阵和矢量又可以相互转化,矢量文件经过扫描转换可在光栅显示器上产生点阵图像;图像通过识别和处理可转化为矢量表示的图形形式。
当放大图像时,位图图像的轮廓会随着放大而成比例地增加锯齿形,图像中的瑕疵也会因放大而突兀明显起来;而矢量图则可以被任意缩放却仍保持图像的清晰程度。
4.从给定集合基元的几何描述来生成图像。
输入:客观对象表示,输出:图像显示。
重点在于如何生成模型
5.重要人物
Sutherland——图形学之父,开创交互式图形技术;
Bezier——CAGD的先驱,Bezier曲线曲面。
Lesson 2 光栅图形扫描转换算法
光栅图形学研究内容
直线段的扫描转换算法、圆弧的扫描转换算法、多边形的扫描转换与区域填充、字符、裁剪、反走样、消隐。
扫描转换一个点
自动取整 : 所有满足 x’≤ x<x’+1 和 y’ ≤ y<y’+1 的数学点(x,y)都映射到像素点(x’,y’)处
四舍五入 : 所有满足 x’-0.5 ≤ x<x’+0.5 和 y’-0.5 ≤ y< y’+0.5 都映射到像素点(x’,y’)处
光栅扫描转换
为了在有限的像素集上表示一个无限的集合,就必须采用一些近似的算法,这就是光栅扫描转换的本意。
1.直线段的扫描转换算法
确定最逼近于该直线的一组像素,并按照扫描线顺序对这些像素进行写操作
常用算法:数值微分法(DDA)、中点画线法、Bresenham算法
直线方程表示方法:
点斜式:y-y1 = k*(x-x1)
斜截式:y = k*x+b
两点式:y-y1 / y2-y1 = x-x1 / x2-x1
一般式:Ax+By.+C = 0。
( k = y2-y1 / x2-x1 )
数值微分法(DDA)
基本思想:
由 y=kx+b ,带入x求出对应y,取像素点(x,int(y))。计算量过大——>增量算法
x每递增1,y递增k。
即:当前步的y值等于前一步的y值加上斜率k。
算法:取 x,int(y+0.5) y+=k;
void DDALINE(int x0,int y0,int x1,int y1,int color)
{
int x;
float dx,dy,k,y; // k不可以定义为整型
dx = x1-x0;
dy = y1-y0;
k = dy/dx;
y = y0;
for(x=x0;x<=x1;x++)
{
putpixel(x,(int)y+0.5,color);// 0.5 是为了四舍五入
y+=k;
}
}
// 增加改善的方式——————x0>x1,|k|>1等情况
特点:方法直观、效率低(y,k必须浮点数表示,每一次要对y四舍五入)、迭代算法、仅适用于k<=±1。
(x0>x1,交换两点坐标值)
(|k|>1 会变为一串孤立点,交换x,y地位 Xi+1 = Xi + 1/K)
两条直线可以有多个不连续交点。
中点画线法
中点画线法提出的直线生成算法的基本原理是每次在最大位移方向上走一步,而另一个方向是走步还是不走步要取 决于误差项的判断。
对于直线上的点:F(x, y) = 0;
对于直线上方的点:F(x, y) > 0 ;
对于直线下方的点:F(x, y) < 0 。
画直线段的过程中,当前像素点为p(xi, yi)
0≤k≤1为例
每次在x方向上加1,y方向上或加1(Pu)或加0(Pd)。x是最大位移方向。
M为Pu与Pd中点, Q为实际交点 。
当M在Q的下方,则说明Pu离直线近,应取Pu为下一点;
当M在Q的上方,则说明Pd离直线近,应取Pd 为下一点。
为判断M与Q关系,构建判别式d
为简化运算,采用增量算法:
由于使用的只是d的符号,可以用2d代替d来摆脱小数,此时算法只涉及整数运算。
中点划线法算法:
- 输入直线的两端点p0(x0,y0)和p1(x1,y1)
- 计算初始值a=y0-y1,b=x1-x0,d=2a+b,x=x0,y=y0
- 绘制点(x,y),判断d的符号:
若d<0,则(x,y)更新为(x+1,y+1),d更新为:d+2a+2b
否则(x,y)更新为(x+1,y),d更新为:d+2a - 当直线没有画完时,重复步骤3。否则结束。
void MidPointLine(int x0,int y0,int x1,int y1,int color)
{
int a,b,delta1,delta2,d,x,y;
a=y0-y1;b=x1-x0;
d=2*a+b;
delta1=2*(a+b);
delta2=2*a;
x=x0;y=y0;
putpixel(x,y,color);
while(x<x1)
{
if(d<0)
{
x++;y++;
d+=delta1;
}
else
{
x++;
d+=delta2;
}
putpixel(x,y,color);
}
}
Bresenham算法
该算法的思想是在各像素的中心构造一个虚拟的网格线,按照直线起点到终点的顺序,计算直线与各垂直网格线交点,然后根据误差项的符号确定该列像素中与此交点最近的像素。
算法步骤为:
- 输入直线的两端点p0(x0,y0)和p1(x1,y1)。
- 计算初始值△x,△y,e=-△x,x=x0,y=y0
- 绘制点(x,y),e更新为e+2△y,判断e的符号:
若e>0,则(x,y)更新为(x+1,y+1),e更新为e-2△x
否则(x,y)更新为(x+1,y) - 当直线没有画完时,重复步骤3。否则结束。
void BresenhamLine(int x0,int y0,int x1,int y1,int color)
{
int x,y,dx,dy,i;
int e;
dx=x1-x0;
dy=y1-y0;
e=