图形学第三章

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
⎧ y − ( y i + 1) − 0.5 + k e( xi +1 ) >= 0 = ⎨ r +1 e( xi +1 ) < 0 ⎩ y r +1 − y i − 0.5 + k ⎧e( x ) + k − 1 e( xi +1 ) >= 0 = ⎨ i +1 e( xi +1 ) < 0 ⎩ e( xi +1 ) + k
记Hi(xHi, yHi), Li(xLi, yLi) sM 对应的圆半径Rm , 且满足: (xHi2 + yHi2 – Rm2) + (xLi2 + yLi2 – Rm2 ) = 0 如何判断弧AB在sM 的上方还是下方? 设AB弧对应半径为R, 令D(P) = x2 +y2 – R2 且 di = D(Hi) + D(Li) = (xHi2 + yHi2 –R2) + (xLi2 + yLi2 –R2) 易知 di 是R的递减函数, R = Rm时, di = 0;取Hi 或Li 。 R > Rm时, AB弧在sM上方, di < 0,取Hi; R< Rm 时, AB弧在sM下方, di > 0,取Li。
3.2.1 Bresenham 生成圆弧算法
void BshCircle(double Radius, int color) {
int x, y, d; x = 0; y = Radius; d = 3 – 2*Radius; while(x <= y) {
SetPixel(x,y,color); if (d < 0) d += 4*x + 6; else { d += 4*(x-y) + 10; y - -; } x++;
i i i i-1
di+1 = di +4xi – 4yi-1 + 6 = di +4(xi-1 – yi-1) + 10
3.2.1 Bresenham 生成圆弧算法
di 的初值。 A(x0,y0), x0 = 0, y0 = R; d1 = D(H1) +D(L1) = ((x0 + 1)2 + y02 – R2) + ((x0 + 1)2 + (y0 – 1)2 – R2) = 3 – 2y0 = 3 – 2R
3.1 直线的扫描转换
在第一个八分象限内讨论
直线斜率 < 1, 将 x 坐标每次递增一 个单位, 计算对应的 y 值,点亮相应象 素.
算法原理
过各行各列象素中心构造一组虚拟网格 线。按直线从起点到终点的顺序计算直 线与各垂直网格线的交点,然后确定该 列象素中与此交点最近的象素。
3.1.1 基本增量算法(DDA算法)
1
2 3 45
6
7 8
3.3.2 扫描线算法
解决几个问题
a) 扫描线与多边形的顶点相交: 计算交点个数时,仅对边的ymin顶 点计数,其ymax顶点不计。 b) 边界象素的取舍:
若填充段端点为实数,左端点向上取 整,右端点向下取整。 若填充段端点为整数,左端点填充,右 端点不填充。
1
2 3 45
6
3.3.2 扫描线算法
数据结构和实现
struct E { double ymax; // 边的上顶点y值 double xmin; // 边的下顶点x值 double △x; // 相邻扫描线间该边
// 在x方向的偏移量
E * pointer ;
// 该扫描线交的下条边
} 每条扫描线具有一个包含相关边信息的链 表,所有的链表构成一个全局的边表。
通过判断di的符号,确定选择 的象素。
3.2.1 Bresenham 生成圆弧算法
di = D(Hi) + D(Li) = (xHi2 + yHi2 –R2) + (xLi2 + yLi2 –R2) 增量法实现di的快速计算 设Pi-1(xi-1, yi-1), Hi(xi, yi-1), Li(xi, yi-1 – 1), Hi+1(xi+1, yi), Li+1(xi+1, yi – 1) di = (xi2 + yi-12 –R2) + (xi2 + (yi-1 – 1)2 –R2) 所以 当di < 0 时, 选Hi, 有yi = yi-1 di+1 = (xi+12 + yi2 –R2) + di+1 = di +4xi + 2 = di + 4xi-1 + 6 2 + (y – 1)2 –R2) (xi+1 i 当 d > = 0 时, 选L , 有 y = y -1,
几种容易实现但效率不高的算法: 1)圆方程显式求解 y = ± R 2 − x 2 ,画出1/4圆周, 对称化整个圆。(乘法、开方;且x ≈ R时,y值 产生大的间断--点分布不均匀)。 2)画点( R cosθ , R sin θ ),从0到90,再对称,效率同1)差 不多,但避免点分布不均。
3.2.1 Bresenham 生成圆弧算法
Bresenham 算 法 误 差 项 的几何含义( |MI| )
3.1.2 Bresenham 算法
CD中点记为M,如果理想点 I(xi+1,yr+1 )在M的上面,取 D(xi+1, yi+1), 否则取C(xi+1, yi)。 为了确定I在M的上面还是下 面,引入误差项: e(xi+1) = yr+1 – yi – 0.5 若e(xi+1)>= 0,I在M的上面, yi+1 = yi + 1; 若e(xi+1) < 0 ,I在M的下面, yi+1 = yi 。
7 8
3.3.2 扫描线算法
解决几个问题
c) 水平边不考虑交点。 d)特殊情况:当填充区域小于1 个象素的窄条填充时,许多扫描 线上按规则一个象素都不能画, 这是走样的一个例子。需要采用 反走样,不严格遵守填充规则- “只填充在多边形内部和多边形左 边线和底线边的象素”。 e) 增量法取代求交点。- 效率 优化
3.3.2 扫描线算法
边表ET
初始化时我们建立这 个全局边表(ET),包含 多边形所有边,按边端 点的ymin排序存放。即, 若边的较低端点为ymin, 则该边就放在扫描线ymin 的链表中。每条扫描线 交的多边形的边按其低 端点的x坐标增序排列。
3.3.2 扫描线算法
活跃边表AET
与当前扫描线相交的边称为活性 边,按与扫描线交点x坐标递增的顺 序存放在一个链表中,称此链表为 活性边表(AET)
// d 的初值 // 绘制 1/8 圆周
} // end while
}
3.3 多边形区域填充
区域填充是光栅系统的一大亮点,优于向量系 统 区域填充利于物体的真实感建模
3.3.1 逐点比较法
逐个象素判别,确定其是否位于多边 形内,给出多边形内部象素的集合。 如何确定一个点是否位于某多边形内 呢?射线法:验证点(x,y)是否位于 多边形P内,则从(x,y)到(+∞, y)的射线与P的交点个数为奇数时, 在内部,否则,点在多边形外。 致命缺点:速度太慢,每个象素去多 次求交点孤立判断,需要大量的乘除 运算。
3.1.1 基本增量算法(DDA算法)
算法描述:
void Line (int x0, int y0, int x1, int y1,int Color) { double k = (y1 – y0)/(x1- x0); double y = y0; for(x = x0; x < = x1; x++) { SetPixel(x, (int)(y + 0.5), Color); y += k; } }
Bresenham 算 法 误 差 项 的几何含义( |MI| )
3.1.2 Bresenham 算法
至此,yi+1 可以通过误差项的符 号由yi推出,但 e 计算复杂. 因此对误差项进行增量运算: 由e(xi+1) = yr+1 – yi – 0.5 得e(xi+2) = yr+2 – yi+1 – 0.5 又 yr+1 = yr+ k , e(xi+2) = yr+1 + k – yi+1 – 0.5
3.3.2 扫描线算法
原理 确定扫描线与多边形边 的交点位置,自左向右存 储,并对每对内部交点间的 帧缓存填写指定颜色
1 2 3 45 6 7 8
3.3.2 扫描线算法
步骤
1)求交 求出扫描线与多边形各边的交点。 2)排序 按x 递增顺序对交点排序。 3)交点匹配 1-2,3-4, 5-6等。 4)运用奇偶规则,填充每对交点间在 多边形区域内部的象素。奇偶规则决 定一个点是否在区域内部:初始化为 偶,遇一交点奇偶性变换一次,奇画 偶不画。
第三章 二维图形的基本光栅图形学算法
直线的扫描转换 圆的扫描转换 多边形填充 线段裁剪 多边形裁剪 反走样
3.1 直线的扫描转换
定义
在二维栅格上计算位于该直线 上的象素坐标(光栅化),直线由起 始坐标确定
要求
1) 观感好,象素分布均匀 2) 误差小,象素尽可能接近数学理想 坐标 3) 速度快--避免乘除法和浮点数运算
3.1.2 Bresenham 算法
Bresenham算法是计算机图形学领域使用最广 泛的直线扫描转换算法,与该方法类似的有中 点法。 特点:采用增量计算,对于每一列,只要检查 一个误差项的符号,就可确定该列的所求象 素。
3.1.2 Bresenham 算法
由于x步长为1递增,光 栅直线方程为 yr+1 = yr+ k, yi = Round(yr)为 整数栅格坐标。 xi 列象素(xi,yi )确定 后,xi+1列象素必然从 C、D 之中产生。
if (e >= 0) { y++;e - -;} e += k; SetPixel(x, y, color);
} }
Bresenham 算 法 误 差 项 的几何含义( |MI| )
3.1.2 Bresenham 算法
举例:用Bresenham方法扫描转换连接两点 P0(0,0)和P1(5,2)的直线段。
k =2/5 = 0.4, e(1) = k – 0.5 = -0.1 x y e 0 0 e(1) = -0.1 1 0 e(2) = 0.3 2 1 e(3) = -0.3 3 1 e(4) = 0.1 4 2 e(5) = -0.5 5 2 e(6) = -0.1
Bresenham算法源自3.2 圆的扫描转换Bresenham 算 法 误 差 项 的几何含义( |MI| )
3.1.2 Bresenham 算法
初始值e(xi+1) = k – 0.5
void Bresenhamline (int x0,int y0, int x1, int y1,int color) { double k = (y1-y0)/(x1-x0); // 斜率 double e = k – 0.5; // 误差项 int y = y0; for (int x = x0;x < x1;x++) {
最简单、最容易想到的策略 计算直线斜率 k = ∆ y / ∆x = ( y1 − y 0 ) /( x1 − x0 ) 从直线最左端点开始,x 每次递增一个单位,对 xi 计算 y i = kx i + B 显示坐标为 ( xi , floor (0.5 + yi )) 的象素。 通过增量计算去除其中的乘法 由于 y i +1 = kx i +1 + B = k ( x i + ∆ x ) + B = y i + k ∆ x 又 ∆x = 1, 所以 y i + 1 = y i + k . 即x y值可以根据前一点的值推算出来,不用算截距。
扫描线6的AET
3.3.2 扫描线算法
void polyfill (polygon, color) { 1 建立全局边表: for (各条扫描线i ) { 把ymin == i 的边结构->边表ET [i]; } 2 y = 最低扫描线号; 初始化活性边表AET为空; 3 for (各条扫描线i ){ (1) 把边表ET[i]中的边结点插入AET表; (2) 遍历AET表,把y max== i 的结点从AET中删除,并按x坐标值 增序排列各边; (3) 把配对交点区间(左闭右开)上的象素(x, i),用Setpixel (x, i, color) 改写颜色值; (4) 把AET中每条边结点的x值递增△x; } } /* polyfill */
已知Pi-1 是弧AB上确定 的一点,要从Hi/Li中选 择距离弧最近的作为下 一个象素。而sL,sM,sH 是半径不等的圆弧。且 弧sM满足:Hi Li到该弧 的距离相等。于是弧sM 成为一条分界线。当弧 AB在sM下面时,选择点 Li, 否则选择Hi。
3.2.1 Bresenham 生成圆弧算法
相关文档
最新文档