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