1db72f797d9cf3ec84960d151f21387be57e4e7f
[occt.git] / src / TopOpeBRepTool / TopOpeBRepTool_RegularizeW.cxx
1 // File:        TopOpeBRepTool_RegularizeW.cxx
2 // Created:     Wed Dec 23 15:34:12 1998
3 // Author:      Xuan PHAM PHU
4 //              <xpu@poulopox.paris1.matra-dtv.fr>
5
6
7 #include <TopOpeBRepTool.hxx>
8 #include <TopOpeBRepTool_EXPORT.hxx>
9 #include <TopOpeBRepTool_CLASSI.hxx>
10 #include <TopOpeBRepTool_REGUW.hxx>
11 #include <TopOpeBRepTool_TOOL.hxx>
12 #include <TopOpeBRepTool_define.hxx>
13 #include <TopExp_Explorer.hxx>
14 #include <BRep_Tool.hxx>
15 #include <TopAbs.hxx>
16 #include <TopoDS.hxx>
17
18 #ifdef DRAW
19 #include <TopOpeBRepTool_DRAW.hxx>
20 #endif
21
22 #define SAME     (-1)
23 #define DIFF     (-2)
24 #define UNKNOWN  ( 0)
25 #define oneINtwo ( 1)
26 #define twoINone ( 2)
27
28 #define M_FORWARD(sta)  (sta == TopAbs_FORWARD)
29 #define M_REVERSED(sta) (sta == TopAbs_REVERSED)
30 #define M_INTERNAL(sta) (sta == TopAbs_INTERNAL)
31 #define M_EXTERNAL(sta) (sta == TopAbs_EXTERNAL)
32
33 #ifdef DEB
34 Standard_EXPORT Standard_Boolean TopOpeBRepTool_GettraceREGUFA(); 
35 static TopTools_IndexedMapOfShape STATIC_mapw,STATIC_mapf;
36 static Standard_Integer FUN_adds(const TopoDS_Shape& s) {
37   TopAbs_ShapeEnum typ = s.ShapeType();
38   TCollection_AsciiString aa; Standard_Integer is = 0;
39   if (typ == TopAbs_WIRE)   {aa = TCollection_AsciiString("wi"); is = STATIC_mapw.Add(s); }
40   if (typ == TopAbs_FACE)   {aa = TCollection_AsciiString("fa"); is = STATIC_mapf.Add(s); }
41 #ifdef DRAW 
42   FUN_tool_draw(aa,s,is);  
43 #endif
44   return is;
45 }
46 Standard_EXPORT void FUN_tool_coutsta(const Standard_Integer& sta, const Standard_Integer& i1, const Standard_Integer& i2)
47 {
48   switch (sta) {
49   case SAME:
50     cout<<i1<<" gives SAME bnd with "<<i2<<endl; break;
51   case DIFF:
52     cout<<i1<<" gives  OUT bnd with "<<i2<<endl; break;
53   case oneINtwo:
54     cout<<i1<<" is IN "<<i2<<endl; break;
55   case twoINone:
56     cout<<i2<<" is IN "<<i1<<endl; break;
57   }
58 }
59 #endif
60
61 Standard_EXPORT void FUN_addOwlw(const TopoDS_Shape& Ow, const TopTools_ListOfShape& lw, TopTools_ListOfShape& lresu);
62
63 //=======================================================================
64 //function : RegularizeWires
65 //purpose  : 
66 //=======================================================================
67
68 Standard_Boolean TopOpeBRepTool::RegularizeWires(const TopoDS_Face& theFace,
69                                     TopTools_DataMapOfShapeListOfShape& mapoldWnewW,
70                                     TopTools_DataMapOfShapeListOfShape& ESplits) // (e,esp); esp = splits of e
71 {
72   if (theFace.IsNull()) return Standard_False;
73  TopoDS_Shape aLocalShape = theFace.Oriented(TopAbs_FORWARD);  
74   TopoDS_Face aFace = TopoDS::Face(aLocalShape);
75 //  TopoDS_Face aFace = TopoDS::Face(theFace.Oriented(TopAbs_FORWARD));
76
77   TopOpeBRepTool_REGUW REGUW(aFace);
78   REGUW.SetOwNw(mapoldWnewW);
79   REGUW.SetEsplits(ESplits);
80
81 //  Standard_Boolean hasregu = Standard_False;
82   TopExp_Explorer exw(aFace, TopAbs_WIRE);
83   for (; exw.More(); exw.Next()) {   
84     const TopoDS_Shape& W = exw.Current(); 
85     REGUW.Init(W);
86     Standard_Boolean ok = REGUW.MapS();
87     if (!ok) return Standard_False;
88     ok = REGUW.SplitEds();
89     if (!ok) return Standard_False;
90     ok = REGUW.REGU();
91     if (!ok) return Standard_False;
92   }
93
94   REGUW.GetEsplits(ESplits); 
95   REGUW.GetOwNw(mapoldWnewW);
96   return Standard_True;
97 }
98
99 //=======================================================================
100 //function : Regularize
101 //purpose  : 
102 //=======================================================================
103
104 Standard_Boolean TopOpeBRepTool::Regularize(const TopoDS_Face& theFace,
105                                TopTools_ListOfShape& aListOfFaces,
106                                TopTools_DataMapOfShapeListOfShape& ESplits) 
107 {   
108   TopOpeBRepTool_REGUW REGUW(theFace);
109   aListOfFaces.Clear();
110   TopTools_DataMapOfShapeListOfShape mapoldWnewW;
111   Standard_Boolean regu = TopOpeBRepTool::RegularizeWires(theFace,mapoldWnewW,ESplits);
112   if (regu) {
113     regu = TopOpeBRepTool::RegularizeFace(theFace,mapoldWnewW,aListOfFaces);
114   }
115   return regu;
116 }
117
118 //**********************************************************************
119 //   classifying wires
120 //**********************************************************************
121
122 // ------------------------------------------------------------
123 // ------------------ classifying wires -----------------------
124
125 // function : bFgreaterbFF (F,FF)
126 // purpose  : returns False if <F>'s 3d bounding box smaller than <FF>'s
127
128 // function : mkBnd2d (W,F,B2d)
129 // purpose  : get 2d bounding box <B2d> of wire <W>'s UV  
130 //            representation on face <F>.
131
132 // function : classiBnd2d (B,ismaller)
133 // purpose  : compare the two 2d bounding boxes of array <B>
134 //            if found, B<ismaller> is the smaller one and returns IN
135 //            else if boxes are disjoint, returns OUT
136 //            else return UNKNOWN
137 // function : classiBnd2d (B)
138 // purpose  : returns SAME,DIFF,UNKNOWN,oneINtwo or twoINone
139
140
141 // function : mkboundedF(W,boundedF)
142 // purpose  : 
143
144 // function : FindAPointInTheFace(F,u,v)
145 // purpose  : 
146
147 // function : GetFP2d(W,boundedF,p2d)
148 // purpose  : computes <boundedF> the bounded face built up with wire <W>
149 //            and <p2d> a point in <boundedF>
150 //            
151
152 // function : classiwithp2d(wi)
153 // purpose  : classify wires (wi(k),k = 1,2)
154 //            prequesitory : wires of <wi> are not intersecting each other.
155
156 // function : ClassifW(F,mapoldWnewW,mapWlow)
157 // purpose  : all wires described in <mapoldWnewW> are on face <F>
158 //            <mapoldWnewW> = map with :
159 //             key = a wire of <F>
160 //             item = the splits of the previous wire (can be an empty list)
161 //            the aim is to get map <mapWlow> with :
162 //             key = a new face's boundary
163 //             item = wires dexcribing holes in the previous face 
164 //                    (can be an empty list) 
165 // ------------------------------------------------------------
166
167 /*static TopAbs_State FUN_tool_classiBnd2d(const Bnd_Array1OfBox2d& B,Standard_Integer& ismaller,
168                                  const Standard_Boolean chklarge = Standard_True)
169 {
170   // purpose : 
171   //   Getting <ismaller>, index of the smallest Bnd Box
172   //   if B(i) is IN B(j): ismaller = i,
173   //                       return IN.
174   //   else: ismaller = 1,
175   //         if B(1) and B(2) are disjoint, return OUT
176   //         if B(1) and B(2) are same, return ON
177   //         else return UNKNOWN.
178   ismaller = 1;
179   
180   TColStd_Array2OfReal UV(1,2, 1,4);
181   for (Standard_Integer i = 1; i <= 2; i++)
182     //      (Umin(i), Vmin(i), Umax(i), Vmax(i))
183     B(i).Get(UV(i,1), UV(i,3), UV(i,2), UV(i,4));
184
185 #ifdef DEB
186   Standard_Boolean trc = Standard_False;
187   if (trc) {
188     for (Standard_Integer i = 1; i <= 2; i++)
189       cout<<"B("<<i<<") = ("<<UV(i,1)<<" "<<UV(i,3)<<" "<<UV(i,2)<<" "<<UV(i,4)<<")"<<endl;
190   }
191 #endif
192
193   Standard_Boolean smaller, same;
194   Standard_Integer ii, jj;
195   Standard_Real tol = 1.e-6;
196
197   Standard_Boolean disjoint = Standard_False;
198   for (Standard_Integer k = 1; k <= 3; k+=2) { 
199     for (i = 1; i <= 2; i++) {
200       ii = i; jj = (i == 1) ?  2 : 1;         
201       //  diff = Umin<ii> - Umax<jj> : k = 1
202       //  diff = Vmin<ii> - Vmax<jj> : k = 3
203       Standard_Real diff = UV(ii,k) - UV(jj,k+1);
204       // IMPORTANT : for splitted faces sharing same edge, use
205       // chklarge = True.
206       disjoint = chklarge ? (diff >= -tol) : (diff > 0.);
207       if (disjoint) {ismaller = 1; return TopAbs_OUT;}
208     }
209   }
210   
211   for (i = 1; i <= 2; i++) {
212     ii = i; jj = (i == 1) ? 2 : 1; 
213     smaller = same = Standard_True;
214     for (Standard_Integer k = 1; k <= 3; k += 2){         
215       //  diff = Umin<ii> - Umin<jj> : k = 1        
216       //  diff = Vmin<ii> - Vmin<jj> : k = 3 
217       Standard_Real diff = UV(ii,k) - UV(jj,k);  
218       smaller = chklarge ? (smaller && (diff > -tol)) : (smaller && (diff > 0.));
219       same = same && (Abs(diff) <= tol);
220     }    
221     for (k = 2; k <= 4; k +=2){      
222       //  diff = Umax<ii> - Umax<jj> : k = 2        
223       //  diff = Vmax<ii> - Vmax<jj> : k = 4
224       Standard_Real diff = UV(ii,k) - UV(jj,k); 
225       smaller = chklarge ? (smaller && (diff < tol)) : (smaller && (diff < 0.));
226       same = same && (Abs(diff) <= tol);
227     }
228
229     if (same) return TopAbs_ON;
230     if (smaller) {
231       ismaller = ii;
232       return TopAbs_IN;
233     }
234   }
235   return TopAbs_UNKNOWN;
236 }
237
238 #define SAME     (-1)
239 #define DIFF     (-2)
240 #define UNKNOWN  ( 0)
241 #define oneINtwo ( 1)
242 #define twoINone ( 2)
243
244 Standard_EXPORT Standard_Integer FUN_tool_classiBnd2d(const Bnd_Array1OfBox2d& B,
245                                          const Standard_Boolean chklarge = Standard_True)
246 {
247   Standard_Integer ismaller;
248   TopAbs_State sta = FUN_tool_classiBnd2d(B, ismaller, chklarge);
249   Standard_Integer res = -10;
250   switch (sta) {
251   case TopAbs_IN :
252     res = ismaller; break;
253   case TopAbs_OUT :
254     res = DIFF; break;
255   case TopAbs_ON :
256     res = SAME; break;
257   case TopAbs_UNKNOWN :
258     res = UNKNOWN; break;
259   }
260   return res;
261 }
262
263 static Standard_Boolean FUN_tool_mkboundedF(const TopoDS_Wire& W, TopoDS_Face& boundedF)
264 {
265   BRepLib_MakeFace mf(W, Standard_False);
266   Standard_Boolean done = mf.IsDone();
267   if (done) boundedF = mf.Face();
268   return done;
269 }
270 Standard_Boolean FUN_tool_FindAPointInTheFace(const TopoDS_Face& F,
271                                  Standard_Real& u, Standard_Real& v)
272 {
273   Standard_Boolean ok = BRepClass3d_SolidExplorer::FindAPointInTheFace(F,u,v);
274   return ok;
275 }
276 static Standard_Boolean FUN_tool_GetFP2d(const TopoDS_Shape& W,
277                             TopoDS_Shape& boundedF, gp_Pnt2d& p2d)
278 {
279   Standard_Boolean ok = FUN_tool_mkboundedF(TopoDS::Wire(W), TopoDS::Face(boundedF)); 
280   if (!ok) return Standard_False;
281   
282   Standard_Real u,v; ok = FUN_tool_FindAPointInTheFace(TopoDS::Face(boundedF),u,v);
283   if (!ok) return Standard_False;
284   p2d = gp_Pnt2d(u,v);
285   return Standard_True;
286 }
287 static Standard_Integer FUN_tool_classiwithp2d(const TopTools_Array1OfShape& wi)
288 {
289   Standard_Integer stares = UNKNOWN;
290   TopTools_Array1OfShape fa(1,2);
291   TColgp_Array1OfPnt     p3d(1,2);
292   for (Standard_Integer k = 1; k <= 2; k++) {
293     gp_Pnt2d p2d;
294     Standard_Boolean ok = FUN_tool_GetFP2d(wi(k), fa(k), p2d);
295     if (!ok) return UNKNOWN;
296     BRepAdaptor_Surface BS(TopoDS::Face(fa(k)));
297     p3d(k) = BS.Value(p2d.X(),p2d.Y());
298   }
299
300   TopAbs_State sta;
301   Standard_Integer i,j; i = j = 0;
302   for (Standard_Integer nite = 1; nite <= 2; nite++) {
303     i = nite;
304     j = (i == 1) ? 2 : 1;
305     TopoDS_Face f = TopoDS::Face(fa(j));
306     const gp_Pnt p = p3d(i);
307     Standard_Real tol = BRep_Tool::Tolerance(f);
308     BRepClass_FaceClassifier Fclass(f, p, tol);
309     sta = Fclass.State();
310     if (sta == TopAbs_IN) break;
311   }
312   switch (sta) {
313   case TopAbs_IN :
314     stares = i; break;
315   case TopAbs_OUT :
316     stares = DIFF; break;
317   case TopAbs_ON :
318   case TopAbs_UNKNOWN :
319     stares = UNKNOWN; break;
320   }
321   return stares;
322 }
323
324 Standard_EXPORT Standard_Boolean FUN_tool_ClassifW(const TopoDS_Face& F,
325                                       const TopTools_DataMapOfShapeListOfShape& mapoldWnewW,
326                                       TopTools_DataMapOfShapeListOfShape& mapWlow)
327 {
328   // NYI : create maps to store Bnd_Box2d, and faces.
329
330 #ifdef DEB
331   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA();
332   if (trc) cout<<"** ClassifW :"<<endl;
333   STATIC_mapw.Clear();    
334 #endif  
335
336   // Purpose :
337   // --------
338   // Filling the map <mapWlow> : with (key + item) = new face,
339   //  item = (newface has holes) ? list of wires IN the wire key: empty list
340
341   // prequesitory : <mapoldWnewW> binds (non splitted wire of <F>, emptylos)
342   //                                    (splitted wire of <F>, splits of the wire)
343
344   // Mapping :
345   // --------
346   // Filling <oldW> : list of wires of <F>
347   // Filling <mapWlow> : with (non-splitted old wire, emptylos),
348   //                          (split of old wire, emptylos)
349   TopTools_ListOfShape oldW;
350   Standard_Integer noldW = mapoldWnewW.Extent();
351   Standard_Boolean oneoldW = (noldW == 1);
352   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape ite(mapoldWnewW);
353   TopTools_ListOfShape emptylos;
354
355   // --------------
356   // * noldW == 1 :
357   // --------------
358   if (oneoldW) {
359     const TopoDS_Wire& oldwi = TopoDS::Wire(ite.Key());
360     const TopTools_ListOfShape& low = ite.Value();
361     Standard_Integer nw = low.Extent();
362     if (nw == 0) {mapWlow.Bind(oldwi,emptylos); return Standard_True;}
363     if (nw == 1) {mapWlow.Bind(low.First(),emptylos); return Standard_True;}
364
365     // <complWoldw> = {(newwire, emptylos)}
366     TopTools_DataMapOfShapeListOfShape complWoldw;
367     TopTools_ListIteratorOfListOfShape itlw(low);
368     for (; itlw.More(); itlw.Next()) complWoldw.Bind(itlw.Value(), emptylos);    
369
370     // iteration on <complWoldw> :
371     Standard_Integer ncompl = complWoldw.Extent();
372     Standard_Boolean go = Standard_True;
373     Standard_Integer nite = 0, nitemax = Standard_Integer(ncompl*(ncompl-1)/2);
374     while (go && (nite <= nitemax)){
375       Bnd_Array1OfBox2d Bnd2d(1,2);
376       TopTools_Array1OfShape wi(1,2);
377       
378       TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itmap(complWoldw);
379       wi(1) = itmap.Key();
380       if (ncompl == 1) {
381         mapWlow.Bind(wi(1),itmap.Value()); 
382         break;
383       }
384       FUN_tool_mkBnd2d(wi(1), F, Bnd2d(1));      
385       Standard_Boolean OUTall = Standard_False;
386       Standard_Boolean oneINother = Standard_False; 
387       Standard_Integer sma,gre; // dummy if !oneINother
388
389       for (; itmap.More(); itmap.Next()) {      
390         wi(2) = itmap.Key();
391         if (wi(1).IsSame(wi(2))) continue;
392         FUN_tool_mkBnd2d(wi(2), F, Bnd2d(2));
393
394         // sta : wi(1) / wi(2)
395         Standard_Integer sta = FUN_tool_classiBnd2d(Bnd2d);
396         nite++;
397         if ((sta == SAME)||(sta == UNKNOWN)) sta = FUN_tool_classiwithp2d(wi);
398 #ifdef DEB      
399         if (trc) {cout<<"#wi :";FUN_tool_coutsta(sta,FUN_adds(wi(1)),FUN_adds(wi(2)));}
400 #endif          
401         if ((sta == SAME)||(sta == UNKNOWN)) return Standard_False;      
402         if ((sta == DIFF) && itmap.More()) {OUTall = Standard_True; continue;}// w(1) OUT w(2)    
403         sma = (sta == oneINtwo) ? 1 : 2;
404         gre = (sta == oneINtwo) ? 2 : 1;        
405         oneINother = Standard_True;
406         break;
407       } // itmap
408
409       if (oneINother) {
410         // Updating map <complWoldw> with : 
411         //  - key = wi(gre), 
412         //    item += wi(sma) && item += item(wi(sma))
413         //  - unbinding key = (wi(sma))
414         TopTools_ListOfShape& lwgre = complWoldw.ChangeFind(wi(gre));
415         lwgre.Append(wi(sma));    
416         TopTools_ListIteratorOfListOfShape itwsma(complWoldw.Find(wi(sma)));
417         for (; itwsma.More(); itwsma.Next()) lwgre.Append(itwsma.Value());
418         complWoldw.UnBind(wi(sma));
419       }
420       else if (OUTall) {mapWlow.Bind(wi(1),emptylos); complWoldw.UnBind(wi(1));}
421       else return Standard_False;
422
423       ncompl = complWoldw.Extent();
424       go = (ncompl >= 1);
425     }
426     return Standard_True;
427   } // oneoldW
428
429
430   // -------------
431   // * noldW > 1 :
432   // -------------
433   for (; ite.More(); ite.Next()){
434     const TopoDS_Wire& oldwi = TopoDS::Wire(ite.Key());
435     const TopTools_ListOfShape& low = ite.Value();
436     TopTools_ListIteratorOfListOfShape itlow(low);
437     if (low.IsEmpty()) mapWlow.Bind(oldwi, emptylos);
438     else
439       for (; itlow.More(); itlow.Next()) mapWlow.Bind(itlow.Value(), emptylos);
440     oldW.Append(oldwi);
441   }
442     
443   // classifying wires of <mapoldWnewW> :
444   // -----------------------------------
445   // <Owi>            : old wires
446   // <OBnd2d>         : old wires' bounding boxes
447   // <Owhassp>(k) : Owi(k) has splits
448
449   TopTools_ListOfShape oldWcopy; oldWcopy.Assign(oldW); 
450   for (TopTools_ListIteratorOfListOfShape itoldW(oldW); itoldW.More(); itoldW.Next()) { 
451  
452     TopTools_Array1OfShape Owi(1,2);
453     Bnd_Array1OfBox2d OBnd2d(1,2);
454     TColStd_Array1OfBoolean Owhassp(1,2);
455
456     Owi(1) = itoldW.Value();
457     if (oldWcopy.Extent() <1) break; 
458     oldWcopy.RemoveFirst();
459     
460     Owhassp(1) = !mapoldWnewW.Find(Owi(1)).IsEmpty();
461     Standard_Boolean Owi1notkey = !mapWlow.IsBound(Owi(1));
462     if (Owi1notkey && !Owhassp(1)) continue;
463     
464     FUN_tool_mkBnd2d(Owi(1), F, OBnd2d(1));      
465
466     // Classifying oldwire(i) with oldwires(j): j = i+1..nwiresofF 
467     Standard_Integer osma,ogre,osta;
468     TopTools_ListIteratorOfListOfShape itoldWcopy(oldWcopy);
469     for (; itoldWcopy.More(); itoldWcopy.Next()) {
470
471       TopTools_Array1OfListOfShape newwi(1,2); 
472       Owi(2) = TopoDS::Wire(itoldWcopy.Value()); 
473       Standard_Boolean Owi2notkey = !mapWlow.IsBound(Owi(2));
474       Owhassp(2) = !mapoldWnewW.Find(Owi(2)).IsEmpty(); 
475       if (Owi2notkey && !Owhassp(2)) continue;  
476       FUN_tool_mkBnd2d(Owi(2), F, OBnd2d(2));
477       
478       // <osma>, <ogre> :
479       // ----------------
480       // Classifying Ow<i> with Ow<j> :
481       osta = FUN_tool_classiBnd2d(OBnd2d);
482       if ((osta == SAME)||(osta == UNKNOWN)) osta = FUN_tool_classiwithp2d(Owi);
483 #ifdef DEB      
484       if (trc) {cout<<"wi : "; FUN_tool_coutsta(osta,FUN_adds(Owi(1)),FUN_adds(Owi(2)));}
485 #endif          
486       if ((osta == SAME)||(osta == UNKNOWN)) return Standard_False;      
487       if (osta == DIFF)                    continue; // Ow(1), Ow(2) are disjoint               
488       // Owi<sma> is IN Owi<grea>
489       osma = (osta == oneINtwo) ? 1 : 2;
490       ogre = (osta == oneINtwo) ? 2 : 1;
491
492       // Owhassp<k>  : newwi<k> = splits (Owi<k>)
493       // !Owhassp<k> : newwi<k> = Owi<k> 
494       for (Standard_Integer i = 1; i <= 2; i++) {
495         const TopoDS_Shape& owi = Owi(i);
496         if (!Owhassp(i)) newwi(i).Append(owi);
497         else             newwi(i) = mapoldWnewW.Find(owi);
498       }
499
500       //
501       // classifying wires of newwi<sma> with wires of newwi<gre> :
502       //
503       Standard_Integer sta, sma, gre;
504       TopTools_ListIteratorOfListOfShape itnwi(newwi(osma));
505       for (; itnwi.More(); itnwi.Next()) {
506         // <wi>    : new wires
507         // <Bnd2d> : new wires' bounding boxes
508         TopTools_Array1OfShape wi(1,2);
509         Bnd_Array1OfBox2d Bnd2d(1,2);
510         
511         wi(1) = itnwi.Value(); // wi(1) in {newwi(osma)}
512         Standard_Boolean wi1notkey = !mapWlow.IsBound(wi(1));
513         if (wi1notkey) continue;
514
515         if (!Owhassp(osma)) Bnd2d(1).Add(OBnd2d(osma));
516         else               FUN_tool_mkBnd2d(wi(1), F, Bnd2d(1));
517         
518         TopTools_ListIteratorOfListOfShape itnwj(newwi(ogre));
519         for (; itnwj.More(); itnwj.Next()) {
520
521           wi(2) = itnwj.Value(); // wi(2) in {newwi(ogre)}
522           Standard_Boolean wi2notkey = !mapWlow.IsBound(wi(2));
523           if (wi2notkey) continue;
524
525           // empty the bounding box
526           Bnd_Box2d newB2d;       
527           if (!Owhassp(ogre)) newB2d.Add(OBnd2d(ogre));
528           else                FUN_tool_mkBnd2d(wi(2), F, newB2d);
529            FUN_tool_UpdateBnd2d(Bnd2d(2),newB2d);
530
531           // Classifying wi(1)  with wi(2) :
532           sta = FUN_tool_classiBnd2d(Bnd2d); 
533 #ifdef DEB
534           if (trc) {cout<<"wi : "; FUN_tool_coutsta(sta,STATIC_mapw.FindIndex(wi(1)),
535                                                     STATIC_mapw.FindIndex(wi(2)));}
536 #endif
537           if ((sta == SAME)||(sta == UNKNOWN)) sta = FUN_tool_classiwithp2d(wi);
538           if ((sta == SAME)||(sta == UNKNOWN)) return Standard_False;
539           if (sta == DIFF)                   continue;  
540           // wi<sma> is IN wi<grea>
541           sma = (sta == oneINtwo) ? 1 : 2;
542           gre = (sta == oneINtwo) ? 2 : 1;      
543           
544           // Updating map <mapWlow> with : 
545           //  - key = wi(gre), 
546           //    item += wi(sma) && item += item(wi(sma))
547           //  - unbinding key = (wi(sma))
548           TopTools_ListOfShape& lwgre = mapWlow.ChangeFind(wi(gre));
549           lwgre.Append(wi(sma));          
550           TopTools_ListIteratorOfListOfShape itwsma(mapWlow.Find(wi(sma)));
551           for (; itwsma.More(); itwsma.Next()) lwgre.Append(itwsma.Value());
552           mapWlow.UnBind(wi(sma));          
553           break; 
554           // wi<sma> IN wi<gre>, wi<sma> is OUT {newwi<gre>} / wi<gre>
555           // wi<sma> is classified / all newwires.
556         } 
557       } // itnwi(newwi(sma))
558     }// itoldWcopy   
559   } // itoldW 
560   return Standard_True;
561 }
562 // ------------------------------------------------------------
563 // -------------------- building up faces ---------------------
564 // ------------------------------------------------------------
565
566 Standard_EXPORT Standard_Boolean FUN_tool_MakeFaces(const TopoDS_Face& theFace,
567                                        TopTools_DataMapOfShapeListOfShape& mapWlow,
568                                        TopTools_ListOfShape& aListOfFaces)
569 {
570 #ifdef DEB
571   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA();
572   if (trc) cout<<"** MakeFaces :"<<endl;
573 #endif
574   Standard_Boolean toreverse = M_REVERSED(theFace.Orientation());
575   TopoDS_Face F = TopoDS::Face(theFace.Oriented(TopAbs_FORWARD));
576   BRep_Builder BB;
577
578   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(mapWlow);
579   for (; itm.More(); itm.Next()) {
580     const TopoDS_Wire& wi = TopoDS::Wire(itm.Key());  
581     TopoDS_Shape FF = F.EmptyCopied(); BB.Add(FF,wi);
582 //    BB.MakeFace(FF); // put a TShape
583       
584     TopTools_ListIteratorOfListOfShape itlow(itm.Value());      
585     for (; itlow.More(); itlow.Next()) {
586       const TopoDS_Wire& wwi = TopoDS::Wire(itlow.Value());
587       BB.Add(FF,wwi);
588     }
589
590     if (toreverse) FF.Orientation(TopAbs_REVERSED);
591     aListOfFaces.Append(FF);
592   }
593
594 #ifdef DEB
595   if (trc) {
596     cout<<"sp(fa"<<FUN_adds(theFace)<<")=";
597     TopTools_ListIteratorOfListOfShape it(aListOfFaces);
598     for (; it.More(); it.Next()) cout<<" fa"<<FUN_adds(it.Value());
599     cout<<endl;
600   }
601 #endif
602
603   return Standard_True;
604 }*/
605
606 Standard_EXPORT Standard_Boolean FUN_tool_ClassifW(const TopoDS_Face& F,
607                                       const TopTools_DataMapOfShapeListOfShape& mapOwNw,
608                                       TopTools_DataMapOfShapeListOfShape& mapWlow)
609 {  
610 #ifdef DEB
611   Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA();
612   if (trc) cout<<"** ClassifW :"<<endl;
613 #endif  
614   Standard_Real tolF = BRep_Tool::Tolerance(F);
615   Standard_Real toluv = TopOpeBRepTool_TOOL::TolUV(F,tolF);
616   TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);  
617   TopoDS_Face FFOR = TopoDS::Face(aLocalShape);
618 //  TopoDS_Face FFOR = TopoDS::Face(F.Oriented(TopAbs_FORWARD));
619   TopOpeBRepTool_CLASSI CLASSI; CLASSI.Init2d(FFOR);
620
621   TopTools_ListOfShape null;
622   TopTools_ListOfShape oldW;
623   Standard_Integer noldW = mapOwNw.Extent();
624   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(mapOwNw);
625   
626   // noldW = 1
627   // ---------
628   if (noldW == 1) {
629 #ifdef DEB
630     const TopoDS_Shape& owi =
631 #endif  
632                      itm.Key(); // DEB
633     const TopTools_ListOfShape& low = itm.Value();
634     Standard_Boolean ok = CLASSI.Classilist(low,mapWlow);
635     if (!ok) return Standard_False;
636     return Standard_True;
637   }
638
639   // noldW > 1
640   // ---------
641   TopTools_ListOfShape lOws;
642   for (; itm.More(); itm.Next()){
643     const TopoDS_Shape& owi = itm.Key(); 
644     lOws.Append(owi);
645     const TopTools_ListOfShape& low = itm.Value();
646     TopTools_ListOfShape lwresu; FUN_addOwlw(owi,low,lwresu);
647     TopTools_ListIteratorOfListOfShape itw(lwresu);
648     for (; itw.More(); itw.Next()) mapWlow.Bind(itw.Value(), null);    
649   }//itm(mapOwNw)
650
651   TopTools_MapOfShape mapdone;
652   Standard_Integer nOw = noldW;
653   Standard_Integer nite = 0, nitemax = Standard_Integer(nOw*(nOw-1)/2);
654   while (nite <= nitemax){
655     nOw = lOws.Extent();
656     if (nOw == 0) break;
657
658     TopTools_ListIteratorOfListOfShape itOw(lOws);
659     const TopoDS_Shape& Ow1 = itOw.Value();
660     Standard_Boolean isb1 = mapWlow.IsBound(Ow1);
661     isb1 = isb1 || !mapdone.Contains(Ow1);
662     if (!isb1) continue; 
663
664     const TopTools_ListOfShape& lw1 = mapOwNw.Find(Ow1);
665 #ifdef DEB
666     Standard_Integer nw1 =
667 #endif
668               lw1.Extent();
669     if (nOw == 1) { 
670       // all wires of <mapWs> have been treated, except the last one
671       // if (nw1 == 0) mapWlow binds already (Ow1,null); 
672       // else         {mapWlow binds already (w1k,null), w1k in lw1} 
673       break;
674     }//nOw == 1
675
676     itOw.Next();
677     Standard_Boolean OUTall = Standard_False;
678     TopoDS_Shape Ow2;
679     Standard_Integer sta12 = UNKNOWN;
680     for (; itOw.More(); itOw.Next()){
681       Ow2 = itOw.Value();
682       Standard_Boolean isb2 = mapWlow.IsBound(Ow2);
683       isb2 = isb2 || !mapdone.Contains(Ow2);
684       if (!isb2) continue;
685       Standard_Integer stabnd2d12 = CLASSI.ClassiBnd2d(Ow1,Ow2,toluv,Standard_True);
686       sta12 = CLASSI.Classip2d(Ow1,Ow2, stabnd2d12);
687       if      (sta12 == DIFF)                       {OUTall = Standard_True; continue;}
688       else if ((sta12 == UNKNOWN)||(sta12 == SAME)) return Standard_False;
689       break;
690     }
691     if (OUTall) {
692       // if (nw1 == 0) mapWlow binds already (Ow1,null); 
693       // else         {mapWlow binds already (w1k,null), w1k in lw1} 
694       TopTools_ListOfShape ldone; FUN_addOwlw(Ow1,lw1,ldone);
695       TopTools_ListIteratorOfListOfShape itw(ldone);
696       for (; itw.More(); itw.Next()) mapdone.Add(itw.Value());
697 #ifdef DEB
698       if (trc) cout<<"old wires :wi"<<FUN_adds(Ow1)<<" is OUT all old wires"<<endl;
699 #endif      
700       lOws.RemoveFirst();
701     }//OUTall    
702     else {
703 #ifdef DEB
704       if (trc) {cout<<"old wires :wi -> ";
705                 FUN_tool_coutsta(sta12,FUN_adds(Ow1),FUN_adds(Ow2));
706                 cout<<endl;}
707 #endif
708       const TopTools_ListOfShape& lw2 = mapOwNw.Find(Ow2);
709 #ifdef DEB
710       Standard_Integer nw2 =
711 #endif
712                 lw2.Extent();
713      
714       TopTools_ListOfShape lw1r; FUN_addOwlw(Ow1,lw1,lw1r);
715       TopTools_ListOfShape lw2r; FUN_addOwlw(Ow2,lw2,lw2r);
716       TopTools_ListOfShape lgre,lsma;
717       if (sta12 == oneINtwo) {lgre.Append(lw2r); lsma.Append(lw1r);}
718       if (sta12 == twoINone) {lgre.Append(lw1r); lsma.Append(lw2r);}
719       
720       TopTools_ListIteratorOfListOfShape itsma(lsma);
721       for (; itsma.More(); itsma.Next()){
722         const TopoDS_Shape& wsma = itsma.Value();
723         Standard_Boolean isbsma = mapWlow.IsBound(wsma);
724         isbsma = isbsma || !mapdone.Contains(wsma);
725         if (!isbsma) continue;
726         
727         TopTools_ListIteratorOfListOfShape itgre(lgre);
728         for (; itgre.More(); itgre.Next()){
729           const TopoDS_Shape& wgre = itgre.Value();
730           Standard_Boolean isbgre = mapWlow.IsBound(wgre);
731           isbgre = isbgre || !mapdone.Contains(wgre);
732           if (!isbgre) continue;
733         
734           Standard_Integer stabnd2d = CLASSI.ClassiBnd2d(wsma,wgre,toluv,Standard_True);
735           Standard_Integer sta = CLASSI.Classip2d(wsma,wgre, stabnd2d);
736 #ifdef DEB
737       if (trc) {cout<<" wires :wi -> ";
738                 FUN_tool_coutsta(sta,FUN_adds(wsma),FUN_adds(wgre));
739                 cout<<endl;}
740 #endif
741         
742           if      (sta == DIFF) continue;
743           else if (sta == oneINtwo) {// wsma IN wgre
744             mapWlow.ChangeFind(wgre).Append(mapWlow.ChangeFind(wsma));
745             mapWlow.UnBind(wsma);
746           }
747           else if (sta == twoINone) {// wgre IN wsma
748             mapWlow.ChangeFind(wsma).Append(mapWlow.ChangeFind(wgre));
749             mapWlow.UnBind(wgre);
750           }
751           else return Standard_False;
752         }//itgre
753       }//itsma
754       lOws.RemoveFirst(); 
755     } //!OUTall
756   }//nite
757   return Standard_True;
758 }
759
760 //=======================================================================
761 //function : RegularizeFace
762 //purpose  : 
763 //=======================================================================
764
765 Standard_Boolean TopOpeBRepTool::RegularizeFace(const TopoDS_Face& theFace,
766                                    const TopTools_DataMapOfShapeListOfShape& mapoldWnewW,
767                                    TopTools_ListOfShape& newFaces) 
768 {  
769   // <mapWlow> 
770   // ---------
771   // key = wire <w>,
772   // item = if the new face has holes, the item contains wires
773   //        classified IN the area described by the boundary <w>
774   //        on <aFace>,
775   //        else : the item is an empty list, <w> describes the
776   //        whole new face.  
777   TopTools_DataMapOfShapeListOfShape mapWlow;
778   
779   // Classifying  wires :
780   // -------------------
781   //  Standard_Boolean classifok = FUN_tool_ClassifW(theFace, mapoldWnewW, mapWlow);
782   TopoDS_Shape aLocalShape = theFace.Oriented(TopAbs_FORWARD);
783   TopoDS_Face aFace = TopoDS::Face(aLocalShape);
784 //  TopoDS_Face aFace = TopoDS::Face(theFace.Oriented(TopAbs_FORWARD));
785   
786   Standard_Boolean classifok = FUN_tool_ClassifW(aFace, mapoldWnewW, mapWlow);  
787   if (!classifok) return Standard_False;
788   
789   // <aListOfFaces>
790   // -------------  
791   Standard_Boolean facesbuilt = TopOpeBRepTool_TOOL::WireToFace(theFace, mapWlow, newFaces); 
792   if (!facesbuilt) return Standard_False;  
793   return Standard_True;
794 }