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