7fd59977 |
1 | // File: TopOpeBRepTool_REGUW.cxx |
2 | // Created: Tue Dec 8 18:07:24 1998 |
3 | // Author: Xuan PHAM PHU |
4 | // <xpu@poulopox.paris1.matra-dtv.fr> |
5 | |
6 | |
7 | #include <Geom2d_Curve.hxx> |
8 | #include <TopoDS.hxx> |
9 | #include <BRep_Tool.hxx> |
10 | #include <Precision.hxx> |
11 | #include <TopExp_Explorer.hxx> |
12 | #include <TopOpeBRepTool_C2DF.hxx> |
13 | #include <TopOpeBRepTool_REGUW.ixx> |
14 | #include <TopOpeBRepTool_EXPORT.hxx> |
15 | #include <TopOpeBRepTool_TOOL.hxx> |
16 | #include <TopOpeBRepTool_define.hxx> |
17 | |
18 | #ifdef DRAW |
19 | #include <TopOpeBRepTool_DRAW.hxx> |
20 | #endif |
21 | |
22 | #define FORWARD (1) |
23 | #define REVERSED (2) |
24 | #define INTERNAL (3) |
25 | #define EXTERNAL (4) |
26 | #define CLOSING (5) |
27 | |
28 | #define M_FORWARD(ori) (ori == TopAbs_FORWARD) |
29 | #define M_REVERSED(ori) (ori == TopAbs_REVERSED) |
30 | #define M_INTERNAL(ori) (ori == TopAbs_INTERNAL) |
31 | #define M_EXTERNAL(ori) (ori == TopAbs_EXTERNAL) |
32 | |
33 | #ifdef DEB |
34 | Standard_IMPORT Standard_Boolean TopOpeBRepTool_GettraceREGUFA(); |
35 | static TopTools_IndexedMapOfShape STATIC_mapf, STATIC_mapw, STATIC_mapv; |
36 | static TopTools_IndexedMapOfOrientedShape STATIC_mapeds; |
37 | void FUN_tro(const Standard_Integer i) |
38 | { |
39 | if (i==1) cout<<"FORWARD"; |
40 | else if (i==2) cout<<"REVERSED"; |
41 | else if (i==3) cout<<"INTERNAL"; |
42 | else if (i==4) cout<<"EXTERNAL"; |
43 | else if (i==5) cout<<"CLOSING"; |
44 | } |
45 | Standard_EXPORT Standard_Integer FUN_adds(const TopoDS_Shape& s) { |
46 | TopAbs_ShapeEnum typ = s.ShapeType(); |
47 | TCollection_AsciiString aa; Standard_Integer is = 0; |
48 | if (typ == TopAbs_VERTEX) {aa = TCollection_AsciiString("v"); is = STATIC_mapv.Add(s);} |
49 | if (typ == TopAbs_EDGE) {aa = TCollection_AsciiString("e"); is = STATIC_mapeds.Add(s);} |
50 | if (typ == TopAbs_WIRE) {aa = TCollection_AsciiString("wi"); is = STATIC_mapw.Add(s);} |
51 | if (typ == TopAbs_FACE) {aa = TCollection_AsciiString("f"); is = STATIC_mapf.Add(s);} |
52 | #ifdef DRAW |
53 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
54 | if (trc) FUN_tool_draw(aa,s,is); |
55 | #endif |
56 | return is; |
57 | } |
58 | #endif |
59 | |
60 | Standard_IMPORT void FUN_tool_tori(const TopAbs_Orientation Or); |
61 | |
62 | void FUN_tool_Add(TopTools_DataMapOfShapeListOfShape& map,const TopoDS_Shape& key, const TopoDS_Shape& subitem) |
63 | { |
64 | if (map.IsBound(key)) map.ChangeFind(key).Append(subitem); |
65 | else {TopTools_ListOfShape los; los.Append(subitem); map.Bind(key,los);} |
66 | } |
67 | static void FUN_Raise() { |
68 | #ifdef DEB |
69 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
70 | if (trc) cout<<"*** Raise REGUW"<<endl; |
71 | // Standard_Failure::Raise("REGUW"); |
72 | #endif |
73 | } |
74 | |
75 | //======================================================================= |
76 | //function : CORRISO |
77 | //purpose : |
78 | //======================================================================= |
79 | |
80 | TopOpeBRepTool_REGUW::TopOpeBRepTool_REGUW(const TopoDS_Face& Fref) |
81 | : myCORRISO(Fref) |
82 | { |
83 | myS.Nullify(); |
84 | hasnewsplits = Standard_False; |
85 | |
86 | myEsplits.Clear(); |
87 | myOwNw.Clear(); |
88 | |
89 | mymapvEds.Clear(); |
90 | mymapvmultiple.Clear(); |
91 | myListVmultiple.Clear(); |
92 | |
93 | iStep = 0; |
94 | } |
95 | |
96 | //======================================================================= |
97 | //function : Fref |
98 | //purpose : |
99 | //======================================================================= |
100 | |
101 | const TopoDS_Face& TopOpeBRepTool_REGUW::Fref() const |
102 | { |
103 | return (myCORRISO.Fref()); |
104 | } |
105 | |
106 | //======================================================================= |
107 | //function : SetEsplits |
108 | //purpose : |
109 | //======================================================================= |
110 | |
111 | void TopOpeBRepTool_REGUW::SetEsplits(TopTools_DataMapOfShapeListOfShape& Esplits) |
112 | { |
113 | myEsplits = Esplits; |
114 | } |
115 | //======================================================================= |
116 | //function : GetEsplits |
117 | //purpose : |
118 | //======================================================================= |
119 | |
120 | void TopOpeBRepTool_REGUW::GetEsplits(TopTools_DataMapOfShapeListOfShape& Esplits) const |
121 | { |
122 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
123 | Esplits = myEsplits; |
124 | } |
125 | |
126 | //======================================================================= |
127 | //function : SetOwNw |
128 | //purpose : |
129 | //======================================================================= |
130 | |
131 | void TopOpeBRepTool_REGUW::SetOwNw(TopTools_DataMapOfShapeListOfShape& OwNw) |
132 | { |
133 | myOwNw = OwNw; |
134 | } |
135 | //======================================================================= |
136 | //function : GetOwNw |
137 | //purpose : |
138 | //======================================================================= |
139 | |
140 | void TopOpeBRepTool_REGUW::GetOwNw(TopTools_DataMapOfShapeListOfShape& OwNw) const |
141 | { |
142 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
143 | OwNw = myOwNw; |
144 | } |
145 | |
146 | //======================================================================= |
147 | //function : SplitEds |
148 | //purpose : |
149 | //======================================================================= |
150 | |
151 | Standard_Boolean TopOpeBRepTool_REGUW::SplitEds() |
152 | { |
153 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
154 | #ifdef DEB |
155 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
156 | if (trc) cout<<"** SPLITTING EDGES **"<<endl; |
157 | #endif |
158 | |
159 | TopTools_IndexedMapOfShape mehasIv; |
160 | Standard_Integer i; |
161 | for (i = 1; i <= mymapvEds.Extent(); i++) { |
162 | const TopOpeBRepTool_connexity& co = mymapvEds(i); |
163 | TopTools_ListOfShape loe; Standard_Integer ni = co.IsInternal(loe); |
164 | if (ni == 0) continue; |
165 | TopTools_ListIteratorOfListOfShape ite(loe); |
166 | for (; ite.More(); ite.Next()) mehasIv.Add(ite.Value()); |
167 | } |
168 | |
169 | for (i = 1; i <= mehasIv.Extent(); i++) { |
170 | const TopoDS_Edge& e = TopoDS::Edge(mehasIv.FindKey(i)); |
171 | TopTools_ListOfShape splits; Standard_Boolean issp = Standard_False; |
172 | Standard_Boolean isdone = myEsplits.IsBound(e); |
173 | if (isdone) splits.Assign(myEsplits.Find(e)); |
174 | else issp = TopOpeBRepTool_TOOL::SplitE(e,splits); |
175 | if (issp) hasnewsplits = Standard_True; |
176 | #ifdef DEB |
177 | if (trc) cout<<"e"<<FUN_adds(e)<<" gives splits ="<<endl; |
178 | #endif |
179 | if (!(issp || isdone)) continue; //nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnyi |
180 | |
181 | // e gives splits = {esp has vertices {vv}} |
182 | TopTools_ListIteratorOfListOfShape ite(splits); |
183 | for (; ite.More(); ite.Next()){ |
184 | const TopoDS_Shape& esp = ite.Value(); |
185 | #ifdef DEB |
186 | if (trc) {cout<<" e"<<FUN_adds(esp);} |
187 | #endif |
188 | TopExp_Explorer exvv(esp, TopAbs_VERTEX); |
189 | for (; exvv.More(); exvv.Next()){ |
190 | const TopoDS_Shape& vv = exvv.Current(); |
191 | TopOpeBRepTool_connexity& co = mymapvEds.ChangeFromKey(vv); |
192 | Standard_Boolean isb = co.RemoveItem(INTERNAL,e); |
193 | if (!isb) continue; |
194 | Standard_Integer ivv = TopOpeBRepTool_TOOL::OriinSorclosed(vv,esp); |
195 | co.AddItem(ivv,esp); |
196 | }//exvv(exvv,VERTEX) |
197 | }//ite(splits) |
198 | #ifdef DEB |
199 | if (trc) cout<<endl; |
200 | #endif |
201 | } |
202 | return Standard_True; |
203 | } |
204 | |
205 | |
206 | //======================================================================= |
207 | //function : S |
208 | //purpose : |
209 | //======================================================================= |
210 | |
211 | const TopoDS_Shape& TopOpeBRepTool_REGUW::S() const |
212 | { |
213 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
214 | return myS; |
215 | } |
216 | |
217 | //======================================================================= |
218 | //function : Init |
219 | //purpose : |
220 | //======================================================================= |
221 | |
222 | void TopOpeBRepTool_REGUW::Init(const TopoDS_Shape& S) |
223 | { |
224 | myS = S; |
225 | InitStep(S); |
226 | } |
227 | |
228 | //======================================================================= |
229 | //function : HasInit |
230 | //purpose : |
231 | //======================================================================= |
232 | |
233 | Standard_Boolean TopOpeBRepTool_REGUW::HasInit() const |
234 | { |
235 | return (!myS.IsNull()); |
236 | } |
237 | |
238 | |
239 | |
240 | //======================================================================= |
241 | //function : InitStep |
242 | //purpose : |
243 | //======================================================================= |
244 | |
245 | void TopOpeBRepTool_REGUW::InitStep(const TopoDS_Shape& S) |
246 | { |
247 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
248 | TopoDS_Shape null;myCORRISO.Init(null); myCORRISO.Init(S); |
249 | |
250 | mymapvEds.Clear(); |
251 | mymapvmultiple.Clear(); |
252 | myListVmultiple.Clear(); |
253 | } |
254 | |
255 | |
256 | |
257 | //======================================================================= |
258 | //function : MapS |
259 | //purpose : |
260 | //======================================================================= |
261 | |
262 | Standard_Boolean TopOpeBRepTool_REGUW::MapS() |
263 | { |
264 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
265 | #ifdef DEB |
266 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
267 | if (trc) cout<<"** MAPPING **"<<endl; |
268 | #endif |
269 | |
270 | // Prequesitories : |
271 | // 0) an edge with an INTERNAL vertex binded in <mapVedges> must be |
272 | // splitted |
273 | // After splitting such edges, we deal only with FORWARD and |
274 | // REVERSED vertices. |
275 | // 1) a vertex belonging to a CLOSING edge is represented by 2 distinct |
276 | // 2d points in the UV space. |
277 | // 2) a vertex belonging to a DEGENERATED edge has at least 2 UV rep. |
278 | // (if the original degenerated edge has been splitted). |
279 | // the bounds of the degenerated edge share the same TShape. |
280 | // 3) a CLOSED edge binds the same vertex oriented FORWARD and REVERSED. |
281 | |
282 | // For each vertex get non-"singular" edges in which the vertex is oriented |
283 | // FORWARD and REVERSED. |
284 | // <mymapvmultiple(1)> binds v and ed if : |
285 | // v is FORWARD in ed FORWARD : oriFF(v,ed) = FORWARD |
286 | // v is REVERSED in ed REVERSED : oriFF(v,ed) = FORWARD |
287 | // oriFF(v,ed) = (ori(ed) == FORWARD) ? ori(ed) : ori(ed).Reverse. |
288 | |
289 | // A "singular" edge is a closed, a closing or a degenerated edge. |
290 | // In <mymapvmultiple(5)>, we bind with the key <v>: |
291 | // - the FORWARD and the REVERSED CLOSING ancestor edges of <v> |
292 | // - the DEGENERATED ancestor edge of <v> |
293 | // - the CLOSED edge ancestor edge of <v> |
294 | |
295 | // A MULTIPLE vertex has its single UV representation's connexity > 2 |
296 | |
297 | const TopoDS_Shape& CS = myCORRISO.S(); |
298 | TopExp_Explorer exe(CS, TopAbs_EDGE); |
299 | for (; exe.More(); exe.Next()){ |
300 | const TopoDS_Edge& ed = TopoDS::Edge(exe.Current()); |
7fd59977 |
301 | |
302 | Standard_Boolean isdgE = BRep_Tool::Degenerated(ed); |
303 | Standard_Boolean iscE = TopOpeBRepTool_TOOL::IsClosingE(ed,myCORRISO.S(),Fref()); |
304 | iscE = iscE && !isdgE; // closing ed |
305 | TopoDS_Shape vcl; Standard_Boolean isvcl = TopOpeBRepTool_TOOL::ClosedE(ed,TopoDS::Vertex(vcl)); isvcl = isvcl && !isdgE; |
306 | |
307 | TopExp_Explorer exv(ed, TopAbs_VERTEX); |
308 | for (; exv.More(); exv.Next()){ |
309 | const TopoDS_Vertex& v = TopoDS::Vertex(exv.Current()); |
310 | Standard_Boolean isb = mymapvEds.Contains(v); |
311 | TopOpeBRepTool_connexity theconnexity(v); |
312 | if (!isb) mymapvEds.Add(v, theconnexity); |
313 | TopOpeBRepTool_connexity& co = mymapvEds.ChangeFromKey(v); |
314 | |
315 | if (isdgE) { |
316 | // avoid adding it twice |
317 | co.RemoveItem(CLOSING,ed); |
318 | co.AddItem(CLOSING,ed); |
319 | break; |
320 | } |
321 | else if (iscE) { |
322 | // FORWARD and REVERSED edge is added |
323 | co.AddItem(CLOSING,ed); |
324 | } |
325 | else if (isvcl && (v.IsSame(vcl))) { |
326 | // avoid adding it twice |
327 | co.RemoveItem(CLOSING,ed); |
328 | co.AddItem(CLOSING,ed); |
329 | } |
330 | else { |
331 | Standard_Integer iov = TopOpeBRepTool_TOOL::OriinSor(v,ed,Standard_False); //iov != 0 |
332 | co.AddItem(iov,ed); |
333 | } |
334 | |
335 | }//exv |
336 | }//exe |
337 | |
338 | #ifdef DEB |
339 | if (trc) { |
340 | for (Standard_Integer iv = 1; iv <= mymapvEds.Extent(); iv++) { |
341 | const TopoDS_Vertex& v = TopoDS::Vertex(mymapvEds.FindKey(iv)); |
342 | cout <<"#v"<<FUN_adds(v)<<" :\n"; |
343 | const TopOpeBRepTool_connexity& co = mymapvEds(iv); |
344 | for (Standard_Integer i=1; i<=5; i++) { |
345 | TopTools_ListOfShape eds; Standard_Integer ieds = co.Item(i,eds); |
346 | if (ieds == 0) continue; |
347 | cout<<" is ";FUN_tro(i);cout<<" in "; |
348 | TopTools_ListIteratorOfListOfShape ite(eds); |
349 | for (; ite.More(); ite.Next()) |
350 | {const TopoDS_Edge& e = TopoDS::Edge(ite.Value()); |
351 | cout<<"e"<<FUN_adds(e);FUN_tool_tori(e.Orientation()); |
352 | TopoDS_Vertex vclo; Standard_Boolean cloE = TopOpeBRepTool_TOOL::ClosedE(e,vclo); if (cloE) cout<<"closed"; |
353 | Standard_Boolean dgE = BRep_Tool::Degenerated(e); if (dgE) cout<<"degenerated"; |
354 | Standard_Boolean iscE = TopOpeBRepTool_TOOL::IsClosingE(e,myCORRISO.S(),Fref()); |
355 | if (iscE) cout<<"closing"; |
356 | cout<<" ";} |
357 | cout<<endl; |
358 | }//i=1..5 |
359 | } |
360 | }//trc |
361 | #endif |
362 | |
363 | Standard_Integer nV = mymapvEds.Extent(); |
364 | if (nV < 1) return Standard_False; |
365 | |
366 | Standard_Integer i; |
367 | for (i = 1; i <= mymapvEds.Extent(); i++) { |
368 | const TopoDS_Shape& v = mymapvEds.FindKey(i); |
369 | const TopOpeBRepTool_connexity& co = mymapvEds(i); |
370 | Standard_Boolean faulty = co.IsFaulty(); |
371 | if (faulty) return Standard_False; |
372 | Standard_Boolean multiple = co.IsMultiple(); |
373 | if (multiple) |
374 | if (mymapvmultiple.Add(v)) |
375 | myListVmultiple.Append(v); |
376 | } |
377 | return Standard_True; |
378 | }//MapS |
379 | |
380 | static void FUN_nextdata(const Standard_Integer iStep,const TopoDS_Edge& e,const Handle(Geom2d_Curve)& pc, |
381 | TopoDS_Vertex& v,gp_Pnt2d& p2d,gp_Dir2d& tg) |
382 | // prequesitory : pc = 2drep(e), |
383 | // ori(v,e)=iv1e1 -> v, p2d=pt2d(v,e), tg=tg2d(v,e). |
384 | { |
385 | Standard_Integer iv1e1 = (iStep == 1) ? FORWARD : REVERSED; |
386 | TopoDS_Shape aLocalShape = TopOpeBRepTool_TOOL::Vertex(iv1e1,e); |
387 | v = TopoDS::Vertex(aLocalShape); |
388 | // v = TopoDS::Vertex(TopOpeBRepTool_TOOL::Vertex(iv1e1,e)); |
389 | Standard_Real par1 = TopOpeBRepTool_TOOL::ParE(iv1e1,e); |
390 | Standard_Boolean line = FUN_tool_line(pc); |
391 | Standard_Boolean quad = FUN_tool_quad(pc);// mytg2d is reapproximated if PCquad |
392 | Standard_Boolean approx = quad && (!line); |
393 | |
394 | gp_Vec2d tg2d; |
395 | if (approx) { |
396 | p2d = pc->Value(par1); |
397 | |
398 | Standard_Integer iv0e1 = (iStep == 1) ? REVERSED : FORWARD; |
399 | Standard_Real par0 = TopOpeBRepTool_TOOL::ParE(iv0e1,e); |
400 | // Getting a point near point<Index> of <E> |
401 | Standard_Real x = 0.2345; Standard_Real par = (1-x)*par1+x*par0; |
402 | gp_Pnt2d pmil; pc->D1(par,pmil,tg2d); |
403 | } |
404 | else { |
405 | pc->D1(par1,p2d,tg2d); |
406 | } |
407 | tg = gp_Dir2d(tg2d); |
408 | if (M_REVERSED(e.Orientation())) tg.Reverse(); |
409 | } |
410 | |
411 | //======================================================================= |
412 | //function : InitBlock |
413 | //purpose : |
414 | //======================================================================= |
415 | |
416 | Standard_Boolean TopOpeBRepTool_REGUW::InitBlock() |
417 | { |
418 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
419 | #ifdef DEB |
420 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
421 | #endif |
422 | |
423 | myv0.Nullify(); myp2d0=gp_Pnt2d(1.e7,1.e7); |
424 | myed.Nullify(); |
425 | Standard_Integer iv0e1 = (iStep == 1) ? REVERSED : FORWARD; |
426 | |
427 | // updating <mymapvmultiple> and myListVmultiple |
428 | TopTools_ListIteratorOfListOfShape itmu(myListVmultiple); |
429 | while (itmu.More()) { |
430 | const TopoDS_Shape& vmu = itmu.Value(); |
431 | const TopOpeBRepTool_connexity& cmu = mymapvEds.FindFromKey(vmu); |
432 | Standard_Boolean mult = cmu.IsMultiple(); |
433 | if (!mult) { |
434 | myListVmultiple.Remove(itmu); |
435 | mymapvmultiple.Remove(vmu); |
436 | } |
437 | else itmu.Next(); |
438 | } |
439 | |
440 | // myv0 : |
441 | if (myListVmultiple.IsEmpty()) { |
442 | Standard_Integer i; |
443 | for (i = 1; i <= mymapvEds.Extent(); i++) { |
444 | const TopoDS_Vertex& v = TopoDS::Vertex(mymapvEds.FindKey(i)); |
445 | const TopOpeBRepTool_connexity& co = mymapvEds(i); |
446 | TopTools_ListOfShape lea; Standard_Integer nea = co.Item(iv0e1,lea); |
447 | TopTools_ListOfShape leb; Standard_Integer neb = co.Item(CLOSING,leb); |
448 | TopTools_ListOfShape le; le.Append(lea); le.Append(leb); Standard_Integer ne = nea+neb; |
449 | if (ne != 0) {myv0 = v; break;} |
450 | } |
451 | } |
452 | else { |
453 | myv0 = TopoDS::Vertex(myListVmultiple.First()); |
454 | } |
455 | if (myv0.IsNull()) return Standard_False; |
456 | // myed : |
457 | const TopOpeBRepTool_connexity& co = mymapvEds.FindFromKey(myv0); |
458 | |
459 | TopTools_ListOfShape lea; Standard_Integer nea = co.Item(iv0e1,lea); |
460 | TopTools_ListOfShape leb; Standard_Integer neb = co.Item(CLOSING,leb); |
461 | TopTools_ListOfShape le; le.Append(lea); le.Append(leb); Standard_Integer ne = nea+neb; |
462 | if (ne == 0) return Standard_False; |
463 | |
464 | if (nea > 0) myed = TopoDS::Edge(le.First()); |
465 | else {// <myv0> CLOSING in <myed> |
466 | TopTools_ListIteratorOfListOfShape itb(le); |
467 | for (; itb.More(); itb.Next()){ |
468 | const TopoDS_Edge& eb = TopoDS::Edge(itb.Value()); |
469 | Standard_Boolean iscE = TopOpeBRepTool_TOOL::IsClosingE(myed,myCORRISO.S(),Fref()); |
470 | if (!iscE) {myed = eb; break;} |
471 | Standard_Integer iov0 = TopOpeBRepTool_TOOL::OriinSorclosed(myv0,myed); |
472 | if (iov0 != iv0e1) continue; |
473 | }//itb(leb) |
474 | } |
475 | if (myed.IsNull()) return Standard_False; |
476 | |
477 | TopExp_Explorer exv(myed, TopAbs_VERTEX); |
478 | for (; exv.More(); exv.Next()){ |
479 | const TopoDS_Shape& vcur = exv.Current(); |
480 | TopOpeBRepTool_connexity& cco = mymapvEds.ChangeFromKey(vcur); |
6e6cd5d9 |
481 | //#ifdef DEB |
482 | // Standard_Boolean ok = |
483 | //#endif |
7fd59977 |
484 | cco.RemoveItem(myed); |
485 | // if (!ok) return Standard_False; see for closing vertices |
486 | } |
487 | |
488 | // myp2d0 : |
489 | TopOpeBRepTool_C2DF c2df;Standard_Boolean bound = myCORRISO.UVRep(myed,c2df); |
490 | if (!bound) return Standard_False; |
491 | Standard_Real f,l,tol; const Handle(Geom2d_Curve)& pc = c2df.PC(f,l,tol); |
492 | Standard_Real par0 = TopOpeBRepTool_TOOL::ParE(iv0e1,myed); |
493 | pc->D0(par0,myp2d0); |
494 | |
495 | // myv, myp2d, mytg2d : |
496 | ::FUN_nextdata(iStep,myed,pc, myv,myp2d,mytg2d); |
497 | |
498 | #ifdef DEB |
499 | if (trc) { |
500 | cout<<endl<<" v0 = v"<<FUN_adds(myv0)<<" p2d0 = ("<<myp2d0.X()<<" "<<myp2d0.Y()<<")"<<endl; |
501 | cout<<" vcur = v"<<FUN_adds(myv)<<" p2d = ("<<myp2d.X()<<" "<<myp2d.Y()<<")"<<endl; |
502 | cout<<" ecur = e"<<FUN_adds(myed)<<endl; |
503 | } |
504 | #endif |
505 | return Standard_True; |
506 | } |
507 | |
508 | //======================================================================= |
509 | //function : NearestE |
510 | //purpose : |
511 | //======================================================================= |
512 | |
513 | Standard_Boolean TopOpeBRepTool_REGUW::NearestE(const TopTools_ListOfShape& loe, TopoDS_Edge& efound) const |
514 | { |
515 | #ifdef DEB |
516 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
517 | #endif |
518 | |
519 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
520 | efound.Nullify(); |
521 | Standard_Real fac = 0.45678; |
522 | Standard_Real tola = Precision::Angular(); |
523 | Standard_Integer iv0e1 = (iStep == 1) ? REVERSED : FORWARD; |
7fd59977 |
524 | |
525 | // initializing |
526 | TopTools_ListIteratorOfListOfShape ite(loe); |
527 | efound = TopoDS::Edge(ite.Value()); |
528 | if (ite.More()) ite.Next(); |
529 | else return Standard_True; |
530 | |
531 | TopOpeBRepTool_C2DF c2defound;Standard_Boolean isbfound = myCORRISO.UVRep(efound,c2defound); |
532 | if (!isbfound) return Standard_False; |
533 | |
534 | gp_Vec2d tg2dfound = TopOpeBRepTool_TOOL::tryTg2dApp(iv0e1,efound,c2defound,fac); |
535 | if (M_REVERSED(efound.Orientation())) tg2dfound.Reverse(); |
536 | Standard_Real angfound = 1.e7; |
537 | if (iStep == 1) angfound = TopOpeBRepTool_TOOL::Matter(mytg2d,tg2dfound); |
c6541a0c |
538 | else angfound = 2.*M_PI - TopOpeBRepTool_TOOL::Matter(tg2dfound,mytg2d); |
7fd59977 |
539 | #ifdef DEB |
540 | if (trc) cout<<"ang(e"<<FUN_adds(myed)<<",e"<<FUN_adds(efound)<<")="<<angfound<<endl; |
541 | #endif |
542 | |
543 | // purpose : finding out <efound> / |
544 | // ecur is given by <tg2d> |
545 | // le = {ei} |
546 | // iStep=1 : matterang2d(efound,ecur) = min(ei,ecur) |
547 | // iStep=2 : oppomatterang2d(efound,ecur) = min(ei,ecur) |
548 | for (; ite.More(); ite.Next()){ |
549 | const TopoDS_Edge& ei = TopoDS::Edge(ite.Value()); |
550 | // for INTERNAL edge eI -> eF+eR |
551 | if (ei.IsSame(myed)) continue; |
552 | |
553 | TopOpeBRepTool_C2DF c2dei;Standard_Boolean isbi = myCORRISO.UVRep(ei,c2dei); |
554 | if (!isbi) return Standard_False; |
555 | gp_Vec2d tg2di = TopOpeBRepTool_TOOL::tryTg2dApp(iv0e1,ei,c2dei,fac); |
556 | if (M_REVERSED(ei.Orientation())) tg2di.Reverse(); |
557 | |
558 | Standard_Real angi = 1.e7; |
559 | if (iStep == 1) angi = TopOpeBRepTool_TOOL::Matter(mytg2d,tg2di); |
c6541a0c |
560 | else angi = 2.*M_PI - TopOpeBRepTool_TOOL::Matter(tg2di,mytg2d); |
7fd59977 |
561 | Standard_Boolean eq = Abs(angi-angfound) < tola; |
562 | #ifdef DEB |
563 | if (trc) cout<<"ang(e"<<FUN_adds(myed)<<",e"<<FUN_adds(ei)<<")="<<angi<<endl; |
564 | #endif |
565 | if (eq) { |
7fd59977 |
566 | FUN_Raise(); |
567 | return Standard_False; |
568 | } |
569 | |
570 | if (angi < angfound) {efound = ei; angfound = angi;} |
571 | } |
572 | return Standard_True; |
573 | } |
574 | |
575 | //======================================================================= |
576 | //function : NextinBlock |
577 | //purpose : |
578 | //======================================================================= |
579 | |
580 | Standard_Boolean TopOpeBRepTool_REGUW::NextinBlock() |
581 | { |
582 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
583 | #ifdef DEB |
584 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
585 | if (trc) cout<<endl<<" vcur = v"<<FUN_adds(myv)<<" p2d = ("<<myp2d.X()<<" "<<myp2d.Y()<<")"<<endl; |
586 | #endif |
587 | |
588 | Standard_Integer iv0e1 = (iStep == 1) ? REVERSED : FORWARD; |
589 | const TopOpeBRepTool_connexity& co = mymapvEds.FindFromKey(myv); |
590 | |
591 | // {e} : e is connexed to <myv> && ori(<myv>,e)=iv0e1 |
592 | TopTools_ListOfShape lea; Standard_Integer nea = co.Item(iv0e1,lea); |
593 | TopTools_ListOfShape leb; Standard_Integer neb = co.Item(CLOSING,leb); |
594 | TopTools_ListOfShape le; le.Append(lea); le.Append(leb); Standard_Integer ne = nea + neb; |
595 | |
596 | TopTools_ListIteratorOfListOfShape ite(le); |
597 | while (ite.More()) { |
598 | const TopoDS_Edge& e = TopoDS::Edge(ite.Value()); |
599 | #ifdef DEB |
600 | if (trc) cout<<" e"<<FUN_adds(e); |
601 | #endif |
602 | |
603 | Standard_Boolean issame = e.IsSame(myed); |
604 | if (issame) {//xpu240299 FRA60275, fsp4 |
605 | #ifdef DEB |
606 | if (trc) cout<<" is same : not valid"<<endl; |
607 | #endif |
608 | le.Remove(ite); continue; |
609 | } |
610 | |
611 | TopOpeBRepTool_C2DF c2df;Standard_Boolean bound = myCORRISO.UVRep(e,c2df); |
612 | if (!bound) {FUN_Raise(); return Standard_False;} |
613 | Standard_Real f,l,tol; const Handle(Geom2d_Curve)& pc = c2df.PC(f,l,tol); |
614 | Standard_Real par = TopOpeBRepTool_TOOL::ParE(iv0e1,e); |
615 | gp_Pnt2d p2de; pc->D0(par,p2de); |
616 | |
617 | // p2d(myv,ed)=p2d(myv,e) |
618 | Standard_Boolean samep2d = p2de.IsEqual(myp2d,mytol2d); |
619 | if (!samep2d) le.Remove(ite); |
620 | else ite.Next(); |
621 | #ifdef DEB |
622 | if (trc) {if (samep2d) cout<<" valid"<<endl; |
623 | else cout<<" not valid"<<endl;} |
624 | #endif |
625 | }//ite(le) |
626 | ne = le.Extent(); |
627 | if (ne == 0) {FUN_Raise(); return Standard_False;} |
628 | |
629 | // myed : |
630 | ne = le.Extent(); |
631 | if (ne == 1) myed = TopoDS::Edge(le.First()); |
632 | else { |
633 | TopoDS_Edge efound; Standard_Boolean found = NearestE(le,efound); |
634 | if (!found) {FUN_Raise(); return Standard_False;} |
635 | myed = efound; |
636 | } |
637 | |
7fd59977 |
638 | TopExp_Explorer exv(myed, TopAbs_VERTEX); |
639 | for (; exv.More(); exv.Next()){ |
640 | TopOpeBRepTool_connexity& cco = mymapvEds.ChangeFromKey(exv.Current()); |
6e6cd5d9 |
641 | //#ifdef DEB |
642 | // Standard_Boolean ok = |
643 | //#endif |
7fd59977 |
644 | cco.RemoveItem(myed); |
645 | // if (!ok) {FUN_Raise(); return Standard_False;} closed edges |
646 | } |
647 | |
648 | TopOpeBRepTool_C2DF c2df; myCORRISO.UVRep(myed,c2df); |
649 | Standard_Real f,l,tol; const Handle(Geom2d_Curve)& pc = c2df.PC(f,l,tol); |
650 | ::FUN_nextdata(iStep,myed,pc, myv,myp2d,mytg2d); |
651 | |
652 | #ifdef DEB |
653 | if (trc) { |
654 | cout<<" vcur = v"<<FUN_adds(myv)<<" p2d = ("<<myp2d.X()<<" "<<myp2d.Y()<<")"<<endl; |
655 | cout<<" ecur = e"<<FUN_adds(myed)<<endl; |
656 | } |
657 | #endif |
658 | return Standard_True; |
659 | }//NextinBlock |
660 | |
661 | //======================================================================= |
662 | //function : REGU |
663 | //purpose : step <iStep> for regularization |
664 | //======================================================================= |
665 | |
666 | Standard_Boolean TopOpeBRepTool_REGUW::REGU(const Standard_Integer istep, |
667 | #ifdef DEB |
668 | const TopoDS_Shape& Scur, |
669 | #else |
670 | const TopoDS_Shape& , |
671 | #endif |
672 | TopTools_ListOfShape& Splits) |
673 | { |
674 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
675 | iStep = istep; |
676 | #ifdef DEB |
677 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
678 | if (trc) cout<<endl<<"** REGU istep=**"<<iStep<<endl; |
679 | #endif |
680 | |
681 | Splits.Clear(); |
682 | // A valid face is built on "valid" wires. |
683 | // A valid wire has for UV representation a set of 2d edges of connexity = 2. |
684 | |
685 | // Starting element is a vertex of single UV representation with connexity greater |
686 | // than 2. |
687 | // Given <v0m>, we get : |
688 | // - <e1> an edge where <v0m> is oriented REVERSED(step1)/FORWARD(step2) |
689 | // - <v1> the other vertex of <e1> oriented FORWARD(step1)/REVERSED(step2) |
690 | // - <p2d1> is <v1>'s UV representation attached to <e1>, |
691 | // - tg2d<e1> = Tgt(p2d1,e1) if <e1> FORWARD(step1) |
692 | // = -Tgt(p2d1,e1) if <e1> is REVERSED(step1) in the face with |
693 | // Tgt(p2d1,e1) = tangent to <e1>'s pcurve at point <p2d1> |
694 | |
695 | // step1 : |
696 | // ------- |
697 | // Given a starting couple (<vi>, <p2di>, tg2d<e1>, <ei>) with : |
698 | // - <vi> oriented FORWARD in <ei>, |
699 | // - <vi>'s 2d representation falling on an UV bound of <ei>'s pcurve (if <vi> is |
700 | // on a closing edge), |
701 | // We get the edge <ei+1> such that : |
702 | // - <ei+1> is not already touched, |
703 | // - <vi> is oriented REVERSED(step1) in <ei+1>, |
704 | // - <ei+1> has an UV bound falling into geometry <p2di>. |
705 | // - The oriented angle (-tg2d<ei>, tg2d<ei+1>) is the lowest, |
706 | // ( The angle is computed in the anti-trigonometric sense; |
707 | // the tangents's orientation are reversed if the edge is oriented REVERSED in the face ) |
708 | // = Smaller oriented (following trigonometric sense) angle (tg2d<ei+1>, -tg2d<ei>) |
709 | // |
710 | // step2 : reverse the orientations and the angle describes non-matter. |
711 | // ------- |
712 | |
713 | // tol2d = 1.e-2*(lowest distance (p2df,p2dl) between all non-closed |
714 | // and non-degenerated pcurves seen during the regularization). |
715 | // This value is updated in method chkp2dFORinE. |
716 | // The comparision of p2d points is coupled with comparision of vertices |
717 | // We should in fact use bounding boxes on pcurves but this is too expensive!!! |
718 | mytol2d = 1.e-5; |
719 | isinit0 = Standard_True; |
720 | TopTools_ListOfShape loEcur, loW; |
721 | |
722 | Standard_Integer nite = 0; |
723 | Standard_Integer nE = myCORRISO.Eds().Extent();// recall myCORRISO.Init(myS); |
724 | TopTools_ListIteratorOfListOfShape ite(myCORRISO.Eds()); |
725 | for (; ite.More(); ite.Next()) { |
726 | TopAbs_Orientation oe = ite.Value().Orientation(); |
727 | if (M_INTERNAL(oe) || M_EXTERNAL(oe)) nE--; |
728 | } |
729 | |
730 | while (nite <= nE) { |
731 | Standard_Boolean FINI = (nite == nE); |
732 | |
733 | //*** Getting starts elements if not defined |
734 | // ----------------------------------------- |
735 | if (isinit0 && !FINI) { |
736 | Standard_Boolean ok = InitBlock(); |
737 | if (!ok) { |
738 | #ifdef DEB |
739 | if (trc) cout<<"** InitBlock fails"<<endl; |
740 | #endif |
741 | {FUN_Raise(); return Standard_False;} |
742 | } |
743 | loEcur.Append(myed);// add it to the current wire |
744 | nite++; // increment nite |
745 | isinit0 = Standard_False; |
746 | continue; |
747 | } |
748 | |
749 | //*** Checking the wire is not already closed |
750 | // ------------------------------------------ |
751 | // If last vertex <v> is the first one <v0> and <p2d> == <p2d0>, the wire is closed |
752 | Standard_Boolean wireisclosed = myp2d.IsEqual(myp2d0,mytol2d); |
753 | if (wireisclosed) { |
754 | |
755 | //* Adding INTERNAL/EXTERNAL edges to wires |
756 | // ---------------------------------------- |
757 | TopTools_ListIteratorOfListOfShape ite1(loEcur); |
758 | for (; ite1.More(); ite1.Next()){ |
759 | const TopoDS_Shape& e = ite1.Value(); |
760 | TopExp_Explorer exv(e, TopAbs_VERTEX); |
761 | for (; exv.More(); exv.Next()){ |
762 | const TopoDS_Shape& v = exv.Current(); |
763 | TopOpeBRepTool_connexity& co = mymapvEds.ChangeFromKey(v); |
764 | TopTools_ListOfShape& le = co.ChangeItem(INTERNAL); |
765 | TopTools_ListIteratorOfListOfShape itte(le); |
766 | while (itte.More()) { |
767 | const TopoDS_Shape& ee = itte.Value(); |
768 | TopAbs_Orientation oe = ee.Orientation(); |
769 | if (M_INTERNAL(oe) || M_EXTERNAL(oe)) {loEcur.Append(ee);le.Remove(itte);} |
770 | else itte.Next(); |
771 | }//itte(le) |
772 | }//exv(e) |
773 | }//ite(loEcur) |
774 | FINI = (nite == nE); |
775 | |
776 | // if Scur = <currentW> gives only one new wire, and has no new splitted edges, <currentW> |
777 | // is valid and unchanged. |
778 | Standard_Boolean onewok = FINI && loW.IsEmpty() && !hasnewsplits; |
779 | if (onewok){ |
780 | #ifdef DEB |
781 | if (trc) cout<<"wire "<<FUN_adds(Scur)<<" is found valid\n"; |
782 | #endif |
783 | return Standard_True; |
784 | }//onewok |
785 | |
786 | TopoDS_Wire newW; Standard_Boolean wiok = FUN_tool_MakeWire(loEcur, newW); |
787 | if (wiok) loW.Append(newW); |
788 | else { |
789 | #ifdef DEB |
790 | if (trc) cout<<"** FUN_tool_MakeWire fails"<<endl; |
791 | #endif |
792 | {FUN_Raise(); return Standard_False;} |
793 | } |
794 | #ifdef DEB |
795 | if (trc) {cout<<"#->new wire = wi"<<FUN_adds(newW)<<" = "; |
796 | for (TopTools_ListIteratorOfListOfShape it(loEcur); it.More(); it.Next()) |
797 | cout<<" e"<<FUN_adds(it.Value()); |
798 | cout<<"\n\n";} |
799 | #endif |
800 | isinit0 = Standard_True; |
801 | loEcur.Clear(); |
802 | |
803 | if (FINI) { |
804 | Splits.Append(loW); |
805 | return Standard_True; |
806 | } |
807 | continue; |
808 | } // wireisclosed |
809 | |
810 | //*** Iteration on UV connexed edges |
811 | // --------------------------------- |
812 | // <v> is in <ed>, <p2d> = <v> current UV representation |
813 | Standard_Boolean gotonext = NextinBlock(); |
814 | if (!gotonext) { |
815 | #ifdef DEB |
816 | if (trc) cout<<"** NextinBlock fails"<<endl; |
817 | #endif |
818 | {FUN_Raise(); return Standard_False;} |
819 | } |
820 | loEcur.Append(myed); |
821 | nite++; |
822 | } // nite |
823 | |
824 | return Standard_True; |
825 | } |
826 | |
827 | //======================================================================= |
828 | //function : REGU |
829 | //purpose : complete regularization |
830 | //======================================================================= |
831 | |
832 | Standard_Boolean TopOpeBRepTool_REGUW::REGU() |
833 | { |
834 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
835 | TopTools_ListOfShape null; |
836 | |
837 | Standard_Boolean toregu = !myListVmultiple.IsEmpty(); |
838 | toregu = toregu || hasnewsplits; |
839 | TopTools_ListOfShape Splits; |
840 | if (!toregu) { |
841 | myOwNw.Bind(S(),Splits); |
842 | return Standard_True; |
843 | } |
844 | |
845 | // iStep = 1; |
846 | TopTools_ListOfShape loS; Standard_Boolean ok = REGU(1,S(),loS); |
847 | if (!ok) {FUN_Raise(); return Standard_False;} |
848 | |
849 | // iStep = 2; |
850 | if (loS.IsEmpty()) loS.Append(S());// no new shape |
851 | |
852 | TopTools_ListIteratorOfListOfShape it(loS); |
853 | for (; it.More(); it.Next()){ |
854 | const TopoDS_Shape& Scur = it.Value(); |
855 | InitStep(Scur); |
856 | MapS(); |
857 | Standard_Boolean toregu1 = !myListVmultiple.IsEmpty(); |
858 | if (!toregu1) {Splits.Append(Scur); continue;} |
859 | |
860 | TopTools_ListOfShape sp; ok = REGU(2,Scur,sp); |
861 | if (!ok) {FUN_Raise(); return Standard_False;} |
862 | if (sp.IsEmpty()) sp.Append(Scur);// no new shape |
863 | Splits.Append(sp); |
864 | } |
865 | myOwNw.Bind(S(),Splits); |
866 | return Standard_True; |
867 | } |
868 | |
869 | //======================================================================= |
870 | //function : GetSplits |
871 | //purpose : |
872 | //======================================================================= |
873 | |
874 | Standard_Boolean TopOpeBRepTool_REGUW::GetSplits(TopTools_ListOfShape& Splits) const |
875 | { |
876 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
877 | Standard_Boolean isb = myOwNw.IsBound(S()); |
878 | if (!isb) return Standard_False; |
879 | Splits = myOwNw.Find(S()); |
880 | return Standard_True; |
881 | } |
882 | |
883 | //======================================================================= |
884 | //function : Connexity |
885 | //purpose : |
886 | //======================================================================= |
887 | |
888 | Standard_Boolean TopOpeBRepTool_REGUW::Connexity(const TopoDS_Vertex& v, TopOpeBRepTool_connexity& co) const |
889 | { |
890 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
891 | Standard_Boolean isb = mymapvEds.Contains(v); |
892 | if (!isb) return Standard_False; |
893 | co = mymapvEds.FindFromKey(v); |
894 | return Standard_True; |
895 | } |
896 | |
897 | //======================================================================= |
898 | //function : AddNewConnexity |
899 | //purpose : |
900 | //======================================================================= |
901 | |
902 | Standard_Boolean TopOpeBRepTool_REGUW::AddNewConnexity(const TopoDS_Vertex& v, const Standard_Integer OriKey,const TopoDS_Edge& e) |
903 | { |
904 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
905 | Standard_Boolean isb = mymapvEds.Contains(v); |
906 | if (!isb) return Standard_False; |
907 | |
908 | Standard_Boolean ok = myCORRISO.AddNewConnexity(v,e); |
909 | if (!ok) return Standard_False; |
910 | |
911 | TopOpeBRepTool_connexity& co = mymapvEds.ChangeFromKey(v); |
912 | co.AddItem(OriKey,e); |
913 | |
914 | #ifdef DEB |
915 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
916 | if (trc) |
917 | {cout<<"** setting new connexity : v"<<FUN_adds(v)<<" is ";FUN_tro(OriKey); |
918 | cout<<" in "<<" e"<<FUN_adds(e);FUN_tool_tori(e.Orientation()); |
919 | TopoDS_Vertex vclo; Standard_Boolean cloE = TopOpeBRepTool_TOOL::ClosedE(e,vclo); if (cloE) cout<<" closed"; |
920 | Standard_Boolean dgE = BRep_Tool::Degenerated(e); if (dgE) cout<<" degenerated";cout<<endl;} |
921 | #endif |
922 | return Standard_True; |
923 | } |
924 | |
925 | //======================================================================= |
926 | //function : RemoveOldConnexity |
927 | //purpose : |
928 | //======================================================================= |
929 | |
930 | Standard_Boolean TopOpeBRepTool_REGUW::RemoveOldConnexity(const TopoDS_Vertex& v, const Standard_Integer OriKey,const TopoDS_Edge& e) |
931 | { |
932 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
933 | Standard_Boolean isb = mymapvEds.Contains(v); |
934 | if (!isb) return Standard_False; |
935 | |
936 | Standard_Boolean ok = myCORRISO.RemoveOldConnexity(v,e); |
937 | // if (!ok) return Standard_False; |
938 | |
939 | TopOpeBRepTool_connexity& co = mymapvEds.ChangeFromKey(v); |
940 | ok = co.RemoveItem(OriKey,e); |
941 | if (!ok) return Standard_False; |
942 | |
943 | #ifdef DEB |
944 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); |
945 | if (trc) |
946 | {cout<<"** removing old connexity : v"<<FUN_adds(v)<<" for e"<<FUN_adds(e);FUN_tool_tori(e.Orientation()); |
947 | TopoDS_Vertex vclo; Standard_Boolean cloE = TopOpeBRepTool_TOOL::ClosedE(e,vclo); if (cloE) cout<<" closed"; |
948 | Standard_Boolean dgE = BRep_Tool::Degenerated(e); if (dgE) cout<<" degenerated";cout<<endl;} |
949 | #endif |
950 | return Standard_True; |
951 | } |
952 | |
953 | //======================================================================= |
954 | //function : UpdateMultiple |
955 | //purpose : |
956 | //======================================================================= |
957 | |
958 | Standard_Boolean TopOpeBRepTool_REGUW::UpdateMultiple(const TopoDS_Vertex& v) |
959 | { |
960 | if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); |
961 | Standard_Boolean isb = mymapvEds.Contains(v); |
962 | if (!isb) return Standard_False; |
963 | const TopOpeBRepTool_connexity& co = mymapvEds.FindFromKey(v); |
964 | Standard_Boolean ismult = co.IsMultiple(); |
965 | if (ismult) |
966 | if (mymapvmultiple.Add(v)) |
967 | myListVmultiple.Append(v); |
968 | return Standard_True; |
969 | |
970 | } |