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