二维填充图元的生成
填充图元的扫描转换步骤
多边形扫描转换与区域填充可以统称为区域填充,就是如何用颜色或图案来填充一个二维区域。填充主要做两件工作:
- 确定哪些像素位于填充图元的内部;
- 确定以什么颜色/图案填充这些像素。
1. 扫描转换矩形
问题:
- 矩形是简单的多边形,为什么要单独处理矩形?
相比一般多边形扫描算法来讲,可简化计算、提高效率。应用非常多,窗口系统。 - 共享边界如何处理
原则:左闭右开,下闭上开。
typedef struct {
int xmin, xmax, ymin, ymax;
} Rectangle; // 定义一个矩形结构体
void FillRectangle(Rectangle *rect, int color) {
int x, y;
for (y = rect->ymin; y <= rect->ymax; y++) {
for (x = rect->xmin; x <= rect->xmax; x++) {
PutPixel(x, y, color); // 像素点填充颜色
}
}
}
2. 扫描转换多边形
多边形分为凸多边形、凹多边形、含内环的多边形。
2.1 多边形的表示方法
2.1.1 顶点表示
用多边形顶点的序列来刻画多边形。直观、几何意义强、占内存少;不能直接用于面着色。
2.2.2 点阵表示
用位于多边形内的像素的集合来刻画多边形。 失去了许多重要的几何信息;便于运用帧缓冲存储器表示图形,易于面着色。
2.2 多边形的扫描转换
把多边形的顶点表示转换为点阵表示,也就是从多边形的给定边界出发,求位于其内的各个像素,并给帧缓冲器内的各个对应元素设置相应的灰度和颜色,通常称这种转换为多边形的扫描转换。
2.3 扫描转换方法:
2.3.1 逐点判断法
逐点判断的算法虽然程序简单,但不可取。原因是速度太慢,主要是由于算法割断了各像素之间的联系,孤立地考察各像素与多边形的内外关系,使得几十万甚至几百万个像素都要一一判别,每次判别又要多次求交点,需要做大量的乘除运算,花费很多时间。
#define MAX 100
typedef struct {
int PolygonNum; // 多边形顶点的个数
Point vertexces[MAX]; // 多边形顶点数组
} Polygon
void FillPolygonPbyP(Polygon *P, int polygonColor) {
int x, y;
for (y = ymin; y <= ymax; y++)
for (x = xmin; x <= xmax; x++)
if (IsInside(P, x, y)) // 判断像素点是否在多边形内部
PutPixel(x, y, PolygonColor);
else
PutPixel(x, y, backgroundColor);
} // end of FillPolyPbyP()
- 逐个判断绘图窗口内的像素。
- 如何判断点在多边形的内外关系?
- 射线法
- 累计角度法
- 编码法
2.3.1.1 射线法
从此点出发,向左或向右做射线,如果射线和多边形交点数为奇数,则这一点在多边形区域内,否则在多边形区域外。
2.3.1.2 累计角度法
- 从 v v v点向多边形 P P P顶点发出射线,形成有向角 θ i = ∠ P i v P i + 1 。 \theta_i = \angle P_ivP_{i+1}。 θi=∠PivPi+1。(大小计算可用余弦定理)
- 计算有向角的和,得出结论:
∑ i = 0 n θ i = { 0 , v 位 于 P 之 外 ± 2 π , v 位 于 P 之 内 \sum\limits_{i = 0}^n\theta_i = \begin{cases} 0, \ \qquad v位于P之外 \\ \pm2\pi, \quad v位于P之内 \end{cases} i=0∑nθi={ 0, v位于P之外±2π,v位于P之内
2.3.1.3 编码方法
- 预处理,测试点是否在边上;
- 以 V V V为原点作局部坐标系,对其象限按逆时针(或顺时针)编码;
- 对多边形的顶点进行编码, I p i Ip_i Ip