0025880: fuzzy booleans with multiple tools
[occt.git] / src / BOPTools / BOPTools_AlgoTools.cxx
index eebf260..1ed5095 100644 (file)
@@ -1,24 +1,19 @@
 // Created by: Peter KURNEV
-// Copyright (c) 2010-2012 OPEN CASCADE SAS
+// Copyright (c) 2010-2014 OPEN CASCADE SAS
 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
 //                         EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
-
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <BOPTools_AlgoTools.ixx>
 //
@@ -69,7 +64,8 @@
 #include <BOPCol_IndexedMapOfShape.hxx>
 #include <BOPCol_MapOfShape.hxx>
 //
-#include <BOPInt_ShrunkRange.hxx>
+#include <IntTools_ShrunkRange.hxx>
+#include <Precision.hxx>
 //
 
 static
@@ -81,7 +77,7 @@ static
   Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
                                   const BOPCol_ListOfShape& thLF,
                                   BOPTools_ListOfCoupleOfShape& theLCFF,
-                                  Handle(BOPInt_Context)& theContext);
+                                  Handle(IntTools_Context)& theContext);
 static
   TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
                                  const TopoDS_Face& aF);
@@ -94,25 +90,33 @@ static
                   const gp_Dir& aDTgt,
                   gp_Dir& aDN,
                   gp_Dir& aDB,
-                  Handle(BOPInt_Context)& theContext,
-                  GeomAPI_ProjectPointOnSurf& aProjPL);
+                  Handle(IntTools_Context)& theContext,
+                  GeomAPI_ProjectPointOnSurf& aProjPL,
+                  const Standard_Real aDt);
 static
-  Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
-                                   const TopoDS_Face& aF,
+  Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
                                    const gp_Pnt& aP,
                                    gp_Dir& aDB,
                                    gp_Pnt& aPOut,
-                                   Handle(BOPInt_Context)& theContext,
-                                   GeomAPI_ProjectPointOnSurf& aProjPL);
+                                   Handle(IntTools_Context)& theContext,
+                                   GeomAPI_ProjectPointOnSurf& aProjPL,
+                                   const Standard_Real aDt,
+                                   const Standard_Real aTolE);
+static 
+  Standard_Real MinStep3D(const TopoDS_Edge& theE1,
+                          const TopoDS_Face& theF1,
+                          const BOPTools_ListOfCoupleOfShape& theLCS,
+                          const gp_Pnt& aP);
 
 //=======================================================================
 // function: MakeConnexityBlocks
 // purpose: 
 //=======================================================================
-void BOPTools_AlgoTools::MakeConnexityBlocks (const TopoDS_Shape& theS,
-                                              const TopAbs_ShapeEnum theType1,
-                                              const TopAbs_ShapeEnum theType2,
-                                              BOPCol_ListOfShape& theLCB)
+void BOPTools_AlgoTools::MakeConnexityBlocks 
+  (const TopoDS_Shape& theS,
+   const TopAbs_ShapeEnum theType1,
+   const TopAbs_ShapeEnum theType2,
+   BOPCol_ListOfShape& theLCB)
 {
   Standard_Integer  aNbF, aNbAdd, aNbAdd1, i;
   BRep_Builder aBB;
@@ -208,7 +212,9 @@ void BOPTools_AlgoTools::OrientFacesOnShell (TopoDS_Shape& aShell)
   //
   BOPTools_AlgoTools::MakeContainer(TopAbs_SHELL, aShellNew);
   //
-  BOPTools::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
+  BOPTools::MapShapesAndAncestors(aShell, 
+                                  TopAbs_EDGE, TopAbs_FACE, 
+                                  aEFMap);
   aNbE=aEFMap.Extent();
   // 
   // One seam edge  in aEFMap contains  2 equivalent faces.
@@ -339,18 +345,15 @@ TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
   }
   return anOr;
 }
-
-////////////
-
-
 //=======================================================================
 // function: MakeConnexityBlock.
 // purpose: 
 //=======================================================================
-void BOPTools_AlgoTools::MakeConnexityBlock (BOPCol_ListOfShape& theLFIn,
-                                             BOPCol_IndexedMapOfShape& theMEAvoid,
-                                             BOPCol_ListOfShape& theLCB,
-                                             const Handle(NCollection_BaseAllocator)& theAllocator)
+void BOPTools_AlgoTools::MakeConnexityBlock 
+  (BOPCol_ListOfShape& theLFIn,
+   BOPCol_IndexedMapOfShape& theMEAvoid,
+   BOPCol_ListOfShape& theLCB,
+   const Handle(NCollection_BaseAllocator)& theAllocator)
 {
   Standard_Integer  aNbF, aNbAdd1, aNbAdd, i;
   TopExp_Explorer aExp;
@@ -427,10 +430,11 @@ void BOPTools_AlgoTools::MakeConnexityBlock (BOPCol_ListOfShape& theLFIn,
 // function:  ComputeStateByOnePoint
 // purpose: 
 //=======================================================================
-TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint(const TopoDS_Shape& theS,
-                                                        const TopoDS_Solid& theRef,
-                                                        const Standard_Real theTol,
-                                                        Handle(BOPInt_Context)& theContext)
+TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint
+  (const TopoDS_Shape& theS,
+   const TopoDS_Solid& theRef,
+   const Standard_Real theTol,
+   Handle(IntTools_Context)& theContext)
 {
   TopAbs_State aState;
   TopAbs_ShapeEnum aType;
@@ -452,11 +456,12 @@ TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint(const TopoDS_Shape& theS
 // function:  ComputeState
 // purpose: 
 //=======================================================================
-TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Face& theF,
-                                              const TopoDS_Solid& theRef,
-                                              const Standard_Real theTol,
-                                              BOPCol_IndexedMapOfShape& theBounds,
-                                              Handle(BOPInt_Context)& theContext)
+TopAbs_State BOPTools_AlgoTools::ComputeState
+  (const TopoDS_Face& theF,
+   const TopoDS_Solid& theRef,
+   const Standard_Real theTol,
+   BOPCol_IndexedMapOfShape& theBounds,
+   Handle(IntTools_Context)& theContext)
 {
   TopAbs_State aState;
   TopExp_Explorer aExp; 
@@ -475,7 +480,8 @@ TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Face& theF,
     //
     if (!theBounds.Contains(aSE)) {
       const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aSE));
-      aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
+      aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, 
+                                              theContext);
       return aState;
     }
     if (aE1.IsNull()) {
@@ -484,8 +490,10 @@ TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Face& theF,
   }
   // !!<- process edges that are all on theRef
   if (!aE1.IsNull()) {
-    BOPTools_AlgoTools3D::PointNearEdge(aE1, theF, aP2D, aP3D, theContext);
-    aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
+    BOPTools_AlgoTools3D::PointNearEdge(aE1, theF, 
+                                        aP2D, aP3D, theContext);
+    aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, 
+                                            theContext);
   }
   //
   return aState;
@@ -494,26 +502,29 @@ TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Face& theF,
 // function:  ComputeState
 // purpose: 
 //=======================================================================
-TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Vertex& theV,
-                                              const TopoDS_Solid& theRef,
-                                              const Standard_Real theTol,
-                                              Handle(BOPInt_Context)& theContext)
+TopAbs_State BOPTools_AlgoTools::ComputeState
+  (const TopoDS_Vertex& theV,
+   const TopoDS_Solid& theRef,
+   const Standard_Real theTol,
+   Handle(IntTools_Context)& theContext)
 {
   TopAbs_State aState;
   gp_Pnt aP3D; 
   //
   aP3D=BRep_Tool::Pnt(theV);
-  aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
+  aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, 
+                                          theContext);
   return aState;
 }
 //=======================================================================
 // function:  ComputeState
 // purpose: 
 //=======================================================================
-TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Edge& theE,
-                                              const TopoDS_Solid& theRef,
-                                              const Standard_Real theTol,
-                                              Handle(BOPInt_Context)& theContext)
+TopAbs_State BOPTools_AlgoTools::ComputeState
+  (const TopoDS_Edge& theE,
+   const TopoDS_Solid& theRef,
+   const Standard_Real theTol,
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Real aT1, aT2, aT = 0.;
   TopAbs_State aState;
@@ -552,7 +563,8 @@ TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Edge& theE,
     aC3D->D0(aT, aP3D);
   }
   //
-  aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
+  aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, 
+                                          theContext);
   //
   return aState;
 }
@@ -560,10 +572,11 @@ TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Edge& theE,
 // function:  ComputeState
 // purpose: 
 //=======================================================================
-TopAbs_State BOPTools_AlgoTools::ComputeState(const gp_Pnt& theP,
-                                              const TopoDS_Solid& theRef,
-                                              const Standard_Real theTol,
-                                              Handle(BOPInt_Context)& theContext)
+TopAbs_State BOPTools_AlgoTools::ComputeState
+  (const gp_Pnt& theP,
+   const TopoDS_Solid& theRef,
+   const Standard_Real theTol,
+   Handle(IntTools_Context)& theContext)
 {
   TopAbs_State aState;
   //
@@ -583,7 +596,7 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace
    const TopoDS_Solid& theSolid,
    BOPCol_IndexedDataMapOfShapeListOfShape& theMEF,
    const Standard_Real theTol,
-   Handle(BOPInt_Context)& theContext)
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bDegenerated;
   Standard_Integer aNbF, iRet, iFound;
@@ -638,7 +651,8 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace
         break;
       }
       //
-      iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1, theContext);
+      iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1, 
+                                              theContext);
       break;
     }
     //
@@ -648,7 +662,8 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace
       //
       if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
         // treat as it was for 1 face
-        iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2, theContext);
+        iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2, 
+                                                theContext);
         break;
       }
     }
@@ -658,7 +673,8 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace
       return iRet; // it can not be so
     }
     else { // aNbF=2,4,6,8,...
-      iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF, theContext);
+      iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF, 
+                                              theContext);
       break;
     }
   }//for(; aExp.More(); aExp.Next()) {
@@ -680,7 +696,8 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace
   //
   BOPTools::MapShapes(theSolid, TopAbs_EDGE, aBounds);
   //
-  aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid, theTol, aBounds, theContext);
+  aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid, 
+                                          theTol, aBounds, theContext);
   //
   iRet=(aState==TopAbs_IN)? 1 : 0;
   //
@@ -690,10 +707,11 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace
 //function : IsInternalFace
 //purpose  : 
 //=======================================================================
-Standard_Integer BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
-                                                    const TopoDS_Edge& theEdge,
-                                                    BOPCol_ListOfShape& theLF,
-                                                    Handle(BOPInt_Context)& theContext)
+Standard_Integer BOPTools_AlgoTools::IsInternalFace
+  (const TopoDS_Face& theFace,
+   const TopoDS_Edge& theEdge,
+   BOPCol_ListOfShape& theLF,
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Integer aNbF, iRet;
   //
@@ -703,7 +721,8 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
   if (aNbF==2) {
     const TopoDS_Face& aF1=(*(TopoDS_Face*)(&theLF.First()));
     const TopoDS_Face& aF2=(*(TopoDS_Face*)(&theLF.Last()));
-    iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
+    iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, 
+                                            theContext);
     return iRet;
   }
   //
@@ -719,7 +738,8 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
       //
       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aCSFF.Shape1()));
       const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCSFF.Shape2()));
-      iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
+      iRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, 
+                                              theContext);
       if (iRet) {
         return iRet;
       }
@@ -736,7 +756,7 @@ Standard_Integer BOPTools_AlgoTools::IsInternalFace
    const TopoDS_Edge& theEdge,
    const TopoDS_Face& theFace1,
    const TopoDS_Face& theFace2,
-   Handle(BOPInt_Context)& theContext)
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bRet;
   Standard_Integer iRet;
@@ -790,11 +810,11 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
    const TopoDS_Face& theF1,
    BOPTools_ListOfCoupleOfShape& theLCSOff,
    TopoDS_Face& theFOff,
-   Handle(BOPInt_Context)& theContext)
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bRet;
-  Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin;
-  Standard_Real aUmin, aUsup, aVmin, aVsup;
+  Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin, aDt3D;
+  Standard_Real aUmin, aUsup, aVmin, aVsup, aPA;
   gp_Pnt aPn1, aPn2, aPx;
   gp_Dir aDN1, aDN2, aDBF, aDBF2, aDTF;
   gp_Vec aVTgt;
@@ -804,6 +824,7 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
   BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
   GeomAPI_ProjectPointOnSurf aProjPL;
   //
+  aPA=Precision::Angular();
   aAngleMin=100.;
   aTwoPI=M_PI+M_PI;
   aC3D =BRep_Tool::Curve(theE1, aT1, aT2);
@@ -818,7 +839,9 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
   aPL->Bounds(aUmin, aUsup, aVmin, aVsup);
   aProjPL.Init(aPL, aUmin, aUsup, aVmin, aVsup);
   //
-  GetFaceDir(theE1, theF1, aPx, aT, aDTgt, aDN1, aDBF, theContext, aProjPL);
+  aDt3D = MinStep3D(theE1, theF1, theLCSOff, aPx);
+  GetFaceDir(theE1, theF1, aPx, aT, aDTgt, aDN1, aDBF, theContext, 
+             aProjPL, aDt3D);
   //
   aDTF=aDN1^aDBF;
   //
@@ -830,7 +853,8 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
     const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCS.Shape2()));
     //
     aDTgt2 = (aE2.Orientation()==aOr) ? aDTgt : aDTgt.Reversed();
-    GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, aDN2, aDBF2, theContext, aProjPL);
+    GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, aDN2, aDBF2, theContext, 
+               aProjPL, aDt3D);
     //Angle
     aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
     //
@@ -838,7 +862,7 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
       aAngle=aTwoPI+aAngle;
     }
     //
-    if (aAngle<Precision::Angular()) {
+    if (aAngle<aPA) {
       if (aF2==theF1) {
         aAngle=M_PI;
       }
@@ -847,6 +871,11 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
       }
     }
     //
+    if (fabs(aAngle-aAngleMin)<aPA) {
+      // the minimal angle can not be found
+      bRet=Standard_False; 
+    }
+    //
     if (aAngle<aAngleMin){
       aAngleMin=aAngle;
       theFOff=aF2;
@@ -893,9 +922,10 @@ Standard_Boolean BOPTools_AlgoTools::GetEdgeOff(const TopoDS_Edge& theE1,
 //function : AreFacesSameDomain
 //purpose  : 
 //=======================================================================
-Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain(const TopoDS_Face& theF1,
-                                                        const TopoDS_Face& theF2,
-                                                        Handle(BOPInt_Context)& theContext)
+Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain
+  (const TopoDS_Face& theF1,
+   const TopoDS_Face& theF2,
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bFlag;
   Standard_Integer iErr;
@@ -927,7 +957,8 @@ Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain(const TopoDS_Face& theF1
   aTolF2=BRep_Tool::Tolerance(aF2);
   aTol=aTolF1+aTolF2;
   //
-  iErr = BOPTools_AlgoTools3D::PointInFace(aF1, aP, aP2D, theContext);
+  iErr = BOPTools_AlgoTools3D::PointInFace(aF1, aP, aP2D,
+                                           theContext);
   if (!iErr) {
     bFlag=theContext->IsValidPointForFace(aP, aF2, aTol);
   }
@@ -939,9 +970,10 @@ Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain(const TopoDS_Face& theF1
 //function : CheckSameGeom
 //purpose  : 
 //=======================================================================
-Standard_Boolean BOPTools_AlgoTools::CheckSameGeom(const TopoDS_Face& theF1,
-                                                   const TopoDS_Face& theF2,
-                                                   Handle(BOPInt_Context)& theContext)
+Standard_Boolean BOPTools_AlgoTools::CheckSameGeom
+  (const TopoDS_Face& theF1,
+   const TopoDS_Face& theF2,
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bRet;
   Standard_Real aTolF1, aTolF2, aTol;
@@ -1014,9 +1046,10 @@ Standard_Integer BOPTools_AlgoTools::Sense (const TopoDS_Face& theF1,
 // function: IsSplitToReverse
 // purpose: 
 //=======================================================================
-Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Shape& theSp,
-                                                      const TopoDS_Shape& theSr,
-                                                      Handle(BOPInt_Context)& theContext)
+Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
+  (const TopoDS_Shape& theSp,
+   const TopoDS_Shape& theSr,
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bRet;
   TopAbs_ShapeEnum aType;
@@ -1048,9 +1081,10 @@ Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Shape& theSp,
 //function :IsSplitToReverse
 //purpose  : 
 //=======================================================================
-Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
-                                                      const TopoDS_Face& theFSr,
-                                                      Handle(BOPInt_Context)& theContext)
+Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
+  (const TopoDS_Face& theFSp,
+   const TopoDS_Face& theFSr,
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bRet, bFound, bInFace;
   Standard_Real aT1, aT2, aT, aU, aV, aScPr;
@@ -1089,7 +1123,8 @@ Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
     Standard_Integer iErr;
     gp_Pnt2d aP2DFSp;
     //
-    iErr=BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
+    iErr=BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, 
+                                           theContext);
     if (iErr) {
       return bRet;
     }
@@ -1099,11 +1134,17 @@ Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
     if (!bFlag) {
       return bRet;
     }
+    //
+    if (theFSp.Orientation()==TopAbs_REVERSED){
+      aDNFSp.Reverse();
+    }
   }
   else {
     BRep_Tool::Range(aESp, aT1, aT2);
     aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
-    BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT, aPFSp, aDNFSp, theContext);
+    BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT, 
+                                                      aPFSp, aDNFSp, 
+                                                      theContext);
   }
   //
   // Parts of theContext->ComputeVS(..) 
@@ -1115,7 +1156,7 @@ Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
   //
   aProjector.LowerDistanceParameters(aU, aV);
   gp_Pnt2d aP2D(aU, aV);
-  bInFace=theContext->IsPointInFace (theFSr, aP2D);
+  bInFace=theContext->IsPointInOnFace (theFSr, aP2D);
   if (!bInFace) {
     return bRet;
   }
@@ -1137,9 +1178,10 @@ Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
 //function :IsSplitToReverse
 //purpose  : 
 //=======================================================================
-Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Edge& aEF1,
-                                                      const TopoDS_Edge& aEF2,
-                                                      Handle(BOPInt_Context)& theContext)
+Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse
+  (const TopoDS_Edge& aEF1,
+   const TopoDS_Edge& aEF2,
+   Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bRet, bIsDegenerated;
   //
@@ -1194,7 +1236,7 @@ Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
   Standard_Boolean bIsHole;
   Standard_Integer i, aNbS;
   Standard_Real aT1, aT2, aS;
-  Standard_Real aU1, aU2, aU, dU;
+  Standard_Real aU1, aU, dU;
   Standard_Real aX1, aY1, aX0, aY0;
   TopAbs_Orientation aOr;
   
@@ -1233,11 +1275,9 @@ Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
     dU=(aT2-aT1)/(Standard_Real)(aNbS-1);
     aU =aT1;
     aU1=aT1;
-    aU2=aT2;
     if (aOr==TopAbs_REVERSED) {
       aU =aT2;
       aU1=aT2;
-      aU2=aT1;
       dU=-dU;
     }
     //
@@ -1329,7 +1369,8 @@ void BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
   aTolE=BRep_Tool::Tolerance(aE);
   //
   const Handle(Geom_Curve)& aC3DE=BRep_Tool::Curve(aE, aT1, aT2);
-  Handle(Geom_TrimmedCurve)aC3DETrim=new Geom_TrimmedCurve(aC3DE, aT1, aT2);
+  Handle(Geom_TrimmedCurve)aC3DETrim=
+    new Geom_TrimmedCurve(aC3DE, aT1, aT2);
   //
   for (i=0; i<2; ++i) {
     bPC = !i ? bPC1 : bPC2;
@@ -1357,10 +1398,12 @@ void BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
       }
     //
     if (aC3DE->IsPeriodic()) {
-      BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2,  aC2D, aC2DA); 
+      BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2,  aC2D, 
+                                               aC2DA); 
     }
     else {
-      BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D, aC2DA); 
+      BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D, 
+                                               aC2DA); 
     }
     //
     aBB.UpdateEdge(aE, aC2DA, aFFWD, aTolE);
@@ -1383,7 +1426,8 @@ void BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
   Standard_Real aTolV;
   BRep_Builder aBB;
   //
-  BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2, theE);
+  BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2, 
+                                    theE);
   //
   aBB.UpdateEdge(theE, theTolR3D);
   //
@@ -1453,13 +1497,67 @@ void BOPTools_AlgoTools::MakeVertex(BOPCol_ListOfShape& aLV,
                                     TopoDS_Vertex& aVnew)
 {
   Standard_Integer aNb;
-  Standard_Real aTi, aDi, aDmax;
-  gp_Pnt aPi, aP;
-  gp_XYZ aXYZ(0.,0.,0.), aXYZi;
-  BOPCol_ListIteratorOfListOfShape aIt;
   //
   aNb=aLV.Extent();
-  if (aNb) {
+  if (!aNb) {
+    return;
+  }
+  //
+  else if (aNb==1) {
+    aVnew=*((TopoDS_Vertex*)(&aLV.First()));
+    return;
+  }
+  //
+  else if (aNb==2) {
+    Standard_Integer m, n;
+    Standard_Real aR[2], dR, aD, aEps;
+    TopoDS_Vertex aV[2];
+    gp_Pnt aP[2];
+    BRep_Builder aBB;
+    //
+    aEps=RealEpsilon();
+    for (m=0; m<aNb; ++m) {
+      aV[m]=(!m)? 
+       *((TopoDS_Vertex*)(&aLV.First())):
+       *((TopoDS_Vertex*)(&aLV.Last()));
+      aP[m]=BRep_Tool::Pnt(aV[m]);
+      aR[m]=BRep_Tool::Tolerance(aV[m]);
+    }  
+    //
+    m=0; // max R
+    n=1; // min R
+    if (aR[0]<aR[1]) {
+      m=1;
+      n=0;
+    }
+    //
+    dR=aR[m]-aR[n]; // dR >= 0.
+    gp_Vec aVD(aP[m], aP[n]);
+    aD=aVD.Magnitude();
+    //
+    if (aD<=dR || aD<aEps) { 
+      aBB.MakeVertex (aVnew, aP[m], aR[m]);
+    }
+    else {
+      Standard_Real aRr;
+      gp_XYZ aXYZr;
+      gp_Pnt aPr;
+      //
+      aRr=0.5*(aR[m]+aR[n]+aD);
+      aXYZr=0.5*(aP[m].XYZ()+aP[n].XYZ()-aVD.XYZ()*(dR/aD));
+      aPr.SetXYZ(aXYZr);
+      //
+      aBB.MakeVertex (aVnew, aPr, aRr);
+    }
+    return;
+  }// else if (aNb==2) {
+  //
+  else { // if (aNb>2) 
+    Standard_Real aTi, aDi, aDmax;
+    gp_Pnt aPi, aP;
+    gp_XYZ aXYZ(0.,0.,0.), aXYZi;
+    BOPCol_ListIteratorOfListOfShape aIt;
+    //
     aIt.Initialize(aLV);
     for (; aIt.More(); aIt.Next()) {
       TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
@@ -1493,9 +1591,10 @@ void BOPTools_AlgoTools::MakeVertex(BOPCol_ListOfShape& aLV,
 //function : GetEdgeOnFace
 //purpose  : 
 //=======================================================================
-Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace(const TopoDS_Edge& theE1,
-                                                   const TopoDS_Face& theF2,
-                                                   TopoDS_Edge& theE2)
+Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace
+(const TopoDS_Edge& theE1,
+ const TopoDS_Face& theF2,
+ TopoDS_Edge& theE2)
 {
   Standard_Boolean bFound;
   TopoDS_Iterator aItF, aItW;
@@ -1524,7 +1623,7 @@ Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace(const TopoDS_Edge& theE1,
 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
                                 const BOPCol_ListOfShape& thLF,
                                 BOPTools_ListOfCoupleOfShape& theLCFF,
-                                Handle(BOPInt_Context)& theContext)
+                                Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bFound;
   Standard_Integer i, aNbCEF;
@@ -1646,10 +1745,11 @@ Standard_Real AngleWithRef(const gp_Dir& theD1,
 // function: IsBlockInOnFace
 // purpose: 
 //=======================================================================
-Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace (const IntTools_Range& aShrR,
-                                                      const TopoDS_Face& aF,
-                                                      const TopoDS_Edge& aE1,
-                                                      Handle(BOPInt_Context)& aContext)
+Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace
+  (const IntTools_Range& aShrR,
+   const TopoDS_Face& aF,
+   const TopoDS_Edge& aE1,
+   Handle(IntTools_Context)& aContext)
 {
   Standard_Boolean bFlag;
   Standard_Real f1, l1, ULD, VLD;
@@ -1736,8 +1836,9 @@ Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace (const IntTools_Range& aShr
 //function : IsMicroEdge
 //purpose  : 
 //=======================================================================
-Standard_Boolean BOPTools_AlgoTools::IsMicroEdge(const TopoDS_Edge& aE,
-                                                 const Handle(BOPInt_Context)& aCtx) 
+Standard_Boolean BOPTools_AlgoTools::IsMicroEdge
+  (const TopoDS_Edge& aE,
+   const Handle(IntTools_Context)& aCtx) 
 {
   Standard_Boolean bRet;
   Standard_Integer iErr;
@@ -1761,8 +1862,9 @@ Standard_Boolean BOPTools_AlgoTools::IsMicroEdge(const TopoDS_Edge& aE,
     aT2=aTmp;
   }
   //
-  BOPInt_ShrunkRange aSR;
-  aSR.SetData(aE, aT1, aT2, aV1, aV2, aCtx);
+  IntTools_ShrunkRange aSR;
+  aSR.SetContext(aCtx);
+  aSR.SetData(aE, aT1, aT2, aV1, aV2);
   aSR.Perform();
   iErr=aSR.ErrorStatus();
   bRet = !(iErr==0);
@@ -1781,107 +1883,231 @@ void GetFaceDir(const TopoDS_Edge& aE,
                 const gp_Dir& aDTgt,
                 gp_Dir& aDN,
                 gp_Dir& aDB,
-                Handle(BOPInt_Context)& theContext,
-                GeomAPI_ProjectPointOnSurf& aProjPL)
+                Handle(IntTools_Context)& theContext,
+                GeomAPI_ProjectPointOnSurf& aProjPL,
+                const Standard_Real aDt)
 {
+  Standard_Real aTolE;
+  gp_Pnt aPx;
+  //
   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE, aF, aT, aDN);
   if (aF.Orientation()==TopAbs_REVERSED){
     aDN.Reverse();
   }
+  //
+  aTolE=BRep_Tool::Tolerance(aE); 
   aDB = aDN^aDTgt;
   //
-  gp_Pnt aPx;
-  if (!FindPointInFace(aE, aF, aP, aDB, aPx, theContext, aProjPL)) {
-    BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aE, aF, aT, aPx, aDN, theContext);
+  if (!FindPointInFace(aF, aP, aDB, aPx, theContext, aProjPL, aDt, aTolE)) {
+    BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aE, aF, aT, aPx, 
+                                                      aDN, theContext);
     aProjPL.Perform(aPx);
     aPx = aProjPL.NearestPoint();
     gp_Vec aVec(aP, aPx);
     aDB.SetXYZ(aVec.XYZ());
   }
 }
-
 //=======================================================================
 //function : FindPointInFace
 //purpose  : Find a point in the face in direction of <aDB>
 //=======================================================================
-Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
-                                 const TopoDS_Face& aF,
+Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
                                  const gp_Pnt& aP,
                                  gp_Dir& aDB,
                                  gp_Pnt& aPOut,
-                                 Handle(BOPInt_Context)& theContext,
-                                 GeomAPI_ProjectPointOnSurf& aProjPL) 
+                                 Handle(IntTools_Context)& theContext,
+                                 GeomAPI_ProjectPointOnSurf& aProjPL,
+                                 const Standard_Real aDt,
+                                 const Standard_Real aTolE)
 {
   Standard_Integer aNbItMax;
-  Standard_Real aDt, aDtMin, aTolE, aTolF, aDist;
+  Standard_Real aDist, aDTol, aPM, anEps;
   Standard_Boolean bRet;
-  gp_Pnt aP1;
-  BRepAdaptor_Surface aBAS;
+  gp_Pnt aP1, aPS;
   //
+  aDTol = Precision::Angular();
+  aPM = aP.XYZ().Modulus();
+  if (aPM > 1000.) {
+    aDTol = 5.e-16 * aPM;
+  }
   bRet = Standard_False;
-  aTolE = BRep_Tool::Tolerance(aE);
-  aTolF = BRep_Tool::Tolerance(aF);
-  aDt = 2*(aTolE+aTolF);
-  aBAS.Initialize(aF, Standard_False);
-  //
-  aDtMin=5.e-4;
-  if (aDt < aDtMin) {
-    Standard_Real aR;
-    GeomAbs_SurfaceType aSType=aBAS.GetType();
+  aNbItMax = 15;
+  anEps = Precision::SquareConfusion();
+  //
+  GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
+  //
+  aPS=aP;
+  aProj.Perform(aPS);
+  if (!aProj.IsDone()) {
+    return bRet;
+  }
+  aPS=aProj.NearestPoint();
+  aProjPL.Perform(aPS);
+  aPS=aProjPL.NearestPoint();
+  //
+  aPS.SetXYZ(aPS.XYZ()+2.*aTolE*aDB.XYZ());
+  aProj.Perform(aPS);
+  if (!aProj.IsDone()) {
+    return bRet;
+  }
+  aPS=aProj.NearestPoint();
+  aProjPL.Perform(aPS);
+  aPS=aProjPL.NearestPoint();
+  //
+  do {
+    aP1.SetXYZ(aPS.XYZ()+aDt*aDB.XYZ());
+    //
+    aProj.Perform(aP1);
+    if (!aProj.IsDone()) {
+      return bRet;
+    }
+    aPOut = aProj.NearestPoint();
+    aDist = aProj.LowerDistance();
+    //
+    aProjPL.Perform(aPOut);
+    aPOut = aProjPL.NearestPoint();
+    //
+    gp_Vec aV(aPS, aPOut);
+    if (aV.SquareMagnitude() < anEps) {
+      return bRet;
+    }
+    aDB.SetXYZ(aV.XYZ());
+  } while (aDist > aDTol && --aNbItMax);
+  //
+  bRet = aDist < aDTol;
+  return bRet;
+}
+//=======================================================================
+//function : MinStep3D
+//purpose  : 
+//=======================================================================
+Standard_Real MinStep3D(const TopoDS_Edge& theE1,
+                        const TopoDS_Face& theF1,
+                        const BOPTools_ListOfCoupleOfShape& theLCS,
+                        const gp_Pnt& aP)
+{
+  Standard_Real aDt, aTolE, aTolF, aDtMax, aDtMin, aR;
+  BOPTools_CoupleOfShape aCS1;
+  BOPTools_ListOfCoupleOfShape aLCS;
+  BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
+  BRepAdaptor_Surface aBAS;
+  //
+  aLCS = theLCS;
+  aCS1.SetShape1(theE1);
+  aCS1.SetShape2(theF1);
+  aLCS.Append(aCS1);
+  //
+  aTolE = BRep_Tool::Tolerance(theE1);
+  aDtMax = -1.;
+  aDtMin = 5.e-6;
+  //
+  aIt.Initialize(aLCS);
+  for (; aIt.More(); aIt.Next()) {
+    const BOPTools_CoupleOfShape& aCS = aIt.Value();
+    const TopoDS_Face& aF = (*(TopoDS_Face*)(&aCS.Shape2()));
+    //
+    aTolF = BRep_Tool::Tolerance(aF);
+    aDt = 2*(aTolE + aTolF);
+    //
+    aR = 0.;
+    aBAS.Initialize(aF, Standard_False);
+    GeomAbs_SurfaceType aSType = aBAS.GetType();
     switch (aSType) {
-    case GeomAbs_Cylinder:
+    case GeomAbs_Cylinder: {
       aR = aBAS.Cylinder().Radius();
       break;
+    }
     case GeomAbs_Cone: {
       gp_Lin aL(aBAS.Cone().Axis());
       aR = aL.Distance(aP);
       break;
     }
-    case GeomAbs_Sphere:
+    case GeomAbs_Sphere: {
+      aDtMin = Max(aDtMin, 5.e-4);
       aR = aBAS.Sphere().Radius();
       break;
-    case GeomAbs_Torus:
-      aR = aBAS.Torus().MinorRadius();
-      break;
-    case GeomAbs_SurfaceOfRevolution:
-      aR=1.;
+    }
+    case GeomAbs_Torus: {
+      aR = aBAS.Torus().MajorRadius();
       break;
-    default:
-      aR=0.001;
     }
-    if (aR < 0.01) {
-      aDtMin=5.e-6;
+    default:
+      aDtMin = Max(aDtMin, 5.e-4);
+      break;
     }
-    else if (aR > 100.) {
-      aDtMin*=10;
+    //
+    if (aR > 100.) {
+      Standard_Real d = 10*Precision::PConfusion();
+      aDtMin = Max(aDtMin, sqrt(d*d + 2*d*aR));
     }
-    if (aDt < aDtMin) {
-      aDt=aDtMin;
+    //
+    if (aDt > aDtMax) {
+      aDtMax = aDt;
     }
   }
   //
-  GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
-  aNbItMax = 15;
+  if (aDtMax < aDtMin) {
+    aDtMax = aDtMin;
+  }
   //
-  do {
-    aP1.SetCoord(aP.X()+aDt*aDB.X(),
-                 aP.Y()+aDt*aDB.Y(),
-                 aP.Z()+aDt*aDB.Z());
-    //
-    aProj.Perform(aP1);
-    if (!aProj.IsDone()) {
-      return bRet;
+  return aDtMax;
+}
+//=======================================================================
+//function : IsOpenShell
+//purpose  : 
+//=======================================================================
+Standard_Boolean BOPTools_AlgoTools::IsOpenShell(const TopoDS_Shell& aSh)
+{
+  Standard_Boolean bRet;
+  Standard_Integer i, aNbE, aNbF;
+  TopAbs_Orientation aOrF;
+  BOPCol_IndexedDataMapOfShapeListOfShape aMEF; 
+  BOPCol_ListIteratorOfListOfShape aItLS;
+  //
+  bRet=Standard_False;
+  //
+  BOPTools::MapShapesAndAncestors(aSh, TopAbs_EDGE, TopAbs_FACE, aMEF);
+  // 
+  aNbE=aMEF.Extent();
+  for (i=1; i<=aNbE; ++i) {
+    const TopoDS_Edge& aE=*((TopoDS_Edge*)&aMEF.FindKey(i));
+    if (BRep_Tool::Degenerated(aE)) {
+      continue;
     }
-    aPOut = aProj.NearestPoint();
-    aDist = aProj.LowerDistance();
     //
-    aProjPL.Perform(aPOut);
-    aPOut = aProjPL.NearestPoint();
+    aNbF=0;
+    const BOPCol_ListOfShape& aLF=aMEF(i);
+    aItLS.Initialize(aLF);
+    for (; aItLS.More(); aItLS.Next()) {
+      const TopoDS_Shape& aF=aItLS.Value();
+      aOrF=aF.Orientation();
+      if (aOrF==TopAbs_INTERNAL || aOrF==TopAbs_EXTERNAL) {
+        continue;
+      }
+      ++aNbF;
+    }
     //
-    gp_Vec aV(aP, aPOut);
-    aDB.SetXYZ(aV.XYZ());
-  } while (aDist>Precision::Angular() && --aNbItMax);
+    if (aNbF==1) {
+      bRet=!bRet; // True
+      break;
+    }
+  }
   //
-  bRet = aDist < Precision::Angular();
   return bRet;
 }
+//=======================================================================
+//function : IsInvertedSolid
+//purpose  : 
+//=======================================================================
+Standard_Boolean BOPTools_AlgoTools::IsInvertedSolid
+  (const TopoDS_Solid& aSolid)
+{
+  Standard_Real aTolS;
+  TopAbs_State aState;
+  BRepClass3d_SolidClassifier aSC(aSolid);
+  //
+  aTolS=1.e-7;
+  aSC.PerformInfinitePoint(aTolS);
+  aState=aSC.State();
+  return (aState==TopAbs_IN); 
+}