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