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