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