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