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