1
1
2
-
3
-
4
-
5
2
MaxPoint = 100000 ;
6
3
7
4
class Point :
@@ -18,18 +15,19 @@ def __str__(self) -> str:
18
15
19
16
20
17
class Edge :
18
+ # p1, p2是点的索引
21
19
def __init__ (self , p1 , p2 ):
22
20
self .p1 = p1
23
21
self .p2 = p2
24
22
25
23
def __str__ (self ) -> str :
26
24
return "[{},{}]" .format (self .p1 , self .p2 )
27
25
28
-
26
+ # 输入点的索引,返回另一个点的索引
29
27
def other (self , p ):
30
28
return self .p1 if self .p2 == p else self .p2
31
29
32
-
30
+ # 生成edge的索引
33
31
def EdgeIndex (p1 , p2 ):
34
32
if p1 < p2 :
35
33
return p1 * MaxPoint + p2
@@ -47,8 +45,9 @@ def markEdge(edgeindex):
47
45
48
46
class Polygon :
49
47
50
- def __init__ (self , Points ):
48
+ def __init__ (self , Points : list ):
51
49
self .Points = self .Merge ( Points )
50
+
52
51
p0 = Points [0 ];
53
52
minx = p0 .x ;
54
53
miny = p0 .y ;
@@ -71,15 +70,10 @@ def __init__(self, Points):
71
70
maxy = y
72
71
73
72
# 左上角为坐标原点,向下向右坐标为坐标轴的正方向
74
- self .lt .x = minx ; # left top
75
- self .lt .y = miny ;
76
- self .rb .x = maxx ; # right bottom
77
- self .rb .y = maxy ;
78
-
79
- p = Points [maxxn ];
80
- pre = Points [ cnt if maxxn - 1 < 0 else maxxn - 1 ];
81
- nxt = Points [ 0 if maxxn + 1 > cnt else maxxn + 1 ];
73
+ self .lt = Point (minx , maxy ) # left top
74
+ self .rb = Point (maxx , maxy ) # right bottom
82
75
76
+
83
77
# 判断点的集合是否是顺时针
84
78
for i in range (cnt + 2 ): # 最大到 cnt + 1
85
79
if (i == cnt + 1 ):
@@ -93,7 +87,7 @@ def __init__(self, Points):
93
87
nxt = Points [0 if n + 1 > cnt else n + 1 ];
94
88
v1 = p .sub (pre );
95
89
v2 = nxt .sub (p );
96
- dxy = v1 .x * v2 .y - v2 .x * v1 .y ;
90
+ dxy = v1 .x * v2 .y - v2 .x * v1 .y ; # 二维向量叉乘判断是否顺时针
97
91
if (dxy != 0 ):
98
92
self .clock = dxy > 0 ;
99
93
break ;
@@ -108,7 +102,7 @@ def Merge(Points):
108
102
109
103
110
104
# 多边形是否包含另一个多边形p
111
- def Contain (self , p ): # p: Polygon
105
+ def Contain (self , p : ' Polygon' ):
112
106
plt = p .lt ;
113
107
prb = p .rb ;
114
108
if (self .lt .x > plt .x or self .lt .y > plt .y ):
@@ -117,17 +111,17 @@ def Contain(self, p): # p:Polygon
117
111
return False ;
118
112
return True ;
119
113
120
- # 自己被包含在其他多边形中
121
- def Contained (self , polygons ): # polygons: list<Polygon>
114
+ # 返回包围自己的多边形
115
+ def Contained (self , polygons : list [ 'Polygon' ] ):
122
116
for i in range (len (polygons )):
123
- polygon = polygons [i ];
124
- if (polygon != self and polygon .Contain (self )):
117
+ polygon = polygons [i ]
118
+ if (polygon is not self and polygon .Contain (self )):
125
119
return polygon ;
126
-
120
+
127
121
return None
128
122
129
123
130
- def Add (self , p ): #p:Polygon
124
+ def Add (self , p : 'Polygon' ):
131
125
self .polygons .Add (p );
132
126
133
127
@@ -150,10 +144,18 @@ def ToList(self, clock, list ):
150
144
return True ;
151
145
152
146
147
+ class NavPath :
148
+ def __init__ (self ):
149
+ self .polygons = []
150
+
151
+ def Add (self ,p :Polygon ):
152
+ self .polygons .append (p )
153
153
154
- def GenTxt (vertices , indices ):
155
154
156
- # 找到所有没有被两个三角形给引用的边,用于找回环
155
+
156
+ def GenPath (vertices , indices ):
157
+
158
+ # 遍历所有三角的edge,找到所有没有被两个三角形给引用的边,用于找回环,分外回环和内回环
157
159
for i in range (0 , len (indices ), 3 ):
158
160
p1 = indices [i ];
159
161
p2 = indices [i + 1 ];
@@ -163,67 +165,101 @@ def GenTxt(vertices, indices):
163
165
edge2 = EdgeIndex (p2 , p3 );
164
166
edge3 = EdgeIndex (p3 , p1 );
165
167
166
- edge2triangle = {}; # key是边的index,value是以该边为三角形的数量
168
+ edge2triangle_num = {}; # key是边的index,value是以该边为三角形的数量
167
169
168
- if (edge1 in edge2triangle ):
169
- edge2triangle [edge1 ] = edge2triangle [edge1 ] + 1 ;
170
+ if (edge1 in edge2triangle_num ):
171
+ edge2triangle_num [edge1 ] = edge2triangle_num [edge1 ] + 1 ;
170
172
else :
171
- edge2triangle [edge1 ] = 1 ;
173
+ edge2triangle_num [edge1 ] = 1 ;
172
174
173
- if (edge2 in edge2triangle ):
174
- edge2triangle [edge2 ] = edge2triangle [edge2 ] + 1 ;
175
+ if (edge2 in edge2triangle_num ):
176
+ edge2triangle_num [edge2 ] = edge2triangle_num [edge2 ] + 1 ;
175
177
else :
176
- edge2triangle [edge2 ] = 1 ;
178
+ edge2triangle_num [edge2 ] = 1 ;
177
179
178
- if (edge3 in edge2triangle ):
179
- edge2triangle [edge3 ] = edge2triangle [edge3 ] + 1 ;
180
+ if (edge3 in edge2triangle_num ):
181
+ edge2triangle_num [edge3 ] = edge2triangle_num [edge3 ] + 1 ;
180
182
else :
181
- edge2triangle [edge3 ] = 1 ;
183
+ edge2triangle_num [edge3 ] = 1 ;
182
184
183
185
# 点所在边集合
184
186
border = [] # 多边形边界,每个边界边只有一个三角形
185
- point2edge = {} # {point_index:[border中的边 ]} 点到边的映射,一个点可以映射到两个边
186
- for item in edge2triangle :
187
- if (edge2triangle [ item ] == 1 ):
187
+ point2edges = {} # {point_index:[border中边的index ]} 点到边的映射,一个点可以映射到两个边
188
+ for edge in edge2triangle_num :
189
+ if (edge2triangle_num [ edge ] == 1 ):
188
190
i = len (border )
189
- edge = markEdge (item ) # 通过边的索引获得边的对象,边的对象包含两个点
191
+ edge = markEdge (edge ) # 通过边的索引获得边的对象,边的对象包含两个点
190
192
border .append (edge );
191
193
192
194
p1 = edge .p1 ;
193
195
p2 = edge .p2 ;
194
196
195
- if p1 not in point2edge :
196
- point2edge [p1 ] = []
197
- point2edge [p1 ].append (i )
197
+ if p1 not in point2edges :
198
+ point2edges [p1 ] = []
199
+ point2edges [p1 ].append (i )
198
200
199
- if p2 not in point2edge :
200
- point2edge [p2 ] = []
201
- point2edge [p2 ].append (i )
201
+ if p2 not in point2edges :
202
+ point2edges [p2 ] = []
203
+ point2edges [p2 ].append (i )
202
204
203
- elif edge2triangle [ item ] >= 3 :
204
- print ("error: edge2triangle[item ] != 1" )
205
+ elif edge2triangle_num [ edge ] >= 3 :
206
+ print ("error: edge2triangle_num[edge ] != 1" )
205
207
206
208
207
- # 从任意边出发,找到回环,,回环有最外层的回环和内部包含的回环
209
+ # 从任意边出发,找到回环,会有多个回环,有最外层的回环和内部包含的回环
210
+ polygons = [] # 多边形集合
208
211
visited = {}
209
212
for i in range (0 , len (border )):
210
213
if (i not in visited ):
211
214
edge = border [i ]
212
215
p = edge .p2
213
- b = True
214
- polygon = []
215
- pindexs = []
216
+ polygon = [] # 一个回环,内含所有回环的点,而非点的索引
216
217
polygon .append (vertices [edge .p1 ])
217
218
polygon .append (vertices [edge .p2 ])
218
219
visited [i ] = True
219
220
220
221
while True :
221
- edge_list = point2edge [p ]
222
+ edges = point2edges [p ]
223
+ # 异常点判断
224
+ if len (edges ) != 2 :
225
+ print ("error: len(edges) != 2" )
226
+ break
227
+ e0 = edges [0 ]
228
+ e1 = edges [1 ]
229
+
230
+ e = None
231
+ if e0 not in visited :
232
+ e = border [e0 ]
233
+ visited [e0 ] = True
234
+ elif e1 not in visited :
235
+ e = border [e1 ]
236
+ visited [e1 ] = True
237
+
238
+ # 转了一圈,回到起点
239
+ if e == None :
240
+ break
241
+
242
+ nxtp = e .other (p )
243
+ polygon .append (vertices [nxtp ])
244
+ p = nxtp
245
+
246
+
247
+ polygons .append (Polygon (polygon ))
248
+
249
+
222
250
223
251
224
- # 判断单个连线是否在别的多边形内
252
+ # 用内回环和外回环构造最终的多边形
253
+ path = NavPath ();
254
+ for i in range (len (polygons )):
255
+ polygon = polygons [i ];
256
+ container = polygon .Contained (polygons )
257
+ if (container == None ): # 外回环
258
+ path .Add (polygon )
259
+ else : # 内回环,添加到外回环中
260
+ container .Add (polygon )
225
261
226
- pass
262
+ return path
227
263
228
264
229
265
# ==========test=============
@@ -254,7 +290,7 @@ def GenTxt(vertices, indices):
254
290
2 ,3 ,4 ,
255
291
4 ,5 ,6
256
292
]
257
- GenTxt (vertices , indices )
293
+ GenPath (vertices , indices )
258
294
259
295
260
296
0 commit comments