0023024: Update headers of OCCT files
[occt.git] / src / BRepAlgo / BRepAlgo_Loop.cxx
1 // Created on: 1995-11-10
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #include <stdio.h>
23
24 #include <BRepAlgo_Loop.ixx>
25
26 #include <BRep_Builder.hxx>
27 #include <BRepAlgo_FaceRestrictor.hxx>
28 #include <BRep_Tool.hxx>
29
30 #include <Geom2d_Curve.hxx>
31 #include <Geom_Surface.hxx>
32 #include <TopExp.hxx>
33 #include <TopTools_SequenceOfShape.hxx>
34 #include <TopTools_MapOfShape.hxx>
35 #include <TopTools_ListIteratorOfListOfShape.hxx>
36 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
37
38 #include <TopoDS.hxx>
39 #include <TopoDS_Vertex.hxx>
40 #include <TopoDS_Wire.hxx>
41 #include <gp_Pnt.hxx>
42 #include <gp_Pnt2d.hxx>
43 #include <Precision.hxx>
44 #include <BRep_TVertex.hxx>
45 #include <BRep_TEdge.hxx>
46 #include <TopExp_Explorer.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
49
50 #ifdef DRAW
51 #include <DBRep.hxx>
52 #endif
53 #ifdef DEB
54 Standard_Boolean AffichLoop  = Standard_False;
55 Standard_Integer NbLoops     = 0;
56 Standard_Integer NbWires     = 1;
57 static char* name = new char[100];
58 #endif
59
60 //=======================================================================
61 //function : BRepAlgo_Loop
62 //purpose  : 
63 //=======================================================================
64
65 BRepAlgo_Loop::BRepAlgo_Loop()
66 {
67 }
68
69
70 //=======================================================================
71 //function : Init
72 //purpose  : 
73 //=======================================================================
74
75 void BRepAlgo_Loop::Init(const TopoDS_Face& F)
76 {
77   myConstEdges.Clear(); 
78   myVerOnEdges.Clear();
79   myNewWires  .Clear();
80   myNewFaces  .Clear();
81   myNewEdges  .Clear();
82   myFace = F;
83 }
84
85
86 //=======================================================================
87 //function : Bubble
88 //purpose  : Orders the sequence of vertices by increasing parameter. 
89 //=======================================================================
90
91 static void Bubble(const TopoDS_Edge&        E,
92                    TopTools_SequenceOfShape& Seq) 
93 {
94   Standard_Boolean Invert   = Standard_True;
95   Standard_Integer NbPoints = Seq.Length();
96   Standard_Real    U1,U2;
97   TopoDS_Vertex    V1,V2;
98
99   while (Invert) {
100     Invert = Standard_False;
101     for ( Standard_Integer i = 1; i < NbPoints; i++) {
102       TopoDS_Shape aLocalV = Seq.Value(i)  .Oriented(TopAbs_INTERNAL);
103       V1 = TopoDS::Vertex(aLocalV);
104       aLocalV = Seq.Value(i+1).Oriented(TopAbs_INTERNAL);
105       V2 = TopoDS::Vertex(aLocalV);
106 //      V1 = TopoDS::Vertex(Seq.Value(i)  .Oriented(TopAbs_INTERNAL));
107 //      V2 = TopoDS::Vertex(Seq.Value(i+1).Oriented(TopAbs_INTERNAL));
108
109       U1 = BRep_Tool::Parameter(V1,E);
110       U2 = BRep_Tool::Parameter(V2,E);
111       if (U2 < U1) {
112         Seq.Exchange(i,i+1);
113         Invert = Standard_True;
114       }
115     }
116   }
117 }
118
119
120
121 //=======================================================================
122 //function : AddEdges
123 //purpose  : 
124 //=======================================================================
125
126 void BRepAlgo_Loop::AddEdge (TopoDS_Edge&                E, 
127                              const TopTools_ListOfShape& LV)
128 {
129   myVerOnEdges.Bind(E,LV);
130 }
131
132
133 //=======================================================================
134 //function : AddConstEdges
135 //purpose  : 
136 //=======================================================================
137
138 void BRepAlgo_Loop::AddConstEdge (const TopoDS_Edge& E)
139 {
140   myConstEdges.Append(E);
141 }
142
143 //=======================================================================
144 //function : AddConstEdges
145 //purpose  : 
146 //=======================================================================
147
148 void BRepAlgo_Loop::AddConstEdges(const TopTools_ListOfShape& LE)
149 {
150   TopTools_ListIteratorOfListOfShape itl(LE);
151   for (; itl.More(); itl.Next()) {
152     myConstEdges.Append(itl.Value());
153   }
154 }
155
156
157 //=======================================================================
158 //function : UpdateClosedEdge
159 //purpose  : If the first or the last vertex of intersection
160 //           coincides with the closing vertex, it is removed from SV.
161 //           it will be added at the beginning and the end of SV by the caller.
162 //=======================================================================
163
164 static TopoDS_Vertex  UpdateClosedEdge(const TopoDS_Edge&         E,
165                                        TopTools_SequenceOfShape&  SV)
166 {
167   TopoDS_Vertex    VB [2], V1, V2, VRes;
168   gp_Pnt           P,PC;
169   Standard_Boolean OnStart = 0, OnEnd = 0;
170   //// modified by jgv, 13.04.04 for OCC5634 ////
171   TopExp::Vertices (E,V1,V2);
172   //Standard_Real    Tol = Precision::Confusion();
173   Standard_Real    Tol = BRep_Tool::Tolerance( V1 );
174   ///////////////////////////////////////////////
175   
176   if (SV.IsEmpty()) return VRes;
177
178   VB[0] = TopoDS::Vertex(SV.First());
179   VB[1] = TopoDS::Vertex(SV.Last ());
180   PC = BRep_Tool::Pnt(V1);
181
182   for ( Standard_Integer i = 0 ; i < 2 ; i++) {
183     P = BRep_Tool::Pnt(VB [i]);
184     if (P.IsEqual(PC,Tol)) {
185       VRes = VB [i];
186       if (i == 0) OnStart = Standard_True;
187       else        OnEnd   = Standard_True;
188     }
189   }
190   if (OnStart && OnEnd) {
191     if (!VB[0].IsSame(VB[1])) {
192 #ifdef DEB
193       if (AffichLoop)
194         cout <<"Two different vertices on the closing vertex"<<endl;
195 #endif
196     }
197     else {
198       SV.Remove(1);
199       if (!SV.IsEmpty()) SV.Remove(SV.Length());
200     }
201   }
202   else if (OnStart) SV.Remove(1);
203   else if (OnEnd  ) SV.Remove(SV.Length());
204
205   return VRes;
206 }
207
208
209
210 //=======================================================================
211 //function : RemovePendingEdges
212 //purpose  : 
213 //=======================================================================
214
215 static void RemovePendingEdges(TopTools_DataMapOfShapeListOfShape& MVE)
216 {
217   //--------------------------------
218   // Remove hanging edges.
219   //--------------------------------
220   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;
221   TopTools_ListOfShape                     ToRemove;
222   TopTools_ListIteratorOfListOfShape       itl;
223   Standard_Boolean                         YaSupress = Standard_True;
224   TopoDS_Vertex                            V1,V2;
225   
226   while (YaSupress) {
227     YaSupress = Standard_False;
228     TopTools_ListOfShape VToRemove;
229     TopTools_MapOfShape  EToRemove;
230
231     for (Mapit.Initialize(MVE); Mapit.More(); Mapit.Next()) {
232
233       if (Mapit.Value().IsEmpty()) {
234         VToRemove.Append(Mapit.Key());
235       }
236       if (Mapit.Value().Extent() == 1) {
237         const TopoDS_Edge& E = TopoDS::Edge(Mapit.Value().First());
238         TopExp::Vertices(E,V1,V2) ;
239         if (!V1.IsSame(V2)) {
240           VToRemove.Append(Mapit.Key());
241           EToRemove.Add(Mapit.Value().First());
242         }
243       }
244     }
245     
246     if (!VToRemove.IsEmpty()) {
247       YaSupress = Standard_True;
248       for (itl.Initialize(VToRemove); itl.More(); itl.Next()) {
249         MVE.UnBind(itl.Value());
250       }
251       if (!EToRemove.IsEmpty()) {
252         for (Mapit.Initialize(MVE); Mapit.More(); Mapit.Next()) {
253           TopTools_ListOfShape& LE = MVE.ChangeFind(Mapit.Key());
254           itl.Initialize(LE);
255           while (itl.More()) {
256             if (EToRemove.Contains(itl.Value())) {
257               LE.Remove(itl);
258             }
259             else itl.Next();
260           }
261         }
262       }
263     } 
264   }
265 }
266 //=======================================================================
267 //function : SamePnt2d
268 //purpose  : 
269 //=======================================================================
270
271 static Standard_Boolean  SamePnt2d(TopoDS_Vertex  V,
272                                    TopoDS_Edge&   E1,
273                                    TopoDS_Edge&   E2,
274                                    TopoDS_Face&   F)
275 {
276   Standard_Real   f1,f2,l1,l2;
277   gp_Pnt2d        P1,P2;
278   TopoDS_Shape aLocalF = F.Oriented(TopAbs_FORWARD);
279   TopoDS_Face FF = TopoDS::Face(aLocalF);
280 //  TopoDS_Face FF = TopoDS::Face(F.Oriented(TopAbs_FORWARD));
281   Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1,FF,f1,l1);  
282   Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E2,FF,f2,l2);  
283   if (E1.Orientation () == TopAbs_FORWARD) P1 = C1->Value(f1);
284   else                                     P1 = C1->Value(l1);
285   
286   if (E2.Orientation () == TopAbs_FORWARD) P2 = C2->Value(l2);
287   else                                     P2 = C2->Value(f2);
288   Standard_Real Tol  = 100*BRep_Tool::Tolerance(V);
289   Standard_Real Dist = P1.Distance(P2);
290   return Dist < Tol; 
291 }
292
293 //=======================================================================
294 //function : SelectEdge
295 //purpose  : Find edge <NE> connected to <CE> by vertex <CV> in the
296 //           list <LE>. <NE> is removed from the list. If <CE> is 
297 //           also in the list <LE> with the same orientation, it is
298 //           removed from the list.
299 //=======================================================================
300
301 static Standard_Boolean  SelectEdge(const TopoDS_Face&    F,
302                                     const TopoDS_Edge&    CE,
303                                     const TopoDS_Vertex&  CV,
304                                     TopoDS_Edge&          NE,
305                                     TopTools_ListOfShape& LE)
306 {
307   TopTools_ListIteratorOfListOfShape itl;
308   NE.Nullify();
309 #ifdef DEB  
310   if (AffichLoop) {
311     if ( LE.Extent() > 2) {
312       cout <<"vertex on more than 2 edges in a face."<<endl;
313     }
314   }
315 #endif
316   for ( itl.Initialize(LE); itl.More(); itl.Next()) {
317     if (itl.Value().IsEqual(CE)) {
318       LE.Remove(itl);
319       break;
320     }
321   }
322   if (LE.Extent() > 1) {
323     //--------------------------------------------------------------
324     // Several edges possible.  
325     // - Test edges different from CE , Selection of edge
326     // for which CV has U,V closer to the face
327     // than corresponding to CE.
328     // - If several edges give representation less than the tolerance.
329     // discrimination on tangents.
330     //--------------------------------------------------------------
331     TopLoc_Location L;
332     Standard_Real   f,l;
333     TopoDS_Face FForward = F;
334     FForward.Orientation(TopAbs_FORWARD);
335
336     Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(CE,FForward,f,l);
337     Standard_Integer k = 1, kmin = 0;
338     Standard_Real    dist,distmin  = 100*BRep_Tool::Tolerance(CV);
339     Standard_Real    u ;
340     if (CE.Orientation () == TopAbs_FORWARD) u = l;
341     else                                     u = f;
342
343     gp_Pnt2d         P2,PV = C->Value(u); 
344     
345     for ( itl.Initialize(LE); itl.More(); itl.Next()) {
346       const TopoDS_Edge& E = TopoDS::Edge(itl.Value());
347       if (!E.IsSame(CE)) {
348         C    = BRep_Tool::CurveOnSurface(E,FForward,f,l);
349         if (E.Orientation () == TopAbs_FORWARD) u = f;
350         else                                    u = l;
351         P2   = C->Value(u); 
352         dist = PV.Distance(P2);
353         if ( dist <= distmin) {
354           kmin    = k;
355           distmin = dist;
356         }
357       }
358       k++;
359     }
360     if (kmin == 0) return Standard_False;
361
362     k = 1; itl.Initialize(LE);
363     while (k < kmin) {k++; itl.Next();}
364     NE = TopoDS::Edge(itl.Value());
365     LE.Remove(itl);
366   }
367   else if (LE.Extent() == 1) {
368     NE = TopoDS::Edge(LE.First());
369     LE.RemoveFirst();
370   }
371   else {
372     return Standard_False;
373   }
374 #ifdef DRAW
375   if (AffichLoop) {  
376     DBRep::Set("Selected",NE);
377   }
378
379 #endif
380   return Standard_True;
381 }
382 //=======================================================================
383 //function : Store
384 //purpose  : 
385 //=======================================================================
386
387 static void  PurgeNewEdges(TopTools_DataMapOfShapeListOfShape& NewEdges,
388                            const TopTools_MapOfShape&          UsedEdges)
389 {
390   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it(NewEdges);
391   for (; it.More(); it.Next()) {
392     TopTools_ListOfShape& LNE = NewEdges.ChangeFind(it.Key());
393     TopTools_ListIteratorOfListOfShape itL(LNE);
394     while (itL.More()) {
395       const TopoDS_Shape& NE = itL.Value();
396       if (!UsedEdges.Contains(NE)) {
397         LNE.Remove(itL);
398       }
399       else {
400         itL.Next();
401       }
402     }
403   }
404   
405 }
406
407 //=======================================================================
408 //function : Store
409 //purpose  : 
410 //=======================================================================
411
412 static void StoreInMVE (const TopoDS_Face&                  F,
413                         TopoDS_Edge&                  E,
414                         TopTools_DataMapOfShapeListOfShape& MVE,
415                         Standard_Boolean&                   YaCouture,
416                         TopTools_DataMapOfShapeShape& VerticesForSubstitute )
417 {      
418   TopoDS_Vertex V1, V2, V;
419   TopTools_ListOfShape Empty;
420   
421   Standard_Real Tol = 0.001; //5.e-05; //5.e-07;
422 //  gp_Pnt P1, P2, P;
423   gp_Pnt P1, P;
424   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;
425   BRep_Builder BB;
426   for (Mapit.Initialize( MVE ); Mapit.More(); Mapit.Next())
427     {
428       V = TopoDS::Vertex( Mapit.Key() );
429       P = BRep_Tool::Pnt( V );
430       TopTools_ListOfShape VList;
431       TopoDS_Iterator VerExp( E );
432       for (; VerExp.More(); VerExp.Next())
433         VList.Append( VerExp.Value() );
434       TopTools_ListIteratorOfListOfShape itl( VList );
435       for (; itl.More(); itl.Next())
436         {
437           V1 = TopoDS::Vertex( itl.Value() );
438           P1 = BRep_Tool::Pnt( V1 );
439           if (P.IsEqual( P1, Tol ) && !V.IsSame(V1))
440             {
441               V.Orientation( V1.Orientation() );
442               if (VerticesForSubstitute.IsBound( V1 ))
443                 {
444                   TopoDS_Shape OldNewV = VerticesForSubstitute( V1 );
445                   if (! OldNewV.IsSame( V ))
446                     {
447                       VerticesForSubstitute.Bind( OldNewV, V );
448                       VerticesForSubstitute( V1 ) = V;
449                     }
450                 }
451               else
452                 {
453                   if (VerticesForSubstitute.IsBound( V ))
454                     {
455                       TopoDS_Shape NewNewV = VerticesForSubstitute( V );
456                       if (! NewNewV.IsSame( V1 ))
457                         VerticesForSubstitute.Bind( V1, NewNewV );
458                     }
459                   else
460                     {
461                       VerticesForSubstitute.Bind( V1, V );
462                       TopTools_DataMapIteratorOfDataMapOfShapeShape mapit( VerticesForSubstitute );
463                       for (; mapit.More(); mapit.Next())
464                         if (mapit.Value().IsSame( V1 ))
465                           VerticesForSubstitute( mapit.Key() ) = V;
466                     }
467                 }
468               E.Free( Standard_True );
469               BB.Remove( E, V1 );
470               BB.Add( E, V );
471             }
472         }
473     }
474
475   TopExp::Vertices(E,V1,V2);
476   if( V1.IsNull() && V2.IsNull() ){ YaCouture = Standard_False; return; }
477   if (!MVE.IsBound(V1)) {
478     MVE.Bind(V1,Empty);
479   }
480   MVE(V1).Append(E);
481   if (!V1.IsSame(V2)) {
482      if (!MVE.IsBound(V2)) {
483       MVE.Bind(V2,Empty);
484     }
485     MVE(V2).Append(E);
486   }
487   TopLoc_Location L ;
488   Handle(Geom_Surface) S = BRep_Tool::Surface(F,L);
489   if (BRep_Tool::IsClosed(E,S,L)) {
490     MVE(V2).Append(E.Reversed());
491     if (!V1.IsSame(V2)) {
492       MVE(V1).Append(E.Reversed());
493     }
494     YaCouture = Standard_True;
495   }
496 }
497
498 //=======================================================================
499 //function : Perform
500 //purpose  : 
501 //=======================================================================
502
503 void BRepAlgo_Loop::Perform()
504 {
505   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;  
506   TopTools_ListIteratorOfListOfShape                  itl;
507   TopoDS_Vertex                                       V1,V2;
508   Standard_Boolean                                    YaCouture = Standard_False;
509
510 #ifdef DEB
511   if (AffichLoop) {
512     cout <<"NewLoop"<<endl;
513     Standard_Integer NbEdges = 1;
514     NbLoops++;
515 #ifdef DRAW
516     sprintf(name,"FLoop_%d",NbLoops);
517     DBRep::Set(name,myFace);
518 #endif
519     for (Mapit.Initialize(myVerOnEdges); Mapit.More(); Mapit.Next()) { 
520       const TopoDS_Edge& E = TopoDS::Edge(Mapit.Key());
521 #ifdef DRAW
522       sprintf(name,"EEE_%d_%d",NbLoops,NbEdges++);
523       DBRep::Set(name,E);
524 #endif
525     }
526     for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) {
527       const TopoDS_Edge& E = TopoDS::Edge(itl.Value());    
528 #ifdef DRAW
529       sprintf(name,"EEE_%d_%d",NbLoops,NbEdges++);
530       DBRep::Set(name,E);
531 #endif
532     }
533   }
534 #endif
535   
536   //------------------------------------------------
537   // Cut edges
538   //------------------------------------------------
539   for (Mapit.Initialize(myVerOnEdges); Mapit.More(); Mapit.Next()) {
540     TopTools_ListOfShape LCE;
541
542     CutEdge (TopoDS::Edge(Mapit.Key()),Mapit.Value(), LCE);
543
544     myNewEdges.Bind(Mapit.Key(),LCE);
545   }
546   //-----------------------------------
547   // Construction map vertex => edges
548   //-----------------------------------
549   TopTools_DataMapOfShapeListOfShape MVE;
550
551   // add cut edges.
552   for (Mapit.Initialize(myNewEdges); Mapit.More(); Mapit.Next()) {
553     for (itl.Initialize(myNewEdges(Mapit.Key())); itl.More(); itl.Next()) {
554       TopoDS_Edge& E = TopoDS::Edge(itl.Value());
555       StoreInMVE(myFace,E,MVE,YaCouture,myVerticesForSubstitute);
556     }
557   }
558   
559   // add const edges
560   // Sewn edges can be doubled or not in myConstEdges
561   // => call only once StoreInMVE which should double them
562   TopTools_MapOfShape DejaVu;
563   for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) {
564     TopoDS_Edge& E = TopoDS::Edge(itl.Value());
565     if (DejaVu.Add(E))
566       StoreInMVE(myFace,E,MVE,YaCouture,myVerticesForSubstitute);
567   }
568
569 #ifdef DRAW
570   if (AffichLoop) {
571     cout <<"NewLoop"<<endl;
572     Standard_Integer NbEdges = 1;
573     TopTools_MapOfShape Done;
574     for (Mapit.Initialize(MVE); Mapit.More();Mapit.Next()) {
575       for (itl.Initialize(Mapit.Value()); itl.More(); itl.Next()) {
576         TopoDS_Edge& E = TopoDS::Edge(itl.Value());
577         if (Done.Add(E)) {
578           sprintf(name,"EEC_%d_%d",NbLoops,NbEdges++);
579           DBRep::Set(name,E);
580         }
581       }
582     }
583   }
584 #endif
585
586   //-----------------------------------------------
587   // Construction of wires and new faces. 
588   //----------------------------------------------
589   TopoDS_Vertex    VF,VL,CV;
590   TopoDS_Edge      CE,NE,EF;
591   BRep_Builder     B;
592   TopoDS_Wire      NW;
593   Standard_Boolean End;
594
595   TopTools_MapOfShape UsedEdges;
596
597   while (!MVE.IsEmpty()) {
598     B.MakeWire(NW);
599     //--------------------------------
600     // Removal of hanging edges.
601     //--------------------------------
602     RemovePendingEdges(MVE);
603
604     if (MVE.IsEmpty()) break; 
605     //--------------------------------
606     // Start edge.
607     //--------------------------------
608     Mapit.Initialize(MVE);
609     EF = CE = TopoDS::Edge(Mapit.Value().First());
610     TopExp::Vertices(CE,V1,V2);
611     //--------------------------------
612     // VF vertex start of new wire
613     //--------------------------------
614     if (CE.Orientation() == TopAbs_FORWARD) { CV = VF = V1;}
615     else                                    { CV = VF = V2;}
616     if (!MVE.IsBound(CV)) continue;
617     for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) {
618       if (itl.Value().IsEqual(CE)) {
619         MVE(CV).Remove(itl);
620         break;
621       }
622     }
623     End  = Standard_False;
624     
625     while (!End) {
626       //-------------------------------
627       // Construction of a wire.
628       //-------------------------------
629       TopExp::Vertices(CE,V1,V2);
630       if (!CV.IsSame(V1)) CV = V1; else CV = V2;
631
632       B.Add (NW,CE);
633       UsedEdges.Add(CE);
634
635       if (!MVE.IsBound(CV) || MVE(CV).IsEmpty()) {
636         End = Standard_True;
637       }
638       else {
639         End = !SelectEdge(myFace,CE,CV,NE,MVE(CV));
640         if (!End) {
641           CE = NE;
642           if (MVE(CV).IsEmpty()) MVE.UnBind(CV);
643         }       
644       }
645     }
646     //--------------------------------------------------
647     // Add new wire to the set of wires
648     //------------------------------------------------
649     Standard_Real Tol = 0.001; //5.e-05; //5.e-07;
650     TopExp_Explorer explo( NW, TopAbs_VERTEX );
651     for (; explo.More(); explo.Next())
652       {
653         const TopoDS_Vertex& aV = TopoDS::Vertex( explo.Current() );
654         Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &(aV).TShape());
655         TV->Tolerance( Tol );
656         TV->Modified( Standard_True );
657       }
658     for (explo.Init( NW, TopAbs_EDGE ); explo.More(); explo.Next())
659       {
660         const TopoDS_Edge& aE = TopoDS::Edge( explo.Current() );
661         Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &(aE).TShape());
662         TE->Tolerance( Tol );
663         TE->Modified( Standard_True );
664       }
665
666     if (VF.IsSame(CV) && SamePnt2d(VF,EF,CE,myFace))
667       myNewWires.Append (NW);
668     else {
669 #ifdef DEB
670       cout <<"BRepAlgo_Loop: Open Wire"<<endl;
671       if (AffichLoop)
672         cout << "OpenWire is : NW_"<<NbLoops<<"_"<<NbWires<<endl;
673 #endif
674     }
675 #ifdef DRAW
676     if (AffichLoop) {
677       sprintf(name,"NW_%d_%d",NbLoops,NbWires++);       
678       DBRep::Set(name,NW);
679     }
680 #endif
681   }
682   
683   PurgeNewEdges(myNewEdges,UsedEdges);
684 }
685
686 //=======================================================================
687 //function : CutEdges
688 //purpose  : 
689 //=======================================================================
690
691 void BRepAlgo_Loop::CutEdge (const TopoDS_Edge&          E,
692                              const TopTools_ListOfShape& VOnE,
693                                      TopTools_ListOfShape& NE   ) const 
694 {
695   TopoDS_Shape aLocalE  = E.Oriented(TopAbs_FORWARD);
696   TopoDS_Edge WE = TopoDS::Edge(aLocalE);
697 //  TopoDS_Edge WE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
698
699   Standard_Real                      U1,U2;
700   TopoDS_Vertex                      V1,V2;
701   TopTools_SequenceOfShape           SV;
702   TopTools_ListIteratorOfListOfShape it(VOnE);
703   BRep_Builder                       B;
704
705   for ( ; it.More(); it.Next()) {
706     SV.Append(it.Value());
707   }
708   //--------------------------------
709   // Parse vertices on the edge.
710   //--------------------------------
711   Bubble (WE,SV);
712
713   Standard_Integer NbVer = SV.Length();
714   //----------------------------------------------------------------
715   // Construction of new edges.
716   // Note :  vertices at the extremities of edges are not 
717   //         onligatorily in the list of vertices
718   //----------------------------------------------------------------
719   if (SV.IsEmpty()) {
720     NE.Append(E);
721     return;
722   }
723   TopoDS_Vertex    VF,VL;
724   Standard_Real    f,l;
725   BRep_Tool::Range(WE,f,l);
726   TopExp::Vertices(WE,VF,VL);
727
728   if (NbVer == 2) {
729     if (SV(1).IsEqual(VF) && SV(2).IsEqual(VL)) {
730       NE.Append(E);
731 #ifdef DRAW
732       if (AffichLoop) {  
733       DBRep::Set("ECOpied",E);
734     }      
735 #endif
736       return;
737     }
738   }
739   //----------------------------------------------------
740   // Processing of closed edges 
741   // If a vertex of intersection is on the common vertex
742   // it should appear at the beginning and end of SV.
743   //----------------------------------------------------
744   TopoDS_Vertex VCEI;
745   if (!VF.IsNull() && VF.IsSame(VL)) {
746     VCEI = UpdateClosedEdge(WE,SV);    
747     if (!VCEI.IsNull()) {
748       TopoDS_Shape aLocalV = VCEI.Oriented(TopAbs_FORWARD);
749       VF = TopoDS::Vertex(aLocalV);
750       aLocalV = VCEI.Oriented(TopAbs_REVERSED); 
751       VL = TopoDS::Vertex(aLocalV);
752 //      VF = TopoDS::Vertex(VCEI.Oriented(TopAbs_FORWARD));
753 //      VL = TopoDS::Vertex(VCEI.Oriented(TopAbs_REVERSED)); 
754     }
755     SV.Prepend(VF);
756     SV.Append(VL);
757   }
758   else {
759     //-----------------------------------------
760     // Eventually all extremities of the edge.
761     //-----------------------------------------
762     if (!VF.IsNull() && !VF.IsSame(SV.First())) SV.Prepend(VF);
763     if (!VL.IsNull() && !VL.IsSame(SV.Last ())) SV.Append (VL);
764   }
765
766   while (!SV.IsEmpty()) {
767     while (!SV.IsEmpty() && 
768            SV.First().Orientation() != TopAbs_FORWARD) {
769       SV.Remove(1);
770     }
771     if (SV.IsEmpty())
772       break;
773     V1  = TopoDS::Vertex(SV.First());
774     SV.Remove(1);
775     if (SV.IsEmpty())
776       break;
777     if (SV.First().Orientation() == TopAbs_REVERSED) {
778       V2  = TopoDS::Vertex(SV.First());
779       SV.Remove(1);
780       //-------------------------------------------
781       // Copy the edge and restriction by V1 V2.
782       //-------------------------------------------
783       TopoDS_Shape NewEdge = WE.EmptyCopied();
784       TopoDS_Shape aLocalEdge = V1.Oriented(TopAbs_FORWARD);
785       B.Add  (NewEdge,aLocalEdge);
786       aLocalEdge = V2.Oriented(TopAbs_REVERSED);
787       B.Add  (TopoDS::Edge(NewEdge),aLocalEdge);
788 //      B.Add  (NewEdge,V1.Oriented(TopAbs_FORWARD));
789 //      B.Add  (NewEdge,V2.Oriented(TopAbs_REVERSED));
790       if (V1.IsSame(VF)) 
791         U1 = f;
792       else 
793 //      U1=BRep_Tool::Parameter
794 //        (TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),WE);
795         {
796           TopoDS_Shape aLocalV = V1.Oriented(TopAbs_INTERNAL);
797           U1=BRep_Tool::Parameter(TopoDS::Vertex(aLocalV),WE);
798         }
799       if (V2.IsSame(VL))
800         U2 = l;
801       else
802         {
803           TopoDS_Shape aLocalV = V2.Oriented(TopAbs_INTERNAL);
804           U2=BRep_Tool::Parameter(TopoDS::Vertex(aLocalV),WE);
805 //      U2=BRep_Tool::Parameter
806 //        (TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),WE);
807         }
808       B.Range (TopoDS::Edge(NewEdge),U1,U2);
809 #ifdef DRAW
810     if (AffichLoop) {  
811       DBRep::Set("Cut",NewEdge);
812     }
813 #endif
814       NE.Append(NewEdge.Oriented(E.Orientation()));
815     }
816   }
817
818   //Remove edges with size <= tolerance
819   Standard_Real Tol = 0.001; //5.e-05; //5.e-07;
820   it.Initialize(NE);
821   while (it.More())
822     {
823       // skl : I change "E" to "EE"
824       TopoDS_Edge EE = TopoDS::Edge( it.Value() );
825       Standard_Real fpar, lpar;
826       BRep_Tool::Range( EE, fpar, lpar );
827       if (lpar - fpar <= Precision::Confusion())
828         NE.Remove(it);
829       else
830         {
831           gp_Pnt2d pf, pl;
832           BRep_Tool::UVPoints( EE, myFace, pf, pl );
833           if (pf.Distance(pl) <= Tol && !EE.Closed())
834             NE.Remove(it);
835           else
836             it.Next();
837         }
838     }
839 }
840
841 //=======================================================================
842 //function : NewWires
843 //purpose  : 
844 //=======================================================================
845
846 const TopTools_ListOfShape&  BRepAlgo_Loop::NewWires() const 
847 {  
848   return myNewWires;
849 }
850
851 //=======================================================================
852 //function : NewFaces
853 //purpose  : 
854 //=======================================================================
855
856 const TopTools_ListOfShape&  BRepAlgo_Loop::NewFaces() const 
857 {  
858   return myNewFaces;
859 }
860  
861 //=======================================================================
862 //function : WiresToFaces
863 //purpose  : 
864 //=======================================================================
865
866 void  BRepAlgo_Loop::WiresToFaces() 
867 {  
868   if (!myNewWires.IsEmpty()) {
869     BRepAlgo_FaceRestrictor FR;
870     TopoDS_Shape aLocalS = myFace.Oriented(TopAbs_FORWARD);
871     FR.Init (TopoDS::Face(aLocalS),Standard_False);
872 //    FR.Init (TopoDS::Face(myFace.Oriented(TopAbs_FORWARD)),
873 //           Standard_False);
874     TopTools_ListIteratorOfListOfShape it(myNewWires);
875     for (; it.More(); it.Next()) {
876       FR.Add(TopoDS::Wire(it.Value()));
877     }
878
879     FR.Perform();
880     
881     if (FR.IsDone()) {
882       TopAbs_Orientation OriF = myFace.Orientation();
883       for (; FR.More(); FR.Next()) {
884         myNewFaces.Append(FR.Current().Oriented(OriF));
885       }
886     }
887   }
888 }
889
890
891 //=======================================================================
892 //function : NewEdges
893 //purpose  : 
894 //=======================================================================
895
896 const TopTools_ListOfShape&  BRepAlgo_Loop::NewEdges(const TopoDS_Edge& E) const 
897 {
898   return myNewEdges(E);
899 }
900
901 //=======================================================================
902 //function : GetVerticesForSubstitute
903 //purpose  : 
904 //=======================================================================
905
906 void  BRepAlgo_Loop::GetVerticesForSubstitute( TopTools_DataMapOfShapeShape& VerVerMap ) const
907 {
908   VerVerMap = myVerticesForSubstitute;
909 }
910 //=======================================================================
911 //function : VerticesForSubstitute
912 //purpose  : 
913 //=======================================================================
914
915 void  BRepAlgo_Loop::VerticesForSubstitute( TopTools_DataMapOfShapeShape& VerVerMap )
916 {
917   myVerticesForSubstitute = VerVerMap;
918 }