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