多边形区域填充算法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

(2) 填充函数 po_fill 的实现和主函数的实现 #include "base_class.h" #include "graphics.h" #include <iostream.h>
void po_fill(ET<int> &etp, int ep, int color) //多边形填充函数的实现 {
template <class T> struct Enode {
Enode() {next=NULL;} Enode(T pymax, float pxi, float pm, Enode *pnext) {
ymax=pymax; xi=pxi; m=pm; next=pnext; } T ymax, xi; //ymax 表示最大的 y 值,xi 表示最底端点的 x 坐标值 float m; //m 表示斜率的倒数 Enode *next; }; //定义了 ET 表和 AET 表中结点的结构体
DC 5 8 4/3
DC 5 28/3 -4/3
DC 5 32/3 -4/3
DC
54
-4/3
5 DE
5 12 4/3
BA 10 15 -1
AET 6
AET 7
AET 8
EA 10 26/5 6/5
EA 10 32/5 6/5
EA 10 38/5 6/5
BA 10 14 -1
BA 10 13 -1
BA 10 12 -1
扫描的次序:先上后下 进栈的次序:先右后左 测试数据: 第一个多边形:A(50, 150),B(50, 100),C(100, 50),D(250, 50),E(200, 150); 第二个多边形:F(100, 100),G(100, 75),H(175, 135); *****************************************************************************/ #include <graphics.h> #include <stdio.h> #include <dos.h> #include <conio.h> #include <stdlib.h>
if(etp.a[0]!=NULL) {
Enode<int> *w; int s=1; while(s) {
Enode<int> *z=NULL; w=etp.a[0]; s=0; while(w && w->ymax!=i) {
z=w; w=w->next; } if(!w) break; if(z) z->next=w->next; else etp.a[0]=w->next; delete w; s=1; } //删去 AET 表中 i 值已经等于 ymax 的结点记录
p=a[i]; q=p; while(p) {
p=p->next; delete q; q=p; } } delete []a; } //析构函数负责回收内存空间 template <class T> ResultCode ET<T>::Insert(int u, T ymax, float xi, float m) { if(u<0||u>n-1) return Failure; Enode<T> *p=new Enode<T>(ymax, xi, m, a[u]); a[u]=p; return Success; } //依次插入结点构建出边表,其中 a[1]到 a[10]用于构建 ET 边表 //a[0]用于构建活动 AET 边表
if(etp.a[0]) {
Enode<int> *u,*v; u=etp.a[0]; while(u) {
v=u; u=u->next; v->xi=v->xi+v->m; } } //用 xi+m 来替代原有的 xi } i++; //进入下一条扫描线 } }
void main() //主函数的实现 {
AET 9
EA 10 44/5 6/5
BA 10 11 -1
AET 10
EA 10 10 6/5
BA 10 10 -1
具体编程实现如下:
第 1 步:(1) 根据输入的五个顶点坐标找到 y 值最小的点(例如点 D,此时 y=2),并找到与 D 有边关系的两个顶点(此时为 E 和 C),在 y=2 处建立 ET 边表记录(ymax、xi 和 m 值均可通 过顶点坐标间的计算得到,例如 DE 边的建立,特别注意:当 D 点和 E 点 y 坐标值相同时, 也即是 DE 与 x 轴平行,该边不能计入 ET 边表),之后标记 D 点被访问过;(2) 排除访问过 的点以及和该点相关联的边,重复(1)直至将 ET 表建立完善。 [注]边关系的建立可通过邻接矩阵的数据结构实现,权值可以为该矩阵行编号对应点的 y 坐 标值,ET 边表采用邻接表的数据结构 第 2 步:根据 ET 表构建 AET 表,并逐行完成多边形填充,具体的 C++代码如下: (1) 建立头文件 base_class.h,主要是边表结点结构体和 ET 边表类的实现 enum ResultCode{Success, Failure};
1
P5P6
P5P4
2 8 -2
284
该多边形的 AET 指针的内容为:(每条扫描线均有 3 行指针链,第 1 行表示将 ET 表加入 AET 中,第 2 行表示从 AET 表中删去 yi=ymax,第 3 行表示 xi=xi+1/m 后,学生只要写出第 2 行 即可)
AET 1
P5P6 2 8 -2
int gdriver, gmode; gdriver=DETECT;
gmode=VGAHI; initgraph(&gdriver, &gmode,""); //图形系统初始化
int e=11; int color=5; //color 用于标识填充颜色 ET<int> et(e); et.Insert(2,5,8,4/3); et.Insert(2,5,8,-4/3); et.Insert(5,10,15,-1); et.Insert(5,10,4,6/5); //根据初始数据建立边表 po_fill(et, e, color); //调用填充函数
EA 10 4 6/5
4
3 DE
2
5 8 -4/3
1
0
用于存放 AET 活动边表
该多边形的 AET 指针的内容为: 1 AET 为空
AET 2
DE 5 8 -4/3
AET
3
AET 4
DE 5 20/3 -4/3
DE 5 16/3 -4/3
AET
EA
10 4
6/5
BA 10 15 -1
DC 5 8 4/3
AET
P1P2 420
P1P2 420
P1P2 420
P4P3 6 11 -1
P4P3 6 11 -1
P4P3 6 10 -1
AET 4
AET
AET
AET 5
AET
AET
6 AET
P1P2 420
P2P3 623
P2P3 653
P2P3 653
P2P3 653
P2P3 683
P2P3 683
P2P3 623
getch(); closegraph(); }
[注]第 2 步的实现存在两个问题:(1) 没有实现世界坐标系统(第 1 象限)到设备坐标系统的转 换,所以显示出来的图形是以上所画图形的倒置,解决方法就是从世界坐标系统的最高 y 值开始扫描;(2) 由于 m 的取值为分数(浮点型),这就导致像素点坐标值出现浮点型,这样 经过取整运算,计算出来的像素点坐标值将可能与多边形填充点真实值之间存在偏差,导致 所绘制的图形不完全与实际吻合。
}; //定义了边表类
template <class T> ET<T>::ET(int mSize) {
n=mSize; a=new Enode<T> *[n]; for(int i=0;i<n;i++) a[i]=0; } //ET 边表的初始化 template <class T> ET<T>::~ET() { Enode<T> *p, *q; delete a[0]; for(int i=1;i<n;i++) {
P4P3 6 10 -1
P4P3 6 9 -1
P4P3 6 9 -1
P4P3 6 9 -1
P4P3 6 8 -1
P4P3 6 8 -1
15. 用扫描线种子填充算法,编写一个填充多边形区域的程序。
A
F B
G C
E H
P4P3 6 10 -1
D
该测试多边形的各个端点坐标分别为: A(50, 150),B(50, 100),C(100, 50),D(250, 50),E(200, 150); F(100, 100),G(100, 75),H(175, 135); /**************************************************************************** 本程序实现区域填充功能,首先输入多边形顶点的个数,回车, 然后依次输入各顶点的坐标格式如下:100,123 回车 一定要在中间用逗号隔开噢,输完最后一个点后,屏幕上会依次 画出各条边,最后填充满 程序还不完善,比如颜色值应该用变量表示以易于修改,画多边形和求种子点 应该做成独立的函数等等,以后再做上吧,这是细节的问题
template <class T> class ET {
public: ET(int mSize); ~ET(); ResultCode Insert(int u, T ymax, float xi, float m); int n; //覆盖该多边形的扫描线的总数,从 0 开始计数 Enode<T> **a;
int i=1; //i 作为控制变量标识扫描线 while(i<ep-1) { if(etp.a[i]!=NULL) {
Enode<int> *p,*r; p=etp.a[i]; r=etp.a[0]; while(p) {
Enode<int> *q=new Enode<int>(p->ymax,p->xi,p->m,NULL); if(!etp.a[0]) {etp.a[0]=q; r=q;} else {
13. 设五边形的五个顶点坐标为(10, 10),(15, 5),(12, 5),(8, 2)和(4, 5),利用多边形区域填 充算法,编一程序生成一个实心图。 解:假设以上五个顶点依次对应编号 A-B-C-D-E,首先计算得到 ET 表:
A
E
B
C
D
ymax x|ymin 1/k next
6-10 … 5
Enode<int> *f,*g; if(etp.a[0]) {
f=etp.a[0]; while(f->next) {
g=f; f=f->next; for(int j=g->xi;j<=g->next->xi;j++)
putpixel(j,i,color); } //把一对相邻结点的 xi 区间范围进行填充 }
P5P4 284
AET
P5P6
2 8 -2
AET
P5P6
2 6 -2
P5P4 284
P5P4 2 12 4
AET 2
2
4Leabharlann Baidu
P5P4 12 4
P1P2 20
AET
P1P2
420
AET
P1P2
420
P5P6 2 6 -2 P4P3 6 12 -1
P4P3 6 12 -1
P4P3 6 11 -1
AET 3
AET
//creat a stack struct stack_node {
14. 已知多边形各顶点坐标为(2, 2)(2, 4)(8, 6)(12, 2)(8, 1)(6, 2)及(2, 2),在用多边形区域填充 时,请写出 ET 及全部 AET 内容。 解:如图所示:
P3
P2
P6
P4
P1
P5
则该多边形的 ET 表为:
6
5 P2P3
623
4
3
P1P2
P4P3
2
420
6 12 -1
if(r->xi==q->xi) {q->next=r->next; r->next=q; r=q;} if(r->xi>q->xi) {etp.a[0]=q; q->next=r;} else {
while(q->xi>r->xi && r->next) r=r->next; if(r->next) {q->next=r->next; r->next=q; } else {r->next=q; q->next=NULL;} } } p=p->next; } } //按照 xi 值的大小将当前 ET 表中的记录放置到 AET 表中
相关文档
最新文档