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