Salome HOME
Merging with WPdev
[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   //modified by NIZNHY-PKV Tue Nov 14 16:56:19 2006f
493   /*
494   UVTolerance2D(aVb, aGAS, aTolUVb, aTolVVb);
495   aTolUVb = 2.*aTolUVb;
496   aTolVVb = 2.*aTolVVb;
497   */
498   //modified by NIZNHY-PKV Tue Nov 14 16:56:26 2006t
499   //
500   aNb=aLS.Length();
501   if (aNb>0) {
502     //
503     TopTools_ListOfShape aBuf;
504     //
505     for (i=aNb; i>0; i--) {
506       const TopoDS_Shape& aVPrev=aVertVa(i);
507       const gp_Pnt2d& aPaPrev=aCoordVa(i);
508       const TopoDS_Shape& aEPrev=aLS(i);
509
510       aBuf.Append(aEPrev);
511
512       anIsSameV=aVPrev.IsSame(aVb);
513       anIsSameV2d=Standard_False;
514
515       if (anIsSameV) {
516         anIsSameV2d = Standard_True;
517         //
518         aD2=aPaPrev.SquareDistance(aPb);
519         anIsSameV2d =aD2<aTol2;
520         //
521         //modified by NIZNHY-PKV Tue Nov 14 16:56:49 2006f
522         /*
523         if(anIsSameV2d) {
524           Standard_Real udist, vdist;
525           //
526           udist=fabs(aPaPrev.X() - aPb.X());
527           vdist=fabs(aPaPrev.Y() - aPb.Y());
528           if((udist > aTolUVb) || (vdist > aTolVVb)) {
529             anIsSameV2d=!anIsSameV2d;
530           }
531         }
532         */
533         //modified by NIZNHY-PKV Tue Nov 14 16:56:54 2006t
534       }//if (anIsSameV) {
535       //
536       if (anIsSameV && anIsSameV2d) {
537         myShapes.Append(aBuf);
538         //
539         TopTools_SequenceOfShape aLSt, aVertVat;
540         TColgp_SequenceOfPnt2d aCoordVat;
541         //
542         aNbj=i-1;
543         if (aNbj<1) {
544           //
545           aLS.Clear();
546           aVertVa.Clear();
547           aCoordVa.Clear();
548           //
549           return;
550         }
551
552         aVb=TopoDS::Vertex(aVertVa(i));
553
554         for (j=1; j<=aNbj; j++) {
555           aLSt.Append(aLS(j));
556           aVertVat.Append(aVertVa(j));
557           aCoordVat.Append(aCoordVa(j));
558         }
559         //
560         aLS.Clear();
561         aVertVa.Clear();
562         aCoordVa.Clear();
563
564         aLS=aLSt;
565         aVertVa=aVertVat;
566         aCoordVa=aCoordVat;
567         //
568         break;
569       }
570     }
571   }
572   //
573   aTol2D=2.*Tolerance2D(aVb, aGAS);
574   aTol2D2=aTol2D*aTol2D;
575   //
576   // anAngleIn in Vb from edge aEOuta
577   const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
578   //
579   anAngleIn=AngleIn(aEOuta, aLEInfo);
580   //
581   // aEOutb
582   BOP_EdgeInfo *pEdgeInfo=NULL;
583
584   aMinAngle=100.;
585   anIsFound=Standard_False;
586
587   Standard_Integer aCurIndexE = 0;
588
589   anIt.Initialize(aLEInfo);
590   for (; anIt.More(); anIt.Next()) {
591     BOP_EdgeInfo& anEI=anIt.Value();
592     const TopoDS_Edge& aE=anEI.Edge();
593     anIsOut=!anEI.IsIn();
594     anIsNotPassed=!anEI.Passed();
595     
596     if (anIsOut && anIsNotPassed) {
597       aCurIndexE++;
598       //
599       // Is there one way to go out of the vertex 
600       // we have to use it only.
601       Standard_Integer iCnt;
602       iCnt=NbWaysOut (aLEInfo);
603       //
604       if (!iCnt) {
605         // no way to go . (Error)
606         return ;
607       }
608       //
609       if (iCnt==1) {
610         // the one and only way to go out .
611         pEdgeInfo=&anEI;
612         anIsFound=Standard_True;
613         break;
614       }
615       //
616       // Look for minimal angle and make the choice.
617       gp_Pnt2d aP2Dx;
618       //
619       aP2Dx=Coord2dVf(aE, myFace);
620       //
621       aD2=aP2Dx.SquareDistance(aPb);
622       if (aD2 > aTol2D2){
623         continue;
624       }
625       //
626       //
627       anAngleOut=anEI.Angle();
628       //
629       anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
630       if (anAngle < aMinAngle) {
631         aMinAngle=anAngle;
632         pEdgeInfo=&anEI;
633         anIsFound=Standard_True;
634       }
635     }
636   } // for (; anIt.More(); anIt.Next()) 
637   //
638   if (!anIsFound) {
639     // no way to go . (Error)
640     return;
641   }
642   
643   aEOutb=pEdgeInfo->Edge();
644   //
645   Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS, 
646         aVertVa, aCoordVa, myShapes, mySmartMap);
647 }
648 //=======================================================================
649 // function:  Coord2dVf
650 // purpose:
651 //=======================================================================
652  gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
653                      const TopoDS_Face& aF)
654 {
655   Standard_Real aCoord=99.;
656   gp_Pnt2d aP2D1(aCoord, aCoord);
657   TopoDS_Iterator aIt;
658   //
659   aIt.Initialize(aE);
660   for (; aIt.More(); aIt.Next()) {
661     const TopoDS_Shape& aVx=aIt.Value();
662     if (aVx.Orientation()==TopAbs_FORWARD) {
663       const TopoDS_Vertex& aVxx=TopoDS::Vertex(aVx);
664       aP2D1=Coord2d(aVxx, aE, aF);
665       return aP2D1;
666     }
667   }
668   return aP2D1;
669 }
670 //=======================================================================
671 // function:  Tolerance2D
672 // purpose:
673 //=======================================================================
674  Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
675                             const GeomAdaptor_Surface& aGAS)                 
676 {
677   Standard_Real aTol2D, anUr, aVr, aTolV3D;
678   GeomAbs_SurfaceType aType;
679   //
680   aType=aGAS.GetType();
681   aTolV3D=BRep_Tool::Tolerance(aV);
682
683   anUr=aGAS.UResolution(aTolV3D);
684   aVr =aGAS.VResolution(aTolV3D);
685   aTol2D=(aVr>anUr) ? aVr : anUr;
686   //
687   if (aType==GeomAbs_BSplineSurface||
688       aType==GeomAbs_Sphere) {
689     if (aTol2D < aTolV3D) {
690       aTol2D=aTolV3D;
691     }
692   }
693   if (aType==GeomAbs_BSplineSurface) {
694     aTol2D=1.1*aTol2D;
695   }
696   //
697   return aTol2D;
698 }
699
700 //=======================================================================
701 // function:  Coord2d
702 // purpose:
703 //=======================================================================
704  gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
705                    const TopoDS_Edge& aE1,
706                    const TopoDS_Face& aF)
707 {
708   Standard_Real aT, aFirst, aLast;
709   Handle(Geom2d_Curve) aC2D;
710   gp_Pnt2d aP2D1;
711   //
712   aT=BRep_Tool::Parameter (aV1, aE1, aF);
713   aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
714   aC2D->D0 (aT, aP2D1);
715   //
716   return aP2D1;
717 }
718 //=======================================================================
719 // function:  AngleIn
720 // purpose:
721 //=======================================================================
722  Standard_Real AngleIn(const TopoDS_Edge& aEIn,
723                        const BOP_ListOfEdgeInfo& aLEInfo)
724 {
725   Standard_Real anAngleIn;
726   Standard_Boolean anIsIn;
727   BOP_ListIteratorOfListOfEdgeInfo anIt;
728
729   anIt.Initialize(aLEInfo);
730   for (; anIt.More(); anIt.Next()) {
731     BOP_EdgeInfo& anEdgeInfo=anIt.Value();
732     const TopoDS_Edge& aE=anEdgeInfo.Edge();
733     anIsIn=anEdgeInfo.IsIn();
734     //
735     if (anIsIn && aE==aEIn) {
736       anAngleIn=anEdgeInfo.Angle();
737       return anAngleIn;
738     }
739   }
740   anAngleIn=0.;
741   return anAngleIn;
742 }
743 //=======================================================================
744 // function:  ClockWiseAngle
745 // purpose:
746 //=======================================================================
747  Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
748                               const Standard_Real aAngleOut)
749 {
750   Standard_Real aTwoPi=Standard_PI+Standard_PI;
751   Standard_Real dA, A1, A2, AIn, AOut ;
752
753   AIn=aAngleIn;
754   AOut=aAngleOut;
755   if (AIn >= aTwoPi) {
756     AIn=AIn-aTwoPi;
757   }
758   
759   if (AOut >= aTwoPi) {
760     AOut=AOut-aTwoPi;
761   }
762
763   A1=AIn+Standard_PI;
764   
765   if (A1 >= aTwoPi) {
766     A1=A1-aTwoPi;
767   }
768   
769   A2=AOut;
770   
771   dA=A1-A2;
772   if (dA <= 0.) {
773     dA=aTwoPi+dA;
774   }
775   //xx
776   //else if (dA <= 1.e-15) {
777   else if (dA <= 1.e-14) {
778     dA=aTwoPi;
779   }
780   return dA;
781 }
782 //=======================================================================
783 // function: GetNextVertex
784 // purpose: 
785 //=======================================================================
786  void GetNextVertex(const TopoDS_Vertex& aV,
787                     const TopoDS_Edge& aE,
788                     TopoDS_Vertex& aV1)
789 {
790   TopoDS_Iterator aIt;
791   //
792   aIt.Initialize(aE);
793   for (; aIt.More(); aIt.Next()) {
794     const TopoDS_Shape& aVx=aIt.Value();
795     if (!aVx.IsEqual(aV)) {
796       aV1=TopoDS::Vertex(aVx);
797       return ;
798     }
799   }
800   aV1=aV;
801 }
802 //=======================================================================
803 // function: Angle2D
804 // purpose: 
805 //=======================================================================
806   Standard_Real Angle2D (const TopoDS_Vertex& aV,
807                          const TopoDS_Edge& anEdge,
808                          const TopoDS_Face& myFace,
809                          const GeomAdaptor_Surface& aGAS,
810                          const Standard_Boolean aFlag)
811 {
812   Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle;
813   
814   Handle(Geom2d_Curve) aC2D;
815   
816   BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D, 
817                                     aFirst, aLast, aToler, Standard_True);
818
819   aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
820   if (Precision::IsInfinite(aTV))
821     return 0.;
822
823   //dt=1.e-7;
824   dt=Tolerance2D(aV, aGAS);
825   
826   if(dt > (aLast - aFirst) * 0.25) {
827     // to save direction of the curve as much as it possible
828     // in the case of big tolerances
829     dt = (aLast - aFirst) * 0.25; 
830   }
831   //
832   if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
833     aTV1=aTV + dt;
834   }
835   else {
836     aTV1=aTV - dt;
837   }
838   
839   gp_Pnt2d aPV, aPV1;
840   aC2D->D0 (aTV, aPV);
841   aC2D->D0 (aTV1, aPV1);
842   
843   gp_Vec2d aV2D;
844   //
845   if (aFlag) {//IN
846     gp_Vec2d aV2DIn(aPV1, aPV);
847     //
848     aV2D=aV2DIn;
849   }
850
851   else {
852     gp_Vec2d aV2DOut(aPV, aPV1);
853     aV2D=aV2DOut;
854   }
855
856   gp_Dir2d aDir2D(aV2D);
857   anAngle=Angle(aDir2D);
858
859   return anAngle;
860 }
861 //=======================================================================
862 // function: Angle
863 // purpose: 
864 //=======================================================================
865 Standard_Real Angle (const gp_Dir2d& aDir2D)
866 {
867   gp_Dir2d      aRefDir(1., 0.);
868   Standard_Real anAngle = aRefDir.Angle(aDir2D);
869
870   if (anAngle < 0.)
871     anAngle += Standard_PI + Standard_PI;
872
873   return anAngle;
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 //modified by NIZNHY-PKV Tue Nov 14 16:55:31 2006f
899 /*
900 static
901   void UVTolerance2D (const TopoDS_Vertex& aV,
902                       const GeomAdaptor_Surface& aGAS,
903                       Standard_Real& aTolU,
904                       Standard_Real& aTolV);
905 */
906 /*
907 //=======================================================================
908 //function : UVTolerance2D
909 //purpose  : 
910 //=======================================================================
911 void UVTolerance2D (const TopoDS_Vertex& aV,
912                     const GeomAdaptor_Surface& aGAS,
913                     Standard_Real& aTolU,
914                     Standard_Real& aTolV)
915 {
916   Standard_Real aTolV3D;
917   //
918   aTolV3D = BRep_Tool::Tolerance(aV);
919   aTolU=aGAS.UResolution(aTolV3D);
920   aTolV=aGAS.VResolution(aTolV3D);
921 }
922 */
923 //modified by NIZNHY-PKV Tue Nov 14 16:55:39 2006