多边形填充算法

C/C++ code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// 
// 功能:  填充多边形 
// 
// 参数:  lpPoints: 指向顶点坐标数组的指针,数组类型为POINT,多边形由它们顺次封闭连接得到 
//    nCount:  顶点的个数 
//    nColor:  填充的颜色 默认为黑色 
//    pDC:  设备句柄指针 
// 
// 返回:  无返回值 
// 
// 说明:  可以是边相交的多边形 
// 
// 
void  FillPolygon(LPPOINT lpPoints, int  nCount, CDC *pDC,  int  nColor /*=0*/
// 检查参数合法性 
ASSERT_VALID(pDC); 
ASSERT(lpPoints); 
ASSERT(nCount>2); 
ASSERT(nColor>=0); 
 
// 边结构数据类型 
typedef  struct  Edge{ 
   int  ymax;   // 边的最大y坐标 
   float  x;  // 与当前扫描线的交点x坐标 
   float  dx;  // 边所在直线斜率的倒数 
   struct  Edge * pNext;  // 指向下一条边 
}Edge, * LPEdge; 
 
int  i=0,j=0,k=0; 
int  y0=0,y1=0;   // 扫描线的最大和最小y坐标 
LPEdge pAET=NULL;  // 活化边表头指针 
LPEdge * pET=NULL;   // 边表头指针 
 
pAET= new  Edge;  // 初始化表头指针,第一个元素不用 
pAET->pNext=NULL; 
 
// 获取y方向扫描线边界 
y0=y1=lpPoints[0].y; 
for (i=1;i <nCount;i++) 
   if (lpPoints[i].y <y0) 
   y0=lpPoints[i].y; 
   else  if (lpPoints[i].y>y1) 
   y1=lpPoints[i].y; 
if (y0>=y1)  return
 
// 初始化边表,第一个元素不用 
pET= new  LPEdge[y1-y0+1]; 
for (i=0;i <=y1-y0;i++) 
   pET[i]=  new  Edge; 
   pET[i]->pNext=NULL; 
 
for (i=0;i <nCount;i++) 
   j=(i+1)%nCount;  // 组成边的下一点 
   if (lpPoints[i].y != lpPoints[j].y) // 如果该边不是水平的则加入边表 
  
   LPEdge peg;   // 指向该边的指针 
   LPEdge ppeg;   // 指向边指针的指针 
 
   // 构造边 
   peg = new  Edge; 
   k=(lpPoints[i].y>lpPoints[j].y)?i:j; 
   peg->ymax=lpPoints[k].y;  // 该边最大y坐标 
   k=(k==j)?i:j;  
   peg->x=( float )lpPoints[k].x;  // 该边与扫描线焦点x坐标 
   if (lpPoints[i].y != lpPoints[j].y) 
     peg->dx=( float )(lpPoints[i].x-lpPoints[j].x)/(lpPoints[i].y-lpPoints[j].y); // 该边斜率的倒数 
   peg->pNext=NULL; 
 
   // 插入边 
   ppeg=pET[lpPoints[k].y-y0]; 
   while (ppeg->pNext) 
     ppeg=ppeg->pNext; 
   ppeg->pNext=peg; 
   } // end if 
} // end for i 
 
// 扫描 
for (i=y0;i <=y1;i++) 
   LPEdge peg0=pET[i-y0]->pNext; 
   LPEdge peg1=pET[i-y0]; 
   if (peg0) // 有新边加入 
  
   while (peg1->pNext) 
     peg1=peg1->pNext; 
   peg1->pNext=pAET->pNext; 
   pAET->pNext=peg0; 
  
 
   // 按照x递增排序pAET 
   peg0=pAET; 
   while (peg0->pNext) 
  
   LPEdge pegmax=peg0; 
   LPEdge peg1=peg0; 
   LPEdge pegi=NULL; 
 
   while (peg1->pNext) 
  
     if (peg1->pNext->x>pegmax->pNext->x) 
     pegmax=peg1; 
     peg1=peg1->pNext; 
  
   pegi=pegmax->pNext; 
   pegmax->pNext=pegi->pNext; 
   pegi->pNext=pAET->pNext; 
   pAET->pNext=pegi; 
   if (peg0 == pAET) 
     peg0=pegi; 
  
 
   // 遍历活边表,画线 
   peg0=pAET; 
   while (peg0->pNext) 
  
   if (peg0->pNext->pNext) 
  
     DrawLine(( int )peg0->pNext->x,i,( int )peg0->pNext->pNext->x,i,pDC,nColor); 
     peg0=peg0->pNext->pNext; 
  
   else 
     break
  
 
   // 把ymax=i的节点从活边表删除并把每个节点的x值递增dx 
   peg0=pAET; 
   while (peg0->pNext) 
  
   if (peg0->pNext->ymax < i+2) 
  
     peg1=peg0->pNext; 
     peg0->pNext=peg0->pNext->pNext;  //删除 
     delete  peg1; 
     continue
  
   peg0->pNext->x+=peg0->pNext->dx;  //把每个节点的x值递增dx 
   peg0=peg0->pNext; 
  
 
// 删除边表 
for (i=0;i <y1-y0;i++) 
   if (pET[i]) 
   delete  pET[i]; 
if (pAET) 
   delete  pAET; 
if (pET) 
   delete [] pET; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuckyJiang.2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值