d97e88802f837c571be115bdfb115b467148350c
[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 #ifdef DEB
344     Standard_Integer nf =
345 #endif
346              lfsp.Extent();
347     if (!issp) continue;
348
349     myFsplits.Bind(f,lfsp);
350     
351     // updating the map of connexity : 
352     // f -> lfsp = {fsp}
353     mynF--;
354     TopTools_ListIteratorOfListOfShape itf(lfsp);
355     for (; itf.More(); itf.Next()){
356       const TopoDS_Shape& fsp = itf.Value(); mynF++;
357
358       TopExp_Explorer exe(fsp, TopAbs_EDGE);
359       for (; exe.More(); exe.Next()) {
360         // fsp -> {e}
361         const TopoDS_Shape& e = exe.Current();
362         Standard_Boolean isb = mymapeFs.IsBound(e);
363         if (!isb) {FUN_Raise(); return Standard_False;}
364         
365         // <mymapeFs>
366         TopTools_ListOfShape& lof = mymapeFs.ChangeFind(e);
367         TopOpeBRepTool_TOOL::Remove(lof,f);
368         lof.Append(fsp);
369
370         // <mymapemult>
371         Standard_Integer nf = lof.Extent();
372         if (nf > 2) mymapemult.Add(e);
373       }//exe(fsp)
374     }//itf(lfsp)
375
376 #ifdef DEB
377     if (trc)  {
378       cout <<"split(f"<<FUN_adds(f)<<")= ";
379       TopTools_ListIteratorOfListOfShape it(lfsp);
380       for (; it.More(); it.Next()) cout<<" f"<<FUN_adds(it.Value());
381       cout<<endl;}
382 #endif
383   }//exf(myS)
384   return Standard_True;  
385 }
386
387 static void FUN_update(const TopoDS_Shape& fcur, TopTools_MapOfShape& edstoconnect)
388 // purpose : <e> edge of <fcur>
389 //  1. <e> is INTERNAL or EXTERNAL   -> nothing is done
390 //  2. <e> is closing edge of <fcur> -> nothing is done
391 //  3. <e> is already bound in <edstoconnect> -> remove it from the map
392 //     (then has 2 ancestor faces stored in the current Block)
393 //  4. elsewhere, add it in the map.
394 //
395 // !! if <fcur> is INTERNAL/EXTERNAL -> nothing is done
396 {
397   TopAbs_Orientation ofcur = fcur.Orientation();
398   if (M_INTERNAL(ofcur) || M_EXTERNAL(ofcur)) return;
399
400   TopExp_Explorer exe(fcur, TopAbs_EDGE);
401   for (; exe.More(); exe.Next()){
402     const TopoDS_Shape& e = exe.Current();
403     TopAbs_Orientation oe = e.Orientation();
404     if (M_INTERNAL(oe) || M_EXTERNAL(oe)) continue;
405
406     Standard_Boolean isclo = TopOpeBRepTool_TOOL::IsClosingE(TopoDS::Edge(e),TopoDS::Face(fcur));
407     if (isclo) continue;
408
409     Standard_Boolean isb = edstoconnect.Contains(e);
410     if (isb) edstoconnect.Remove(e);
411     else     edstoconnect.Add(e);
412   }//exe
413 }
414
415 //=======================================================================
416 //function : REGU
417 //purpose  : 
418 //=======================================================================
419
420 Standard_Boolean TopOpeBRepTool_REGUS::REGU()
421 {
422 #ifdef DEB
423   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO();
424   Standard_Integer ishe = FUN_adds(myS);
425   if (trc) cout<<"**    REGU    **"<<ishe<<endl;
426 #endif
427   TopTools_ListOfShape Splits;
428   Standard_Boolean toregu = !mymapemult.IsEmpty() || (mynF != myoldnF);
429   if (!toregu) return Standard_False;
430
431   // purpose : myS -> {Blocks}, 
432   //           a Block is a closed shell with "valid" edges.
433   //           - a valid edge in a Block has at most two ancestor faces -
434   //
435   // Give us the starting couple (<ei>, <fi>) :
436   // * If <ei> has only one untouched ancestor face <fj> left, fj+1 <- fj
437   //   Else among the untouched ancestors faces, we choose the one for which
438   //   angle (<veci>, <vecj>) is the smallest; providing face <fj> reduces
439   //   the matter described by <fi>.
440   // * update <mymapeFs> for <ei> (<fj> as touched).
441   // * Update <mymapemult> for <fi>'s bound edges :
442   //   - if bound edge is not in the map, add it.
443   //   - else if bound edge has two ancestor faces in current list <mylFinBlock>,
444   //     delete it form the map.
445   //
446 //  TopTools_ListOfShape lFinBlock; // <lFinBlock> describes a valid closed shell when <myedstoconnect> is emptied.   
447   mylFinBlock.Clear();
448   Standard_Integer nite = 0;
449   while (nite <= mynF) {
450     Standard_Boolean startBlock = mylFinBlock.IsEmpty();
451     Standard_Boolean endBlock = myedstoconnect.IsEmpty() && (!startBlock);
452
453 #ifdef DEB
454     Standard_Boolean tr=Standard_False;
455     if (tr) {
456       TopTools_MapIteratorOfMapOfShape it(myedstoconnect);
457       cout<<"still to connect : ";
458       for (; it.More(); it.Next()) cout<<" e"<<FUN_adds(it.Key());
459       cout<<endl;
460     }
461 #endif
462
463     //* endBlock
464     // ---------
465     if (endBlock) {
466       // building up shell on <mylFinBlock>
467       Standard_Integer nFcur = mylFinBlock.Extent();
468       Standard_Boolean unchanged = (nFcur==myoldnF) && (mynF==myoldnF);
469       if (unchanged) {
470 #ifdef DEB
471         if (trc) cout<<"#** shell"<<ishe<<" valid\n";
472 #endif
473         return Standard_False; // nyi analysis if we should raise or not  
474       }
475       else {
476         TopoDS_Shell newShe; TopOpeBRepTool_TOOL::MkShell(mylFinBlock,newShe);
477         Splits.Append(newShe);
478 #ifdef DEB
479         if (trc) {cout<<"#** shell "<<ishe<<" gives new shell "<<FUN_adds(newShe)<<endl;
480                   for (TopTools_ListIteratorOfListOfShape it(mylFinBlock); it.More(); it.Next()) cout <<";dins f"<<FUN_adds(it.Value());
481                   cout<<endl<<endl;}
482 #endif
483         mylFinBlock.Clear(); 
484         startBlock = Standard_True;
485       }
486     }//endBlock
487
488     //* all faces touched
489     // ------------------
490     Standard_Boolean FINI = (nite == mynF);
491     if (FINI) break;
492
493     Standard_Integer advance=Standard_False;
494     //* initializing a new Block
495     // -------------------------
496     if (startBlock || endBlock) {
497       advance = InitBlock();
498       if (!advance) return Standard_False;
499     }//startBlock||endBlock
500
501     //* choosing next face
502     // -------------------
503     else {
504      advance  = NextinBlock();      
505     }
506
507     // ** updating connexity     
508     ::FUN_update(myf,myedstoconnect);
509
510     if (!advance) {
511       endBlock = myedstoconnect.IsEmpty() && (!startBlock);
512       if (!endBlock) return Standard_False;
513       else           continue;
514     }
515     
516     TopExp_Explorer exe(myf, TopAbs_EDGE);
517     for (; exe.More(); exe.Next()){
518       const TopoDS_Shape& e = exe.Current();
519       Standard_Boolean isb = mymapeFs.IsBound(e);
520       if (!isb) continue; // ancestors faces of <e> are stored in Blocks        
521       TopOpeBRepTool_TOOL::Remove(mymapeFs.ChangeFind(e),myf);
522     }//exe        
523
524     mylFinBlock.Append(myf); nite++;
525   }//nite <= mynF
526
527   myOshNsh.Bind(S(), Splits);
528   return Standard_True;
529 }
530  
531 //=======================================================================
532 //function : InitBlock
533 //purpose  : 
534 //=======================================================================
535
536 Standard_Boolean TopOpeBRepTool_REGUS::InitBlock()
537 {
538   Standard_Integer nec = myedstoconnect.Extent();
539   if (nec != 0) return Standard_False; // should be empty
540
541   TopTools_ListOfShape eds;
542   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(mymapeFs);
543   for (; itm.More(); itm.Next()) eds.Append(itm.Key());
544
545   TopTools_ListIteratorOfListOfShape ite(eds);
546   for (; ite.More(); ite.Next()){
547     const TopoDS_Shape& e = ite.Value();
548     const TopTools_ListOfShape& lof = mymapeFs.Find(e);
549     if (lof.IsEmpty()) {mymapeFs.UnBind(e); continue;}
550     myf = lof.First(); 
551 #ifdef DEB
552     Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); 
553     if (trc) cout<<"* Block : first face = f"<<FUN_adds(myf)<<endl;
554 #endif 
555     return Standard_True;
556   }
557   return Standard_False;
558 }
559
560 //=======================================================================
561 //function : NextinBlock
562 //purpose  : 
563 //=======================================================================
564
565 Standard_Boolean TopOpeBRepTool_REGUS::NextinBlock()
566 {
567 #ifdef DEB
568   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); 
569 #endif
570   // we try to connect first edge of <myf> bound in <myedstoconnect> 
571   TopTools_ListOfShape eds;
572   TopExp_Explorer exe(myf, TopAbs_EDGE);
573   for (; exe.More(); exe.Next()){
574     const TopoDS_Shape& e = exe.Current();
575     Standard_Boolean isb = myedstoconnect.Contains(e);
576     if (isb) eds.Append(e);
577   }//exe
578   Standard_Boolean alleftouched = eds.IsEmpty();
579   if (alleftouched) {
580     TopTools_MapIteratorOfMapOfShape itc(myedstoconnect);
581     for (; itc.More(); itc.Next()){
582       const TopoDS_Shape& e = itc.Key();
583       Standard_Boolean isb = mymapeFs.IsBound(e);
584       // all ancestor faces of <e> have been stored
585       if (!isb)    {myedstoconnect.Remove(e); continue;}
586
587       const TopTools_ListOfShape& lof = mymapeFs.Find(e); Standard_Integer nf = lof.Extent();
588       if (nf == 0) {myedstoconnect.Remove(e); mymapeFs.UnBind(e);
589                     continue;}
590
591 //      myf = lof.First(); 130499
592       if (lof.Extent() == 1) myf = lof.First();
593       else {
594         // looking for first face stored in the current block
595         // connexed to e
596
597         TopTools_ListIteratorOfListOfShape itff(mylFinBlock);
598         TopTools_MapOfShape mapf;for (; itff.More(); itff.Next()) mapf.Add(itff.Value());       
599         // lofc : the list of faces connexed to e in <myS>
600         // lof  : the list of untouched faces connexed to e in <myS>    
601         const TopTools_ListOfShape& lofc = mymapeFsstatic.Find(e);
602 #ifdef DEB
603         Standard_Integer nfc =
604 #endif
605                   lofc.Extent();
606         itff.Initialize(lofc);
607         TopoDS_Face fref;
608         for (; itff.More(); itff.Next()) {
609           const TopoDS_Face& fc = TopoDS::Face(itff.Value());
610           Standard_Boolean isb = mapf.Contains(fc);
611           if (isb) {fref = fc; break;}
612         } // itff(lofc)
613         if (fref.IsNull()) {
614           return Standard_False; // !!!!!!!!!! a revoir 130499
615         }
616         else {
617           myf = fref;
618           TopoDS_Face ffound; Standard_Boolean ok = NearestF(TopoDS::Edge(e),lof,ffound);
619           if (!ok) return Standard_False;
620           myf = ffound;
621         }
622       }
623
624       return Standard_True;
625     }
626     return Standard_False;
627   }
628
629   TopTools_ListIteratorOfListOfShape ite(eds);
630   for (; ite.More(); ite.Next()){
631     const TopoDS_Shape& e = ite.Value();
632     Standard_Boolean isb = mymapeFs.IsBound(e);
633     // all ancestor faces of <e> have been stored
634     if (!isb)    {myedstoconnect.Remove(e); continue;}
635
636     const TopTools_ListOfShape& lof = mymapeFs.Find(e); Standard_Integer nf = lof.Extent();
637     if (nf == 0) {myedstoconnect.Remove(e); mymapeFs.UnBind(e);
638                   continue;}
639 #ifdef DEB
640     if (trc) {cout<<"e"<<FUN_adds(e)<<" on "<<nf<<" untouched f:"<<endl;}
641 #endif
642     if (nf == 1) myf = lof.First();
643     else {
644       TopoDS_Face ffound; Standard_Boolean ok = NearestF(TopoDS::Edge(e),lof,ffound);
645       if (!ok) return Standard_False;
646       myf = ffound;
647     }
648 #ifdef DEB
649     if (trc) cout<<"->myf = f"<<FUN_adds(myf)<<endl;
650 #endif
651     return Standard_True;
652   }//itm(myedstoconnect)
653   return Standard_False;
654 }
655
656 static Standard_Boolean FUN_vectors(const TopoDS_Face& f, const TopoDS_Edge& e, const Standard_Real pare,
657                        gp_Dir& nt, gp_Dir& xx, const Standard_Real tola, const Standard_Boolean approx)
658 {
659   // <nt> :  
660   if (approx) {
661     Standard_Boolean ok = TopOpeBRepTool_TOOL::tryNgApp(pare,e,f,tola,nt);  
662     if (!ok) return Standard_False; 
663   }  
664   else   {
665     gp_Vec tmp; Standard_Boolean  ok = FUN_tool_nggeomF(pare,e,f,tmp);
666     if (!ok) return Standard_False; 
667     nt = gp_Dir(tmp); 
668   }
669   if (M_REVERSED(f.Orientation())) nt.Reverse();
670   // <xx> : 
671   Standard_Boolean ok = FUN_tool_getxx(f,e,pare,xx);
672   if (!ok) return Standard_False;
673   return Standard_True;
674 }
675
676 //=======================================================================
677 //function : NearestF
678 //purpose  : 
679 //=======================================================================
680
681 Standard_Boolean TopOpeBRepTool_REGUS::NearestF(const TopoDS_Edge& e, const TopTools_ListOfShape& lof, TopoDS_Face& ffound) const
682 // prequesitory : <e> is shared by <myf> and faces of <lof>.  
683 //
684 // NYIXPU!!!!!!!! if (xx1 tg xx2) -> use curvatures
685 //
686 {
687 #ifdef DEB
688   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); 
689 #endif
690   ffound.Nullify();
691   TopoDS_Face fref = TopoDS::Face(myf);
692 #ifdef DEB
693   Standard_Integer nf =
694 #endif
695            lof.Extent();//deb
696
697   // Give us egde <e>, and a reference face <fref> (= <myf>)
698   // - parameter on <e> = <pare>.
699   // - xxi = tangent fo face fi at pnt(e,pare) oriented INSIDE 2d(fi)
700   //        normal to tge = tg(e,pare).
701   // purpose : looking for ffound / 
702   //  MatterAng(xxref, xxfound) = Min{ MatterAng(xxref, xxi), xxi for fi in <lof> 
703   //                                 providing fi reduces 3d(fref) }
704   
705   // <parone> :
706   Standard_Real f,l; FUN_tool_bounds(e,f,l); Standard_Real eps = 0.45678; Standard_Real pare = (1-eps)*f+eps*l;
707
708   // RONd (x,y,z) = (xxref,ntref,x^y)
709   Standard_Real tola = Precision::Angular()*1.e3; //gp_Dir xapp,yapp; Standard_Boolean refapp = Standard_False;
710   gp_Dir x,y; Standard_Boolean ok = ::FUN_vectors(fref,e,pare,y,x,tola,Standard_False);
711   if (!ok) {FUN_Raise(); return Standard_False;}
712 #ifdef DEB
713   gp_Dir z = x^y;    
714 #endif
715   
716   // initializing
717   // ------------
718   Standard_Real angfound = 0;   
719   TopTools_ListIteratorOfListOfShape itf(lof);
720   for (; itf.More(); itf.Next()){
721     ffound = TopoDS::Face(itf.Value());
722     gp_Dir ntfound,xxfound;
723     ok = ::FUN_vectors(ffound,e,pare,ntfound,xxfound,tola,Standard_False);
724     if (!ok) {FUN_Raise(); return Standard_False;}
725
726     Standard_Boolean oppo = TopOpeBRepTool_TOOL::Matter(x,y,xxfound,ntfound,tola, angfound);
727 #ifdef DEB
728     if (trc&&!oppo) cout<<"   f"<<FUN_adds(fref)<<",f"<<FUN_adds(ffound)<<" not oppo"<<endl;
729 #endif
730     if (!oppo) {ffound.Nullify(); continue;}
731     
732     if (angfound < tola) { 
733 //      refapp = Standard_True; ::FUN_vectors(fref,e,pare,yapp,xapp,tola,Standard_True);
734 //      ::FUN_vectors(ffound,e,pare,ntfound,xxfound,tola,Standard_True);
735 //      TopOpeBRepTool_TOOL::Matter(xapp,yapp,xxfound,ntfound,tola, angfound);
736       ok = TopOpeBRepTool_TOOL::MatterKPtg(fref,ffound,e,angfound);
737       if (!ok) {FUN_Raise(); return Standard_False;}
738     }
739 #ifdef DEB
740     if (trc) cout<<"   ang("<<"f"<<FUN_adds(fref)<<",f"<<FUN_adds(ffound)<<")="<<angfound<<endl;
741 #endif
742     break;
743   }
744   if (ffound.IsNull()) {FUN_Raise(); return Standard_False;}
745   if (itf.More()) itf.Next();
746   else            return Standard_True;
747
748   // selecting nearest face
749   // ----------------------
750   for (; itf.More(); itf.Next()){
751     gp_Dir nti,xxi;
752     const TopoDS_Face& fi = TopoDS::Face(itf.Value());
753     ok = ::FUN_vectors(fi,e,pare,nti,xxi,tola,Standard_False);
754     if (!ok) {FUN_Raise(); return Standard_False;}
755         
756     Standard_Real angi = 0; 
757     Standard_Boolean oppo = TopOpeBRepTool_TOOL::Matter(x,y,xxi,nti,tola, angi);
758 #ifdef DEB
759     if (trc&&!oppo) cout<<"   f"<<FUN_adds(fref)<<",f"<<FUN_adds(fi)<<" not oppo"<<endl;
760 #endif
761     if (!oppo) continue;    
762
763     if (angi < tola) {
764 //      if (!refapp) ::FUN_vectors(fref,e,pare,yapp,xapp,tola,Standard_True);
765 //      ::FUN_vectors(fi,e,pare,nti,xxi,tola,Standard_True);
766 //      TopOpeBRepTool_TOOL::Matter(xapp,yapp,xxi,nti,tola, angi);
767       ok = TopOpeBRepTool_TOOL::MatterKPtg(fref,fi,e,angi);
768       if (!ok) {FUN_Raise(); return Standard_False;}
769     }
770 #ifdef DEB
771     if (trc) cout<<"   ang("<<"f"<<FUN_adds(fref)<<",f"<<FUN_adds(fi)<<")="<<angi<<endl;
772 #endif
773     if (angi > angfound) continue; 
774     angfound = angi;
775     ffound = fi;
776   }
777   return Standard_True;
778 }
779
780
781