0029293: Boolean Operations algorithm does not preserve the orientations of the faces
[occt.git] / src / BOPAlgo / BOPAlgo_Builder_2.cxx
index 026990b..c818e16 100644 (file)
 // 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 <BOPAlgo_Builder.ixx>
 
-#include <NCollection_IncAllocator.hxx>
-
-#include <TopoDS_Shape.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS_Compound.hxx>
-
-#include <BRep_Tool.hxx>
-#include <BRep_Builder.hxx>
-
-#include <TopExp_Explorer.hxx>
-
-#include <BOPCol_ListOfShape.hxx>
-#include <BOPCol_ListOfInteger.hxx>
-#include <BOPCol_MapOfInteger.hxx>
+#include <BOPAlgo_Builder.hxx>
+#include <BOPAlgo_BuilderFace.hxx>
+#include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Tools.hxx>
 #include <BOPCol_DataMapOfIntegerListOfShape.hxx>
 #include <BOPCol_DataMapOfShapeShape.hxx>
-
-#include <BOPInt_Context.hxx>
-
-#include <BOPDS_PaveBlock.hxx>
-#include <BOPDS_ShapeInfo.hxx>
+#include <BOPCol_ListOfInteger.hxx>
+#include <BOPCol_ListOfShape.hxx>
+#include <BOPCol_MapOfInteger.hxx>
+#include <BOPCol_NCVector.hxx>
+#include <BOPCol_Parallel.hxx>
 #include <BOPDS_DS.hxx>
 #include <BOPDS_FaceInfo.hxx>
-#include <BOPDS_MapOfPaveBlock.hxx>
-#include <BOPDS_VectorOfInterfFF.hxx>
 #include <BOPDS_Interf.hxx>
+#include <BOPDS_MapOfPaveBlock.hxx>
+#include <BOPDS_PaveBlock.hxx>
+#include <BOPDS_ShapeInfo.hxx>
 #include <BOPDS_VectorOfCurve.hxx>
+#include <BOPDS_VectorOfInterfFF.hxx>
 #include <BOPDS_VectorOfPoint.hxx>
-
 #include <BOPTools.hxx>
 #include <BOPTools_AlgoTools.hxx>
 #include <BOPTools_AlgoTools2D.hxx>
 #include <BOPTools_AlgoTools3D.hxx>
-#include <BOPAlgo_BuilderFace.hxx>
 #include <BOPTools_CoupleOfShape.hxx>
+#include <BOPTools_DataMapOfShapeSet.hxx>
 #include <BOPTools_ListOfCoupleOfShape.hxx>
 #include <BOPTools_MapOfSet.hxx>
-#include <BOPTools_DataMapOfShapeSet.hxx>
-#include <BOPAlgo_Builder_2Cnt.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <GeomAdaptor_Surface.hxx>
+#include <GeomLib.hxx>
+#include <Precision.hxx>
+#include <IntTools_Context.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Vertex.hxx>
 
+//
 static
   Standard_Boolean HasPaveBlocksOnIn(const BOPDS_FaceInfo& aFI1,
                                      const BOPDS_FaceInfo& aFI2);
+//
 static
-  void FillMap(const TopoDS_Shape& aS1,
-               const TopoDS_Shape& aS2,
-               BOPCol_IndexedDataMapOfShapeListOfShape& aDMSLS,
-               Handle(NCollection_IncAllocator)& aAllocator);
-static
-  void MakeBlocksCnx(const BOPCol_IndexedDataMapOfShapeListOfShape& aMILI,
-                     BOPCol_DataMapOfIntegerListOfShape& aMBlocks,
-                     Handle(NCollection_IncAllocator)& aAllocator);
+  TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
+                             const BOPCol_DataMapOfShapeListOfShape& theImages,
+                             Handle(IntTools_Context)& theCtx);
+//
+typedef BOPCol_NCVector<TopoDS_Shape> BOPAlgo_VectorOfShape;
+//
+typedef BOPCol_NCVector<BOPAlgo_VectorOfShape> \
+  BOPAlgo_VectorOfVectorOfShape;
+//
+typedef NCollection_IndexedDataMap\
+  <BOPTools_Set, Standard_Integer, BOPTools_SetMapHasher> \
+    BOPAlgo_IndexedDataMapOfSetInteger;
+//
+//=======================================================================
+//class    : BOPAlgo_PairOfShapeBoolean
+//purpose  : 
+//=======================================================================
+class BOPAlgo_PairOfShapeBoolean : public BOPAlgo_Algo {
 
+ public:
+  DEFINE_STANDARD_ALLOC
+
+  BOPAlgo_PairOfShapeBoolean() : 
+    BOPAlgo_Algo(),
+    myFlag(Standard_False) {
+  }
+  //
+  virtual ~BOPAlgo_PairOfShapeBoolean() {
+  }
+  //
+  TopoDS_Shape& Shape1() {
+    return myShape1;
+  }
+  //
+  TopoDS_Shape& Shape2() {
+    return myShape2;
+  }
+  //
+  Standard_Boolean& Flag() {
+    return myFlag;
+  }
+  //
+  void SetContext(const Handle(IntTools_Context)& aContext) {
+    myContext=aContext;
+  }
+  //
+  const Handle(IntTools_Context)& Context()const {
+    return myContext;
+  }
+  //
+  virtual void Perform() {
+    BOPAlgo_Algo::UserBreak();
+    //  
+    const TopoDS_Face& aFj=*((TopoDS_Face*)&myShape1);
+    const TopoDS_Face& aFk=*((TopoDS_Face*)&myShape2);
+    myFlag=BOPTools_AlgoTools::AreFacesSameDomain(aFj, aFk, myContext, myFuzzyValue);
+  }
+  //
+ protected: 
+  Standard_Boolean myFlag;
+  TopoDS_Shape myShape1;
+  TopoDS_Shape myShape2;
+  Handle(IntTools_Context) myContext;
+};
+//
+typedef BOPCol_NCVector<BOPAlgo_PairOfShapeBoolean> \
+  BOPAlgo_VectorOfPairOfShapeBoolean;
+//
+typedef BOPCol_ContextFunctor 
+  <BOPAlgo_PairOfShapeBoolean,
+  BOPAlgo_VectorOfPairOfShapeBoolean,
+  Handle(IntTools_Context), 
+  IntTools_Context> BOPCol_BuilderSDFaceFunctor;
+//
+typedef BOPCol_ContextCnt 
+  <BOPCol_BuilderSDFaceFunctor,
+  BOPAlgo_VectorOfPairOfShapeBoolean,
+  Handle(IntTools_Context)> BOPAlgo_BuilderSDFaceCnt;
+//
+//=======================================================================
+// BuilderFace
+//
+typedef BOPCol_NCVector<BOPAlgo_BuilderFace> BOPAlgo_VectorOfBuilderFace;
+//
+typedef BOPCol_Functor 
+  <BOPAlgo_BuilderFace,
+  BOPAlgo_VectorOfBuilderFace> BOPAlgo_BuilderFaceFunctor;
+//
+typedef BOPCol_Cnt 
+  <BOPAlgo_BuilderFaceFunctor,
+  BOPAlgo_VectorOfBuilderFace> BOPAlgo_BuilderFaceCnt;
+//
+//=======================================================================
+//class    : BOPAlgo_VFI
+//purpose  : 
+//=======================================================================
+class BOPAlgo_VFI : public BOPAlgo_Algo {
 
+ public:
+  DEFINE_STANDARD_ALLOC
+  
+  BOPAlgo_VFI() :
+    BOPAlgo_Algo(),
+    myFlag(-1) {
+  }
+  //
+  virtual ~BOPAlgo_VFI(){
+  }
+  //
+  void SetVertex(const TopoDS_Vertex& aV) {
+    myV=aV;
+  }
+  //
+  TopoDS_Vertex& Vertex() {
+    return myV;
+  }
+  //
+  void SetFace(const TopoDS_Face& aF) {
+    myF=aF;
+  }
+  //
+  TopoDS_Face& Face() {
+    return myF;
+  }
+  //
+  Standard_Integer Flag()const {
+    return myFlag;
+  }
+  //
+  void SetContext(const Handle(IntTools_Context)& aContext) {
+    myContext=aContext;
+  }
+  //
+  const Handle(IntTools_Context)& Context()const {
+    return myContext;
+  }
+  //
+  virtual void Perform() {
+    Standard_Real aT1, aT2, dummy;
+    //
+    BOPAlgo_Algo::UserBreak();
+    myFlag = myContext->ComputeVF(myV, myF, aT1, aT2, dummy, myFuzzyValue);
+  }
+  //
+ protected:
+  Standard_Integer myFlag;
+  TopoDS_Vertex myV;
+  TopoDS_Face myF;
+  Handle(IntTools_Context) myContext;
+};
+//
+typedef BOPCol_NCVector<BOPAlgo_VFI> BOPAlgo_VectorOfVFI; 
+//
+typedef BOPCol_ContextFunctor 
+  <BOPAlgo_VFI,
+  BOPAlgo_VectorOfVFI,
+  Handle(IntTools_Context), 
+  IntTools_Context> BOPAlgo_VFIFunctor;
+//
+typedef BOPCol_ContextCnt 
+  <BOPAlgo_VFIFunctor,
+  BOPAlgo_VectorOfVFI,
+  Handle(IntTools_Context)> BOPAlgo_VFICnt;
+//
 //=======================================================================
 //function : FillImagesFaces
 //purpose  : 
 //=======================================================================
 void BOPAlgo_Builder::FillImagesFaces()
 {
-  myErrorStatus=0;
-  //
   BuildSplitFaces();
   FillSameDomainFaces();
   FillImagesFaces1();
@@ -97,8 +246,6 @@ void BOPAlgo_Builder::BuildSplitFaces()
 {
   Standard_Boolean bHasFaceInfo, bIsClosed, bIsDegenerated, bToReverse;
   Standard_Integer i, j, k, aNbS, aNbPBIn, aNbPBOn, aNbPBSc, aNbAV, nSp;
-  Standard_Boolean bRunParallel;
-  Standard_Size aNbBF;
   TopoDS_Face aFF, aFSD;
   TopoDS_Edge aSp, aEE;
   TopAbs_Orientation anOriF, anOriE;
@@ -107,18 +254,19 @@ void BOPAlgo_Builder::BuildSplitFaces()
   BOPCol_ListOfInteger aLIAV;
   BOPCol_MapOfShape aMFence;
   Handle(NCollection_BaseAllocator) aAllocator;
-  BOPCol_ListOfShape aLFIm(myAllocator);
-  BOPCol_MapIteratorOfMapOfShape aItMS;
   BOPAlgo_VectorOfBuilderFace aVBF;
   //
-  myErrorStatus=0;
-  //
   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope f
-  aAllocator=new NCollection_IncAllocator();
+  aAllocator=
+    NCollection_BaseAllocator::CommonBaseAllocator();
   //
   BOPCol_ListOfShape aLE(aAllocator);
   BOPCol_MapOfShape aMDE(100, aAllocator);
   //
+  // Build temporary map of faces images to avoid rebuilding
+  // of the faces without any IN or section edges
+  NCollection_IndexedDataMap<Standard_Integer, BOPCol_ListOfShape> aFacesIm;
+  //
   aNbS=myDS->NbSourceShapes();
   //
   for (i=0; i<aNbS; ++i) {
@@ -128,6 +276,9 @@ void BOPAlgo_Builder::BuildSplitFaces()
     }
     //
     const TopoDS_Face& aF=(*(TopoDS_Face*)(&aSI.Shape()));
+    Standard_Boolean isUClosed = Standard_False,
+                     isVClosed = Standard_False,
+                     isChecked = Standard_False;
     //
     bHasFaceInfo=myDS->HasFaceInfo(i);
     if(!bHasFaceInfo) {
@@ -149,26 +300,37 @@ void BOPAlgo_Builder::BuildSplitFaces()
     if (!aNbPBIn && !aNbPBOn && !aNbPBSc && !aNbAV) { // not compete
       continue;
     }
-    //
+
+    if (!aNbPBIn && !aNbPBSc)
+    {
+      // No internal parts for the face, so just build the draft face
+      // and keep it to pass directly into result.
+      // If the original face has any internal edges, the draft face
+      // will be null, as the internal edges may split the face on parts
+      // (as in the case "bugs modalg_5 bug25245_1").
+      // The BuilderFace algorithm will be called in this case.
+      TopoDS_Face aFD = BuildDraftFace(aF, myImages, myContext);
+      if (!aFD.IsNull())
+      {
+        aFacesIm(aFacesIm.Add(i, BOPCol_ListOfShape())).Append(aFD);
+        continue;
+      }
+    }
+
     aMFence.Clear();
     //
     anOriF=aF.Orientation();
     aFF=aF;
     aFF.Orientation(TopAbs_FORWARD);
     //
-    
-    //
-    // 1. Fill the egdes set for the face aFF -> LE
+    // 1. Fill the edges set for the face aFF -> LE
     aLE.Clear();
-    //
-    //
+
     // 1.1 Bounding edges
     aExp.Init(aFF, TopAbs_EDGE);
     for (; aExp.More(); aExp.Next()) {
       const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
       anOriE=aE.Orientation();
-      bIsDegenerated=BRep_Tool::Degenerated(aE);
-      bIsClosed=BRep_Tool::IsClosed(aE, aF);
       //
       if (!myImages.IsBound(aE)) {
         if (anOriE==TopAbs_INTERNAL) {
@@ -181,48 +343,71 @@ void BOPAlgo_Builder::BuildSplitFaces()
         else {
           aLE.Append(aE);
         }
+
+        continue;
       }
-      else {//else 1
-        const BOPCol_ListOfShape& aLIE=myImages.Find(aE);
-        aIt.Initialize(aLIE);
-        for (; aIt.More(); aIt.Next()) {
-          aSp=(*(TopoDS_Edge*)(&aIt.Value()));
-          if (bIsDegenerated) {
-            aSp.Orientation(anOriE);
-            aLE.Append(aSp);
-            continue;
-          }
+
+      if(!isChecked)
+      {
+        const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aF);
+        GeomLib::IsClosed(aSurf, BRep_Tool::Tolerance(aE),
+          isUClosed, isVClosed);
+
+        isChecked = Standard_True;
+      }
+
+      bIsClosed = Standard_False;
+
+      if((isUClosed || isVClosed) && BRep_Tool::IsClosed(aE, aF)) 
+      {
+
+        Standard_Boolean isUIso = Standard_False, isVIso = Standard_False;
+        BOPTools_AlgoTools2D::IsEdgeIsoline(aE, aF, isUIso, isVIso);
+
+        bIsClosed = ((isUClosed && isUIso) || (isVClosed && isVIso));
+      }
+
+      bIsDegenerated=BRep_Tool::Degenerated(aE);
+
+      const BOPCol_ListOfShape& aLIE=myImages.Find(aE);
+      aIt.Initialize(aLIE);
+      for (; aIt.More(); aIt.Next()) {
+        aSp=(*(TopoDS_Edge*)(&aIt.Value()));
+        if (bIsDegenerated) {
+          aSp.Orientation(anOriE);
+          aLE.Append(aSp);
+          continue;
+        }
+        //
+        if (anOriE==TopAbs_INTERNAL) {
+          aSp.Orientation(TopAbs_FORWARD);
+          aLE.Append(aSp);
+          aSp.Orientation(TopAbs_REVERSED);
+          aLE.Append(aSp);
+          continue;
+        }
           //
-          if (anOriE==TopAbs_INTERNAL) {
+        if (bIsClosed) {
+          if (aMFence.Add(aSp)) {
+            if (!BRep_Tool::IsClosed(aSp, aF)){
+              BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, aF);
+            }
+            //
             aSp.Orientation(TopAbs_FORWARD);
             aLE.Append(aSp);
             aSp.Orientation(TopAbs_REVERSED);
             aLE.Append(aSp);
-            continue;
-          }
-          //
-          if (bIsClosed) {
-            if (aMFence.Add(aSp)) {
-              if (!BRep_Tool::IsClosed(aSp, aF)){
-                BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, aF);
-                }
-              //
-              aSp.Orientation(TopAbs_FORWARD);
-              aLE.Append(aSp);
-              aSp.Orientation(TopAbs_REVERSED);
-              aLE.Append(aSp);
-            }// if (aMFence.Add(aSp))
-            continue;
-          }// if (bIsClosed){
-          //
-          aSp.Orientation(anOriE);
-          bToReverse=BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, myContext);
-          if (bToReverse) {
-            aSp.Reverse();
-          }
-          aLE.Append(aSp);
-        }// for (; aIt.More(); aIt.Next()) {
-      }// else 1
+          }// if (aMFence.Add(aSp))
+          continue;
+        }// if (bIsClosed){
+        //
+        aSp.Orientation(anOriE);
+        bToReverse=BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, myContext);
+        if (bToReverse) {
+          aSp.Reverse();
+        }
+        aLE.Append(aSp);
+      }// for (; aIt.More(); aIt.Next()) {
     }// for (; aExp.More(); aExp.Next()) {
     // 
     //
@@ -251,45 +436,47 @@ void BOPAlgo_Builder::BuildSplitFaces()
       aLE.Append(aSp);
     }
     //
-    BOPTools_AlgoTools2D::BuildPCurveForEdgesOnPlane (aLE, aFF);
-    //
+    if (!myPaveFiller->NonDestructive()) {
+      // speed up for planar faces
+      BOPTools_AlgoTools2D::BuildPCurveForEdgesOnPlane (aLE, aFF);
+    }
     // 3 Build split faces
     BOPAlgo_BuilderFace& aBF=aVBF.Append1();
     aBF.SetFace(aF);
     aBF.SetShapes(aLE);
+    aBF.SetRunParallel(myRunParallel);
+    aBF.SetProgressIndicator(myProgressIndicator);
     //
   }// for (i=0; i<aNbS; ++i) {
   //
-  aNbBF=aVBF.Extent();
-  //
   //===================================================
-  bRunParallel=Standard_True;
-  BOPAlgo_BuilderFaceCnt::Perform(bRunParallel, aVBF);
+  BOPAlgo_BuilderFaceCnt::Perform(myRunParallel, aVBF);
   //===================================================
   //
-  for (k=0; k<(Standard_Integer)aNbBF; ++k) {
-    aLFIm.Clear();
-    //
-    BOPAlgo_BuilderFace& aBF=aVBF(k);
-    TopoDS_Face aF=aBF.Face();
-    anOriF=aBF.Orientation();
-    aF.Orientation(anOriF);
-    //
-    const BOPCol_ListOfShape& aLFR=aBF.Areas();
+  Standard_Integer aNbBF = aVBF.Extent();
+  for (k = 0; k < aNbBF; ++k)
+  {
+    BOPAlgo_BuilderFace& aBF = aVBF(k);
+    aFacesIm.Add(myDS->Index(aBF.Face()), aBF.Areas());
+  }
+
+  aNbBF = aFacesIm.Extent();
+  for (k = 1; k <= aNbBF; ++k)
+  {
+    const TopoDS_Face& aF = TopoDS::Face(myDS->Shape(aFacesIm.FindKey(k)));
+    anOriF = aF.Orientation();
+    const BOPCol_ListOfShape& aLFR = aFacesIm(k);
+    //
+    BOPCol_ListOfShape* pLFIm = mySplits.Bound(aF, BOPCol_ListOfShape());
     aIt.Initialize(aLFR);
     for (; aIt.More(); aIt.Next()) {
       TopoDS_Shape& aFR=aIt.ChangeValue();
-      if (anOriF==TopAbs_REVERSED) {
+      if (anOriF==TopAbs_REVERSED)
         aFR.Orientation(TopAbs_REVERSED);
-      }
-      //aFR.Orientation(anOriF);
-      aLFIm.Append(aFR);
+      pLFIm->Append(aFR);
     }
-    //
-    mySplits.Bind(aF, aLFIm); 
-  }// for (k=0; k<aNbBF; ++k) {
+  }
   //
-  aAllocator.Nullify();
   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope t
 }
 //=======================================================================
@@ -299,14 +486,12 @@ void BOPAlgo_Builder::BuildSplitFaces()
 void BOPAlgo_Builder::FillSameDomainFaces()
 {
   Standard_Boolean bFlag;
-  Standard_Integer i, j, k, aNbFFs, aNbCurves, aNbPoints, nF1, nF2, aNbS;
-  Handle(NCollection_IncAllocator) aAllocator;
+  Standard_Integer i, j, k, aNbFFs, nF1, nF2;
+  Handle(NCollection_BaseAllocator) aAllocator;
   BOPCol_ListIteratorOfListOfShape aItF;
   BOPCol_MapOfShape aMFence;
   BOPAlgo_IndexedDataMapOfSetInteger aIDMSS;
   BOPAlgo_VectorOfVectorOfShape aVVS;
-//
-  myErrorStatus=0;
   //
   const BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
   //
@@ -319,30 +504,6 @@ void BOPAlgo_Builder::FillSameDomainFaces()
     const BOPDS_InterfFF& aFF=aFFs(i);
     aFF.Indices(nF1, nF2);
     //
-    const BOPDS_VectorOfCurve& aCurves=aFF.Curves();
-    aNbCurves=aCurves.Extent();
-    if (aNbCurves) {
-      //
-      bFlag=Standard_False;
-      for (j=0; j<aNbCurves; ++j) {
-        const BOPDS_Curve& aNC=aCurves.Value(j);
-        bFlag=aNC.HasEdge();
-        if (bFlag) {
-          break;
-        }
-      }
-      if (bFlag) {
-        continue;
-      }
-      //continue;
-    }
-    //
-    const BOPDS_VectorOfPoint& aPoints=aFF.Points();
-    aNbPoints=aPoints.Extent();
-    if (aNbPoints) {
-      continue;
-    }
-    //
     if (!myDS->HasFaceInfo(nF1) || !myDS->HasFaceInfo(nF2) ) {
       continue;
     }
@@ -358,63 +519,63 @@ void BOPAlgo_Builder::FillSameDomainFaces()
     //
     if (bFlag) {
       for (k=0; k<2; ++k) {
-       const TopoDS_Shape& aF=(!k) ? aF1 : aF2;
-       const BOPCol_ListOfShape& aLF=mySplits.Find(aF);
-       //
-       aItF.Initialize(aLF);
-       for (; aItF.More(); aItF.Next()) {
-         const TopoDS_Shape& aFx=aItF.Value();
-         //
-         if (aMFence.Add(aFx)) {
-           BOPTools_Set aSTx;
-           //
-           aSTx.AddEdges(aFx);
-           //
-           if (!aIDMSS.Contains(aSTx)) {
-             BOPAlgo_VectorOfShape& aVS=aVVS.Append1(); 
-             aVS.Append(aFx);
-             //
-             j=aVVS.Extent()-1;
-             aIDMSS.Add (aSTx, j);
-           }
-           else {
-             j=aIDMSS.ChangeFromKey(aSTx);
-             BOPAlgo_VectorOfShape& aVS=aVVS(j);
-             aVS.Append(aFx);
-           }
-         }
-       }
+        const TopoDS_Shape& aF=(!k) ? aF1 : aF2;
+        const BOPCol_ListOfShape& aLF=mySplits.Find(aF);
+        //
+        aItF.Initialize(aLF);
+        for (; aItF.More(); aItF.Next()) {
+          const TopoDS_Shape& aFx=aItF.Value();
+          //
+          if (aMFence.Add(aFx)) {
+            BOPTools_Set aSTx;
+            //
+            aSTx.Add(aFx, TopAbs_EDGE);
+            //
+            if (!aIDMSS.Contains(aSTx)) {
+              BOPAlgo_VectorOfShape& aVS=aVVS.Append1(); 
+              aVS.Append(aFx);
+              //
+              j=aVVS.Extent()-1;
+              aIDMSS.Add (aSTx, j);
+            }
+            else {
+              j=aIDMSS.ChangeFromKey(aSTx);
+              BOPAlgo_VectorOfShape& aVS=aVVS(j);
+              aVS.Append(aFx);
+            }
+          }
+        }
       }
     }// if (bFlag) {
     else {// if (!bFlag) 
       BOPTools_Set aST1, aST2;
       //
-      aST1.AddEdges(aF1);
-      aST2.AddEdges(aF2);
+      aST1.Add(aF1, TopAbs_EDGE);
+      aST2.Add(aF2, TopAbs_EDGE);
       //
       if (aST1.IsEqual(aST2)) {
-       if (!aIDMSS.Contains(aST1)) {
-         BOPAlgo_VectorOfShape& aVS=aVVS.Append1(); 
-         if (aMFence.Add(aF1)) {
-           aVS.Append(aF1);
-         }
-         if (aMFence.Add(aF2)) {
-           aVS.Append(aF2);
-         }
-         //
-         k=aVVS.Extent()-1;
-         aIDMSS.Add (aST1, k);
-       }
-       else {
-         k=aIDMSS.ChangeFromKey(aST1);
-         BOPAlgo_VectorOfShape& aVS=aVVS(k);
-         if (aMFence.Add(aF1)) {
-           aVS.Append(aF1);
-         }
-         if (aMFence.Add(aF2)) {
-           aVS.Append(aF2);
-         }
-       }
+        if (!aIDMSS.Contains(aST1)) {
+          BOPAlgo_VectorOfShape& aVS=aVVS.Append1(); 
+          if (aMFence.Add(aF1)) {
+            aVS.Append(aF1);
+          }
+          if (aMFence.Add(aF2)) {
+            aVS.Append(aF2);
+          }
+          //
+          k=aVVS.Extent()-1;
+          aIDMSS.Add (aST1, k);
+        }
+        else {
+          k=aIDMSS.ChangeFromKey(aST1);
+          BOPAlgo_VectorOfShape& aVS=aVVS(k);
+          if (aMFence.Add(aF1)) {
+            aVS.Append(aF1);
+          }
+          if (aMFence.Add(aF2)) {
+            aVS.Append(aF2);
+          }
+        }
       }//if (aST1.IsEqual(aST2)) {
     }// else {// if (!bFlag) 
     //
@@ -422,7 +583,7 @@ void BOPAlgo_Builder::FillSameDomainFaces()
   //
   aIDMSS.Clear();
   //
-  Standard_Boolean bRunParallel, bFlagSD;
+  Standard_Boolean bFlagSD;
   Standard_Integer aNbVPSB, aNbVVS, aNbF, aNbF1;
   BOPAlgo_VectorOfPairOfShapeBoolean aVPSB;
   //
@@ -438,20 +599,22 @@ void BOPAlgo_Builder::FillSameDomainFaces()
     for (j=0; j<aNbF1; ++j) {
       const TopoDS_Shape& aFj=aVS(j);
       for (k=j+1; k<aNbF; ++k) {
-       const TopoDS_Shape& aFk=aVS(k);
-       BOPAlgo_PairOfShapeBoolean& aPSB=aVPSB.Append1();
-       aPSB.Shape1()=aFj;
-       aPSB.Shape2()=aFk;
+        const TopoDS_Shape& aFk=aVS(k);
+        BOPAlgo_PairOfShapeBoolean& aPSB=aVPSB.Append1();
+        aPSB.Shape1()=aFj;
+        aPSB.Shape2()=aFk;
+        aPSB.SetFuzzyValue(myFuzzyValue);
+        aPSB.SetProgressIndicator(myProgressIndicator);
       }
     }
   }
-  //====================================================
-  bRunParallel=Standard_True;
-  BOPAlgo_BuilderSDFaceCnt::Perform(bRunParallel, aVPSB);
-  //====================================================
-  aAllocator=new NCollection_IncAllocator();
+  //================================================================
+  BOPAlgo_BuilderSDFaceCnt::Perform(myRunParallel, aVPSB, myContext);
+  //================================================================
+  aAllocator=
+    NCollection_BaseAllocator::CommonBaseAllocator();
   BOPCol_IndexedDataMapOfShapeListOfShape aDMSLS(100, aAllocator);
-  BOPCol_DataMapOfIntegerListOfShape aMBlocks(100, aAllocator);
+  NCollection_List<BOPCol_ListOfShape> aMBlocks(aAllocator);
   //
   aNbVPSB=aVPSB.Extent();
   for (i=0; i<aNbVPSB; ++i) {
@@ -460,21 +623,18 @@ void BOPAlgo_Builder::FillSameDomainFaces()
     if (bFlagSD) {
       const TopoDS_Shape& aFj=aPSB.Shape1();
       const TopoDS_Shape& aFk=aPSB.Shape2();
-      FillMap(aFj, aFk, aDMSLS, aAllocator);
+      BOPAlgo_Tools::FillMap<TopoDS_Shape, TopTools_ShapeMapHasher>(aFj, aFk, aDMSLS, aAllocator);
     }
   }
   aVPSB.Clear();
   //
   // 2. Make blocks
-  MakeBlocksCnx(aDMSLS, aMBlocks, aAllocator);
+  BOPAlgo_Tools::MakeBlocks<TopoDS_Shape, TopTools_ShapeMapHasher>(aDMSLS, aMBlocks, aAllocator);
   //
   // 3. Fill same domain faces map -> aMSDF
-  aNbS = aMBlocks.Extent();
-  for (i=0; i<aNbS; ++i) {
-    const BOPCol_ListOfShape& aLSD=aMBlocks.Find(i);
-    if (aLSD.IsEmpty()) {
-      continue;
-    }
+  NCollection_List<BOPCol_ListOfShape>::Iterator aItB(aMBlocks);
+  for (; aItB.More(); aItB.Next()) {
+    const BOPCol_ListOfShape& aLSD = aItB.Value();
     //
     const TopoDS_Shape& aFSD1=aLSD.First();
     aItF.Initialize(aLSD);
@@ -485,15 +645,14 @@ void BOPAlgo_Builder::FillSameDomainFaces()
       // If the face has no splits but are SD face,
       // it is considered as splitted face
       if (!mySplits.IsBound(aFSD)) {
-       BOPCol_ListOfShape aLS;
-       aLS.Append(aFSD);
-       mySplits.Bind(aFSD, aLS);
+        BOPCol_ListOfShape aLS;
+        aLS.Append(aFSD);
+        mySplits.Bind(aFSD, aLS);
       }
     }
   }
   aMBlocks.Clear();
   aDMSLS.Clear();
-  aAllocator.Nullify();
 }
 //=======================================================================
 // function: FillImagesFaces1
@@ -501,11 +660,15 @@ void BOPAlgo_Builder::FillSameDomainFaces()
 //=======================================================================
 void BOPAlgo_Builder::FillImagesFaces1()
 {
-  Standard_Integer i, aNbS, iSense;
+  Standard_Integer i, aNbS, iSense, nVx, aNbVFI, iFlag;
   TopoDS_Face aFSD;
+  TopoDS_Vertex aVx;
+  BRep_Builder aBB;
   BOPCol_ListOfInteger aLIAV;
   BOPCol_ListOfShape aLFIm;
-  BOPCol_ListIteratorOfListOfShape aItLS;
+  BOPCol_ListIteratorOfListOfInteger aItV;
+  BOPCol_ListIteratorOfListOfShape aItLS, aItF;
+  BOPAlgo_VectorOfVFI aVVFI;
   //
   aNbS=myDS->NbSourceShapes();
   for (i=0; i<aNbS; ++i) {
@@ -519,7 +682,8 @@ void BOPAlgo_Builder::FillImagesFaces1()
     if (!mySplits.IsBound(aF)) {
       continue;
     }
-    //
+    // 
+    // 1.
     aLIAV.Clear();
     myDS->AloneVertices(i, aLIAV);
     aLFIm.Clear();
@@ -533,7 +697,7 @@ void BOPAlgo_Builder::FillImagesFaces1()
       }
       else {
         aFSD=(*(TopoDS_Face*)(&myShapesSD.Find(aFSp)));
-        iSense=BOPTools_AlgoTools::Sense(aFSp, aFSD);
+        iSense=BOPTools_AlgoTools::Sense(aFSp, aFSD, myContext);
         if (iSense<0) {
           aFSD.Reverse();
         }
@@ -541,158 +705,57 @@ void BOPAlgo_Builder::FillImagesFaces1()
       }
     }
     //
-    FillInternalVertices(aLFIm, aLIAV);
+    //FillInternalVertices(aLFIm, aLIAV);
     //
     myImages.Bind(aF, aLFIm); 
     //
-    //fill myOrigins
+    // 2. fill myOrigins
     aItLS.Initialize(aLFIm);
     for (; aItLS.More(); aItLS.Next()) {
       const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&aItLS.Value()));
-      myOrigins.Bind(aFSp, aF);
-    }
-  }// for (i=0; i<aNbS; ++i) {
-}
-//=======================================================================
-// function: FillInternalVertices
-// purpose: 
-//=======================================================================
-void BOPAlgo_Builder::FillInternalVertices(BOPCol_ListOfShape& aLFIm,
-                                          BOPCol_ListOfInteger& aLIAV)
-{
-  Standard_Integer nV, iFlag;
-  Standard_Real aU1, aU2;
-  TopoDS_Vertex aV;
-  BRep_Builder aBB;
-  BOPCol_ListIteratorOfListOfInteger aItV;
-  BOPCol_ListIteratorOfListOfShape aItF;
-  //
-  aItV.Initialize(aLIAV);
-  for (; aItV.More(); aItV.Next()) {
-    nV=aItV.Value();
-    aV=(*(TopoDS_Vertex*)(&myDS->Shape(nV)));
-    aV.Orientation(TopAbs_INTERNAL);
-    //
-    aItF.Initialize(aLFIm);
-    for (; aItF.More(); aItF.Next()) {
-      TopoDS_Face& aF=(*(TopoDS_Face*)(&aItF.Value()));
-      iFlag=myContext->ComputeVF(aV, aF, aU1, aU2);
-      if (!iFlag) {
-        aBB.Add(aF, aV);
-        break;
+      //
+      BOPCol_ListOfShape* pLOr = myOrigins.ChangeSeek(aFSp);
+      if (!pLOr) {
+        pLOr = myOrigins.Bound(aFSp, BOPCol_ListOfShape());
       }
+      pLOr->Append(aF);
     }
-  }
-}
-//=======================================================================
-//function : MakeBlocksCnx
-//purpose  : 
-//=======================================================================
-void MakeBlocksCnx(const BOPCol_IndexedDataMapOfShapeListOfShape& aMILI,
-                   BOPCol_DataMapOfIntegerListOfShape& aMBlocks,
-                   Handle(NCollection_IncAllocator)& aAllocator)
-{
-  Standard_Integer aNbV, aNbVS, aNbVP, aNbEC, k, i, j;
-  BOPCol_ListIteratorOfListOfShape aItLI;
-  //
-  BOPCol_MapOfShape aMVS(100, aAllocator);
-  BOPCol_IndexedMapOfShape aMEC(100, aAllocator);
-  BOPCol_IndexedMapOfShape aMVP(100, aAllocator);
-  BOPCol_IndexedMapOfShape aMVAdd(100, aAllocator);
-  //
-  aNbV=aMILI.Extent();
-  //
-  for (k=0,i=1; i<=aNbV; ++i) {
-    aNbVS=aMVS.Extent();
-    if (aNbVS==aNbV) {
-      break;
-    }
-    //
-    const TopoDS_Shape& nV=aMILI.FindKey(i);
-    if (aMVS.Contains(nV)){
-      continue;
-    }
-    aMVS.Add(nV);
-    //
-    aMEC.Clear();
-    aMVP.Clear();
-    aMVAdd.Clear();
     //
-    aMVP.Add(nV);
-    for(;;) {
-      aNbVP=aMVP.Extent();
-      for (j=1; j<=aNbVP; ++j) {
-        const TopoDS_Shape& nVP=aMVP(j);
-        const BOPCol_ListOfShape& aLV=aMILI.FindFromKey(nVP);
-        aItLI.Initialize(aLV);
-        for (; aItLI.More(); aItLI.Next()) {
-          const TopoDS_Shape& nVx=aItLI.Value();
-          if (aMEC.Contains(nVx)) {
-            continue;
-          }
-          //
-          aMVS.Add(nVx);
-          aMEC.Add(nVx);
-          aMVAdd.Add(nVx);
-        }
-      }
+    // 3.
+    aItV.Initialize(aLIAV);
+    for (; aItV.More(); aItV.Next()) {
+      nVx=aItV.Value();
+      aVx=(*(TopoDS_Vertex*)(&myDS->Shape(nVx)));
+      aVx.Orientation(TopAbs_INTERNAL);
       //
-      aNbVP=aMVAdd.Extent();
-      if (!aNbVP) {
-        break; // from while(1)
+      aItF.Initialize(aLFIm);
+      for (; aItF.More(); aItF.Next()) {
+        TopoDS_Face& aFy=(*(TopoDS_Face*)(&aItF.Value()));
+        //
+        BOPAlgo_VFI& aVFI=aVVFI.Append1();
+        aVFI.SetVertex(aVx);
+        aVFI.SetFace(aFy);
+        aVFI.SetFuzzyValue(myFuzzyValue);
+        aVFI.SetProgressIndicator(myProgressIndicator);
       }
-      //
-      aMVP.Clear();
-      for (j=1; j<=aNbVP; ++j) {
-        aMVP.Add(aMVAdd(j));
-      }
-      aMVAdd.Clear();
-    }//while(1) {
-    //
-    BOPCol_ListOfShape aLIx(aAllocator);
-    //
-    aNbEC = aMEC.Extent();
-    for (j=1; j<=aNbEC; ++j) {
-      const TopoDS_Shape& nVx=aMEC(j);
-      aLIx.Append(nVx);
     }
-    //
-    aMBlocks.Bind(k, aLIx);
-    ++k;
-  }//for (k=0,i=1; i<=aNbV; ++i)
-  aMVAdd.Clear();
-  aMVP.Clear();
-  aMEC.Clear();
-  aMVS.Clear();
-}
-
-//=======================================================================
-//function : FillMap
-//purpose  : 
-//=======================================================================
-void FillMap(const TopoDS_Shape& aS1,
-             const TopoDS_Shape& aS2,
-             BOPCol_IndexedDataMapOfShapeListOfShape& aDMSLS,
-             Handle(NCollection_IncAllocator)& aAllocator)
-{
-  if (aDMSLS.Contains(aS1)) {
-    BOPCol_ListOfShape& aLS=aDMSLS.ChangeFromKey(aS1);
-    aLS.Append(aS2);
-  }
-  else {
-    BOPCol_ListOfShape aLS(aAllocator);
-    aLS.Append(aS2);
-    aDMSLS.Add(aS1, aLS);
-  }
+  }// for (i=0; i<aNbS; ++i) {
   //
-  if (aDMSLS.Contains(aS2)) {
-    BOPCol_ListOfShape& aLS=aDMSLS.ChangeFromKey(aS2);
-    aLS.Append(aS1);
-  }
-  else {
-    BOPCol_ListOfShape aLS(aAllocator);
-    aLS.Append(aS1);
-    aDMSLS.Add(aS2, aLS);
+  // 4. 
+  aNbVFI=aVVFI.Extent();
+  //================================================================
+  BOPAlgo_VFICnt::Perform(myRunParallel, aVVFI, myContext);
+  //================================================================
+  //
+  for (i=0; i < aNbVFI; ++i) {
+    BOPAlgo_VFI& aVFI=aVVFI(i);
+    //
+    iFlag=aVFI.Flag();
+    if (!iFlag) {
+      TopoDS_Vertex& aVertex=aVFI.Vertex();
+      TopoDS_Face& aFy=aVFI.Face(); 
+      aBB.Add(aFy, aVertex);
+    }
   }
 }
 //=======================================================================
@@ -703,48 +766,125 @@ Standard_Boolean HasPaveBlocksOnIn(const BOPDS_FaceInfo& aFI1,
                                    const BOPDS_FaceInfo& aFI2)
 {
   Standard_Boolean bRet;
-  BOPDS_MapIteratorOfMapOfPaveBlock aItMPB;
+  Standard_Integer i, aNbPB;
   //
   bRet=Standard_False;
-  const BOPDS_IndexedMapOfPaveBlock& aMPBOn1=aFI1.PaveBlocksOn();
-  const BOPDS_IndexedMapOfPaveBlock& aMPBIn1=aFI1.PaveBlocksIn();
-  //
-  const BOPDS_IndexedMapOfPaveBlock& aMPBOn2=aFI2.PaveBlocksOn();
-  aItMPB.Initialize(aMPBOn2);
-  for (; aItMPB.More(); aItMPB.Next()) {
-    const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
-    bRet=aMPBOn1.Contains(aPB) || aMPBIn1.Contains(aPB);
+  const BOPDS_IndexedMapOfPaveBlock& aMPBOn1 = aFI1.PaveBlocksOn();
+  const BOPDS_IndexedMapOfPaveBlock& aMPBIn1 = aFI1.PaveBlocksIn();
+  //
+  const BOPDS_IndexedMapOfPaveBlock& aMPBOn2 = aFI2.PaveBlocksOn();
+  aNbPB = aMPBOn2.Extent();
+  for (i = 1; i <= aNbPB; ++i) {
+    const Handle(BOPDS_PaveBlock)& aPB = aMPBOn2(i);
+    bRet = aMPBOn1.Contains(aPB) || aMPBIn1.Contains(aPB);
     if (bRet) {
       return bRet;
     }
   }
   //
-  const BOPDS_IndexedMapOfPaveBlock& aMPBIn2=aFI2.PaveBlocksIn();
-  aItMPB.Initialize(aMPBIn2);
-  for (; aItMPB.More(); aItMPB.Next()) {
-    const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
-    bRet=aMPBOn1.Contains(aPB) || aMPBIn1.Contains(aPB);
+  const BOPDS_IndexedMapOfPaveBlock& aMPBIn2 = aFI2.PaveBlocksIn();
+  aNbPB = aMPBIn2.Extent();
+  for (i = 1; i <= aNbPB; ++i) {
+    const Handle(BOPDS_PaveBlock)& aPB = aMPBIn2(i);
+    bRet = aMPBOn1.Contains(aPB) || aMPBIn1.Contains(aPB);
     if (bRet) {
       return bRet;
     }
   }
   return bRet;
 }
-/*
-//DEBf
+
+//=======================================================================
+//function : BuildDraftFace
+//purpose  : Build draft faces, updating the bounding edges,
+//           according to the information stored into the <theImages> map
+//=======================================================================
+TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
+                           const BOPCol_DataMapOfShapeListOfShape& theImages,
+                           Handle(IntTools_Context)& theCtx)
+{
+  BRep_Builder aBB;
+  // Take the information from the original face
+  TopLoc_Location aLoc;
+  const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLoc);
+  const Standard_Real aTol = BRep_Tool::Tolerance(theFace);
+  // Make the new face, without any wires
+  TopoDS_Face aDraftFace;
+  aBB.MakeFace(aDraftFace, aS, aLoc, aTol);
+
+  // Update wires of the original face and add them to draft face
+  TopoDS_Iterator aItW(theFace.Oriented(TopAbs_FORWARD));
+  for (; aItW.More(); aItW.Next())
+  {
+    const TopoDS_Shape& aW = aItW.Value();
+    if (aW.ShapeType() != TopAbs_WIRE)
+      continue;
+
+    // Rebuild wire using images of edges
+    TopoDS_Iterator aItE(aW.Oriented(TopAbs_FORWARD));
+    if (!aItE.More())
+      continue;
+
+    TopoDS_Wire aNewWire;
+    aBB.MakeWire(aNewWire);
+
+    for (; aItE.More(); aItE.Next())
     {
-      TopoDS_Compound aCx;
-      BRep_Builder aBBx;
-      BOPCol_ListIteratorOfListOfShape aItx;
-      //
-      aBBx.MakeCompound(aCx);
-      aBBx.Add(aCx, aFF);
-      aItx.Initialize(aLE);
-      for (; aItx.More(); aItx.Next()) {
-      const TopoDS_Shape& aEx=aItx.Value();
-      aBBx.Add(aCx, aEx);
+      const TopoDS_Edge& aE = TopoDS::Edge(aItE.Value());
+
+      TopAbs_Orientation anOriE = aE.Orientation();
+      if (anOriE == TopAbs_INTERNAL)
+      {
+        // The internal edges could split the original face on halves.
+        // Thus, use the BuilderFace algorithm to build the new face.
+        TopoDS_Face aNull;
+        return aNull;
+      }
+
+      const BOPCol_ListOfShape* pLEIm = theImages.Seek(aE);
+      if (!pLEIm)
+      {
+        aBB.Add(aNewWire, aE);
+        continue;
+      }
+
+      // Check if the original edge is degenerated
+      Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(aE);
+      // Check if the original edge is closed on the face
+      Standard_Boolean bIsClosed = BRep_Tool::IsClosed(aE, theFace);
+
+      BOPCol_ListIteratorOfListOfShape aItLEIm(*pLEIm);
+      for (; aItLEIm.More(); aItLEIm.Next())
+      {
+        TopoDS_Edge& aSp = TopoDS::Edge(aItLEIm.Value());
+
+        aSp.Orientation(anOriE);
+        if (bIsDegenerated)
+        {
+          aBB.Add(aNewWire, aSp);
+          continue;
+        }
+
+        // Check closeness of the split edge and if it is not
+        // make the second PCurve
+        if (bIsClosed && !BRep_Tool::IsClosed(aSp, theFace))
+          BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, theFace);
+
+        // Check if the split should be reversed
+        if (BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, theCtx))
+          aSp.Reverse();
+
+        aBB.Add(aNewWire, aSp);
       }
-      int a=0;
     }
-    //DEBt
-*/
+
+    aNewWire.Orientation(aW.Orientation());
+    aNewWire.Closed(BRep_Tool::IsClosed(aNewWire));
+    aBB.Add(aDraftFace, aNewWire);
+  }
+
+  if (theFace.Orientation() == TopAbs_REVERSED)
+    aDraftFace.Reverse();
+
+  return aDraftFace;
+}