Salome HOME
Porting to OCCT development version: Standard_PI -> M_PI
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_WireSplitter.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21
22 // File:        GEOMAlgo_WireSplitter.cxx
23 // Author:      Peter KURNEV
24
25 #include <GEOMAlgo_WireSplitter.ixx>
26
27 #include <TColStd_SequenceOfReal.hxx>
28 #include <Precision.hxx>
29
30 #include <gp_Pnt2d.hxx>
31 #include <gp_Vec2d.hxx>
32 #include <TColgp_SequenceOfPnt2d.hxx>
33
34 #include <Geom_Curve.hxx>
35 #include <Geom2d_Curve.hxx>
36 #include <GeomAdaptor_Surface.hxx>
37
38 #include <TopAbs_Orientation.hxx>
39
40 #include <TopoDS.hxx>
41 #include <TopoDS_Vertex.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Iterator.hxx>
45
46
47 #include <BRep_Tool.hxx>
48 #include <BRepAdaptor_Surface.hxx>
49 #include <BRepAdaptor_Curve2d.hxx>
50
51 #include <TopExp.hxx>
52 #include <TopExp_Explorer.hxx>
53
54
55
56 #include <TopTools_SequenceOfShape.hxx>
57 #include <TopTools_ListOfShape.hxx>
58 #include <TopTools_ListIteratorOfListOfShape.hxx>
59 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
60 #include <TopTools_IndexedMapOfShape.hxx>
61
62 #include <BOPTColStd_ListOfListOfShape.hxx>
63 #include <BOPTColStd_ListIteratorOfListOfListOfShape.hxx>
64
65 #include <BOPTools_Tools2D.hxx>
66
67 #include <BOP_EdgeInfo.hxx>
68 #include <BOP_ListOfEdgeInfo.hxx>
69 #include <BOP_ListIteratorOfListOfEdgeInfo.hxx>
70 #include <BOP_IndexedDataMapOfVertexListEdgeInfo.hxx>
71
72 static
73   void Path (const GeomAdaptor_Surface& aGAS,
74              const TopoDS_Face& myFace,
75              const TopoDS_Vertex& aVa,
76              const TopoDS_Edge& aEOuta,
77              BOP_EdgeInfo& anEdgeInfo,
78              TopTools_SequenceOfShape& aLS,
79              TopTools_SequenceOfShape& aVertVa,
80              TColgp_SequenceOfPnt2d& aCoordVa,
81              BOPTColStd_ListOfListOfShape& myShapes,
82              BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap);
83
84
85 static
86   Standard_Real Angle (const gp_Dir2d& aDir2D);
87
88
89 static
90   void GetNextVertex(const TopoDS_Vertex& aV,
91                      const TopoDS_Edge& aE,
92                      TopoDS_Vertex& aV1);
93 static
94   Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
95                                const Standard_Real aAngleOut);
96
97 static
98   Standard_Real AngleIn(const TopoDS_Edge& aEIn,
99                         const BOP_ListOfEdgeInfo& aLEInfo);
100
101 static
102   Standard_Real Angle2D (const TopoDS_Vertex& aV,
103                          const TopoDS_Edge& anEdge,
104                          const TopoDS_Face& myFace,
105                          const GeomAdaptor_Surface& aGAS,
106                          const Standard_Boolean aFlag);
107 static
108   gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
109                     const TopoDS_Edge& aE1,
110                     const TopoDS_Face& aF);
111 static
112   gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
113                       const TopoDS_Face& aF);
114 static
115   Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
116                             const GeomAdaptor_Surface& aGAS);   
117
118 static
119   Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& );
120 //
121
122 //=======================================================================
123 // function: 
124 // purpose: 
125 //=======================================================================
126   GEOMAlgo_WireSplitter::GEOMAlgo_WireSplitter()
127 :
128   GEOMAlgo_Algo(),
129   myNothingToDo(Standard_False)
130 {
131 }
132 //=======================================================================
133 // function: ~
134 // purpose: 
135 //=======================================================================
136   GEOMAlgo_WireSplitter::~GEOMAlgo_WireSplitter()
137 {
138 }
139 //=======================================================================
140 // function: SetFace
141 // purpose: 
142 //=======================================================================
143   void GEOMAlgo_WireSplitter::SetFace(const TopoDS_Face& aFace)
144 {
145   myFace=aFace;
146 }
147 //=======================================================================
148 // function: Face
149 // purpose: 
150 //=======================================================================
151   const TopoDS_Face& GEOMAlgo_WireSplitter::Face()const
152 {
153   return myFace;
154 }
155 //=======================================================================
156 // function: SetEdges
157 // purpose: 
158 //=======================================================================
159   void GEOMAlgo_WireSplitter::SetEdges(const TopTools_ListOfShape& aLE)
160 {
161   TopTools_ListIteratorOfListOfShape anIt;
162   //
163   myEdges.Clear();
164   anIt.Initialize(aLE);
165   for (; anIt.More(); anIt.Next()) {
166     const TopoDS_Shape& aE =anIt.Value();
167     //
168     if (aE.Orientation()==TopAbs_INTERNAL){
169       continue;
170     }
171     //
172     myEdges.Append(aE);
173   }
174 }
175 //=======================================================================
176 // function: Edges
177 // purpose: 
178 //=======================================================================
179   const TopTools_ListOfShape& GEOMAlgo_WireSplitter::Edges()const
180 {
181   return myEdges;
182 }
183 //=======================================================================
184 // function: IsNothingToDo
185 // purpose: 
186 //=======================================================================
187   Standard_Boolean GEOMAlgo_WireSplitter::IsNothingToDo()const
188 {
189   return myNothingToDo;
190 }
191 //=======================================================================
192 // function: Shapes
193 // purpose: 
194 //=======================================================================
195   const BOPTColStd_ListOfListOfShape& GEOMAlgo_WireSplitter::Shapes()const
196 {
197   return myShapes;
198 }
199 //=======================================================================
200 // function: Perform
201 // purpose: 
202 //=======================================================================
203   void GEOMAlgo_WireSplitter::Perform()
204 {
205   myErrorStatus=2;
206   myNothingToDo=Standard_True;
207
208   Standard_Integer index, i, aNb, aCntIn, aCntOut;
209   Standard_Boolean anIsIn;
210   Standard_Real anAngle;
211   
212   BOP_ListOfEdgeInfo emptyInfo;
213   TopTools_ListIteratorOfListOfShape anItList;
214   //
215   // 1.Filling mySmartMap
216   mySmartMap.Clear();
217
218   anItList.Initialize(myEdges);
219   for (; anItList.More(); anItList.Next()) {
220     const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value());
221     //
222     if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) {
223       continue;
224     }
225     //
226     TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX);
227     for (; anExpVerts.More(); anExpVerts.Next()) {
228       const TopoDS_Shape& aVertex= anExpVerts.Current();
229
230       index = mySmartMap.FindIndex(aVertex);
231       if (!index) {
232         index=mySmartMap.Add(aVertex, emptyInfo);
233       }
234       
235       BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index);
236
237       BOP_EdgeInfo aEInfo;
238       aEInfo.SetEdge(anEdge);
239       
240       TopAbs_Orientation anOr=aVertex.Orientation();
241
242       if (anOr==TopAbs_FORWARD) {
243         aEInfo.SetInFlag(Standard_False);
244       }
245
246       else if (anOr==TopAbs_REVERSED) {
247         aEInfo.SetInFlag(Standard_True);
248       }
249
250       aListOfEInfo.Append(aEInfo);
251     }
252   }
253   //
254   aNb=mySmartMap.Extent();
255   //
256   // 2. myNothingToDo 
257   myNothingToDo=Standard_True;
258   
259   for (i=1; i<=aNb; i++) {
260     aCntIn=0;
261     aCntOut=0;
262     const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
263     BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
264     for (; anIt.More(); anIt.Next()) {
265       const BOP_EdgeInfo& anEdgeInfo=anIt.Value();
266       anIsIn=anEdgeInfo.IsIn();
267       if (anIsIn) {
268         aCntIn++;
269       }
270       else {
271         aCntOut++;
272       }
273     }
274     if (aCntIn!=1 || aCntOut!=1) {
275       myNothingToDo=Standard_False;
276       break;
277     }
278   }
279   //
280   // Each vertex has one edge In and one - Out. Good. But it is not enought
281   // to consider that nothing to do with this. We must check edges on TShape
282   // coinsidence. If there are such edges there is something to do with.
283   // 
284   if (myNothingToDo) {
285     Standard_Integer aNbE, aNbMapEE;
286     TopTools_IndexedDataMapOfShapeListOfShape aMapEE;
287     aNbE=myEdges.Extent();
288     
289     anItList.Initialize(myEdges);
290     for (; anItList.More(); anItList.Next()) {
291       const TopoDS_Shape& aE = anItList.Value();
292       
293       if (!aMapEE.Contains(aE)) {
294         TopTools_ListOfShape aLEx;
295         aLEx.Append(aE);
296         aMapEE.Add(aE, aLEx);
297       }
298       else {
299         TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
300         aLEx.Append(aE);
301       }
302     }
303     
304     Standard_Boolean bFlag;
305     bFlag=Standard_True;
306     aNbMapEE=aMapEE.Extent();
307     for (i=1; i<=aNbMapEE; i++) {
308       const TopTools_ListOfShape& aLEx=aMapEE(i);
309       aNbE=aLEx.Extent();
310       if (aNbE==1) {
311         // usual case
312         continue;
313       }
314       else if (aNbE==2){
315         const TopoDS_Shape& aE1=aLEx.First();
316         const TopoDS_Shape& aE2=aLEx.Last();
317         if (aE1.IsSame(aE2)) {
318           bFlag=Standard_False;
319           break;
320         }
321       }
322       else {
323         bFlag=Standard_False;
324         break;
325       }
326     }
327     myNothingToDo=myNothingToDo && bFlag;
328   }
329   // 
330   //
331   if (myNothingToDo) {
332     myErrorStatus=0;
333     return;
334   }
335   //
336   // 3. Angles in mySmartMap
337   BRepAdaptor_Surface aBAS(myFace);
338   const GeomAdaptor_Surface& aGAS=aBAS.Surface();
339   for (i=1; i<=aNb; i++) {
340     const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i));
341     const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
342
343     BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
344     for (; anIt.More(); anIt.Next()) {
345       BOP_EdgeInfo& anEdgeInfo=anIt.Value();
346       const TopoDS_Edge& aE=anEdgeInfo.Edge();
347       //
348       TopoDS_Vertex aVV=aV;
349       //
350       anIsIn=anEdgeInfo.IsIn();
351       if (anIsIn) {
352         //
353         aVV.Orientation(TopAbs_REVERSED);
354         anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
355       }
356       // 
357       else { // OUT
358         //
359         aVV.Orientation(TopAbs_FORWARD);
360         anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
361       }
362       anEdgeInfo.SetAngle(anAngle);
363       
364     }
365   }
366   //
367   // 4. Do
368   //
369   Standard_Boolean anIsOut, anIsNotPassed;
370   
371   TopTools_SequenceOfShape aLS, aVertVa;
372   TColgp_SequenceOfPnt2d aCoordVa;
373   
374   BOP_ListIteratorOfListOfEdgeInfo anIt;
375
376   for (i=1; i<=aNb; i++) {
377     const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i));
378     const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i);
379     
380     anIt.Initialize(aLEInfo);
381     for (; anIt.More(); anIt.Next()) {
382       BOP_EdgeInfo& anEdgeInfo=anIt.Value();
383       const TopoDS_Edge& aEOuta=anEdgeInfo.Edge();
384       
385       anIsOut=!anEdgeInfo.IsIn();
386       anIsNotPassed=!anEdgeInfo.Passed();
387       
388       if (anIsOut && anIsNotPassed) {
389         //
390         aLS.Clear();
391         aVertVa.Clear();
392         aCoordVa.Clear();
393         //
394         Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS, 
395              aVertVa, aCoordVa, myShapes, mySmartMap);
396       }
397     }
398   }
399   //
400   {
401     Standard_Integer aNbV, aNbE;
402     TopoDS_Vertex aV1, aV2;
403     BOPTColStd_ListOfListOfShape aShapes;
404     BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes);
405     
406     for (; anItW.More(); anItW.Next()) {
407       TopTools_IndexedMapOfShape aMV, aME;
408       const TopTools_ListOfShape& aLE=anItW.Value();
409       TopTools_ListIteratorOfListOfShape anItE(aLE);
410       for (; anItE.More(); anItE.Next()) {
411         const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value());
412         aME.Add(aE);
413         TopExp::Vertices(aE, aV1, aV2);
414         aMV.Add(aV1);
415         aMV.Add(aV2);
416       }
417       aNbV=aMV.Extent();
418       aNbE=aME.Extent();
419       if (aNbV<=aNbE) {
420         aShapes.Append(aLE);
421       }
422     }
423     //
424     myShapes.Clear();
425     anItW.Initialize(aShapes);
426     for (; anItW.More(); anItW.Next()) {
427       const TopTools_ListOfShape& aLE=anItW.Value();
428       myShapes.Append(aLE);
429     }
430   }
431   //
432   myErrorStatus=0;
433 }
434 //=======================================================================
435 // function: Path
436 // purpose: 
437 //=======================================================================
438   void Path (const GeomAdaptor_Surface& aGAS,
439              const TopoDS_Face& myFace,
440              const TopoDS_Vertex& aVa,
441              const TopoDS_Edge& aEOuta,
442              BOP_EdgeInfo& anEdgeInfo,
443              TopTools_SequenceOfShape& aLS,
444              TopTools_SequenceOfShape& aVertVa,
445              TColgp_SequenceOfPnt2d& aCoordVa,
446              BOPTColStd_ListOfListOfShape& myShapes,
447              BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap)
448                                
449 {
450   Standard_Integer i,j, aNb, aNbj;
451   Standard_Real aTol, anAngleIn, anAngleOut, anAngle, aMinAngle;
452   Standard_Real aTol2D, aTol2D2;
453   Standard_Real aTol2, aD2;//, aTolUVb, aTolVVb;  
454   Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
455   BOP_ListIteratorOfListOfEdgeInfo anIt;
456   TopoDS_Vertex aVb;
457   TopoDS_Edge aEOutb;
458   //
459   aTol=1.e-7;
460   //
461   // append block
462   //
463   // Do not escape through edge from which you enter 
464   aNb=aLS.Length();
465   if (aNb==1) {
466     const TopoDS_Shape& anEPrev=aLS(aNb);
467     if (anEPrev.IsSame(aEOuta)) {
468       return;
469     }
470   }
471   //
472   //
473   anEdgeInfo.SetPassed(Standard_True);
474   aLS.Append(aEOuta);
475   aVertVa.Append(aVa);
476   
477   TopoDS_Vertex pVa=aVa;
478   pVa.Orientation(TopAbs_FORWARD);
479   gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace);
480   aCoordVa.Append(aPa);
481   
482   GetNextVertex (pVa, aEOuta, aVb);
483
484   gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace);
485
486   //const BOP_ListOfEdgeInfo& aLEInfoVb=mySmartMap.FindFromKey(aVb);
487   //
488   aTol=2.*Tolerance2D(aVb, aGAS);
489   aTol2=10.*aTol*aTol;
490   //
491   aNb=aLS.Length();
492   if (aNb>0) {
493     //
494     TopTools_ListOfShape aBuf;
495     //
496     for (i=aNb; i>0; i--) {
497       const TopoDS_Shape& aVPrev=aVertVa(i);
498       const gp_Pnt2d& aPaPrev=aCoordVa(i);
499       const TopoDS_Shape& aEPrev=aLS(i);
500
501       aBuf.Append(aEPrev);
502
503       anIsSameV=aVPrev.IsSame(aVb);
504       anIsSameV2d=Standard_False;
505
506       if (anIsSameV) {
507         anIsSameV2d = Standard_True;
508         //
509         aD2=aPaPrev.SquareDistance(aPb);
510         anIsSameV2d =aD2<aTol2;
511       }//if (anIsSameV) {
512       //
513       if (anIsSameV && anIsSameV2d) {
514         myShapes.Append(aBuf);
515         //
516         TopTools_SequenceOfShape aLSt, aVertVat;
517         TColgp_SequenceOfPnt2d aCoordVat;
518         //
519         aNbj=i-1;
520         if (aNbj<1) {
521           //
522           aLS.Clear();
523           aVertVa.Clear();
524           aCoordVa.Clear();
525           //
526           return;
527         }
528
529         aVb=TopoDS::Vertex(aVertVa(i));
530
531         for (j=1; j<=aNbj; j++) {
532           aLSt.Append(aLS(j));
533           aVertVat.Append(aVertVa(j));
534           aCoordVat.Append(aCoordVa(j));
535         }
536         //
537         aLS.Clear();
538         aVertVa.Clear();
539         aCoordVa.Clear();
540
541         aLS=aLSt;
542         aVertVa=aVertVat;
543         aCoordVa=aCoordVat;
544         //
545         break;
546       }
547     }
548   }
549   //
550   aTol2D=2.*Tolerance2D(aVb, aGAS);
551   aTol2D2=100.*aTol2D*aTol2D;
552   //
553   // anAngleIn in Vb from edge aEOuta
554   const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
555   //
556   anAngleIn=AngleIn(aEOuta, aLEInfo);
557   //
558   // aEOutb
559   BOP_EdgeInfo *pEdgeInfo=NULL;
560
561   aMinAngle=100.;
562   anIsFound=Standard_False;
563
564   Standard_Integer aCurIndexE = 0;
565
566   anIt.Initialize(aLEInfo);
567   for (; anIt.More(); anIt.Next()) {
568     BOP_EdgeInfo& anEI=anIt.Value();
569     const TopoDS_Edge& aE=anEI.Edge();
570     anIsOut=!anEI.IsIn();
571     anIsNotPassed=!anEI.Passed();
572     
573     if (anIsOut && anIsNotPassed) {
574       aCurIndexE++;
575       //
576       // Is there one way to go out of the vertex 
577       // we have to use it only.
578       Standard_Integer iCnt;
579       iCnt=NbWaysOut (aLEInfo);
580       //
581       if (!iCnt) {
582         // no way to go . (Error)
583         return ;
584       }
585       //
586       if (iCnt==1) {
587         // the one and only way to go out .
588         pEdgeInfo=&anEI;
589         anIsFound=Standard_True;
590         break;
591       }
592       //
593       // Look for minimal angle and make the choice.
594       gp_Pnt2d aP2Dx;
595       //
596       aP2Dx=Coord2dVf(aE, myFace);
597       //
598       aD2=aP2Dx.SquareDistance(aPb);
599       if (aD2 > aTol2D2){
600         continue;
601       }
602       //
603       //
604       anAngleOut=anEI.Angle();
605       //
606       anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
607       if (anAngle < aMinAngle) {
608         aMinAngle=anAngle;
609         pEdgeInfo=&anEI;
610         anIsFound=Standard_True;
611       }
612     }
613   } // for (; anIt.More(); anIt.Next()) 
614   //
615   if (!anIsFound) {
616     // no way to go . (Error)
617     return;
618   }
619   
620   aEOutb=pEdgeInfo->Edge();
621   //
622   Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS, 
623         aVertVa, aCoordVa, myShapes, mySmartMap);
624 }
625 //=======================================================================
626 // function:  Coord2dVf
627 // purpose:
628 //=======================================================================
629  gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
630                      const TopoDS_Face& aF)
631 {
632   Standard_Real aCoord=99.;
633   gp_Pnt2d aP2D1(aCoord, aCoord);
634   TopoDS_Iterator aIt;
635   //
636   aIt.Initialize(aE);
637   for (; aIt.More(); aIt.Next()) {
638     const TopoDS_Shape& aVx=aIt.Value();
639     if (aVx.Orientation()==TopAbs_FORWARD) {
640       const TopoDS_Vertex& aVxx=TopoDS::Vertex(aVx);
641       aP2D1=Coord2d(aVxx, aE, aF);
642       return aP2D1;
643     }
644   }
645   return aP2D1;
646 }
647 //=======================================================================
648 // function:  Tolerance2D
649 // purpose:
650 //=======================================================================
651  Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
652                             const GeomAdaptor_Surface& aGAS)                 
653 {
654   Standard_Real aTol2D, anUr, aVr, aTolV3D;
655   GeomAbs_SurfaceType aType;
656   //
657   aType=aGAS.GetType();
658   aTolV3D=BRep_Tool::Tolerance(aV);
659
660   anUr=aGAS.UResolution(aTolV3D);
661   aVr =aGAS.VResolution(aTolV3D);
662   aTol2D=(aVr>anUr) ? aVr : anUr;
663   //
664   if (aType==GeomAbs_BSplineSurface||
665       aType==GeomAbs_Sphere||
666       GeomAbs_SurfaceOfRevolution) {
667     if (aTol2D < aTolV3D) {
668       aTol2D=aTolV3D;
669     }
670   }
671   if (aType==GeomAbs_BSplineSurface) {
672     aTol2D=1.1*aTol2D;
673   }
674   //
675   return aTol2D;
676 }
677
678 //=======================================================================
679 // function:  Coord2d
680 // purpose:
681 //=======================================================================
682  gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
683                    const TopoDS_Edge& aE1,
684                    const TopoDS_Face& aF)
685 {
686   Standard_Real aT, aFirst, aLast;
687   Handle(Geom2d_Curve) aC2D;
688   gp_Pnt2d aP2D1;
689   //
690   aT=BRep_Tool::Parameter (aV1, aE1, aF);
691   aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
692   aC2D->D0 (aT, aP2D1);
693   //
694   return aP2D1;
695 }
696 //=======================================================================
697 // function:  AngleIn
698 // purpose:
699 //=======================================================================
700  Standard_Real AngleIn(const TopoDS_Edge& aEIn,
701                        const BOP_ListOfEdgeInfo& aLEInfo)
702 {
703   Standard_Real anAngleIn;
704   Standard_Boolean anIsIn;
705   BOP_ListIteratorOfListOfEdgeInfo anIt;
706
707   anIt.Initialize(aLEInfo);
708   for (; anIt.More(); anIt.Next()) {
709     BOP_EdgeInfo& anEdgeInfo=anIt.Value();
710     const TopoDS_Edge& aE=anEdgeInfo.Edge();
711     anIsIn=anEdgeInfo.IsIn();
712     //
713     if (anIsIn && aE==aEIn) {
714       anAngleIn=anEdgeInfo.Angle();
715       return anAngleIn;
716     }
717   }
718   anAngleIn=0.;
719   return anAngleIn;
720 }
721 //=======================================================================
722 // function:  ClockWiseAngle
723 // purpose:
724 //=======================================================================
725  Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
726                               const Standard_Real aAngleOut)
727 {
728   Standard_Real aTwoPi = M_PI+M_PI;
729   Standard_Real dA, A1, A2, AIn, AOut ;
730
731   AIn=aAngleIn;
732   AOut=aAngleOut;
733   if (AIn >= aTwoPi) {
734     AIn=AIn-aTwoPi;
735   }
736   
737   if (AOut >= aTwoPi) {
738     AOut=AOut-aTwoPi;
739   }
740
741   A1 = AIn + M_PI;
742   
743   if (A1 >= aTwoPi) {
744     A1=A1-aTwoPi;
745   }
746   
747   A2=AOut;
748   
749   dA=A1-A2;
750   if (dA <= 0.) {
751     dA=aTwoPi+dA;
752     //modified by NIZNHY-PKV Thu Feb 17 08:26:39 2011f
753     if (dA <= 1.e-14) {
754       dA=aTwoPi;
755     }
756     //modified by NIZNHY-PKV Thu Feb 17 08:26:42 2011t
757   }
758   //xx
759   else if (dA <= 1.e-14) {
760     dA=aTwoPi;
761   }
762   return dA;
763 }
764 //=======================================================================
765 // function: GetNextVertex
766 // purpose: 
767 //=======================================================================
768  void GetNextVertex(const TopoDS_Vertex& aV,
769                     const TopoDS_Edge& aE,
770                     TopoDS_Vertex& aV1)
771 {
772   TopoDS_Iterator aIt;
773   //
774   aIt.Initialize(aE);
775   for (; aIt.More(); aIt.Next()) {
776     const TopoDS_Shape& aVx=aIt.Value();
777     if (!aVx.IsEqual(aV)) {
778       aV1=TopoDS::Vertex(aVx);
779       return ;
780     }
781   }
782   aV1=aV;
783 }
784 //=======================================================================
785 // function: Angle2D
786 // purpose: 
787 //=======================================================================
788   Standard_Real Angle2D (const TopoDS_Vertex& aV,
789                          const TopoDS_Edge& anEdge,
790                          const TopoDS_Face& myFace,
791                          const GeomAdaptor_Surface& aGAS,
792                          const Standard_Boolean aFlag)
793 {
794   Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
795   gp_Pnt2d aPV, aPV1;
796   gp_Vec2d aV2D;
797   Handle(Geom2d_Curve) aC2D;
798   //
799   aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
800   if (Precision::IsInfinite(aTV)) {
801     return 0.;
802   }
803   //
804   BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D, 
805                                     aFirst, aLast, aToler, Standard_True);
806   //dt=1.e-7;
807   dt=2.*Tolerance2D(aV, aGAS);
808   //
809   aTX=0.25*(aLast - aFirst);
810   if(dt > aTX) {
811     // to save direction of the curve as much as it possible
812     // in the case of big tolerances
813     dt = aTX; 
814   }
815   //
816   if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
817     aTV1=aTV + dt;
818   }
819   else {
820     aTV1=aTV - dt;
821   }
822   //
823   aC2D->D0 (aTV, aPV);
824   aC2D->D0 (aTV1, aPV1);
825   //
826   if (aFlag) {//IN
827     gp_Vec2d aV2DIn(aPV1, aPV);
828     aV2D=aV2DIn;
829   }
830   else {
831     gp_Vec2d aV2DOut(aPV, aPV1);
832     aV2D=aV2DOut;
833   }
834   //
835   gp_Dir2d aDir2D(aV2D);
836   anAngle=Angle(aDir2D);
837   //
838   return anAngle;
839 }
840 //=======================================================================
841 // function: Angle
842 // purpose: 
843 //=======================================================================
844 Standard_Real Angle (const gp_Dir2d& aDir2D)
845 {
846   gp_Dir2d      aRefDir(1., 0.);
847   Standard_Real anAngle = aRefDir.Angle(aDir2D);
848
849   if (anAngle < 0.)
850     anAngle += M_PI + M_PI;
851
852   return anAngle;
853 }
854 //
855 //=======================================================================
856 // function: NbWaysOut
857 // purpose: 
858 //=======================================================================
859 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& aLEInfo)
860 {
861   Standard_Boolean bIsOut, bIsNotPassed;
862   Standard_Integer iCnt=0;
863   BOP_ListIteratorOfListOfEdgeInfo anIt;
864   //
865   anIt.Initialize(aLEInfo);
866   for (; anIt.More(); anIt.Next()) {
867     BOP_EdgeInfo& anEI=anIt.Value();
868     //
869     bIsOut=!anEI.IsIn();
870     bIsNotPassed=!anEI.Passed();
871     if (bIsOut && bIsNotPassed) {
872       iCnt++;
873     }
874   }
875   return iCnt;
876 }