0024510: Remove unused local variables
[occt.git] / src / BOPTools / BOPTools_AlgoTools.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
3 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5 //                         EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 //
7 // This file is part of Open CASCADE Technology software library.
8 //
9 // This library is free software; you can redistribute it and / or modify it
10 // under the terms of the GNU Lesser General Public version 2.1 as published
11 // by the Free Software Foundation, with special exception defined in the file
12 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 // distribution for complete text of the license and disclaimer of any warranty.
14 //
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
17
18 #include <BOPTools_AlgoTools.ixx>
19 //
20 #include <Precision.hxx>
21 //
22 #include <gp_Pnt.hxx>
23 #include <gp_XYZ.hxx>
24 #include <gp_Pnt2d.hxx>
25 #include <gp_Cylinder.hxx>
26 #include <gp_Cone.hxx>
27 #include <gp_Sphere.hxx>
28 #include <gp_Torus.hxx>
29 #include <gp_Lin.hxx>
30 //
31 #include <Geom2d_Curve.hxx>
32 #include <Geom_Surface.hxx>
33 #include <Geom_Plane.hxx>
34 #include <Geom_TrimmedCurve.hxx>
35 #include <Geom_Curve.hxx>
36 #include <GeomAPI_ProjectPointOnSurf.hxx>
37 #include <Geom2dInt_Geom2dCurveTool.hxx>
38 //
39 #include <TopAbs_Orientation.hxx>
40 //
41 #include <TopoDS_Compound.hxx>
42 #include <TopoDS_CompSolid.hxx>
43 #include <TopoDS_Solid.hxx>
44 #include <TopoDS_Shell.hxx>
45 #include <TopoDS_Wire.hxx>
46 //
47 #include <BRep_Builder.hxx>
48 #include <BRep_Tool.hxx>
49 #include <BRepLib.hxx>
50 #include <BRepAdaptor_Curve2d.hxx>
51 #include <BRepAdaptor_Surface.hxx>
52 #include <BRepClass3d_SolidClassifier.hxx>
53 #include <TopExp.hxx>
54 #include <TopExp_Explorer.hxx>
55 //
56 #include <IntTools_Tools.hxx>
57 //
58 #include <BOPTools.hxx>
59 #include <BOPTools_CoupleOfShape.hxx>
60 #include <BOPTools_ListOfCoupleOfShape.hxx>
61 #include <BOPTools_AlgoTools2D.hxx>
62 #include <BOPTools_AlgoTools3D.hxx>
63 //
64 #include <BOPCol_IndexedMapOfShape.hxx>
65 #include <BOPCol_MapOfShape.hxx>
66 //
67 #include <BOPInt_ShrunkRange.hxx>
68 //
69
70 static
71   Standard_Real AngleWithRef(const gp_Dir& theD1,
72                              const gp_Dir& theD2,
73                              const gp_Dir& theDRef);
74
75 static
76   Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
77                                   const BOPCol_ListOfShape& thLF,
78                                   BOPTools_ListOfCoupleOfShape& theLCFF,
79                                   Handle(BOPInt_Context)& theContext);
80 static
81   TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
82                                  const TopoDS_Face& aF);
83
84 static
85   void GetFaceDir(const TopoDS_Edge& aE,
86                   const TopoDS_Face& aF,
87                   const gp_Pnt& aP,
88                   const Standard_Real aT,
89                   const gp_Dir& aDTgt,
90                   gp_Dir& aDN,
91                   gp_Dir& aDB,
92                   Handle(BOPInt_Context)& theContext,
93                   GeomAPI_ProjectPointOnSurf& aProjPL);
94 static
95   Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
96                                    const TopoDS_Face& aF,
97                                    const gp_Pnt& aP,
98                                    gp_Dir& aDB,
99                                    gp_Pnt& aPOut,
100                                    Handle(BOPInt_Context)& theContext,
101                                    GeomAPI_ProjectPointOnSurf& aProjPL);
102
103 //=======================================================================
104 // function: MakeConnexityBlocks
105 // purpose: 
106 //=======================================================================
107 void BOPTools_AlgoTools::MakeConnexityBlocks (const TopoDS_Shape& theS,
108                                               const TopAbs_ShapeEnum theType1,
109                                               const TopAbs_ShapeEnum theType2,
110                                               BOPCol_ListOfShape& theLCB)
111 {
112   Standard_Integer  aNbF, aNbAdd, aNbAdd1, i;
113   BRep_Builder aBB;
114   TopoDS_Compound aC;
115   TopoDS_Iterator aIt;
116   TopExp_Explorer aExp;
117   BOPCol_MapOfShape aMP;
118   BOPCol_IndexedMapOfShape aMCB, aMAdd, aMAdd1;
119   BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
120   BOPCol_ListIteratorOfListOfShape aItLF;
121   //
122   // 1. aMEF
123   BOPTools::MapShapesAndAncestors(theS, theType1, theType2, aMEF);
124   //
125   // 2. aMCB
126   aIt.Initialize(theS);
127   for (; aIt.More(); aIt.Next()) {
128     const TopoDS_Shape& aF1=aIt.Value();
129     if (aMP.Contains(aF1)) {
130       continue;
131     }
132     //
133     aMCB.Clear();
134     aMAdd.Clear();
135     aMAdd.Add(aF1);
136     //
137     for(;;) {
138       aMAdd1.Clear();
139       //
140       aNbAdd = aMAdd.Extent();
141       for (i=1; i<=aNbAdd; ++i) {
142         const TopoDS_Shape& aF=aMAdd(i);
143         //
144         aExp.Init(aF, theType1);
145         for (; aExp.More(); aExp.Next()) {
146           const TopoDS_Shape& aE=aExp.Current();
147           //
148           const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
149           aItLF.Initialize(aLF);
150           for (; aItLF.More(); aItLF.Next()) {
151             const TopoDS_Shape& aFx=aItLF.Value();
152             if (aFx.IsSame(aF)) {
153               continue;
154             }
155             if (aMCB.Contains(aFx)) {
156               continue;
157             }
158             aMAdd1.Add(aFx);
159           }
160         }//for (; aExp.More(); aExp.Next()){
161         aMCB.Add(aF);
162       }// for (i=1; i<=aNbAdd; ++i) {
163       //
164       aNbAdd1=aMAdd1.Extent();
165       if (!aNbAdd1) {
166         break;// ->make new CB from aMCB
167       }
168       //
169       aMAdd.Clear();
170       for (i=1; i<=aNbAdd1; ++i) {
171         const TopoDS_Shape& aFAdd = aMAdd1(i);
172         aMAdd.Add(aFAdd);
173       }
174     }//while(1) {
175     //
176     aNbF=aMCB.Extent();
177     if (aNbF) {
178       aBB.MakeCompound(aC);
179       //
180       for (i=1; i<=aNbF; ++i) {
181         const TopoDS_Shape& aF=aMCB(i);
182         aBB.Add(aC, aF);  
183         aMP.Add(aF);
184       }
185       theLCB.Append(aC);
186     }
187   }// for (; aIt.More(); aIt.Next()) 
188 }
189 //=======================================================================
190 // function: OrientFacesOnShell
191 // purpose: 
192 //=======================================================================
193 void BOPTools_AlgoTools::OrientFacesOnShell (TopoDS_Shape& aShell)
194 {
195   Standard_Boolean bIsProcessed1, bIsProcessed2;
196   Standard_Integer i, aNbE, aNbF, j;
197   TopAbs_Orientation anOrE1, anOrE2;
198   TopoDS_Face aF1x, aF2x;
199   TopoDS_Shape aShellNew;
200   BOPCol_IndexedDataMapOfShapeListOfShape aEFMap;
201   BOPCol_IndexedMapOfShape aProcessedFaces;
202   BRep_Builder aBB;
203   //
204   BOPTools_AlgoTools::MakeContainer(TopAbs_SHELL, aShellNew);
205   //
206   BOPTools::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
207   aNbE=aEFMap.Extent();
208   // 
209   // One seam edge  in aEFMap contains  2 equivalent faces.
210   for (i=1; i<=aNbE; ++i) {
211     BOPCol_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
212     aNbF=aLF.Extent();
213     if (aNbF>1) {
214       BOPCol_ListOfShape aLFTmp;
215       BOPCol_IndexedMapOfShape aFM;
216       //
217       BOPCol_ListIteratorOfListOfShape anIt(aLF);
218       for (; anIt.More(); anIt.Next()) {
219         const TopoDS_Shape& aF=anIt.Value();
220         if (!aFM.Contains(aF)) {
221           aFM.Add(aF);
222           aLFTmp.Append(aF);
223         }
224       }
225       aLF.Clear();
226       aLF=aLFTmp;
227     }
228   }
229   //
230   // Do
231   for (i=1; i<=aNbE; ++i) {
232     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
233     if (BRep_Tool::Degenerated(aE)) {
234       continue;
235     }
236     //
237     const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
238     aNbF=aLF.Extent();
239     if (aNbF!=2) {
240       continue;
241     }
242     //
243     TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
244     TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
245     //    
246     bIsProcessed1=aProcessedFaces.Contains(aF1);
247     bIsProcessed2=aProcessedFaces.Contains(aF2);
248     if (bIsProcessed1 && bIsProcessed2) {
249       continue;
250     }
251     
252     if (!bIsProcessed1 && !bIsProcessed2) {
253       aProcessedFaces.Add(aF1);
254       aBB.Add(aShellNew, aF1);
255       bIsProcessed1=!bIsProcessed1;
256     }
257     //
258     aF1x=aF1;
259     if (bIsProcessed1) {
260       j=aProcessedFaces.FindIndex(aF1);
261       aF1x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
262     }
263     //
264     aF2x=aF2;
265     if (bIsProcessed2) {
266       j=aProcessedFaces.FindIndex(aF2);
267       aF2x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
268     }
269     //
270     anOrE1=Orientation(aE, aF1x); 
271     anOrE2=Orientation(aE, aF2x);
272     //
273     if (bIsProcessed1 && !bIsProcessed2) {
274       if (anOrE1==anOrE2) {
275         if (!BRep_Tool::IsClosed(aE, aF1) &&
276             !BRep_Tool::IsClosed(aE, aF2)) {
277           aF2.Reverse();
278         }
279       }
280       aProcessedFaces.Add(aF2);
281       aBB.Add(aShellNew, aF2);
282     }
283     else if (!bIsProcessed1 && bIsProcessed2) {
284       if (anOrE1==anOrE2) {
285         if (!BRep_Tool::IsClosed(aE, aF1) &&
286             !BRep_Tool::IsClosed(aE, aF2)) {
287           aF1.Reverse();
288         }
289       }
290       aProcessedFaces.Add(aF1);
291       aBB.Add(aShellNew, aF1);
292     }
293   }
294   //
295   //
296   for (i=1; i<=aNbE; ++i) {
297     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
298     if (BRep_Tool::Degenerated(aE)) {
299       continue;
300     }
301     //
302     const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
303     aNbF=aLF.Extent();
304     if (aNbF!=2) {
305       BOPCol_ListIteratorOfListOfShape anIt(aLF);
306       for(; anIt.More(); anIt.Next()) {
307         const TopoDS_Face& aF=(*(TopoDS_Face*)(&anIt.Value()));
308         if (!aProcessedFaces.Contains(aF)) {
309           aProcessedFaces.Add(aF);
310           aBB.Add(aShellNew, aF);
311         }
312       }
313     }
314   }
315   aShell=aShellNew;
316 }
317 //=======================================================================
318 //function : Orientation
319 //purpose  :
320 //=======================================================================
321 TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
322                                const TopoDS_Face& aF)
323 {
324   TopAbs_Orientation anOr=TopAbs_INTERNAL;
325
326   TopExp_Explorer anExp;
327   anExp.Init(aF, TopAbs_EDGE);
328   for (; anExp.More(); anExp.Next()) {
329     const TopoDS_Edge& anEF1=(*(TopoDS_Edge*)(&anExp.Current()));
330     if (anEF1.IsSame(anE)) {
331       anOr=anEF1.Orientation();
332       break;
333     }
334   }
335   return anOr;
336 }
337
338 ////////////
339
340
341 //=======================================================================
342 // function: MakeConnexityBlock.
343 // purpose: 
344 //=======================================================================
345 void BOPTools_AlgoTools::MakeConnexityBlock (BOPCol_ListOfShape& theLFIn,
346                                              BOPCol_IndexedMapOfShape& theMEAvoid,
347                                              BOPCol_ListOfShape& theLCB,
348                                              const Handle(NCollection_BaseAllocator)& theAllocator)
349 {
350   Standard_Integer  aNbF, aNbAdd1, aNbAdd, i;
351   TopExp_Explorer aExp;
352   BOPCol_ListIteratorOfListOfShape aIt;
353   //
354   BOPCol_IndexedMapOfShape aMCB(100, theAllocator);
355   BOPCol_IndexedMapOfShape aMAdd(100, theAllocator);
356   BOPCol_IndexedMapOfShape aMAdd1(100, theAllocator);
357   BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, theAllocator);
358   //
359   // 1. aMEF
360   aNbF=theLFIn.Extent();
361   aIt.Initialize(theLFIn);
362   for (; aIt.More(); aIt.Next()) {
363     const TopoDS_Shape& aF=aIt.Value();      
364     BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
365   }
366   //
367   // 2. aMCB
368   const TopoDS_Shape& aF1=theLFIn.First();
369   aMAdd.Add(aF1);
370   //
371   for(;;) {
372     aMAdd1.Clear();
373     aNbAdd = aMAdd.Extent();
374     for (i=1; i<=aNbAdd; ++i) {
375       const TopoDS_Shape& aF=aMAdd(i);
376       //
377       //aMAdd1.Clear();
378       aExp.Init(aF, TopAbs_EDGE);
379       for (; aExp.More(); aExp.Next()) {
380         const TopoDS_Shape& aE=aExp.Current();
381         if (theMEAvoid.Contains(aE)){
382           continue;
383         }
384         //
385         const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
386         aIt.Initialize(aLF);
387         for (; aIt.More(); aIt.Next()) {
388           const TopoDS_Shape& aFx=aIt.Value();
389           if (aFx.IsSame(aF)) {
390             continue;
391           }
392           if (aMCB.Contains(aFx)) {
393             continue;
394           }
395           aMAdd1.Add(aFx);
396         }
397       }//for (; aExp.More(); aExp.Next()){
398       aMCB.Add(aF);
399     }// for (i=1; i<=aNbAdd; ++i) {
400     //
401     aNbAdd1=aMAdd1.Extent();
402     if (!aNbAdd1) {
403       break;
404     }
405     //
406     aMAdd.Clear();
407     for (i=1; i<=aNbAdd1; ++i) {
408       const TopoDS_Shape& aFAdd=aMAdd1(i);
409       aMAdd.Add(aFAdd);
410     }
411     //
412   }//while(1) {
413   
414   //
415   aNbF=aMCB.Extent();
416   for (i=1; i<=aNbF; ++i) {
417     const TopoDS_Shape& aF=aMCB(i);
418     theLCB.Append(aF);
419   }
420 }
421 //=======================================================================
422 // function:  ComputeStateByOnePoint
423 // purpose: 
424 //=======================================================================
425 TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint(const TopoDS_Shape& theS,
426                                                         const TopoDS_Solid& theRef,
427                                                         const Standard_Real theTol,
428                                                         Handle(BOPInt_Context)& theContext)
429 {
430   TopAbs_State aState;
431   TopAbs_ShapeEnum aType;
432   //
433   aState=TopAbs_UNKNOWN;
434   aType=theS.ShapeType();
435   if (aType==TopAbs_VERTEX) {
436     const TopoDS_Vertex& aV=(*(TopoDS_Vertex*)(&theS));
437     aState=BOPTools_AlgoTools::ComputeState(aV, theRef, theTol, theContext);
438   }
439   else if (aType==TopAbs_EDGE) {
440     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&theS));
441     aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
442   }
443   return aState;
444 }
445
446 //=======================================================================
447 // function:  ComputeState
448 // purpose: 
449 //=======================================================================
450 TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Face& theF,
451                                               const TopoDS_Solid& theRef,
452                                               const Standard_Real theTol,
453                                               BOPCol_IndexedMapOfShape& theBounds,
454                                               Handle(BOPInt_Context)& theContext)
455 {
456   TopAbs_State aState;
457   TopExp_Explorer aExp; 
458   TopoDS_Edge aE1;
459   gp_Pnt2d aP2D;
460   gp_Pnt aP3D; 
461   //
462   aState=TopAbs_UNKNOWN;
463   //
464   aExp.Init(theF, TopAbs_EDGE);
465   for (; aExp.More(); aExp.Next()) {
466     const TopoDS_Edge& aSE=(*(TopoDS_Edge*)(&aExp.Current()));
467     if (BRep_Tool::Degenerated(aSE)) {
468       continue;
469     }
470     //
471     if (!theBounds.Contains(aSE)) {
472       const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aSE));
473       aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
474       return aState;
475     }
476     if (aE1.IsNull()) {
477       aE1=(*(TopoDS_Edge*)(&aSE));
478     }
479   }
480   // !!<- process edges that are all on theRef
481   if (!aE1.IsNull()) {
482     BOPTools_AlgoTools3D::PointNearEdge(aE1, theF, aP2D, aP3D, theContext);
483     aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
484   }
485   //
486   return aState;
487 }
488 //=======================================================================
489 // function:  ComputeState
490 // purpose: 
491 //=======================================================================
492 TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Vertex& theV,
493                                               const TopoDS_Solid& theRef,
494                                               const Standard_Real theTol,
495                                               Handle(BOPInt_Context)& theContext)
496 {
497   TopAbs_State aState;
498   gp_Pnt aP3D; 
499   //
500   aP3D=BRep_Tool::Pnt(theV);
501   aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
502   return aState;
503 }
504 //=======================================================================
505 // function:  ComputeState
506 // purpose: 
507 //=======================================================================
508 TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Edge& theE,
509                                               const TopoDS_Solid& theRef,
510                                               const Standard_Real theTol,
511                                               Handle(BOPInt_Context)& theContext)
512 {
513   Standard_Real aT1, aT2, aT = 0.;
514   TopAbs_State aState;
515   Handle(Geom_Curve) aC3D;
516   gp_Pnt aP3D; 
517   //
518   aC3D = BRep_Tool::Curve(theE, aT1, aT2);
519   //
520   if(aC3D.IsNull()) {
521     //it means that we are in degenerated edge
522     const TopoDS_Vertex& aV = TopExp::FirstVertex(theE);
523     if(aV.IsNull()){
524       return TopAbs_UNKNOWN;
525     }
526     aP3D=BRep_Tool::Pnt(aV);
527   }
528   else {//usual case
529     Standard_Boolean bF2Inf, bL2Inf;
530     Standard_Real dT=10.;
531     //
532     bF2Inf = Precision::IsNegativeInfinite(aT1);
533     bL2Inf = Precision::IsPositiveInfinite(aT2);
534     //
535     if (bF2Inf && !bL2Inf) {
536       aT=aT2-dT;
537     }
538     else if (!bF2Inf && bL2Inf) {
539       aT=aT1+dT;
540     }
541     else if (bF2Inf && bL2Inf) {
542       aT=0.;
543     }
544     else {
545       aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
546     }
547     aC3D->D0(aT, aP3D);
548   }
549   //
550   aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
551   //
552   return aState;
553 }
554 //=======================================================================
555 // function:  ComputeState
556 // purpose: 
557 //=======================================================================
558 TopAbs_State BOPTools_AlgoTools::ComputeState(const gp_Pnt& theP,
559                                               const TopoDS_Solid& theRef,
560                                               const Standard_Real theTol,
561                                               Handle(BOPInt_Context)& theContext)
562 {
563   TopAbs_State aState;
564   //
565   BRepClass3d_SolidClassifier& aSC=theContext->SolidClassifier(theRef);
566   aSC.Perform(theP, theTol);
567   //
568   aState=aSC.State();
569   //
570   return aState;
571 }
572 //=======================================================================
573 //function : IsInternalFace
574 //purpose  : 
575 //=======================================================================
576 Standard_Integer BOPTools_AlgoTools::IsInternalFace
577   (const TopoDS_Face& theFace,
578    const TopoDS_Solid& theSolid,
579    BOPCol_IndexedDataMapOfShapeListOfShape& theMEF,
580    const Standard_Real theTol,
581    Handle(BOPInt_Context)& theContext)
582 {
583   Standard_Boolean bDegenerated;
584   Standard_Integer aNbF, iRet, iFound;
585   TopAbs_Orientation aOr;
586   TopoDS_Edge aE1;
587   TopExp_Explorer aExp;
588   BOPCol_ListIteratorOfListOfShape aItF;
589   //
590   // For all invoked functions: [::IsInternalFace(...)] 
591   // the returned value iRet means:
592   // iRet=0;  - state is not IN
593   // iRet=1;  - state is IN
594   // iRet=2;  - state can not be found by the method of angles
595   //
596   // For this function the returned value iRet means:
597   // iRet=0;  - state is not IN
598   // iRet=1;  - state is IN
599   //
600   iRet=0; 
601   // 1 Try to find an edge from theFace in theMEF
602   iFound=0;
603   aExp.Init(theFace, TopAbs_EDGE);
604   for(; aExp.More(); aExp.Next()) {
605     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
606     if (!theMEF.Contains(aE)) {
607       continue;
608     }
609     //
610     ++iFound;
611     //
612     aOr=aE.Orientation();
613     if (aOr==TopAbs_INTERNAL) {
614       continue;
615     }
616     bDegenerated=BRep_Tool::Degenerated(aE);
617     if (bDegenerated){
618       continue;
619     }
620     // aE
621     BOPCol_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
622     aNbF=aLF.Extent();
623     if (!aNbF) {
624       return iRet; // it can not be so
625     }
626     //
627     else if (aNbF==1) {
628       // aE is internal edge on aLF.First()
629       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
630       BOPTools_AlgoTools::GetEdgeOnFace(aE, aF1, aE1);
631       if (aE1.Orientation()!=TopAbs_INTERNAL) {
632         iRet=2; 
633         break;
634       }
635       //
636       iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1, theContext);
637       break;
638     }
639     //
640     else if (aNbF==2) {
641       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
642       const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
643       //
644       if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
645         // treat as it was for 1 face
646         iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2, theContext);
647         break;
648       }
649     }
650     //
651     if (aNbF%2) {
652       iRet=0;
653       return iRet; // it can not be so
654     }
655     else { // aNbF=2,4,6,8,...
656       iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF, theContext);
657       break;
658     }
659   }//for(; aExp.More(); aExp.Next()) {
660   //
661   if (!iFound) {
662     // the face has no shared edges with the solid
663     iRet=2;
664   }
665   //
666   if (iRet!=2) {
667     return iRet;
668   }
669   //
670   //========================================
671   // 2. Classify face using classifier
672   //
673   TopAbs_State aState;
674   BOPCol_IndexedMapOfShape aBounds;
675   //
676   BOPTools::MapShapes(theSolid, TopAbs_EDGE, aBounds);
677   //
678   aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid, theTol, aBounds, theContext);
679   //
680   iRet=(aState==TopAbs_IN)? 1 : 0;
681   //
682   return iRet;
683 }
684 //=======================================================================
685 //function : IsInternalFace
686 //purpose  : 
687 //=======================================================================
688 Standard_Integer BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
689                                                     const TopoDS_Edge& theEdge,
690                                                     BOPCol_ListOfShape& theLF,
691                                                     Handle(BOPInt_Context)& theContext)
692 {
693   Standard_Integer aNbF, iRet;
694   //
695   iRet=0;
696   //
697   aNbF=theLF.Extent();
698   if (aNbF==2) {
699     const TopoDS_Face& aF1=(*(TopoDS_Face*)(&theLF.First()));
700     const TopoDS_Face& aF2=(*(TopoDS_Face*)(&theLF.Last()));
701     iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
702     return iRet;
703   }
704   //
705   else {
706     BOPTools_ListOfCoupleOfShape aLCFF;
707     BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
708     //
709     FindFacePairs(theEdge, theLF, aLCFF, theContext);
710     //
711     aIt.Initialize(aLCFF);
712     for (; aIt.More(); aIt.Next()) {
713       BOPTools_CoupleOfShape& aCSFF=aIt.ChangeValue();
714       //
715       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aCSFF.Shape1()));
716       const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCSFF.Shape2()));
717       iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
718       if (iRet) {
719         return iRet;
720       }
721     }
722   }
723   return iRet;
724 }
725 //=======================================================================
726 //function : IsInternalFace
727 //purpose  : 
728 //=======================================================================
729 Standard_Integer BOPTools_AlgoTools::IsInternalFace
730   (const TopoDS_Face& theFace,
731    const TopoDS_Edge& theEdge,
732    const TopoDS_Face& theFace1,
733    const TopoDS_Face& theFace2,
734    Handle(BOPInt_Context)& theContext)
735 {
736   Standard_Boolean bRet;
737   Standard_Integer iRet;
738   TopoDS_Edge aE1, aE2;
739   TopoDS_Face aFOff;
740   BOPTools_ListOfCoupleOfShape theLCSOff;
741   BOPTools_CoupleOfShape aCS1, aCS2;
742   //
743   BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace1, aE1);
744   if (aE1.Orientation()==TopAbs_INTERNAL) {
745     aE2=aE1;
746     aE1.Orientation(TopAbs_FORWARD);
747     aE2.Orientation(TopAbs_REVERSED);
748   }
749   else if (theFace1==theFace2) {
750     aE2=aE1;
751     aE1.Orientation(TopAbs_FORWARD);
752     aE2.Orientation(TopAbs_REVERSED);
753   }
754   else {
755     BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace2, aE2);
756   }
757   //
758   aCS1.SetShape1(theEdge);
759   aCS1.SetShape2(theFace);
760   theLCSOff.Append(aCS1);
761   //
762   aCS2.SetShape1(aE2);
763   aCS2.SetShape2(theFace2);
764   theLCSOff.Append(aCS2);
765   //
766   bRet=GetFaceOff(aE1, theFace1, theLCSOff, aFOff, theContext);
767   //
768   iRet=0; // theFace is not internal
769   if (theFace.IsEqual(aFOff)) {
770     // theFace is internal
771     iRet=1;  
772     if (!bRet) {
773       // theFace seems to be internal  
774       iRet=2;
775     }
776   }
777   return iRet;
778 }
779 //=======================================================================
780 //function : GetFaceOff
781 //purpose  : 
782 //=======================================================================
783 Standard_Boolean BOPTools_AlgoTools::GetFaceOff
784   (const TopoDS_Edge& theE1,
785    const TopoDS_Face& theF1,
786    BOPTools_ListOfCoupleOfShape& theLCSOff,
787    TopoDS_Face& theFOff,
788    Handle(BOPInt_Context)& theContext)
789 {
790   Standard_Boolean bRet;
791   Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin;
792   Standard_Real aUmin, aUsup, aVmin, aVsup;
793   gp_Pnt aPn1, aPn2, aPx;
794   gp_Dir aDN1, aDN2, aDBF, aDBF2, aDTF;
795   gp_Vec aVTgt;
796   TopAbs_Orientation aOr;
797   Handle(Geom_Curve)aC3D;
798   Handle(Geom_Plane) aPL;
799   BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
800   GeomAPI_ProjectPointOnSurf aProjPL;
801   //
802   aAngleMin=100.;
803   aTwoPI=M_PI+M_PI;
804   aC3D =BRep_Tool::Curve(theE1, aT1, aT2);
805   aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
806   aC3D->D0(aT, aPx);
807   //
808   BOPTools_AlgoTools2D::EdgeTangent(theE1, aT, aVTgt);
809   gp_Dir aDTgt(aVTgt), aDTgt2;
810   aOr = theE1.Orientation();
811   //
812   aPL = new Geom_Plane(aPx, aDTgt);
813   aPL->Bounds(aUmin, aUsup, aVmin, aVsup);
814   aProjPL.Init(aPL, aUmin, aUsup, aVmin, aVsup);
815   //
816   GetFaceDir(theE1, theF1, aPx, aT, aDTgt, aDN1, aDBF, theContext, aProjPL);
817   //
818   aDTF=aDN1^aDBF;
819   //
820   bRet=Standard_True;
821   aIt.Initialize(theLCSOff);
822   for (; aIt.More(); aIt.Next()) {
823     const BOPTools_CoupleOfShape& aCS=aIt.Value();
824     const TopoDS_Edge& aE2=(*(TopoDS_Edge*)(&aCS.Shape1()));
825     const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCS.Shape2()));
826     //
827     aDTgt2 = (aE2.Orientation()==aOr) ? aDTgt : aDTgt.Reversed();
828     GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, aDN2, aDBF2, theContext, aProjPL);
829     //Angle
830     aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
831     //
832     if(aAngle<0.) {
833       aAngle=aTwoPI+aAngle;
834     }
835     //
836     if (aAngle<Precision::Angular()) {
837       if (aF2==theF1) {
838         aAngle=M_PI;
839       }
840       else if (aF2.IsSame(theF1)) {
841         aAngle=aTwoPI;
842       }
843     }
844     //
845     if (aAngle<aAngleMin){
846       aAngleMin=aAngle;
847       theFOff=aF2;
848     }
849     else if (aAngle==aAngleMin) {
850       // the minimal angle can not be found
851       bRet=Standard_False;  
852     }
853   }
854   return bRet;
855 }
856 //=======================================================================
857 //function : GetEdgeOff
858 //purpose  : 
859 //=======================================================================
860 Standard_Boolean BOPTools_AlgoTools::GetEdgeOff(const TopoDS_Edge& theE1,
861                                                 const TopoDS_Face& theF2,
862                                                 TopoDS_Edge& theE2)
863 {
864   Standard_Boolean bFound;
865   TopAbs_Orientation aOr1, aOr1C, aOr2;
866   TopExp_Explorer anExp;
867   //
868   bFound=Standard_False;
869   aOr1=theE1.Orientation();
870   aOr1C=TopAbs::Reverse(aOr1);
871   //
872   anExp.Init(theF2, TopAbs_EDGE);
873   for (; anExp.More(); anExp.Next()) {
874     const TopoDS_Edge& aEF2=(*(TopoDS_Edge*)(&anExp.Current()));
875     if (aEF2.IsSame(theE1)) {
876       aOr2=aEF2.Orientation();
877       if (aOr2==aOr1C) {
878         theE2=aEF2;
879         bFound=!bFound;
880         return bFound;
881       }
882     }
883   }
884   return bFound;
885 }
886
887 //=======================================================================
888 //function : AreFacesSameDomain
889 //purpose  : 
890 //=======================================================================
891 Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain(const TopoDS_Face& theF1,
892                                                         const TopoDS_Face& theF2,
893                                                         Handle(BOPInt_Context)& theContext)
894 {
895   Standard_Boolean bFlag;
896   Standard_Integer iErr;
897   Standard_Real aTolF1, aTolF2, aTol;
898   gp_Pnt2d aP2D;
899   gp_Pnt aP;
900   TopoDS_Face aF1, aF2;
901   TopoDS_Edge aE1;
902   TopExp_Explorer aExp;
903   //
904   bFlag=Standard_False;
905   //
906   aF1=theF1;
907   aF1.Orientation(TopAbs_FORWARD);
908   aF2=theF2;
909   aF2.Orientation(TopAbs_FORWARD);
910   //
911   aTolF1=BRep_Tool::Tolerance(aF1);
912   // 1
913   aExp.Init(aF1, TopAbs_EDGE);
914   for (; aExp.More(); aExp.Next()) {
915     aE1=(*(TopoDS_Edge*)(&aExp.Current()));
916     if (!BRep_Tool::Degenerated(aE1)) {
917       Standard_Real aTolE = BRep_Tool::Tolerance(aE1);
918       aTolF1 = (aTolE > aTolF1) ? aTolE : aTolF1;
919     }
920   }
921   // 2
922   aTolF2=BRep_Tool::Tolerance(aF2);
923   aTol=aTolF1+aTolF2;
924   //
925   iErr = BOPTools_AlgoTools3D::PointInFace(aF1, aP, aP2D, theContext);
926   if (!iErr) {
927     bFlag=theContext->IsValidPointForFace(aP, aF2, aTol);
928   }
929   //
930   return bFlag;
931 }
932
933 //=======================================================================
934 //function : CheckSameGeom
935 //purpose  : 
936 //=======================================================================
937 Standard_Boolean BOPTools_AlgoTools::CheckSameGeom(const TopoDS_Face& theF1,
938                                                    const TopoDS_Face& theF2,
939                                                    Handle(BOPInt_Context)& theContext)
940 {
941   Standard_Boolean bRet;
942   Standard_Real aTolF1, aTolF2, aTol;
943   gp_Pnt2d aP2D;
944   gp_Pnt aP;
945   TopExp_Explorer aExp;
946   //
947   bRet=Standard_False;
948   aExp.Init(theF1, TopAbs_EDGE);
949   for (; aExp.More(); aExp.Next()) {
950     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
951     if (!BRep_Tool::Degenerated(aE)) {
952       aTolF1=BRep_Tool::Tolerance(theF1);
953       aTolF2=BRep_Tool::Tolerance(theF2);
954       aTol=aTolF1+aTolF2;
955       BOPTools_AlgoTools3D::PointNearEdge(aE, theF1, aP2D, aP, theContext);
956       bRet=theContext->IsValidPointForFace(aP, theF2, aTol);
957       break;
958     }
959   }
960   return bRet;
961 }
962 //=======================================================================
963 // function: Sense
964 // purpose: 
965 //=======================================================================
966 Standard_Integer BOPTools_AlgoTools::Sense (const TopoDS_Face& theF1,
967                                             const TopoDS_Face& theF2)
968 {
969   Standard_Integer iSense=0;
970   gp_Dir aDNF1, aDNF2;
971   TopoDS_Edge aE1, aE2;
972   TopExp_Explorer aExp;
973   //
974   aExp.Init(theF1, TopAbs_EDGE);
975   for (; aExp.More(); aExp.Next()) {
976     aE1=(*(TopoDS_Edge*)(&aExp.Current()));
977     if (!BRep_Tool::Degenerated(aE1)) {
978       if (!BRep_Tool::IsClosed(aE1, theF1)) {
979         break;
980       }
981     }
982   }
983   //
984   aExp.Init(theF2, TopAbs_EDGE);
985   for (; aExp.More(); aExp.Next()) {
986     aE2=(*(TopoDS_Edge*)(&aExp.Current()));
987     if (!BRep_Tool::Degenerated(aE2)) {
988       if (!BRep_Tool::IsClosed(aE2, theF2)) {
989         if (aE2.IsSame(aE1)) {
990           iSense=1;
991           break;
992         }
993       }
994     }
995   }
996   //
997   if (!iSense) {
998     return iSense;
999   }
1000   //
1001   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE1, theF1, aDNF1);
1002   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE2, theF2, aDNF2);
1003   //
1004   iSense=BOPTools_AlgoTools3D::SenseFlag(aDNF1, aDNF2);
1005   //
1006   return iSense;
1007 }
1008 //=======================================================================
1009 // function: IsSplitToReverse
1010 // purpose: 
1011 //=======================================================================
1012 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Shape& theSp,
1013                                                       const TopoDS_Shape& theSr,
1014                                                       Handle(BOPInt_Context)& theContext)
1015 {
1016   Standard_Boolean bRet;
1017   TopAbs_ShapeEnum aType;
1018   //
1019   bRet=Standard_False;
1020   //
1021   aType=theSp.ShapeType();
1022   switch (aType) {
1023     case TopAbs_EDGE: {
1024       const TopoDS_Edge& aESp=(*(TopoDS_Edge*)(&theSp));
1025       const TopoDS_Edge& aESr=(*(TopoDS_Edge*)(&theSr));
1026       bRet=BOPTools_AlgoTools::IsSplitToReverse(aESp, aESr, theContext);
1027     }
1028       break;
1029       //
1030     case TopAbs_FACE: {
1031       const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&theSp));
1032       const TopoDS_Face& aFSr=(*(TopoDS_Face*)(&theSr));
1033       bRet=BOPTools_AlgoTools::IsSplitToReverse(aFSp, aFSr, theContext);
1034     }
1035       break;
1036       //
1037     default:
1038       break;
1039   }
1040   return bRet;
1041 }
1042 //=======================================================================
1043 //function :IsSplitToReverse
1044 //purpose  : 
1045 //=======================================================================
1046 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
1047                                                       const TopoDS_Face& theFSr,
1048                                                       Handle(BOPInt_Context)& theContext)
1049 {
1050   Standard_Boolean bRet, bFound, bInFace;
1051   Standard_Real aT1, aT2, aT, aU, aV, aScPr;
1052   gp_Pnt aPFSp, aPFSr;
1053   gp_Dir aDNFSp;
1054   gp_Vec aD1U, aD1V;
1055   Handle(Geom_Surface) aSr, aSp;
1056   TopAbs_Orientation aOrSr, aOrSp;
1057   TopExp_Explorer anExp;
1058   TopoDS_Edge aESp;
1059   //
1060   bRet=Standard_False;
1061   //
1062   aSr=BRep_Tool::Surface(theFSr);
1063   aSp=BRep_Tool::Surface(theFSp);
1064   if (aSr==aSp) {
1065     aOrSr=theFSr.Orientation();
1066     aOrSp=theFSp.Orientation();
1067     bRet=(aOrSr!=aOrSp);
1068     return bRet;
1069   }
1070   //
1071   bFound=Standard_False;
1072   anExp.Init(theFSp, TopAbs_EDGE);
1073   for (; anExp.More(); anExp.Next()) {
1074     aESp=(*(TopoDS_Edge*)(&anExp.Current()));
1075     if (!BRep_Tool::Degenerated(aESp)) {
1076       if (!BRep_Tool::IsClosed(aESp, theFSp)) {
1077         bFound=!bFound;
1078         break;
1079       }
1080     }
1081   }
1082   if (!bFound) {
1083     Standard_Boolean bFlag;
1084     Standard_Integer iErr;
1085     gp_Pnt2d aP2DFSp;
1086     //
1087     iErr=BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
1088     if (iErr) {
1089       return bRet;
1090     }
1091     //
1092     aP2DFSp.Coord(aU, aV);
1093     bFlag=BOPTools_AlgoTools3D::GetNormalToSurface(aSp, aU, aV, aDNFSp);
1094     if (!bFlag) {
1095       return bRet;
1096     }
1097   }
1098   else {
1099     BRep_Tool::Range(aESp, aT1, aT2);
1100     aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
1101     BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT, aPFSp, aDNFSp, theContext);
1102   }
1103   //
1104   // Parts of theContext->ComputeVS(..) 
1105   GeomAPI_ProjectPointOnSurf& aProjector=theContext->ProjPS(theFSr);
1106   aProjector.Perform(aPFSp);
1107   if (!aProjector.IsDone()) {
1108     return bRet;
1109   }
1110   //
1111   aProjector.LowerDistanceParameters(aU, aV);
1112   gp_Pnt2d aP2D(aU, aV);
1113   bInFace=theContext->IsPointInFace (theFSr, aP2D);
1114   if (!bInFace) {
1115     return bRet;
1116   }
1117   //
1118   aSr->D1(aU, aV, aPFSr, aD1U, aD1V);
1119   gp_Dir aDD1U(aD1U); 
1120   gp_Dir aDD1V(aD1V);
1121   gp_Dir aDNFSr=aDD1U^aDD1V; 
1122   if (theFSr.Orientation()==TopAbs_REVERSED){
1123     aDNFSr.Reverse();
1124   }
1125   //
1126   aScPr=aDNFSp*aDNFSr;
1127   bRet=(aScPr<0.);
1128   //
1129   return bRet;
1130 }
1131 //=======================================================================
1132 //function :IsSplitToReverse
1133 //purpose  : 
1134 //=======================================================================
1135 Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Edge& aEF1,
1136                                                       const TopoDS_Edge& aEF2,
1137                                                       Handle(BOPInt_Context)& theContext)
1138 {
1139   Standard_Boolean bRet, bIsDegenerated;
1140   //
1141   bRet=Standard_False;
1142   bIsDegenerated=(BRep_Tool::Degenerated(aEF1) || 
1143                   BRep_Tool::Degenerated(aEF2));
1144   if (bIsDegenerated) {
1145     return bRet;
1146   }
1147   //
1148   Standard_Real a, b;
1149   TopAbs_Orientation aOrE, aOrSp;
1150   Handle(Geom_Curve)aC1, aC2;
1151   //
1152   aC2=BRep_Tool::Curve(aEF2, a, b);
1153   aC1=BRep_Tool::Curve(aEF1, a, b);
1154   //
1155   if (aC1==aC2) {
1156     aOrE=aEF2.Orientation();
1157     aOrSp=aEF1.Orientation();
1158     bRet=(aOrE!=aOrSp);
1159     return bRet;
1160   }
1161   //
1162   Standard_Real aT1, aT2, aScPr;
1163   gp_Vec aV1, aV2;
1164   gp_Pnt aP;
1165   //
1166   aT1=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
1167   aC1->D0(aT1, aP);
1168   BOPTools_AlgoTools2D::EdgeTangent(aEF1, aT1, aV1);
1169   gp_Dir aDT1(aV1);
1170   //
1171   theContext->ProjectPointOnEdge(aP, aEF2, aT2);
1172   //
1173   BOPTools_AlgoTools2D::EdgeTangent(aEF2, aT2, aV2);
1174   gp_Dir aDT2(aV2);
1175   //
1176   aScPr=aDT1*aDT2;
1177   bRet=(aScPr<0.);
1178   //
1179   return bRet;
1180 }
1181
1182 //=======================================================================
1183 //function : IsHole
1184 //purpose  : 
1185 //=======================================================================
1186 Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
1187                                             const TopoDS_Shape& aFace)
1188 {
1189   Standard_Boolean bIsHole;
1190   Standard_Integer i, aNbS;
1191   Standard_Real aT1, aT2, aS;
1192   Standard_Real aU1, aU, dU;
1193   Standard_Real aX1, aY1, aX0, aY0;
1194   TopAbs_Orientation aOr;
1195   
1196   gp_Pnt2d aP2D0, aP2D1;
1197   Handle(Geom2d_Curve) aC2D;
1198   TopoDS_Face aF, aFF;
1199   TopoDS_Iterator aItW;
1200   //
1201   bIsHole=Standard_False;
1202   //
1203   aF=(*(TopoDS_Face *)(&aFace));
1204   aFF=aF;
1205   aFF.Orientation(TopAbs_FORWARD);
1206   //
1207   aS=0.;
1208   aItW.Initialize(aW);
1209   for (; aItW.More(); aItW.Next()) { 
1210     const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
1211     aOr=aE.Orientation();
1212     if (!(aOr==TopAbs_FORWARD || 
1213           aOr==TopAbs_REVERSED)) {
1214       continue;
1215     }
1216     //
1217     aC2D=BRep_Tool::CurveOnSurface(aE, aFF, aT1, aT2);
1218     if (aC2D.IsNull()) {
1219       break; //xx
1220     }
1221     //
1222     BRepAdaptor_Curve2d aBAC2D(aE, aFF);
1223     aNbS=Geom2dInt_Geom2dCurveTool::NbSamples(aBAC2D);
1224     if (aNbS>2) {
1225       aNbS*=4;
1226     }
1227     //
1228     dU=(aT2-aT1)/(Standard_Real)(aNbS-1);
1229     aU =aT1;
1230     aU1=aT1;
1231     if (aOr==TopAbs_REVERSED) {
1232       aU =aT2;
1233       aU1=aT2;
1234       dU=-dU;
1235     }
1236     //
1237     aC2D->D0(aU, aP2D0);
1238     for(i=2; i<=aNbS; i++) {
1239       aU=aU1+(i-1)*dU;
1240       aC2D->D0(aU, aP2D1);
1241       aP2D0.Coord(aX0, aY0);
1242       aP2D1.Coord(aX1, aY1);
1243       //
1244       aS=aS+(aY0+aY1)*(aX1-aX0); 
1245       //
1246       aP2D0=aP2D1;
1247     }
1248   }//for (; aItW.More(); aItW.Next()) { 
1249   bIsHole=(aS>0.);
1250   return bIsHole;
1251 }
1252
1253 //=======================================================================
1254 // function: MakeContainer
1255 // purpose: 
1256 //=======================================================================
1257 void BOPTools_AlgoTools::MakeContainer(const TopAbs_ShapeEnum theType,
1258                                        TopoDS_Shape& theC)
1259 {
1260   BRep_Builder aBB;
1261   //
1262   switch(theType) {
1263     case TopAbs_COMPOUND:{
1264       TopoDS_Compound aC;
1265       aBB.MakeCompound(aC);
1266       theC=aC;
1267     }
1268       break;
1269       //
1270     case TopAbs_COMPSOLID:{
1271       TopoDS_CompSolid aCS;
1272       aBB.MakeCompSolid(aCS);
1273       theC=aCS;
1274     }
1275       break;
1276       //
1277     case TopAbs_SOLID:{
1278       TopoDS_Solid aSolid;
1279       aBB.MakeSolid(aSolid);
1280       theC=aSolid;
1281     }  
1282       break;
1283       //
1284       //
1285     case TopAbs_SHELL:{
1286       TopoDS_Shell aShell;
1287       aBB.MakeShell(aShell);
1288       theC=aShell;
1289     }  
1290       break;
1291       //
1292     case TopAbs_WIRE: {
1293       TopoDS_Wire aWire;
1294       aBB.MakeWire(aWire);
1295       theC=aWire;
1296     }
1297       break;
1298       //
1299     default:
1300       break;
1301   }
1302 }
1303 //=======================================================================
1304 // function: MakePCurve
1305 // purpose: 
1306 //=======================================================================
1307 void BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
1308                                     const TopoDS_Face& aF1,
1309                                     const TopoDS_Face& aF2,
1310                                     const IntTools_Curve& aIC,
1311                                     const Standard_Boolean bPC1,
1312                                     const Standard_Boolean bPC2)
1313
1314 {
1315   Standard_Integer i;
1316   Standard_Real aTolE, aT1, aT2, aOutFirst, aOutLast, aOutTol;
1317   Handle(Geom2d_Curve) aC2D, aC2DA, aC2Dx1;
1318   TopoDS_Face aFFWD; 
1319   BRep_Builder aBB;
1320   Standard_Boolean bPC;
1321   //
1322   aTolE=BRep_Tool::Tolerance(aE);
1323   //
1324   const Handle(Geom_Curve)& aC3DE=BRep_Tool::Curve(aE, aT1, aT2);
1325   Handle(Geom_TrimmedCurve)aC3DETrim=new Geom_TrimmedCurve(aC3DE, aT1, aT2);
1326   //
1327   for (i=0; i<2; ++i) {
1328     bPC = !i ? bPC1 : bPC2;
1329     if (!bPC) {
1330       continue;
1331     }
1332     //
1333     if (!i) {
1334       aFFWD=aF1;
1335       aC2Dx1=aIC.FirstCurve2d();
1336     }
1337     else {
1338       aFFWD=aF2;
1339       aC2Dx1=aIC.SecondCurve2d();
1340     }
1341     //
1342     aFFWD.Orientation(TopAbs_FORWARD);
1343     //
1344     aC2D=aC2Dx1;
1345     if (aC2D.IsNull()) { 
1346       BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aE, aFFWD);
1347       BOPTools_AlgoTools2D::CurveOnSurface(aE, aFFWD, aC2D, 
1348                                        aOutFirst, aOutLast, 
1349                                        aOutTol);
1350       }
1351     //
1352     if (aC3DE->IsPeriodic()) {
1353       BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2,  aC2D, aC2DA); 
1354     }
1355     else {
1356       BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D, aC2DA); 
1357     }
1358     //
1359     aBB.UpdateEdge(aE, aC2DA, aFFWD, aTolE);
1360     //BRepLib::SameParameter(aE);
1361   }
1362   BRepLib::SameParameter(aE);
1363 }
1364 //=======================================================================
1365 // function: MakeEdge
1366 // purpose: 
1367 //=======================================================================
1368 void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
1369                                   const TopoDS_Vertex& theV1,
1370                                   const Standard_Real theT1,
1371                                   const TopoDS_Vertex& theV2,
1372                                   const Standard_Real theT2,
1373                                   const Standard_Real theTolR3D,
1374                                   TopoDS_Edge& theE)
1375 {
1376   Standard_Real aTolV;
1377   BRep_Builder aBB;
1378   //
1379   BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2, theE);
1380   //
1381   aBB.UpdateEdge(theE, theTolR3D);
1382   //
1383   aTolV=BRep_Tool::Tolerance(theV1);
1384   if (aTolV<theTolR3D) {
1385     aBB.UpdateVertex(theV1, theTolR3D);
1386   }
1387   //
1388   aTolV=BRep_Tool::Tolerance(theV2);
1389   if (aTolV<theTolR3D) {
1390     aBB.UpdateVertex(theV2, theTolR3D);
1391   }
1392 }
1393 //=======================================================================
1394 // function: ComputeVV
1395 // purpose: 
1396 //=======================================================================
1397 Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1, 
1398                                                const gp_Pnt& aP2,
1399                                                const Standard_Real aTolP2)
1400 {
1401   Standard_Real aTolV1, aTolSum, aTolSum2, aD2;
1402   gp_Pnt aP1;
1403   //
1404   aTolV1=BRep_Tool::Tolerance(aV1);
1405   
1406   aTolSum=aTolV1+aTolP2;
1407   aTolSum2=aTolSum*aTolSum;
1408   //
1409   aP1=BRep_Tool::Pnt(aV1);
1410   //
1411   aD2=aP1.SquareDistance(aP2);
1412   if (aD2>aTolSum2) {
1413     return 1;
1414   }
1415   return 0;
1416
1417 //=======================================================================
1418 // function: ComputeVV
1419 // purpose: 
1420 //=======================================================================
1421 Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1, 
1422                                                const TopoDS_Vertex& aV2)
1423 {
1424   Standard_Real aTolV1, aTolV2, aTolSum, aTolSum2, aD2;
1425   gp_Pnt aP1, aP2;
1426   //
1427   aTolV1=BRep_Tool::Tolerance(aV1);
1428   aTolV2=BRep_Tool::Tolerance(aV2);
1429   aTolSum=aTolV1+aTolV2;
1430   aTolSum2=aTolSum*aTolSum;
1431   //
1432   aP1=BRep_Tool::Pnt(aV1);
1433   aP2=BRep_Tool::Pnt(aV2);
1434   //
1435   aD2=aP1.SquareDistance(aP2);
1436   if (aD2>aTolSum2) {
1437     return 1;
1438   }
1439   return 0;
1440 }
1441 //=======================================================================
1442 // function: MakeVertex
1443 // purpose : 
1444 //=======================================================================
1445 void BOPTools_AlgoTools::MakeVertex(BOPCol_ListOfShape& aLV,
1446                                     TopoDS_Vertex& aVnew)
1447 {
1448   Standard_Integer aNb;
1449   Standard_Real aTi, aDi, aDmax;
1450   gp_Pnt aPi, aP;
1451   gp_XYZ aXYZ(0.,0.,0.), aXYZi;
1452   BOPCol_ListIteratorOfListOfShape aIt;
1453   //
1454   aNb=aLV.Extent();
1455   if (aNb) {
1456     aIt.Initialize(aLV);
1457     for (; aIt.More(); aIt.Next()) {
1458       TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
1459       aPi=BRep_Tool::Pnt(aVi);
1460       aXYZi=aPi.XYZ();
1461       aXYZ=aXYZ+aXYZi;
1462     }
1463     //
1464     aXYZ.Divide((Standard_Real)aNb);
1465     aP.SetXYZ(aXYZ);
1466     //
1467     aDmax=-1.;
1468     aIt.Initialize(aLV);
1469     for (; aIt.More(); aIt.Next()) {
1470       TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
1471       aPi=BRep_Tool::Pnt(aVi);
1472       aTi=BRep_Tool::Tolerance(aVi);
1473       aDi=aP.SquareDistance(aPi);
1474       aDi=sqrt(aDi);
1475       aDi=aDi+aTi;
1476       if (aDi > aDmax) {
1477         aDmax=aDi;
1478       }
1479     }
1480     //
1481     BRep_Builder aBB;
1482     aBB.MakeVertex (aVnew, aP, aDmax);
1483   }
1484 }
1485 //=======================================================================
1486 //function : GetEdgeOnFace
1487 //purpose  : 
1488 //=======================================================================
1489 Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace(const TopoDS_Edge& theE1,
1490                                                    const TopoDS_Face& theF2,
1491                                                    TopoDS_Edge& theE2)
1492 {
1493   Standard_Boolean bFound;
1494   TopoDS_Iterator aItF, aItW;
1495   //
1496   bFound=Standard_False;
1497   //
1498   aItF.Initialize(theF2);
1499   for (; aItF.More(); aItF.Next()) {
1500     const TopoDS_Shape& aW=aItF.Value();
1501     aItW.Initialize(aW);
1502     for (; aItW.More(); aItW.Next()) {
1503       const TopoDS_Shape& aE=aItW.Value();
1504       if (aE.IsSame(theE1)) {
1505         theE2=(*(TopoDS_Edge*)(&aE));
1506         bFound=!bFound;
1507         return bFound;
1508       }
1509     }
1510   }
1511   return bFound;
1512 }
1513 //=======================================================================
1514 //function : FindFacePairs
1515 //purpose  : 
1516 //=======================================================================
1517 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
1518                                 const BOPCol_ListOfShape& thLF,
1519                                 BOPTools_ListOfCoupleOfShape& theLCFF,
1520                                 Handle(BOPInt_Context)& theContext)
1521 {
1522   Standard_Boolean bFound;
1523   Standard_Integer i, aNbCEF;
1524   TopAbs_Orientation aOr, aOrC = TopAbs_FORWARD;
1525   BOPCol_MapOfShape aMFP;
1526   TopoDS_Face aF1, aF2;
1527   TopoDS_Edge aEL, aE1;
1528   BOPCol_ListIteratorOfListOfShape aItLF;
1529   BOPTools_CoupleOfShape aCEF, aCFF;
1530   BOPTools_ListOfCoupleOfShape aLCEF, aLCEFx;
1531   BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
1532   //
1533   bFound=Standard_True;
1534   //
1535   // Preface aLCEF
1536   aItLF.Initialize(thLF);
1537   for (; aItLF.More(); aItLF.Next()) { 
1538     const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
1539     //
1540     bFound=BOPTools_AlgoTools::GetEdgeOnFace(theE, aFL, aEL);
1541     if (!bFound) {
1542       return bFound; // it can not be so
1543     }
1544     //
1545     aCEF.SetShape1(aEL);
1546     aCEF.SetShape2(aFL);
1547     aLCEF.Append(aCEF);
1548   }
1549   //
1550   aNbCEF=aLCEF.Extent();
1551   while(aNbCEF) {
1552     //
1553     // aLCEFx
1554     aLCEFx.Clear();
1555     aIt.Initialize(aLCEF);
1556     for (i=0; aIt.More(); aIt.Next(), ++i) {
1557       const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1558       const TopoDS_Shape& aEx=aCSx.Shape1();
1559       const TopoDS_Shape& aFx=aCSx.Shape2();
1560       //
1561       aOr=aEx.Orientation();
1562       //
1563       if (!i) {
1564         aOrC=TopAbs::Reverse(aOr);
1565         aE1=(*(TopoDS_Edge*)(&aEx));
1566         aF1=(*(TopoDS_Face*)(&aFx));
1567         aMFP.Add(aFx);
1568         continue;
1569       }
1570       //
1571       if (aOr==aOrC) {
1572         aLCEFx.Append(aCSx);
1573         aMFP.Add(aFx);
1574       }
1575     }
1576     //
1577     // F2
1578     BOPTools_AlgoTools::GetFaceOff(aE1, aF1, aLCEFx, aF2, theContext);
1579     //
1580     aCFF.SetShape1(aF1);
1581     aCFF.SetShape2(aF2);
1582     theLCFF.Append(aCFF);
1583     //
1584     aMFP.Add(aF1);
1585     aMFP.Add(aF2);
1586     //
1587     // refine aLCEF
1588     aLCEFx.Clear();
1589     aLCEFx=aLCEF;
1590     aLCEF.Clear();
1591     aIt.Initialize(aLCEFx);
1592     for (; aIt.More(); aIt.Next()) {
1593       const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1594       const TopoDS_Shape& aFx=aCSx.Shape2();
1595       if (!aMFP.Contains(aFx)) {
1596         aLCEF.Append(aCSx);
1597       }
1598     }
1599     //
1600     aNbCEF=aLCEF.Extent();
1601   }//while(aNbCEF) {
1602   //
1603   return bFound;
1604 }
1605 //=======================================================================
1606 //function : AngleWithRef
1607 //purpose  : 
1608 //=======================================================================
1609 Standard_Real AngleWithRef(const gp_Dir& theD1,
1610                            const gp_Dir& theD2,
1611                            const gp_Dir& theDRef)
1612 {
1613   Standard_Real aCosinus, aSinus, aBeta, aHalfPI, aScPr;
1614   gp_XYZ aXYZ;
1615   //
1616   aHalfPI=0.5*M_PI;
1617   //
1618   const gp_XYZ& aXYZ1=theD1.XYZ();
1619   const gp_XYZ& aXYZ2=theD2.XYZ();
1620   aXYZ=aXYZ1.Crossed(aXYZ2);
1621   aSinus=aXYZ.Modulus();
1622   aCosinus=theD1*theD2;
1623   //
1624   aBeta=0.;
1625   if (aSinus>=0.) {
1626     aBeta=aHalfPI*(1.-aCosinus);
1627   }
1628   else {
1629     aBeta=2.*M_PI-aHalfPI*(3.+aCosinus);
1630   }
1631   //
1632   aScPr=aXYZ.Dot(theDRef.XYZ());
1633   if (aScPr<0.) {
1634     aBeta=-aBeta;
1635   }
1636   return aBeta;
1637 }
1638 //=======================================================================
1639 // function: IsBlockInOnFace
1640 // purpose: 
1641 //=======================================================================
1642 Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace (const IntTools_Range& aShrR,
1643                                                       const TopoDS_Face& aF,
1644                                                       const TopoDS_Edge& aE1,
1645                                                       Handle(BOPInt_Context)& aContext)
1646 {
1647   Standard_Boolean bFlag;
1648   Standard_Real f1, l1, ULD, VLD;
1649   gp_Pnt2d aP2D;
1650   gp_Pnt aP11, aP12;
1651   //
1652   aShrR.Range(f1, l1);
1653   Standard_Real dt=0.0075,  k;//dt=0.001,  k;
1654   k=dt*(l1-f1);
1655   f1=f1+k;
1656   l1=l1-k;
1657   //
1658   // Treatment P11
1659   BOPTools_AlgoTools::PointOnEdge(aE1, f1, aP11);
1660   //
1661   GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF);
1662   aProjector.Perform(aP11);
1663   //
1664   bFlag=aProjector.IsDone();
1665   if (!bFlag) {
1666     return bFlag;
1667   }
1668   
1669   aProjector.LowerDistanceParameters(ULD, VLD);
1670   aP2D.SetCoord(ULD, VLD);
1671   //
1672   bFlag=aContext->IsPointInOnFace (aF, aP2D);
1673   //
1674   if (!bFlag) {
1675     return bFlag;
1676   }
1677   //
1678   // Treatment P12
1679   BOPTools_AlgoTools::PointOnEdge(aE1, l1, aP12);
1680   //
1681   aProjector.Perform(aP12);
1682   //
1683   bFlag=aProjector.IsDone();
1684   if (!bFlag) {
1685     return bFlag;
1686   }
1687   
1688   aProjector.LowerDistanceParameters(ULD, VLD);
1689   aP2D.SetCoord(ULD, VLD);
1690   //
1691   bFlag=aContext->IsPointInOnFace (aF, aP2D);
1692   //
1693   if (!bFlag) {
1694     return bFlag;
1695   }
1696   //
1697   // Treatment intemediate
1698   Standard_Real m1, aTolF, aTolE, aTol, aDist;
1699   m1=IntTools_Tools::IntermediatePoint(f1, l1);
1700   BOPTools_AlgoTools::PointOnEdge(aE1, m1, aP12);
1701   //
1702   aProjector.Perform(aP12);
1703   //
1704   bFlag=aProjector.IsDone();
1705   if (!bFlag) {
1706     return bFlag;
1707   }
1708   //
1709   aTolE=BRep_Tool::Tolerance(aE1);
1710   aTolF=BRep_Tool::Tolerance(aF);
1711   aTol=aTolE+aTolF;
1712   aDist=aProjector.LowerDistance();
1713   if (aDist > aTol){
1714    return Standard_False;
1715   }
1716
1717   aProjector.LowerDistanceParameters(ULD, VLD);
1718   aP2D.SetCoord(ULD, VLD);
1719   //
1720   bFlag=aContext->IsPointInOnFace (aF, aP2D);
1721   //
1722   if (!bFlag) {
1723     return bFlag;
1724   }
1725   return bFlag;
1726 }
1727
1728 //=======================================================================
1729 //function : IsMicroEdge
1730 //purpose  : 
1731 //=======================================================================
1732 Standard_Boolean BOPTools_AlgoTools::IsMicroEdge(const TopoDS_Edge& aE,
1733                                                  const Handle(BOPInt_Context)& aCtx) 
1734 {
1735   Standard_Boolean bRet;
1736   Standard_Integer iErr;
1737   Standard_Real aT1, aT2, aTmp;
1738   Handle(Geom_Curve) aC3D;
1739   TopoDS_Vertex aV1, aV2;
1740   //
1741   bRet=(BRep_Tool::Degenerated(aE) ||
1742         !BRep_Tool::IsGeometric(aE));
1743   if (bRet) {
1744     return bRet;
1745   }
1746   //
1747   aC3D=BRep_Tool::Curve(aE, aT1, aT2);
1748   TopExp::Vertices(aE, aV1, aV2);
1749   aT1=BRep_Tool::Parameter(aV1, aE);
1750   aT2=BRep_Tool::Parameter(aV2, aE);
1751   if (aT2<aT1) {
1752     aTmp=aT1;
1753     aT1=aT2;
1754     aT2=aTmp;
1755   }
1756   //
1757   BOPInt_ShrunkRange aSR;
1758   aSR.SetData(aE, aT1, aT2, aV1, aV2, aCtx);
1759   aSR.Perform();
1760   iErr=aSR.ErrorStatus();
1761   bRet = !(iErr==0);
1762   //
1763   return bRet;
1764 }
1765
1766 //=======================================================================
1767 //function : GetFaceDir
1768 //purpose  : Get binormal direction for the face in the point aP
1769 //=======================================================================
1770 void GetFaceDir(const TopoDS_Edge& aE,
1771                 const TopoDS_Face& aF,
1772                 const gp_Pnt& aP,
1773                 const Standard_Real aT,
1774                 const gp_Dir& aDTgt,
1775                 gp_Dir& aDN,
1776                 gp_Dir& aDB,
1777                 Handle(BOPInt_Context)& theContext,
1778                 GeomAPI_ProjectPointOnSurf& aProjPL)
1779 {
1780   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE, aF, aT, aDN);
1781   if (aF.Orientation()==TopAbs_REVERSED){
1782     aDN.Reverse();
1783   }
1784   aDB = aDN^aDTgt;
1785   //
1786   gp_Pnt aPx;
1787   if (!FindPointInFace(aE, aF, aP, aDB, aPx, theContext, aProjPL)) {
1788     BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aE, aF, aT, aPx, aDN, theContext);
1789     aProjPL.Perform(aPx);
1790     aPx = aProjPL.NearestPoint();
1791     gp_Vec aVec(aP, aPx);
1792     aDB.SetXYZ(aVec.XYZ());
1793   }
1794 }
1795
1796 //=======================================================================
1797 //function : FindPointInFace
1798 //purpose  : Find a point in the face in direction of <aDB>
1799 //=======================================================================
1800 Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
1801                                  const TopoDS_Face& aF,
1802                                  const gp_Pnt& aP,
1803                                  gp_Dir& aDB,
1804                                  gp_Pnt& aPOut,
1805                                  Handle(BOPInt_Context)& theContext,
1806                                  GeomAPI_ProjectPointOnSurf& aProjPL) 
1807 {
1808   Standard_Integer aNbItMax;
1809   Standard_Real aDt, aDtMin, aTolE, aTolF, aDist;
1810   Standard_Boolean bRet;
1811   gp_Pnt aP1;
1812   BRepAdaptor_Surface aBAS;
1813   //
1814   bRet = Standard_False;
1815   aTolE = BRep_Tool::Tolerance(aE);
1816   aTolF = BRep_Tool::Tolerance(aF);
1817   aDt = 2*(aTolE+aTolF);
1818   aBAS.Initialize(aF, Standard_False);
1819   //
1820   aDtMin=5.e-4;
1821   if (aDt < aDtMin) {
1822     Standard_Real aR;
1823     GeomAbs_SurfaceType aSType=aBAS.GetType();
1824     switch (aSType) {
1825     case GeomAbs_Cylinder:
1826       aR = aBAS.Cylinder().Radius();
1827       break;
1828     case GeomAbs_Cone: {
1829       gp_Lin aL(aBAS.Cone().Axis());
1830       aR = aL.Distance(aP);
1831       break;
1832     }
1833     case GeomAbs_Sphere:
1834       aR = aBAS.Sphere().Radius();
1835       break;
1836     case GeomAbs_Torus:
1837       aR = aBAS.Torus().MinorRadius();
1838       break;
1839     case GeomAbs_SurfaceOfRevolution:
1840       aR=1.;
1841       break;
1842     default:
1843       aR=0.001;
1844     }
1845     if (aR < 0.01) {
1846       aDtMin=5.e-6;
1847     }
1848     else if (aR > 100.) {
1849       aDtMin*=10;
1850     }
1851     if (aDt < aDtMin) {
1852       aDt=aDtMin;
1853     }
1854   }
1855   //
1856   GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
1857   aNbItMax = 15;
1858   //
1859   do {
1860     aP1.SetCoord(aP.X()+aDt*aDB.X(),
1861                  aP.Y()+aDt*aDB.Y(),
1862                  aP.Z()+aDt*aDB.Z());
1863     //
1864     aProj.Perform(aP1);
1865     if (!aProj.IsDone()) {
1866       return bRet;
1867     }
1868     aPOut = aProj.NearestPoint();
1869     aDist = aProj.LowerDistance();
1870     //
1871     aProjPL.Perform(aPOut);
1872     aPOut = aProjPL.NearestPoint();
1873     //
1874     gp_Vec aV(aP, aPOut);
1875     aDB.SetXYZ(aV.XYZ());
1876   } while (aDist>Precision::Angular() && --aNbItMax);
1877   //
1878   bRet = aDist < Precision::Angular();
1879   return bRet;
1880 }
1881 //=======================================================================
1882 //function : IsOpenShell
1883 //purpose  : 
1884 //=======================================================================
1885 Standard_Boolean 
1886   BOPTools_AlgoTools::IsOpenShell(const TopoDS_Shell& aSh)
1887 {
1888   Standard_Boolean bRet;
1889   Standard_Integer i, aNbE, aNbF;
1890   TopAbs_Orientation aOrF;
1891   BOPCol_IndexedDataMapOfShapeListOfShape aMEF; 
1892   BOPCol_ListIteratorOfListOfShape aItLS;
1893   //
1894   bRet=Standard_False;
1895   //
1896   BOPTools::MapShapesAndAncestors(aSh, TopAbs_EDGE, TopAbs_FACE, aMEF);
1897   // 
1898   aNbE=aMEF.Extent();
1899   for (i=1; i<=aNbE; ++i) {
1900     const TopoDS_Edge& aE=*((TopoDS_Edge*)&aMEF.FindKey(i));
1901     if (BRep_Tool::Degenerated(aE)) {
1902       continue;
1903     }
1904     //
1905     aNbF=0;
1906     const BOPCol_ListOfShape& aLF=aMEF(i);
1907     aItLS.Initialize(aLF);
1908     for (; aItLS.More(); aItLS.Next()) {
1909       const TopoDS_Shape& aF=aItLS.Value();
1910       aOrF=aF.Orientation();
1911       if (aOrF==TopAbs_INTERNAL || aOrF==TopAbs_EXTERNAL) {
1912         continue;
1913       }
1914       ++aNbF;
1915     }
1916     //
1917     if (aNbF==1) {
1918       bRet=!bRet; // True
1919       break;
1920     }
1921   }
1922   //
1923   return bRet;
1924 }
1925 //=======================================================================
1926 //function : IsInvertedSolid
1927 //purpose  : 
1928 //=======================================================================
1929 Standard_Boolean 
1930   BOPTools_AlgoTools::IsInvertedSolid(const TopoDS_Solid& aSolid)
1931 {
1932   Standard_Real aTolS;
1933   TopAbs_State aState;
1934   BRepClass3d_SolidClassifier aSC(aSolid);
1935   //
1936   aTolS=1.e-7;
1937   aSC.PerformInfinitePoint(aTolS);
1938   aState=aSC.State();
1939   return (aState==TopAbs_IN); 
1940 }