Salome HOME
This commit was generated by cvs2git to create tag 'TRIPOLI_323'.
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_WireSplitter.cxx
1 // Copyright (C) 2007-2012  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 // Author:      Peter KURNEV
25
26 #include <GEOMAlgo_WireSplitter.hxx>
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 #include <BRep_Tool.hxx>
48 #include <BRepAdaptor_Surface.hxx>
49 #include <BRepAdaptor_Curve2d.hxx>
50
51 #include <TopExp.hxx>
52 #include <TopExp_Explorer.hxx>
53
54 #include <TopTools_SequenceOfShape.hxx>
55 #include <TopTools_ListOfShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
58 #include <TopTools_IndexedMapOfShape.hxx>
59
60 #include <BOPTColStd_ListOfListOfShape.hxx>
61 #include <BOPTColStd_ListIteratorOfListOfListOfShape.hxx>
62
63 #include <BOPTools_Tools2D.hxx>
64
65 #include <BOP_EdgeInfo.hxx>
66 #include <BOP_ListOfEdgeInfo.hxx>
67 #include <BOP_ListIteratorOfListOfEdgeInfo.hxx>
68 #include <BOP_IndexedDataMapOfVertexListEdgeInfo.hxx>
69
70 static
71   void Path (const GeomAdaptor_Surface& aGAS,
72              const TopoDS_Face& myFace,
73              const TopoDS_Vertex& aVa,
74              const TopoDS_Edge& aEOuta,
75              BOP_EdgeInfo& anEdgeInfo,
76              TopTools_SequenceOfShape& aLS,
77              TopTools_SequenceOfShape& aVertVa,
78              TColgp_SequenceOfPnt2d& aCoordVa,
79              BOPTColStd_ListOfListOfShape& myShapes,
80              BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap);
81
82
83 static
84   Standard_Real Angle (const gp_Dir2d& aDir2D);
85
86
87 static
88   void GetNextVertex(const TopoDS_Vertex& aV,
89                      const TopoDS_Edge& aE,
90                      TopoDS_Vertex& aV1);
91 static
92   Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
93                                const Standard_Real aAngleOut);
94
95 static
96   Standard_Real AngleIn(const TopoDS_Edge& aEIn,
97                         const BOP_ListOfEdgeInfo& aLEInfo);
98
99 static
100   Standard_Real Angle2D (const TopoDS_Vertex& aV,
101                          const TopoDS_Edge& anEdge,
102                          const TopoDS_Face& myFace,
103                          const GeomAdaptor_Surface& aGAS,
104                          const Standard_Boolean aFlag);
105 static
106   gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
107                     const TopoDS_Edge& aE1,
108                     const TopoDS_Face& aF);
109 static
110   gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
111                       const TopoDS_Face& aF);
112 static
113   Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
114                             const GeomAdaptor_Surface& aGAS);
115
116
117 //modified by NIZNHY-PKV Thu Apr 19 09:04:59 2012f
118 static
119   Standard_Integer NbWaysOut(const TopoDS_Edge& aEOuta,
120                              const BOP_ListOfEdgeInfo& aLEInfo);
121 //static
122 //  Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& );
123 //modified by NIZNHY-PKV Thu Apr 19 09:04:53 2012t
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   Standard_Integer i,j, aNb, aNbj, iCnt;
453   Standard_Real aTol, anAngleIn, anAngleOut, anAngle, aMinAngle;
454   Standard_Real aTol2D, aTol2D2;
455   Standard_Real aTol2, aD2;
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   aTol=2.*Tolerance2D(aVb, aGAS);
489   aTol2=10.*aTol*aTol;
490   //
491   aNb=aLS.Length();
492   if (aNb>0) {
493     //
494     TopTools_ListOfShape aBuf;
495     //
496     for (i=aNb; i>0; i--) {
497       const TopoDS_Shape& aVPrev=aVertVa(i);
498       const gp_Pnt2d& aPaPrev=aCoordVa(i);
499       const TopoDS_Shape& aEPrev=aLS(i);
500
501       aBuf.Append(aEPrev);
502
503       anIsSameV=aVPrev.IsSame(aVb);
504       anIsSameV2d=Standard_False;
505
506       if (anIsSameV) {
507         anIsSameV2d = Standard_True;
508         //
509         aD2=aPaPrev.SquareDistance(aPb);
510         anIsSameV2d =aD2<aTol2;
511       }//if (anIsSameV) {
512       //
513       if (anIsSameV && anIsSameV2d) {
514         myShapes.Append(aBuf);
515         //
516         TopTools_SequenceOfShape aLSt, aVertVat;
517         TColgp_SequenceOfPnt2d aCoordVat;
518         //
519         aNbj=i-1;
520         if (aNbj<1) {
521           //
522           aLS.Clear();
523           aVertVa.Clear();
524           aCoordVa.Clear();
525           //
526           return;
527         }
528
529         aVb=TopoDS::Vertex(aVertVa(i));
530
531         for (j=1; j<=aNbj; j++) {
532           aLSt.Append(aLS(j));
533           aVertVat.Append(aVertVa(j));
534           aCoordVat.Append(aCoordVa(j));
535         }
536         //
537         aLS.Clear();
538         aVertVa.Clear();
539         aCoordVa.Clear();
540
541         aLS=aLSt;
542         aVertVa=aVertVat;
543         aCoordVa=aCoordVat;
544         //
545         break;
546       }
547     }
548   }
549   //
550   aTol2D=2.*Tolerance2D(aVb, aGAS);
551   aTol2D2=100.*aTol2D*aTol2D;
552   //
553   // anAngleIn in Vb from edge aEOuta
554   const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
555   //
556   anAngleIn=AngleIn(aEOuta, aLEInfo);
557   //
558   // aEOutb
559   BOP_EdgeInfo *pEdgeInfo=NULL;
560
561   aMinAngle=100.;
562   anIsFound=Standard_False;
563   //
564   //modified by NIZNHY-PKV Thu Apr 19 09:05:09 2012f
565   iCnt=NbWaysOut (aEOuta, aLEInfo); 
566   //iCnt=NbWaysOut (aLEInfo); 
567   //modified by NIZNHY-PKV Thu Apr 19 09:05:12 2012t
568   if (!iCnt) { // no way to go . (Error)
569     return ;
570   }
571   //
572   anIt.Initialize(aLEInfo);
573   for (; anIt.More(); anIt.Next()) {
574     BOP_EdgeInfo& anEI=anIt.Value();
575     const TopoDS_Edge& aE=anEI.Edge();
576     anIsOut=!anEI.IsIn();
577     anIsNotPassed=!anEI.Passed();
578     //
579     if (anIsOut && anIsNotPassed) {
580       if (aE.IsSame(aEOuta)) {
581         continue;
582       }
583       //
584       if (iCnt==1) {
585         // the one and only way to go out .
586         pEdgeInfo=&anEI;
587         anIsFound=Standard_True;
588         break;
589       }
590       //
591       // Look for minimal angle and make the choice.
592       gp_Pnt2d aP2Dx;
593       //
594       aP2Dx=Coord2dVf(aE, myFace);
595       //
596       aD2=aP2Dx.SquareDistance(aPb);
597       if (aD2 > aTol2D2){
598         continue;
599       }
600       //
601       anAngleOut=anEI.Angle();
602       //
603       anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
604       if (anAngle < aMinAngle) {
605         aMinAngle=anAngle;
606         pEdgeInfo=&anEI;
607         anIsFound=Standard_True;
608       }
609     }
610   } // for (; anIt.More(); anIt.Next())
611   //
612   if (!anIsFound) {
613     // no way to go . (Error)
614     return;
615   }
616   //
617   aEOutb=pEdgeInfo->Edge();
618   //
619   Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS,
620         aVertVa, aCoordVa, myShapes, mySmartMap);
621 }
622 //=======================================================================
623 // function:  Coord2dVf
624 // purpose:
625 //=======================================================================
626  gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
627                      const TopoDS_Face& aF)
628 {
629   Standard_Real aCoord=99.;
630   gp_Pnt2d aP2D1(aCoord, aCoord);
631   TopoDS_Iterator aIt;
632   //
633   aIt.Initialize(aE);
634   for (; aIt.More(); aIt.Next()) {
635     const TopoDS_Shape& aVx=aIt.Value();
636     if (aVx.Orientation()==TopAbs_FORWARD) {
637       const TopoDS_Vertex& aVxx=TopoDS::Vertex(aVx);
638       aP2D1=Coord2d(aVxx, aE, aF);
639       return aP2D1;
640     }
641   }
642   return aP2D1;
643 }
644 //=======================================================================
645 // function:  Tolerance2D
646 // purpose:
647 //=======================================================================
648  Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
649                             const GeomAdaptor_Surface& aGAS)
650 {
651   Standard_Real aTol2D, anUr, aVr, aTolV3D;
652   GeomAbs_SurfaceType aType;
653   //
654   aType=aGAS.GetType();
655   aTolV3D=BRep_Tool::Tolerance(aV);
656
657   anUr=aGAS.UResolution(aTolV3D);
658   aVr =aGAS.VResolution(aTolV3D);
659   aTol2D=(aVr>anUr) ? aVr : anUr;
660   //
661   if (aType==GeomAbs_BSplineSurface||
662       aType==GeomAbs_Sphere||
663       GeomAbs_SurfaceOfRevolution) {
664     if (aTol2D < aTolV3D) {
665       aTol2D=aTolV3D;
666     }
667   }
668   if (aType==GeomAbs_BSplineSurface) {
669     aTol2D=1.1*aTol2D;
670   }
671   //
672   return aTol2D;
673 }
674
675 //=======================================================================
676 // function:  Coord2d
677 // purpose:
678 //=======================================================================
679  gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
680                    const TopoDS_Edge& aE1,
681                    const TopoDS_Face& aF)
682 {
683   Standard_Real aT, aFirst, aLast;
684   Handle(Geom2d_Curve) aC2D;
685   gp_Pnt2d aP2D1;
686   //
687   aT=BRep_Tool::Parameter (aV1, aE1, aF);
688   aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
689   aC2D->D0 (aT, 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   Standard_Real anAngleIn;
701   Standard_Boolean anIsIn;
702   BOP_ListIteratorOfListOfEdgeInfo anIt;
703
704   anIt.Initialize(aLEInfo);
705   for (; anIt.More(); anIt.Next()) {
706     BOP_EdgeInfo& anEdgeInfo=anIt.Value();
707     const TopoDS_Edge& aE=anEdgeInfo.Edge();
708     anIsIn=anEdgeInfo.IsIn();
709     //
710     if (anIsIn && aE==aEIn) {
711       anAngleIn=anEdgeInfo.Angle();
712       return anAngleIn;
713     }
714   }
715   anAngleIn=0.;
716   return anAngleIn;
717 }
718 //=======================================================================
719 // function:  ClockWiseAngle
720 // purpose:
721 //=======================================================================
722  Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
723                               const Standard_Real aAngleOut)
724 {
725   Standard_Real aTwoPi = M_PI+M_PI;
726   Standard_Real dA, A1, A2, AIn, AOut ;
727
728   AIn=aAngleIn;
729   AOut=aAngleOut;
730   if (AIn >= aTwoPi) {
731     AIn=AIn-aTwoPi;
732   }
733
734   if (AOut >= aTwoPi) {
735     AOut=AOut-aTwoPi;
736   }
737
738   A1 = AIn + M_PI;
739
740   if (A1 >= aTwoPi) {
741     A1=A1-aTwoPi;
742   }
743
744   A2=AOut;
745
746   dA=A1-A2;
747   if (dA <= 0.) {
748     dA=aTwoPi+dA;
749     if (dA <= 1.e-14) {
750       dA=aTwoPi;
751     }
752   }
753   //xx
754   else if (dA <= 1.e-14) {
755     dA=aTwoPi;
756   }
757   return dA;
758 }
759 //=======================================================================
760 // function: GetNextVertex
761 // purpose:
762 //=======================================================================
763  void GetNextVertex(const TopoDS_Vertex& aV,
764                     const TopoDS_Edge& aE,
765                     TopoDS_Vertex& aV1)
766 {
767   TopoDS_Iterator aIt;
768   //
769   aIt.Initialize(aE);
770   for (; aIt.More(); aIt.Next()) {
771     const TopoDS_Shape& aVx=aIt.Value();
772     if (!aVx.IsEqual(aV)) {
773       aV1=TopoDS::Vertex(aVx);
774       return ;
775     }
776   }
777   aV1=aV;
778 }
779 //=======================================================================
780 // function: Angle2D
781 // purpose:
782 //=======================================================================
783   Standard_Real Angle2D (const TopoDS_Vertex& aV,
784                          const TopoDS_Edge& anEdge,
785                          const TopoDS_Face& myFace,
786                          const GeomAdaptor_Surface& aGAS,
787                          const Standard_Boolean aFlag)
788 {
789   Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
790   gp_Pnt2d aPV, aPV1;
791   gp_Vec2d aV2D;
792   Handle(Geom2d_Curve) aC2D;
793   //
794   aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
795   if (Precision::IsInfinite(aTV)) {
796     return 0.;
797   }
798   //
799   BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D,
800                                     aFirst, aLast, aToler, Standard_True);
801   //dt=1.e-7;
802   dt=2.*Tolerance2D(aV, aGAS);
803   //
804   aTX=0.25*(aLast - aFirst);
805   if(dt > aTX) {
806     // to save direction of the curve as much as it possible
807     // in the case of big tolerances
808     dt = aTX;
809   }
810   //
811   if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
812     aTV1=aTV + dt;
813   }
814   else {
815     aTV1=aTV - dt;
816   }
817   //
818   aC2D->D0 (aTV, aPV);
819   aC2D->D0 (aTV1, aPV1);
820   //
821   if (aFlag) {//IN
822     gp_Vec2d aV2DIn(aPV1, aPV);
823     aV2D=aV2DIn;
824   }
825   else {
826     gp_Vec2d aV2DOut(aPV, aPV1);
827     aV2D=aV2DOut;
828   }
829   //
830   gp_Dir2d aDir2D(aV2D);
831   anAngle=Angle(aDir2D);
832   //
833   return anAngle;
834 }
835 //=======================================================================
836 // function: Angle
837 // purpose:
838 //=======================================================================
839 Standard_Real Angle (const gp_Dir2d& aDir2D)
840 {
841   gp_Dir2d      aRefDir(1., 0.);
842   Standard_Real anAngle = aRefDir.Angle(aDir2D);
843
844   if (anAngle < 0.)
845     anAngle += M_PI + M_PI;
846
847   return anAngle;
848 }
849 //modified by NIZNHY-PKV Thu Apr 19 09:02:04 2012f
850 //=======================================================================
851 // function: NbWaysOut
852 // purpose:
853 //=======================================================================
854 Standard_Integer NbWaysOut(const TopoDS_Edge& aEOuta,
855                            const BOP_ListOfEdgeInfo& aLEInfo)
856 {
857   Standard_Boolean bIsOut, bIsNotPassed;
858   Standard_Integer iCnt=0;
859   BOP_ListIteratorOfListOfEdgeInfo anIt;
860   //
861   anIt.Initialize(aLEInfo);
862   for (; anIt.More(); anIt.Next()) {
863     BOP_EdgeInfo& aEI=anIt.Value();
864     const TopoDS_Edge& aE=aEI.Edge();
865     bIsOut=!aEI.IsIn();
866     bIsNotPassed=!aEI.Passed();
867     if (bIsOut && bIsNotPassed) {
868       if (!aE.IsSame(aEOuta)) {
869         iCnt++;
870       }
871     }
872   }
873   return iCnt;
874 }
875 /*
876 //=======================================================================
877 // function: NbWaysOut
878 // purpose:
879 //=======================================================================
880 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& aLEInfo)
881 {
882   Standard_Boolean bIsOut, bIsNotPassed;
883   Standard_Integer iCnt=0;
884   BOP_ListIteratorOfListOfEdgeInfo anIt;
885   //
886   anIt.Initialize(aLEInfo);
887   for (; anIt.More(); anIt.Next()) {
888     BOP_EdgeInfo& anEI=anIt.Value();
889     //
890     bIsOut=!anEI.IsIn();
891     bIsNotPassed=!anEI.Passed();
892     if (bIsOut && bIsNotPassed) {
893       iCnt++;
894     }
895   }
896   return iCnt;
897 }
898 */
899 //modified by NIZNHY-PKV Thu Apr 19 09:01:57 2012t