0031035: Coding - uninitialized class fields reported by Visual Studio Code Analysis
[occt.git] / src / BRepTools / BRepTools_WireExplorer.cxx
1 // Created on: 1993-01-21
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-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 <BRepAdaptor_Surface.hxx>
20 #include <BRepTools.hxx>
21 #include <BRepTools_WireExplorer.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <Geom_Surface.hxx>
24 #include <GeomAdaptor_Surface.hxx>
25 #include <gp_Pnt2d.hxx>
26 #include <Precision.hxx>
27 #include <Standard_DomainError.hxx>
28 #include <Standard_NoMoreObject.hxx>
29 #include <Standard_NoSuchObject.hxx>
30 #include <TopExp.hxx>
31 #include <TopExp_Explorer.hxx>
32 #include <TopoDS.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Face.hxx>
35 #include <TopoDS_Iterator.hxx>
36 #include <TopoDS_Vertex.hxx>
37 #include <TopoDS_Wire.hxx>
38 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
39 #include <TopTools_ListIteratorOfListOfShape.hxx>
40 #include <TopTools_ListOfShape.hxx>
41 #include <TopTools_MapIteratorOfMapOfShape.hxx>
42 #include <TopTools_MapOfShape.hxx>
43
44 //=======================================================================
45 // forward declarations of aux functions
46 //=======================================================================
47 static Standard_Boolean SelectDouble(TopTools_MapOfShape& Doubles,
48                                      TopTools_ListOfShape& L,
49                                      TopoDS_Edge&          E);
50
51 static Standard_Boolean SelectDegenerated(TopTools_ListOfShape& L,
52                                           TopoDS_Edge&          E);
53
54 static Standard_Real GetNextParamOnPC(const Handle(Geom2d_Curve)& aPC,
55                                       const gp_Pnt2d& aPRef,
56                                       const Standard_Real& fP,
57                                       const Standard_Real& lP,
58                                       const Standard_Real& tolU,
59                                       const Standard_Real& tolV,
60                                       const Standard_Boolean& reverse);
61
62 //=======================================================================
63 //function : BRepTools_WireExplorer
64 //purpose  : 
65 //=======================================================================
66 BRepTools_WireExplorer::BRepTools_WireExplorer()
67 : myReverse(Standard_False),
68   myTolU(0.0),
69   myTolV(0.0)
70 {
71 }
72
73 //=======================================================================
74 //function : BRepTools_WireExplorer
75 //purpose  : 
76 //=======================================================================
77 BRepTools_WireExplorer::BRepTools_WireExplorer(const TopoDS_Wire& W)
78 {
79   TopoDS_Face F = TopoDS_Face();
80   Init(W,F);
81 }
82
83 //=======================================================================
84 //function : BRepTools_WireExplorer
85 //purpose  : 
86 //=======================================================================
87 BRepTools_WireExplorer::BRepTools_WireExplorer(const TopoDS_Wire& W,
88                                                const TopoDS_Face& F)
89 {
90   Init(W,F);
91 }
92
93 //=======================================================================
94 //function : Init
95 //purpose  : 
96 //=======================================================================
97 void  BRepTools_WireExplorer::Init(const TopoDS_Wire& W)
98 {  
99   TopoDS_Face F = TopoDS_Face();
100   Init(W,F);
101 }
102
103 //=======================================================================
104 //function : Init
105 //purpose  : 
106 //=======================================================================
107 void  BRepTools_WireExplorer::Init(const TopoDS_Wire& W,
108                                    const TopoDS_Face& F)
109 {
110   myEdge = TopoDS_Edge();
111   myVertex = TopoDS_Vertex();
112   myMap.Clear();
113   myDoubles.Clear();
114
115   if (W.IsNull())
116     return;
117
118   Standard_Real UMin(0.0), UMax(0.0), VMin(0.0), VMax(0.0);
119   if (!F.IsNull())
120   {
121     // For the faces based on Cone, BSpline and Bezier compute the
122     // UV bounds to precise the UV tolerance values
123     const GeomAbs_SurfaceType aSurfType = BRepAdaptor_Surface(F, Standard_False).GetType();
124     if (aSurfType == GeomAbs_Cone ||
125         aSurfType == GeomAbs_BSplineSurface ||
126         aSurfType == GeomAbs_BezierSurface)
127     {
128       BRepTools::UVBounds(F, UMin, UMax, VMin, VMax);
129     }
130   }
131
132   Init(W, F, UMin, UMax, VMin, VMax);
133 }
134
135 //=======================================================================
136 //function : Init
137 //purpose  : 
138 //=======================================================================
139 void  BRepTools_WireExplorer::Init(const TopoDS_Wire& W,
140                                    const TopoDS_Face& F,
141                                    const Standard_Real UMin,
142                                    const Standard_Real UMax,
143                                    const Standard_Real VMin,
144                                    const Standard_Real VMax)
145 {
146   myEdge = TopoDS_Edge();
147   myVertex = TopoDS_Vertex();
148   myMap.Clear();
149   myDoubles.Clear();
150
151   if (W.IsNull())
152     return;
153
154   myFace = F;
155   Standard_Real dfVertToler = 0.;
156   myReverse = Standard_False;
157
158   if (!myFace.IsNull())
159   {
160     BRepTools::Update(myFace);
161     TopLoc_Location aL;
162     const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(myFace, aL);
163     GeomAdaptor_Surface aGAS(aSurf);
164     TopExp_Explorer anExp(W, TopAbs_VERTEX);
165     for (; anExp.More(); anExp.Next())
166     {
167       const TopoDS_Vertex& aV = TopoDS::Vertex(anExp.Current());
168       dfVertToler = Max(BRep_Tool::Tolerance(aV), dfVertToler);
169     }
170     if (dfVertToler < Precision::Confusion())
171     {
172       // Use tolerance of edges
173       for (TopoDS_Iterator it(W); it.More(); it.Next())
174         dfVertToler = Max(BRep_Tool::Tolerance(TopoDS::Edge(it.Value())), dfVertToler);
175
176       if (dfVertToler < Precision::Confusion())
177         // empty wire
178         return;
179     }
180     myTolU = 2. * aGAS.UResolution(dfVertToler);
181     myTolV = 2. * aGAS.VResolution(dfVertToler);
182
183     // uresolution for cone with infinite vmin vmax is too small.
184     if (aGAS.GetType() == GeomAbs_Cone)
185     {
186       gp_Pnt aP;
187       gp_Vec aD1U, aD1V;
188       aGAS.D1(UMin, VMin, aP, aD1U, aD1V);
189       Standard_Real tol1, tol2, maxtol = .0005*(UMax - UMin);
190       Standard_Real a = aD1U.Magnitude();
191
192       if (a <= Precision::Confusion())
193         tol1 = maxtol;
194       else
195         tol1 = Min(maxtol, dfVertToler / a);
196
197       aGAS.D1(UMin, VMax, aP, aD1U, aD1V);
198       a = aD1U.Magnitude();
199       if (a <= Precision::Confusion())
200         tol2 = maxtol;
201       else
202         tol2 = Min(maxtol, dfVertToler / a);
203
204       myTolU = 2. * Max(tol1, tol2);
205     }
206
207     if (aGAS.GetType() == GeomAbs_BSplineSurface ||
208       aGAS.GetType() == GeomAbs_BezierSurface)
209     {
210       Standard_Real maxTol = Max(myTolU, myTolV);
211       gp_Pnt aP;
212       gp_Vec aDU, aDV;
213       aGAS.D1((UMax - UMin) / 2., (VMax - VMin) / 2., aP, aDU, aDV);
214       Standard_Real mod = Sqrt(aDU*aDU + aDV*aDV);
215       if (mod > gp::Resolution())
216       {
217         if (mod * maxTol / dfVertToler < 1.5)
218         {
219           maxTol = 1.5 * dfVertToler / mod;
220         }
221         myTolU = maxTol;
222         myTolV = maxTol;
223       }
224     }
225
226     myReverse = (myFace.Orientation() == TopAbs_REVERSED);
227   }
228
229   // map of vertices to know if the wire is open
230   TopTools_MapOfShape vmap;
231   //  map of infinite edges
232   TopTools_MapOfShape anInfEmap;
233
234   // list the vertices
235   TopoDS_Vertex V1, V2;
236   TopTools_ListOfShape empty;
237
238   TopoDS_Iterator it(W);
239   while (it.More())
240   {
241     const TopoDS_Edge& E = TopoDS::Edge(it.Value());
242     TopAbs_Orientation Eori = E.Orientation();
243     if (Eori == TopAbs_INTERNAL || Eori == TopAbs_EXTERNAL)
244     {
245       it.Next();
246       continue;
247     }
248     TopExp::Vertices(E, V1, V2, Standard_True);
249
250     if (!V1.IsNull())
251     {
252       if (!myMap.IsBound(V1))
253         myMap.Bind(V1, empty);
254       myMap(V1).Append(E);
255
256       // add or remove in the vertex map
257       V1.Orientation(TopAbs_FORWARD);
258       if (!vmap.Add(V1))
259         vmap.Remove(V1);
260     }
261
262     if (!V2.IsNull())
263     {
264       V2.Orientation(TopAbs_REVERSED);
265       if (!vmap.Add(V2))
266         vmap.Remove(V2);
267     }
268
269     if (V1.IsNull() || V2.IsNull())
270     {
271       Standard_Real aF = 0., aL = 0.;
272       BRep_Tool::Range(E, aF, aL);
273
274       if (Eori == TopAbs_FORWARD)
275       {
276         if (aF == -Precision::Infinite())
277           anInfEmap.Add(E);
278       }
279       else
280       { // Eori == TopAbs_REVERSED
281         if (aL == Precision::Infinite())
282           anInfEmap.Add(E);
283       }
284     }
285     it.Next();
286   }
287
288   //Construction of the set of double edges.
289   TopoDS_Iterator it2(W);
290   TopTools_MapOfShape emap;
291   while (it2.More()) {
292     if (!emap.Add(it2.Value()))
293       myDoubles.Add(it2.Value());
294     it2.Next();
295   }
296
297   // if vmap is not empty the wire is open, let us find the first vertex
298   if (!vmap.IsEmpty()) {
299     TopTools_MapIteratorOfMapOfShape itt(vmap);
300     while (itt.Key().Orientation() != TopAbs_FORWARD) {
301       itt.Next();
302       if (!itt.More()) break;
303     }
304     if (itt.More()) V1 = TopoDS::Vertex(itt.Key());
305   }
306   else {
307     //   The wire is infinite Try to find the first vertex. It may be NULL.
308     if (!anInfEmap.IsEmpty()) {
309       TopTools_MapIteratorOfMapOfShape itt(anInfEmap);
310
311       for (; itt.More(); itt.Next()) {
312         TopoDS_Edge        anEdge = TopoDS::Edge(itt.Key());
313         TopAbs_Orientation anOri = anEdge.Orientation();
314         Standard_Real      aF;
315         Standard_Real      aL;
316
317         BRep_Tool::Range(anEdge, aF, aL);
318         if ((anOri == TopAbs_FORWARD  && aF == -Precision::Infinite()) ||
319           (anOri == TopAbs_REVERSED && aL == Precision::Infinite())) {
320           myEdge = anEdge;
321           myVertex = TopoDS_Vertex();
322
323           return;
324         }
325       }
326     }
327
328     // use the first vertex in iterator
329     it.Initialize(W);
330     while (it.More()) {
331       const TopoDS_Edge& E = TopoDS::Edge(it.Value());
332       TopAbs_Orientation Eori = E.Orientation();
333       if (Eori == TopAbs_INTERNAL || Eori == TopAbs_EXTERNAL) {
334         // JYL 10-03-97 : waiting for correct processing 
335         // of INTERNAL/EXTERNAL edges
336         it.Next();
337         continue;
338       }
339       TopExp::Vertices(E, V1, V2, Standard_True);
340       break;
341     }
342   }
343
344   if (V1.IsNull()) return;
345   if (!myMap.IsBound(V1)) return;
346
347   TopTools_ListOfShape& l = myMap(V1);
348   myEdge = TopoDS::Edge(l.First());
349   l.RemoveFirst();
350   myVertex = TopExp::FirstVertex(myEdge, Standard_True);
351
352 }
353
354 //=======================================================================
355 //function : More
356 //purpose  : 
357 //=======================================================================
358 Standard_Boolean  BRepTools_WireExplorer::More()const 
359 {
360   return !myEdge.IsNull();
361 }
362
363 //=======================================================================
364 //function : Next
365 //purpose  : 
366 //=======================================================================
367 void  BRepTools_WireExplorer::Next()
368 {
369   myVertex = TopExp::LastVertex (myEdge, Standard_True);
370
371   if (myVertex.IsNull()) {
372      myEdge = TopoDS_Edge();
373      return;
374   }
375   if (!myMap.IsBound(myVertex)) {
376      myEdge = TopoDS_Edge();
377      return;
378   }
379
380   TopTools_ListOfShape& l = myMap(myVertex);
381
382   if (l.IsEmpty()) {
383     myEdge = TopoDS_Edge();
384   }
385   else if (l.Extent() == 1) {
386 //  Modified by Sergey KHROMOV - Fri Jun 21 10:28:01 2002 OCC325 Begin
387     TopoDS_Vertex aV1;
388     TopoDS_Vertex aV2;
389     TopoDS_Edge   aNextEdge = TopoDS::Edge(l.First());
390
391     TopExp::Vertices(aNextEdge, aV1, aV2, Standard_True);
392
393     if (!aV1.IsSame(myVertex)) {
394       myEdge = TopoDS_Edge();
395       return;
396     }
397     if (!myFace.IsNull() && aV1.IsSame(aV2)) {
398       Handle(Geom2d_Curve) aPrevPC;
399       Handle(Geom2d_Curve) aNextPC;
400       Standard_Real        aPar11, aPar12;
401       Standard_Real        aPar21, aPar22;
402       Standard_Real        aPrevPar;
403       Standard_Real        aNextFPar;
404       Standard_Real        aNextLPar;
405
406       aPrevPC = BRep_Tool::CurveOnSurface(myEdge, myFace, aPar11, aPar12);
407       aNextPC = BRep_Tool::CurveOnSurface(aNextEdge, myFace, aPar21, aPar22);
408
409       if (aPrevPC.IsNull() || aNextPC.IsNull()) {
410               myEdge = TopoDS_Edge();
411               return;
412       }
413
414       if (myEdge.Orientation() == TopAbs_FORWARD)
415               aPrevPar = aPar12;
416       else
417               aPrevPar = aPar11;
418
419       if (aNextEdge.Orientation() == TopAbs_FORWARD) {
420               aNextFPar = aPar21;
421               aNextLPar = aPar22;
422       } else {
423               aNextFPar = aPar22;
424               aNextLPar = aPar21;
425       }
426
427       gp_Pnt2d aPPrev  = aPrevPC->Value(aPrevPar);
428       gp_Pnt2d aPNextF = aNextPC->Value(aNextFPar);
429       gp_Pnt2d aPNextL = aNextPC->Value(aNextLPar);
430
431       if (aPPrev.SquareDistance(aPNextF) > aPPrev.SquareDistance(aPNextL)) {
432               myEdge = TopoDS_Edge();
433               return;
434       }
435     }
436 //  Modified by Sergey KHROMOV - Fri Jun 21 11:08:16 2002 End
437     myEdge = TopoDS::Edge(l.First());
438     l.Clear();
439   }
440   else {
441     if (myFace.IsNull()) {
442       // Without Face - try to return edges
443       // as logically as possible
444       // At first degenerated edges.
445       TopoDS_Edge E = myEdge;
446       if (SelectDegenerated(l,E)) {
447               myEdge = E;
448               return;
449       }
450       // At second double edges.
451       E = myEdge;
452       if (SelectDouble(myDoubles,l,E)) {
453               myEdge = E;
454               return;
455       }
456
457       TopTools_ListIteratorOfListOfShape it(l); 
458       Standard_Boolean notfound = Standard_True;
459       while (it.More()) {
460               if (!it.Value().IsSame(myEdge)) {
461                 myEdge = TopoDS::Edge(it.Value());
462                 l.Remove(it);
463                 notfound = Standard_False;
464                 break;
465               }
466               it.Next();
467       }
468       
469       if(notfound) {
470               myEdge = TopoDS_Edge();
471               return;
472       }
473
474     }
475     else
476     {
477       // If we have more than one edge attached to the list
478       // probably wire that we explore contains a loop or loops.
479       Standard_Real dfFPar = 0., dfLPar = 0.;
480       Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface (myEdge, myFace, dfFPar, dfLPar);
481       if(aPCurve.IsNull())
482       {
483         myEdge = TopoDS_Edge();
484         return;
485       }
486       // Note: current < myVertex > which is last on < myEdge >
487       //       equals in 2D to following 2D points:
488       //       edge is FORWARD  - point with MAX parameter on PCurve;
489       //       edge is REVERSED - point with MIN parameter on PCurve.
490
491       // Get 2D point equals to < myVertex > in 2D for current edge.
492       gp_Pnt2d PRef;
493       if( myEdge.Orientation() == TopAbs_REVERSED )
494         aPCurve->D0(dfFPar, PRef);
495       else 
496         aPCurve->D0(dfLPar, PRef);
497
498       // Get next 2D point from current edge's PCurve with parameter
499       // F + dP (REV) or L - dP (FOR)
500       Standard_Boolean isrevese = ( myEdge.Orientation() == TopAbs_REVERSED );
501       Standard_Real dfMPar = GetNextParamOnPC(aPCurve,PRef,dfFPar,dfLPar,myTolU,myTolV,isrevese);
502
503       gp_Pnt2d PRefm;
504       aPCurve->D0(dfMPar, PRefm);
505       // Get vector from PRef to PRefm
506       gp_Vec2d anERefDir(PRef,PRefm);
507       if (anERefDir.SquareMagnitude() < gp::Resolution())
508       {
509         myEdge = TopoDS_Edge();
510         return;
511       }
512
513       // Search the list of edges looking for the edge having hearest
514       // 2D point of connected vertex to current one and smallest angle.
515       // First process all degenerated edges, then - all others.
516
517       TopTools_ListIteratorOfListOfShape it;
518       Standard_Integer k = 1, kMin = 0, iDone = 0;
519       Standard_Boolean isDegenerated = Standard_True;
520       Standard_Real dmin = RealLast();
521       Standard_Real dfMinAngle = 3.0*M_PI, dfCurAngle = 3.0*M_PI;
522
523       for(iDone = 0; iDone < 2; iDone++)
524       {
525         it.Initialize(l);
526         while( it.More() )
527         {
528                 const TopoDS_Edge& E = TopoDS::Edge(it.Value());
529                 if( E.IsSame(myEdge) )
530                 {
531                   it.Next();
532                   k++;
533                   continue;
534                 }
535                 
536                 TopoDS_Vertex aVert1, aVert2;
537                 TopExp::Vertices (E, aVert1, aVert2, Standard_True);
538                 if( aVert1.IsNull() || aVert2.IsNull() )
539           {
540             it.Next();
541             k++;
542             continue;
543           }
544                 
545                 aPCurve = BRep_Tool::CurveOnSurface (E, myFace, dfFPar, dfLPar);
546                 if( aPCurve.IsNull() )
547           {
548             it.Next();
549             k++;
550             continue;
551           }
552                 
553                 gp_Pnt2d aPEb, aPEe;
554                 if( aVert1.IsSame(aVert2) == isDegenerated )
555                 {
556                   if( E.Orientation() == TopAbs_REVERSED )
557                     aPCurve->D0(dfLPar, aPEb);
558                   else  
559                     aPCurve->D0(dfFPar, aPEb);
560
561                   if( Abs(dfLPar-dfFPar) > Precision::PConfusion() )
562                   {
563                           isrevese = ( E.Orientation() == TopAbs_REVERSED );
564                           isrevese = !isrevese;
565                           Standard_Real aEPm = GetNextParamOnPC(aPCurve,aPEb,dfFPar,dfLPar,myTolU,myTolV,isrevese);
566                                 
567                           aPCurve->D0 (aEPm, aPEe);
568               if(aPEb.SquareDistance(aPEe) <= gp::Resolution())
569               {
570                 //seems to be very short curve
571                 gp_Vec2d aD;
572                 aPCurve->D1(aEPm, aPEe, aD);
573                       if( E.Orientation() == TopAbs_REVERSED )
574                   aPEe.SetXY(aPEb.XY()-aD.XY());
575                       else      
576                   aPEe.SetXY(aPEb.XY()+aD.XY());
577
578                 if(aPEb.SquareDistance(aPEe) <= gp::Resolution())
579                 {
580                   it.Next();
581                   k++;
582                   continue;
583                 }
584               }
585                           gp_Vec2d anEDir(aPEb, aPEe);
586                           dfCurAngle = Abs( anEDir.Angle(anERefDir) );
587                   }
588
589                   if( dfCurAngle <= dfMinAngle )
590                   {
591                           Standard_Real d = PRef.SquareDistance(aPEb);
592                           if( d <= Precision::PConfusion() )
593                             d = 0.;
594                           if( Abs(aPEb.X()-PRef.X()) < myTolU  &&  Abs(aPEb.Y()-PRef.Y()) < myTolV )
595                           {
596                             if( d <= dmin )
597                             {
598                                     dfMinAngle = dfCurAngle;
599                                     kMin = k;
600                                     dmin = d;
601                             }
602                           }
603                   }
604                 }
605                 it.Next();
606                 k++;
607         }// while it
608
609         if( kMin == 0 )
610         {
611                 isDegenerated = Standard_False;
612                 k = 1;
613                 dmin = RealLast();
614         }
615         else
616           break;
617       }// for iDone
618
619       if(kMin == 0)
620       {
621         // probably unclosed in 2d space wire
622         myEdge = TopoDS_Edge();
623         return;
624       }
625
626       // Selection the edge.
627       it.Initialize(l);
628       k = 1;
629       while( it.More() )
630       {
631         if( k == kMin )
632         {
633           myEdge = TopoDS::Edge(it.Value());
634           l.Remove(it);
635           break;
636         }
637         it.Next();
638         k++;
639       }
640     }//else face != NULL && l > 1
641   }//else l > 1
642 }
643
644 //=======================================================================
645 //function : Current
646 //purpose  : 
647 //=======================================================================
648 const TopoDS_Edge&  BRepTools_WireExplorer::Current()const 
649 {
650   return myEdge;
651 }
652
653 //=======================================================================
654 //function : Orientation
655 //purpose  : 
656 //=======================================================================
657 TopAbs_Orientation BRepTools_WireExplorer::Orientation() const
658 {
659   if (myVertex.IsNull()
660   && !myEdge.IsNull())
661   {
662     // infinite edge
663     return TopAbs_FORWARD;
664   }
665
666   TopoDS_Iterator it(myEdge,Standard_False);
667   while (it.More()) {
668     if (myVertex.IsSame(it.Value()))
669       return it.Value().Orientation();
670     it.Next();
671   }
672   throw Standard_NoSuchObject("BRepTools_WireExplorer::Orientation");
673 }
674
675 //=======================================================================
676 //function : CurrentVertex
677 //purpose  : 
678 //=======================================================================
679 const TopoDS_Vertex& BRepTools_WireExplorer::CurrentVertex() const
680 {
681   return myVertex;
682 }
683
684 //=======================================================================
685 //function : Clear
686 //purpose  : 
687 //=======================================================================
688
689 void BRepTools_WireExplorer::Clear()
690 {
691   myMap.Clear();
692   myDoubles.Clear();
693   myEdge = TopoDS_Edge();
694   myFace = TopoDS_Face();
695   myVertex = TopoDS_Vertex();
696 }
697
698
699 //=======================================================================
700 //function : SelectDouble
701 //purpose  : 
702 //=======================================================================
703
704 Standard_Boolean SelectDouble(TopTools_MapOfShape& Doubles,
705                               TopTools_ListOfShape& L,
706                               TopoDS_Edge&          E)
707 {
708   TopTools_ListIteratorOfListOfShape it(L);
709   
710   for (; it.More(); it.Next()) {
711     const TopoDS_Shape& CE = it.Value();
712     if (Doubles.Contains(CE) && (!E.IsSame(CE))) {
713       E = TopoDS::Edge(CE);
714       L.Remove(it);
715       return 1;
716     }
717   }
718   return 0;
719 }
720
721 //=======================================================================
722 //function : SelectDegenerated
723 //purpose  : 
724 //=======================================================================
725
726 Standard_Boolean SelectDegenerated(TopTools_ListOfShape& L,
727                                    TopoDS_Edge&          E)
728 {
729   TopTools_ListIteratorOfListOfShape it(L);
730   while (it.More()) {
731     if (!it.Value().IsSame(E)) {
732       E = TopoDS::Edge(it.Value());
733       if (BRep_Tool::Degenerated(E)) {
734         L.Remove(it);
735         return 1;
736       }
737     }
738     it.Next();
739   } 
740   return 0;
741 }
742
743 //=======================================================================
744 //function : GetNextParamOnPC
745 //purpose  : 
746 //=======================================================================
747 Standard_Real GetNextParamOnPC(const Handle(Geom2d_Curve)& aPC,
748                                const gp_Pnt2d& aPRef,
749                                const Standard_Real& fP,
750                                const Standard_Real& lP,
751                                const Standard_Real& tolU,
752                                const Standard_Real& tolV,
753                                const Standard_Boolean& reverse)
754 {
755   Standard_Real result = ( reverse ) ? fP : lP;
756   Standard_Real dP = Abs( lP - fP ) / 1000.; // was / 16.;
757   if( reverse )
758     {
759       Standard_Real startPar = fP;
760       Standard_Boolean nextPntOnEdge = Standard_False;
761       while( !nextPntOnEdge && startPar < lP )
762         {
763           gp_Pnt2d pnt;
764           startPar += dP;
765           aPC->D0(startPar, pnt);
766           if( Abs( aPRef.X() - pnt.X() ) < tolU && Abs( aPRef.Y() - pnt.Y() ) < tolV )
767             continue;
768           else
769             {
770               result = startPar;
771               nextPntOnEdge = Standard_True;
772               break;
773             }
774         }
775       
776       if( !nextPntOnEdge )
777         result = lP;
778
779       if( result > lP )
780         result = lP;
781     }
782   else
783     {
784       Standard_Real startPar = lP;
785       Standard_Boolean nextPntOnEdge = Standard_False;
786       while( !nextPntOnEdge && startPar > fP )
787         {
788           gp_Pnt2d pnt;
789           startPar -= dP;
790           aPC->D0(startPar, pnt);
791           if( Abs( aPRef.X() - pnt.X() ) < tolU && Abs( aPRef.Y() - pnt.Y() ) < tolV )
792             continue;
793           else
794             {
795               result = startPar;
796               nextPntOnEdge = Standard_True;
797               break;
798             }
799         }
800       
801       if( !nextPntOnEdge )
802         result = fP;
803
804       if( result < fP )
805         result = fP;
806     }
807
808   return result;
809 }