0026937: Eliminate NO_CXX_EXCEPTION macro support
[occt.git] / src / TopOpeBRepTool / TopOpeBRepTool_REGUS.cxx
1 // Created on: 1999-01-04
2 // Created by: Xuan PHAM PHU
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Tool.hxx>
19 #include <Precision.hxx>
20 #include <TopExp.hxx>
21 #include <TopExp_Explorer.hxx>
22 #include <TopoDS.hxx>
23 #include <TopoDS_Edge.hxx>
24 #include <TopoDS_Face.hxx>
25 #include <TopoDS_Shape.hxx>
26 #include <TopoDS_Shell.hxx>
27 #include <TopOpeBRepTool_CLASSI.hxx>
28 #include <TopOpeBRepTool_connexity.hxx>
29 #include <TopOpeBRepTool_define.hxx>
30 #include <TopOpeBRepTool_EXPORT.hxx>
31 #include <TopOpeBRepTool_REGUS.hxx>
32 #include <TopOpeBRepTool_REGUW.hxx>
33 #include <TopOpeBRepTool_TOOL.hxx>
34
35 #ifdef DRAW
36 #include <TopOpeBRepTool_DRAW.hxx>
37 #endif
38
39 #define M_FORWARD(ori)  (ori == TopAbs_FORWARD) 
40 #define M_REVERSED(ori) (ori == TopAbs_REVERSED) 
41 #define M_INTERNAL(ori) (ori == TopAbs_INTERNAL) 
42 #define M_EXTERNAL(ori) (ori == TopAbs_EXTERNAL) 
43
44 #define FORWARD  (1)
45 #define REVERSED (2)
46 #define INTERNAL (3)
47 #define EXTERNAL (4)
48 #define CLOSING  (5)
49
50 #ifdef OCCT_DEBUG
51 extern Standard_Boolean TopOpeBRepTool_GettraceREGUSO(); 
52 static TopTools_IndexedMapOfShape STATIC_mape, STATIC_mapf, STATIC_mapw, STATIC_mapsh;
53 static Standard_Integer FUN_adds(const TopoDS_Shape& s) {
54   TopAbs_ShapeEnum typ = s.ShapeType();
55   TCollection_AsciiString aa; Standard_Integer is = 0;
56   if (typ == TopAbs_SHELL)  {aa = TCollection_AsciiString("s"); is = STATIC_mapsh.Add(s);}
57   if (typ == TopAbs_WIRE)   {aa = TCollection_AsciiString("w"); is = STATIC_mapw.Add(s); }
58   if (typ == TopAbs_FACE)   {aa = TCollection_AsciiString("f"); is = STATIC_mapf.Add(s); }
59   if (typ == TopAbs_EDGE)   {aa = TCollection_AsciiString("e"); is = STATIC_mape.Add(s); }
60 #ifdef DRAW
61   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); 
62   if (trc) FUN_tool_draw(aa,s,is);  
63 #endif
64   return is;
65 }
66 #endif
67
68 static void FUN_Raise()
69 {
70 #ifdef OCCT_DEBUG
71   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); 
72   if (trc) cout<<"***** Failure in REGUS **********"<<endl;
73 //  throw Standard_Failure("REGUS");
74 #endif
75 }
76
77 //=======================================================================
78 //function : Create
79 //purpose  : 
80 //=======================================================================
81
82 TopOpeBRepTool_REGUS::TopOpeBRepTool_REGUS()
83 {
84   hasnewsplits = Standard_False;
85   mynF = myoldnF = 0;
86
87   myFsplits.Clear(); 
88   myOshNsh.Clear(); 
89
90   myS.Nullify(); 
91   mymapeFs.Clear(); 
92   mymapeFsstatic.Clear();
93   mymapemult.Clear();
94
95   myedstoconnect.Clear();
96 }
97
98 //=======================================================================
99 //function : Init
100 //purpose  : 
101 //=======================================================================
102
103 void TopOpeBRepTool_REGUS::Init(const TopoDS_Shape& S)
104 {
105   hasnewsplits = Standard_False;
106
107   mynF = myoldnF = 0;
108   myS = S;
109
110   mymapeFs.Clear();
111   mymapeFsstatic.Clear();
112   mymapemult.Clear();
113   myedstoconnect.Clear();
114 }
115
116 //=======================================================================
117 //function : S
118 //purpose  : 
119 //=======================================================================
120
121 const TopoDS_Shape& TopOpeBRepTool_REGUS::S() const 
122 {
123   return myS;
124 }
125
126
127 //=======================================================================
128 //function : SetFsplits
129 //purpose  : 
130 //=======================================================================
131
132 void TopOpeBRepTool_REGUS::SetFsplits(TopTools_DataMapOfShapeListOfShape& Fsplits)
133 {
134   myFsplits = Fsplits;
135 }
136 //=======================================================================
137 //function : GetFsplits
138 //purpose  : 
139 //=======================================================================
140
141 void TopOpeBRepTool_REGUS::GetFsplits(TopTools_DataMapOfShapeListOfShape& Fsplits) const 
142 {
143   Fsplits = myFsplits;
144 }
145
146 //=======================================================================
147 //function : SetOshNsh
148 //purpose  : 
149 //=======================================================================
150
151 void TopOpeBRepTool_REGUS::SetOshNsh(TopTools_DataMapOfShapeListOfShape& OshNsh)
152 {
153   myOshNsh = OshNsh;
154 }
155 //=======================================================================
156 //function : GetOshNsh
157 //purpose  : 
158 //=======================================================================
159
160 void TopOpeBRepTool_REGUS::GetOshNsh(TopTools_DataMapOfShapeListOfShape& OshNsh) const
161 {
162   OshNsh = myOshNsh;
163 }
164
165 //=======================================================================
166 //function : MapS
167 //purpose  : 
168 //=======================================================================
169
170 Standard_Boolean TopOpeBRepTool_REGUS::MapS()
171 {
172 #ifdef OCCT_DEBUG
173   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO();
174   Standard_Integer ish = FUN_adds(S());
175   if (trc) cout<<"**    MAPPING    ** shape"<<ish<<endl;
176 #endif
177
178   // mymapeFs, myoldnF : 
179   myoldnF = 0;
180   TopExp_Explorer exf(myS, TopAbs_FACE);
181   for (; exf.More(); exf.Next()){
182     const TopoDS_Shape& f = exf.Current(); myoldnF++;
183
184     TopExp_Explorer exe(f, TopAbs_EDGE);
185     for (; exe.More(); exe.Next()){
186       const TopoDS_Shape& e = exe.Current();
187       Standard_Boolean isb = mymapeFs.IsBound(e);
188       if (isb) {mymapeFs.ChangeFind(e).Append(f); mymapeFsstatic.ChangeFind(e).Append(f);}
189       else     {TopTools_ListOfShape lof; lof.Append(f); mymapeFs.Bind(e,lof); mymapeFsstatic.Bind(e,lof);}      
190     }//exe
191   }//exf
192   mynF = myoldnF;
193
194   // mymapemult : 
195   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(mymapeFs);
196   for (; itm.More(); itm.Next()){
197     const TopoDS_Shape& e = itm.Key();
198     const TopTools_ListOfShape& lof  = itm.Value();
199     Standard_Integer nf = lof.Extent();
200     if (nf > 2) mymapemult.Add(e);
201 #ifdef OCCT_DEBUG
202     if (trc) {
203       cout <<"co(e"<<FUN_adds(e)<<")= ";
204       TopTools_ListIteratorOfListOfShape it(lof);
205       for (; it.More(); it.Next())cout<<" f"<<FUN_adds(it.Value());
206       cout<<endl;}
207 #endif
208   }//itm(mymapeFs)
209   return Standard_True;
210 }
211
212 //=======================================================================
213 //function : WireToFace
214 //purpose  : 
215 //=======================================================================
216
217 Standard_Boolean TopOpeBRepTool_REGUS::WireToFace(const TopoDS_Face& Fanc, const TopTools_ListOfShape& nWs, TopTools_ListOfShape& nFs)
218 {
219 #ifdef OCCT_DEBUG
220   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO();
221 #endif
222   nFs.Clear();
223   TopTools_DataMapOfShapeListOfShape mapWlow;
224   TopoDS_Shape aLocalShape = Fanc.Oriented(TopAbs_FORWARD);
225   TopoDS_Face aFace = TopoDS::Face(aLocalShape);
226 //  TopoDS_Face aFace = TopoDS::Face(Fanc.Oriented(TopAbs_FORWARD));
227   TopOpeBRepTool_CLASSI classi; classi.Init2d(aFace);
228
229   Standard_Boolean classifok = classi.Classilist(nWs,mapWlow);
230   if (!classifok) {
231 #ifdef OCCT_DEBUG
232     if (trc) cout<<"** classif fails"<<endl;
233 #endif
234     return Standard_False;
235   }
236     
237   Standard_Boolean facesbuilt = TopOpeBRepTool_TOOL::WireToFace(Fanc, mapWlow, nFs); 
238   if (!facesbuilt) {
239 #ifdef OCCT_DEBUG
240     if (trc) cout<<"** facesbuilt fails"<<endl;
241 #endif
242     return Standard_False; 
243   }
244   return Standard_True;
245 }
246
247
248 //=======================================================================
249 //function : SplitF
250 //purpose  : 
251 //=======================================================================
252
253 Standard_Boolean TopOpeBRepTool_REGUS::SplitF(const TopoDS_Face& Fanc, TopTools_ListOfShape& FSplits) 
254 {
255   // prequesitory : All edges have already been splitted, there is no 
256   //                internal vertex on edge, except for internal edge.
257   TopAbs_Orientation oAnc = Fanc.Orientation();
258   TopoDS_Shape aLocalShapeFromFace = Fanc.Oriented(TopAbs_FORWARD);
259   TopoDS_Face aFace = TopoDS::Face(aLocalShapeFromFace);
260 //  TopoDS_Face aFace = TopoDS::Face(Fanc.Oriented(TopAbs_FORWARD));
261   
262   FSplits.Clear();
263
264   TopOpeBRepTool_REGUW REGUW(aFace);
265   
266   TopTools_ListOfShape nWs; Standard_Boolean hassp = Standard_False; 
267   TopExp_Explorer exw(aFace, TopAbs_WIRE);
268   for (; exw.More(); exw.Next()) {
269     const TopoDS_Shape& w = exw.Current();
270     REGUW.Init(w);
271     REGUW.MapS();
272
273     TopTools_ListOfShape eIs;
274     // --------
275     TopExp_Explorer exe(w, TopAbs_EDGE);
276     for (; exe.More(); exe.Next()){
277       const TopoDS_Shape& e = exe.Current();
278       if (M_INTERNAL(e.Orientation())) eIs.Append(e);
279     }//exe
280
281     TopTools_ListIteratorOfListOfShape ite(eIs);
282 //    if (!ite.More()) {nWs.Append(w); continue;}
283
284     while (ite.More()) {
285       const TopoDS_Edge& eI = TopoDS::Edge(ite.Value());
286       TopoDS_Vertex vf,vl; 
287       TopoDS_Shape aLocalShape = eI.Oriented(TopAbs_FORWARD);      
288       TopExp::Vertices(TopoDS::Edge(aLocalShape),vf,vl);
289 //      TopExp::Vertices(TopoDS::Edge(eI.Oriented(TopAbs_FORWARD)),vf,vl);
290       TopOpeBRepTool_connexity cof; REGUW.Connexity(vf,cof); TopTools_ListOfShape lef; Standard_Integer nef = cof.AllItems(lef);
291       TopOpeBRepTool_connexity col; REGUW.Connexity(vl,col); TopTools_ListOfShape lel; Standard_Integer nel = col.AllItems(lel);      
292       if ((nef <= 1)||(nel <= 1)) {eIs.Remove(ite);continue;}
293
294       // prequesitory : we do not have internal vertices in edges oriented FOR     
295       aLocalShape = eI.Oriented(TopAbs_REVERSED);
296       TopoDS_Edge eR = TopoDS::Edge(aLocalShape);
297       aLocalShape = eI.Oriented(TopAbs_FORWARD);
298       TopoDS_Edge eF = TopoDS::Edge(aLocalShape);
299 //      TopoDS_Edge eR = TopoDS::Edge(eI.Oriented(TopAbs_REVERSED));
300 //      TopoDS_Edge eF = TopoDS::Edge(eI.Oriented(TopAbs_FORWARD));
301
302       TopExp_Explorer exv(eI, TopAbs_VERTEX);
303       for (; exv.More(); exv.Next()){
304         const TopoDS_Vertex& v = TopoDS::Vertex(exv.Current());
305         Standard_Boolean ok = REGUW.RemoveOldConnexity(v,INTERNAL,eI);
306         if (!ok) return Standard_False;
307         Standard_Integer ivF = TopOpeBRepTool_TOOL::OriinSor(v,eF);
308         ok = REGUW.AddNewConnexity(v,ivF,eF);
309         if (!ok) return Standard_False;
310         Standard_Integer ivR = TopOpeBRepTool_TOOL::OriinSor(v,eR);
311         ok = REGUW.AddNewConnexity(v,ivR,eR);
312         if (!ok) return Standard_False;
313         ok = REGUW.UpdateMultiple(v);
314         if (!ok) return Standard_False;
315       }//exv
316       ite.Next();
317     }//ite(eIs)
318
319     // now all edges of <eIs> are INTERNAL edges of <w>
320     // their 2 bounds are of connexity > 1.
321 //    if (eIs.IsEmpty()) {nWs.Append(w); continue;}
322
323     TopTools_ListOfShape spW; 
324     // --------
325     Standard_Boolean spok = REGUW.REGU(); // only first step 
326     if (!spok) {FUN_Raise(); return Standard_False;}
327     REGUW.GetSplits(spW);
328     if (!spW.IsEmpty()) {nWs.Append(spW); hassp = Standard_True;}
329   }//exw 
330
331   if (!hassp) return Standard_False;
332   TopTools_ListOfShape nFs; Standard_Boolean ok = TopOpeBRepTool_REGUS::WireToFace(aFace, nWs,nFs);
333   if (!ok) {FUN_Raise(); return Standard_False;}
334   
335   TopTools_ListIteratorOfListOfShape itf(nFs);
336   for (; itf.More(); itf.Next()) FSplits.Append(itf.Value().Oriented(oAnc));  
337   return Standard_True;
338 }
339
340 //=======================================================================
341 //function : SplitFaces
342 //purpose  : 
343 //=======================================================================
344
345 Standard_Boolean TopOpeBRepTool_REGUS::SplitFaces()
346 {
347 #ifdef OCCT_DEBUG
348   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO();
349   Standard_Integer ish = FUN_adds(S());
350   if (trc) cout<<"**    SPLITTING FACES    ** shape"<<ish<<endl;
351 #endif
352   TopExp_Explorer exf(myS, TopAbs_FACE);
353   for (; exf.More(); exf.Next()){
354
355     // splitting face :
356     const TopoDS_Face& f = TopoDS::Face(exf.Current()); 
357     TopTools_ListOfShape lfsp; Standard_Boolean issp = TopOpeBRepTool_REGUS::SplitF(f,lfsp);
358
359     if (!issp) continue;
360
361     myFsplits.Bind(f,lfsp);
362     
363     // updating the map of connexity : 
364     // f -> lfsp = {fsp}
365     mynF--;
366     TopTools_ListIteratorOfListOfShape itf(lfsp);
367     for (; itf.More(); itf.Next()){
368       const TopoDS_Shape& fsp = itf.Value(); mynF++;
369
370       TopExp_Explorer exe(fsp, TopAbs_EDGE);
371       for (; exe.More(); exe.Next()) {
372         // fsp -> {e}
373         const TopoDS_Shape& e = exe.Current();
374         Standard_Boolean isb = mymapeFs.IsBound(e);
375         if (!isb) {FUN_Raise(); return Standard_False;}
376         
377         // <mymapeFs>
378         TopTools_ListOfShape& lof = mymapeFs.ChangeFind(e);
379         TopOpeBRepTool_TOOL::Remove(lof,f);
380         lof.Append(fsp);
381
382         // <mymapemult>
383         Standard_Integer nf = lof.Extent();
384         if (nf > 2) mymapemult.Add(e);
385       }//exe(fsp)
386     }//itf(lfsp)
387
388 #ifdef OCCT_DEBUG
389     if (trc)  {
390       cout <<"split(f"<<FUN_adds(f)<<")= ";
391       TopTools_ListIteratorOfListOfShape it(lfsp);
392       for (; it.More(); it.Next()) cout<<" f"<<FUN_adds(it.Value());
393       cout<<endl;}
394 #endif
395   }//exf(myS)
396   return Standard_True;  
397 }
398
399 static void FUN_update(const TopoDS_Shape& fcur, TopTools_MapOfShape& edstoconnect)
400 // purpose : <e> edge of <fcur>
401 //  1. <e> is INTERNAL or EXTERNAL   -> nothing is done
402 //  2. <e> is closing edge of <fcur> -> nothing is done
403 //  3. <e> is already bound in <edstoconnect> -> remove it from the map
404 //     (then has 2 ancestor faces stored in the current Block)
405 //  4. elsewhere, add it in the map.
406 //
407 // !! if <fcur> is INTERNAL/EXTERNAL -> nothing is done
408 {
409   TopAbs_Orientation ofcur = fcur.Orientation();
410   if (M_INTERNAL(ofcur) || M_EXTERNAL(ofcur)) return;
411
412   TopExp_Explorer exe(fcur, TopAbs_EDGE);
413   for (; exe.More(); exe.Next()){
414     const TopoDS_Shape& e = exe.Current();
415     TopAbs_Orientation oe = e.Orientation();
416     if (M_INTERNAL(oe) || M_EXTERNAL(oe)) continue;
417
418     Standard_Boolean isclo = TopOpeBRepTool_TOOL::IsClosingE(TopoDS::Edge(e),TopoDS::Face(fcur));
419     if (isclo) continue;
420
421     Standard_Boolean isb = edstoconnect.Contains(e);
422     if (isb) edstoconnect.Remove(e);
423     else     edstoconnect.Add(e);
424   }//exe
425 }
426
427 //=======================================================================
428 //function : REGU
429 //purpose  : 
430 //=======================================================================
431
432 Standard_Boolean TopOpeBRepTool_REGUS::REGU()
433 {
434 #ifdef OCCT_DEBUG
435   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO();
436   Standard_Integer ishe = FUN_adds(myS);
437   if (trc) cout<<"**    REGU    **"<<ishe<<endl;
438 #endif
439   TopTools_ListOfShape Splits;
440   Standard_Boolean toregu = !mymapemult.IsEmpty() || (mynF != myoldnF);
441   if (!toregu) return Standard_False;
442
443   // purpose : myS -> {Blocks}, 
444   //           a Block is a closed shell with "valid" edges.
445   //           - a valid edge in a Block has at most two ancestor faces -
446   //
447   // Give us the starting couple (<ei>, <fi>) :
448   // * If <ei> has only one untouched ancestor face <fj> left, fj+1 <- fj
449   //   Else among the untouched ancestors faces, we choose the one for which
450   //   angle (<veci>, <vecj>) is the smallest; providing face <fj> reduces
451   //   the matter described by <fi>.
452   // * update <mymapeFs> for <ei> (<fj> as touched).
453   // * Update <mymapemult> for <fi>'s bound edges :
454   //   - if bound edge is not in the map, add it.
455   //   - else if bound edge has two ancestor faces in current list <mylFinBlock>,
456   //     delete it form the map.
457   //
458 //  TopTools_ListOfShape lFinBlock; // <lFinBlock> describes a valid closed shell when <myedstoconnect> is emptied.   
459   mylFinBlock.Clear();
460   Standard_Integer nite = 0;
461   while (nite <= mynF) {
462     Standard_Boolean startBlock = mylFinBlock.IsEmpty();
463     Standard_Boolean endBlock = myedstoconnect.IsEmpty() && (!startBlock);
464
465 #ifdef OCCT_DEBUG
466     Standard_Boolean tr=Standard_False;
467     if (tr) {
468       TopTools_MapIteratorOfMapOfShape it(myedstoconnect);
469       cout<<"still to connect : ";
470       for (; it.More(); it.Next()) cout<<" e"<<FUN_adds(it.Key());
471       cout<<endl;
472     }
473 #endif
474
475     //* endBlock
476     // ---------
477     if (endBlock) {
478       // building up shell on <mylFinBlock>
479       Standard_Integer nFcur = mylFinBlock.Extent();
480       Standard_Boolean unchanged = (nFcur==myoldnF) && (mynF==myoldnF);
481       if (unchanged) {
482 #ifdef OCCT_DEBUG
483         if (trc) cout<<"#** shell"<<ishe<<" valid\n";
484 #endif
485         return Standard_False; // nyi analysis if we should raise or not  
486       }
487       else {
488         TopoDS_Shell newShe; TopOpeBRepTool_TOOL::MkShell(mylFinBlock,newShe);
489         Splits.Append(newShe);
490 #ifdef OCCT_DEBUG
491         if (trc) {cout<<"#** shell "<<ishe<<" gives new shell "<<FUN_adds(newShe)<<endl;
492                   for (TopTools_ListIteratorOfListOfShape it(mylFinBlock); it.More(); it.Next()) cout <<";dins f"<<FUN_adds(it.Value());
493                   cout<<endl<<endl;}
494 #endif
495         mylFinBlock.Clear(); 
496         startBlock = Standard_True;
497       }
498     }//endBlock
499
500     //* all faces touched
501     // ------------------
502     Standard_Boolean FINI = (nite == mynF);
503     if (FINI) break;
504
505     Standard_Integer advance=Standard_False;
506     //* initializing a new Block
507     // -------------------------
508     if (startBlock || endBlock) {
509       advance = InitBlock();
510       if (!advance) return Standard_False;
511     }//startBlock||endBlock
512
513     //* choosing next face
514     // -------------------
515     else {
516      advance  = NextinBlock();      
517     }
518
519     // ** updating connexity     
520     ::FUN_update(myf,myedstoconnect);
521
522     if (!advance) {
523       endBlock = myedstoconnect.IsEmpty() && (!startBlock);
524       if (!endBlock) return Standard_False;
525       else           continue;
526     }
527     
528     TopExp_Explorer exe(myf, TopAbs_EDGE);
529     for (; exe.More(); exe.Next()){
530       const TopoDS_Shape& e = exe.Current();
531       Standard_Boolean isb = mymapeFs.IsBound(e);
532       if (!isb) continue; // ancestors faces of <e> are stored in Blocks        
533       TopOpeBRepTool_TOOL::Remove(mymapeFs.ChangeFind(e),myf);
534     }//exe        
535
536     mylFinBlock.Append(myf); nite++;
537   }//nite <= mynF
538
539   myOshNsh.Bind(S(), Splits);
540   return Standard_True;
541 }
542  
543 //=======================================================================
544 //function : InitBlock
545 //purpose  : 
546 //=======================================================================
547
548 Standard_Boolean TopOpeBRepTool_REGUS::InitBlock()
549 {
550   Standard_Integer nec = myedstoconnect.Extent();
551   if (nec != 0) return Standard_False; // should be empty
552
553   TopTools_ListOfShape eds;
554   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(mymapeFs);
555   for (; itm.More(); itm.Next()) eds.Append(itm.Key());
556
557   TopTools_ListIteratorOfListOfShape ite(eds);
558   for (; ite.More(); ite.Next()){
559     const TopoDS_Shape& e = ite.Value();
560     const TopTools_ListOfShape& lof = mymapeFs.Find(e);
561     if (lof.IsEmpty()) {mymapeFs.UnBind(e); continue;}
562     myf = lof.First(); 
563 #ifdef OCCT_DEBUG
564     Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); 
565     if (trc) cout<<"* Block : first face = f"<<FUN_adds(myf)<<endl;
566 #endif 
567     return Standard_True;
568   }
569   return Standard_False;
570 }
571
572 //=======================================================================
573 //function : NextinBlock
574 //purpose  : 
575 //=======================================================================
576
577 Standard_Boolean TopOpeBRepTool_REGUS::NextinBlock()
578 {
579 #ifdef OCCT_DEBUG
580   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); 
581 #endif
582   // we try to connect first edge of <myf> bound in <myedstoconnect> 
583   TopTools_ListOfShape eds;
584   TopExp_Explorer exe(myf, TopAbs_EDGE);
585   for (; exe.More(); exe.Next()){
586     const TopoDS_Shape& e = exe.Current();
587     Standard_Boolean isb = myedstoconnect.Contains(e);
588     if (isb) eds.Append(e);
589   }//exe
590   Standard_Boolean alleftouched = eds.IsEmpty();
591   if (alleftouched) {
592     TopTools_MapIteratorOfMapOfShape itc(myedstoconnect);
593     for (; itc.More(); itc.Next()){
594       const TopoDS_Shape& e = itc.Key();
595       Standard_Boolean isBound = mymapeFs.IsBound(e);
596       // all ancestor faces of <e> have been stored
597       if (!isBound)    {myedstoconnect.Remove(e); continue;}
598
599       const TopTools_ListOfShape& lof = mymapeFs.Find(e); Standard_Integer nf = lof.Extent();
600       if (nf == 0) {myedstoconnect.Remove(e); mymapeFs.UnBind(e);
601                     continue;}
602
603 //      myf = lof.First(); 130499
604       if (lof.Extent() == 1) myf = lof.First();
605       else {
606         // looking for first face stored in the current block
607         // connexed to e
608
609         TopTools_ListIteratorOfListOfShape itff(mylFinBlock);
610         TopTools_MapOfShape mapf;for (; itff.More(); itff.Next()) mapf.Add(itff.Value());       
611         // lofc : the list of faces connexed to e in <myS>
612         // lof  : the list of untouched faces connexed to e in <myS>    
613         const TopTools_ListOfShape& lofc = mymapeFsstatic.Find(e);
614
615         itff.Initialize(lofc);
616         TopoDS_Face fref;
617         for (; itff.More(); itff.Next()) {
618           const TopoDS_Face& fc = TopoDS::Face(itff.Value());
619           Standard_Boolean isb = mapf.Contains(fc);
620           if (isb) {fref = fc; break;}
621         } // itff(lofc)
622         if (fref.IsNull()) {
623           return Standard_False; // !!!!!!!!!! a revoir 130499
624         }
625         else {
626           myf = fref;
627           TopoDS_Face ffound; Standard_Boolean ok = NearestF(TopoDS::Edge(e),lof,ffound);
628           if (!ok) return Standard_False;
629           myf = ffound;
630         }
631       }
632
633       return Standard_True;
634     }
635     return Standard_False;
636   }
637
638   TopTools_ListIteratorOfListOfShape ite(eds);
639   for (; ite.More(); ite.Next()){
640     const TopoDS_Shape& e = ite.Value();
641     Standard_Boolean isb = mymapeFs.IsBound(e);
642     // all ancestor faces of <e> have been stored
643     if (!isb)    {myedstoconnect.Remove(e); continue;}
644
645     const TopTools_ListOfShape& lof = mymapeFs.Find(e); Standard_Integer nf = lof.Extent();
646     if (nf == 0) {myedstoconnect.Remove(e); mymapeFs.UnBind(e);
647                   continue;}
648 #ifdef OCCT_DEBUG
649     if (trc) {cout<<"e"<<FUN_adds(e)<<" on "<<nf<<" untouched f:"<<endl;}
650 #endif
651     if (nf == 1) myf = lof.First();
652     else {
653       TopoDS_Face ffound; Standard_Boolean ok = NearestF(TopoDS::Edge(e),lof,ffound);
654       if (!ok) return Standard_False;
655       myf = ffound;
656     }
657 #ifdef OCCT_DEBUG
658     if (trc) cout<<"->myf = f"<<FUN_adds(myf)<<endl;
659 #endif
660     return Standard_True;
661   }//itm(myedstoconnect)
662   return Standard_False;
663 }
664
665 static Standard_Boolean FUN_vectors(const TopoDS_Face& f, const TopoDS_Edge& e, const Standard_Real pare,
666                        gp_Dir& nt, gp_Dir& xx, const Standard_Real tola, const Standard_Boolean approx)
667 {
668   // <nt> :  
669   if (approx) {
670     Standard_Boolean ok = TopOpeBRepTool_TOOL::tryNgApp(pare,e,f,tola,nt);  
671     if (!ok) return Standard_False; 
672   }  
673   else   {
674     gp_Vec tmp; Standard_Boolean  ok = FUN_tool_nggeomF(pare,e,f,tmp);
675     if (!ok) return Standard_False; 
676     nt = gp_Dir(tmp); 
677   }
678   if (M_REVERSED(f.Orientation())) nt.Reverse();
679   // <xx> : 
680   Standard_Boolean ok = FUN_tool_getxx(f,e,pare,xx);
681   if (!ok) return Standard_False;
682   return Standard_True;
683 }
684
685 //=======================================================================
686 //function : NearestF
687 //purpose  : 
688 //=======================================================================
689
690 Standard_Boolean TopOpeBRepTool_REGUS::NearestF(const TopoDS_Edge& e, const TopTools_ListOfShape& lof, TopoDS_Face& ffound) const
691 // prequesitory : <e> is shared by <myf> and faces of <lof>.  
692 //
693 // NYIXPU!!!!!!!! if (xx1 tg xx2) -> use curvatures
694 //
695 {
696 #ifdef OCCT_DEBUG
697   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); 
698 #endif
699   ffound.Nullify();
700   TopoDS_Face fref = TopoDS::Face(myf);
701
702   // Give us egde <e>, and a reference face <fref> (= <myf>)
703   // - parameter on <e> = <pare>.
704   // - xxi = tangent fo face fi at pnt(e,pare) oriented INSIDE 2d(fi)
705   //        normal to tge = tg(e,pare).
706   // purpose : looking for ffound / 
707   //  MatterAng(xxref, xxfound) = Min{ MatterAng(xxref, xxi), xxi for fi in <lof> 
708   //                                 providing fi reduces 3d(fref) }
709   
710   // <parone> :
711   Standard_Real f,l; FUN_tool_bounds(e,f,l); Standard_Real eps = 0.45678; Standard_Real pare = (1-eps)*f+eps*l;
712
713   // RONd (x,y,z) = (xxref,ntref,x^y)
714   Standard_Real tola = Precision::Angular()*1.e3; //gp_Dir xapp,yapp; Standard_Boolean refapp = Standard_False;
715   gp_Dir x,y; Standard_Boolean ok = ::FUN_vectors(fref,e,pare,y,x,tola,Standard_False);
716   if (!ok) {FUN_Raise(); return Standard_False;}
717   
718   // initializing
719   // ------------
720   Standard_Real angfound = 0;   
721   TopTools_ListIteratorOfListOfShape itf(lof);
722   for (; itf.More(); itf.Next()){
723     ffound = TopoDS::Face(itf.Value());
724     gp_Dir ntfound,xxfound;
725     ok = ::FUN_vectors(ffound,e,pare,ntfound,xxfound,tola,Standard_False);
726     if (!ok) {FUN_Raise(); return Standard_False;}
727
728     Standard_Boolean oppo = TopOpeBRepTool_TOOL::Matter(x,y,xxfound,ntfound,tola, angfound);
729 #ifdef OCCT_DEBUG
730     if (trc&&!oppo) cout<<"   f"<<FUN_adds(fref)<<",f"<<FUN_adds(ffound)<<" not oppo"<<endl;
731 #endif
732     if (!oppo) {ffound.Nullify(); continue;}
733     
734     if (angfound < tola) { 
735 //      refapp = Standard_True; ::FUN_vectors(fref,e,pare,yapp,xapp,tola,Standard_True);
736 //      ::FUN_vectors(ffound,e,pare,ntfound,xxfound,tola,Standard_True);
737 //      TopOpeBRepTool_TOOL::Matter(xapp,yapp,xxfound,ntfound,tola, angfound);
738       ok = TopOpeBRepTool_TOOL::MatterKPtg(fref,ffound,e,angfound);
739       if (!ok) {FUN_Raise(); return Standard_False;}
740     }
741 #ifdef OCCT_DEBUG
742     if (trc) cout<<"   ang(f"<<FUN_adds(fref)<<",f"<<FUN_adds(ffound)<<")="<<angfound<<endl;
743 #endif
744     break;
745   }
746   if (ffound.IsNull()) {FUN_Raise(); return Standard_False;}
747   if (itf.More()) itf.Next();
748   else            return Standard_True;
749
750   // selecting nearest face
751   // ----------------------
752   for (; itf.More(); itf.Next()){
753     gp_Dir nti,xxi;
754     const TopoDS_Face& fi = TopoDS::Face(itf.Value());
755     ok = ::FUN_vectors(fi,e,pare,nti,xxi,tola,Standard_False);
756     if (!ok) {FUN_Raise(); return Standard_False;}
757         
758     Standard_Real angi = 0; 
759     Standard_Boolean oppo = TopOpeBRepTool_TOOL::Matter(x,y,xxi,nti,tola, angi);
760 #ifdef OCCT_DEBUG
761     if (trc&&!oppo) cout<<"   f"<<FUN_adds(fref)<<",f"<<FUN_adds(fi)<<" not oppo"<<endl;
762 #endif
763     if (!oppo) continue;    
764
765     if (angi < tola) {
766 //      if (!refapp) ::FUN_vectors(fref,e,pare,yapp,xapp,tola,Standard_True);
767 //      ::FUN_vectors(fi,e,pare,nti,xxi,tola,Standard_True);
768 //      TopOpeBRepTool_TOOL::Matter(xapp,yapp,xxi,nti,tola, angi);
769       ok = TopOpeBRepTool_TOOL::MatterKPtg(fref,fi,e,angi);
770       if (!ok) {FUN_Raise(); return Standard_False;}
771     }
772 #ifdef OCCT_DEBUG
773     if (trc) cout<<"   ang(f"<<FUN_adds(fref)<<",f"<<FUN_adds(fi)<<")="<<angi<<endl;
774 #endif
775     if (angi > angfound) continue; 
776     angfound = angi;
777     ffound = fi;
778   }
779   return Standard_True;
780 }
781
782
783