0024157: Parallelization of assembly part of BO
authorpkv <pkv@opencascade.com>
Tue, 28 Jan 2014 07:09:54 +0000 (11:09 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 30 Jan 2014 09:58:37 +0000 (13:58 +0400)
I. New features:
I.1 class BOPAlgo_ShellSplitter
The new class BOPAlgo_ShellSplitter has been added.
Purpose:  The class provides the splitting of the set of connected faces
on separate loops

II. Changes:
II.1. class BOPAlgo_BuilderSolid
- method:
void BOPAlgo_BuilderSolid::PerformLoops()
the changes that provide parallel run the ShellSplitter algorithm have been done.

- method:
void BOPAlgo_BuilderSolid::PerformAreas()
the classification the grows and holes has been done using
the algorithm of unbalanced binary tree of overlapped bounding boxes

src/BOPAlgo/BOPAlgo.cdl
src/BOPAlgo/BOPAlgo_BuilderSolid.cxx
src/BOPAlgo/BOPAlgo_ShellSplitter.cdl [new file with mode: 0644]
src/BOPAlgo/BOPAlgo_ShellSplitter.cxx [new file with mode: 0644]

index f4097cd..08b283e 100644 (file)
@@ -67,7 +67,8 @@ is
     deferred class BuilderArea;
     class BuilderFace;
     class WireEdgeSet;
     deferred class BuilderArea;
     class BuilderFace;
     class WireEdgeSet;
-    class WireSplitter; 
+    class WireSplitter;  
+    class ShellSplitter;  
     class BuilderSolid; 
     class Tools; 
     class SectionAttribute; 
     class BuilderSolid; 
     class Tools; 
     class SectionAttribute; 
index bf62137..04c9fb4 100644 (file)
 // commercial license or contractual agreement.
 
 #include <BOPAlgo_BuilderSolid.ixx>
 // commercial license or contractual agreement.
 
 #include <BOPAlgo_BuilderSolid.ixx>
-
+//
+#include <NCollection_List.hxx>
+#include <NCollection_DataMap.hxx>
+#include <NCollection_UBTreeFiller.hxx>
+//
 #include <gp_Pnt2d.hxx>
 #include <gp_Pln.hxx>
 #include <gp_Vec.hxx>
 #include <gp_Dir.hxx>
 #include <gp_Pnt.hxx>
 #include <gp_Pnt2d.hxx>
 #include <gp_Pln.hxx>
 #include <gp_Vec.hxx>
 #include <gp_Dir.hxx>
 #include <gp_Pnt.hxx>
-
+//
+#include <TColStd_MapIntegerHasher.hxx>
+//
 #include <Geom_Curve.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom2d_Curve.hxx>
 #include <Geom_Curve.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom2d_Curve.hxx>
-
+//
 #include <TopAbs.hxx>
 #include <TopAbs.hxx>
-
+//
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
 
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
-#include <BRepTools.hxx>
-#include <BRepClass3d_SolidClassifier.hxx>
-
+//
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 //
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 //
-#include <BOPTools_AlgoTools.hxx>
+#include <BRepBndLib.hxx>
+#include <BRepClass3d_SolidClassifier.hxx>
+//
 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
-#include <BOPTools.hxx>
 #include <BOPCol_ListOfShape.hxx>
 #include <BOPCol_MapOfOrientedShape.hxx>
 #include <BOPCol_ListOfShape.hxx>
 #include <BOPCol_MapOfOrientedShape.hxx>
-//
-#include <NCollection_List.hxx> 
-//
 #include <BOPCol_DataMapOfShapeShape.hxx>
 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
 #include <BOPCol_DataMapOfShapeShape.hxx>
 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
-#include <BOPInt_Context.hxx>
-#include <BOPTools_CoupleOfShape.hxx>
 #include <BOPCol_MapOfShape.hxx>
 #include <BOPCol_MapOfShape.hxx>
+#include <BOPCol_BoxBndTree.hxx>
+#include <BOPCol_ListOfInteger.hxx>
+//
+#include <BOPTools.hxx>
+#include <BOPTools_CoupleOfShape.hxx>
+#include <BOPTools_AlgoTools.hxx>
+//
+#include <BOPInt_Context.hxx>
+//
+#include <BOPAlgo_ShellSplitter.hxx>
 
 static
   Standard_Boolean IsGrowthShell(const TopoDS_Shape& ,
 
 static
   Standard_Boolean IsGrowthShell(const TopoDS_Shape& ,
@@ -74,14 +84,61 @@ static
   void MakeInternalShells(const BOPCol_MapOfShape& ,
                           BOPCol_ListOfShape& );
 
   void MakeInternalShells(const BOPCol_MapOfShape& ,
                           BOPCol_ListOfShape& );
 
-static
-  Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell);
-
+//=======================================================================
+//class     : BOPAlgo_BuilderSolid_ShapeBox
+//purpose   : Auxiliary class
+//=======================================================================
+class BOPAlgo_BuilderSolid_ShapeBox {
+ public:
+  BOPAlgo_BuilderSolid_ShapeBox() {
+    myIsHole=Standard_False;
+  };
+  //
+  ~BOPAlgo_BuilderSolid_ShapeBox() {
+  };
+  //
+  void SetShape(const TopoDS_Shape& aS) {
+    myShape=aS;
+  };
+  //
+  const TopoDS_Shape& Shape()const {
+    return myShape;
+  };
+  //
+  void SetBox(const Bnd_Box& aBox) {
+    myBox=aBox;
+  };
+  //
+  const Bnd_Box& Box()const {
+    return myBox;
+  };
+  //
+  void SetIsHole(const Standard_Boolean bFlag) {
+    myIsHole=bFlag;
+  };
+  //
+  Standard_Boolean IsHole()const {
+    return myIsHole;
+  };
+  //
+ protected:
+  Standard_Boolean myIsHole;
+  TopoDS_Shape myShape;
+  Bnd_Box myBox;
+};
+//
+typedef NCollection_DataMap\
+  <Standard_Integer, BOPAlgo_BuilderSolid_ShapeBox, TColStd_MapIntegerHasher> \
+  BOPAlgo_DataMapOfIntegerBSSB; 
+//
+typedef BOPAlgo_DataMapOfIntegerBSSB::Iterator \
+  BOPAlgo_DataMapIteratorOfDataMapOfIntegerBSSB; 
+//
 //=======================================================================
 //function : 
 //purpose  : 
 //=======================================================================
 //=======================================================================
 //function : 
 //purpose  : 
 //=======================================================================
-  BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid()
+BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid()
 :
   BOPAlgo_BuilderArea()
 {
 :
   BOPAlgo_BuilderArea()
 {
@@ -90,7 +147,8 @@ static
 //function : 
 //purpose  : 
 //=======================================================================
 //function : 
 //purpose  : 
 //=======================================================================
-BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid(const Handle(NCollection_BaseAllocator)& theAllocator)
+BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid
+  (const Handle(NCollection_BaseAllocator)& theAllocator)
 :
   BOPAlgo_BuilderArea(theAllocator)
 {
 :
   BOPAlgo_BuilderArea(theAllocator)
 {
@@ -127,8 +185,6 @@ void BOPAlgo_BuilderSolid::Perform()
   myErrorStatus=0;
   //
   if (myContext.IsNull()) {
   myErrorStatus=0;
   //
   if (myContext.IsNull()) {
-    //myErrorStatus=11;// Null Context
-    //return;
     myContext=new BOPInt_Context;
   }
   //
     myContext=new BOPInt_Context;
   }
   //
@@ -237,7 +293,7 @@ void BOPAlgo_BuilderSolid::PerformShapesToAvoid()
       break;
     }
     //
       break;
     }
     //
-  }//while (1) 
+  }//for(;;) {
 }  
 //=======================================================================
 //function : PerformLoops
 }  
 //=======================================================================
 //function : PerformLoops
@@ -245,145 +301,46 @@ void BOPAlgo_BuilderSolid::PerformShapesToAvoid()
 //=======================================================================
 void BOPAlgo_BuilderSolid::PerformLoops()
 {
 //=======================================================================
 void BOPAlgo_BuilderSolid::PerformLoops()
 {
-  myErrorStatus=0;
-  //
-  myLoops.Clear();
-  //
-  Standard_Integer aNbLF, aNbOff, aNbFP;
-  Standard_Integer i;
-  TopAbs_Orientation anOr;
-  TopoDS_Edge aEL;
-  BRep_Builder aBB;
+  Standard_Integer iErr;
+  BOPCol_ListIteratorOfListOfShape aIt;
   TopoDS_Iterator aItS;
   TopoDS_Iterator aItS;
-  //
-  BOPCol_ListIteratorOfListOfShape aItF, aIt;
   BOPCol_MapIteratorOfMapOfOrientedShape aItM;
   BOPCol_MapIteratorOfMapOfOrientedShape aItM;
-  BOPTools_CoupleOfShape aCSOff;
-  //
-  BOPCol_MapOfOrientedShape AddedFacesMap;
-  BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
-  //
-  //=================================================
+  BOPAlgo_ShellSplitter aSSp;
+  // 
+  myErrorStatus=0;
+  myLoops.Clear();
   //
   // 1. Shells Usual
   //
   // 1. Shells Usual
+  aIt.Initialize (myShapes);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aF=aIt.Value();
+    if (!myShapesToAvoid.Contains(aF)) {
+      aSSp.AddStartElement(aF);
+    }
+  }
   //
   //
-  aItF.Initialize (myShapes);
-  for (; aItF.More(); aItF.Next()) {
-    const TopoDS_Shape& aFF = aItF.Value();
-    BOPTools::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
+  aSSp.SetRunParallel(myRunParallel);
+  aSSp.Perform();
+  iErr=aSSp.ErrorStatus();
+  if (iErr) {
+    return;
   }
   //
   }
   //
-  aItF.Initialize (myShapes);
-  for (i=1; aItF.More(); aItF.Next(), ++i) {
-    const TopoDS_Shape& aFF = aItF.Value();
-    if (myShapesToAvoid.Contains(aFF)) {
-      continue;
-    }
-    if (!AddedFacesMap.Add(aFF)) {
-      continue;
-    }
-    //
-    // make a new shell
-    TopoDS_Shell aShell;
-    aBB.MakeShell(aShell);
-    aBB.Add(aShell, aFF);
-    //
-    aMEFP.Clear();
-    BOPTools::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
-    //
-    // loop on faces added to Shell; add their neighbor faces to Shell and so on
-    TopoDS_Iterator aItAddedF (aShell);
-    for (; aItAddedF.More(); aItAddedF.Next()) {
-      const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItAddedF.Value()));
-      //
-      // loop on edges of aF; find a good neighbor face of aF by aE
-      TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
-      for (; aEdgeExp.More(); aEdgeExp.Next()) {
-        const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aEdgeExp.Current()));
-        //
-        //1
-        if (aMEFP.Contains(aE)) {
-          const BOPCol_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
-          aNbFP=aLFP.Extent();
-          if (aNbFP>1) { 
-            continue;
-          }
-        }
-        //2
-        anOr=aE.Orientation();
-        if (anOr==TopAbs_INTERNAL) {
-          continue;
-        }
-        //3
-        if (BRep_Tool::Degenerated(aE)) {
-          continue;
-        }
-        //
-        // candidate faces list
-        const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
-        aNbLF=aLF.Extent();
-        if (!aNbLF) {
-          continue;
-        }
-        //
-        // try to select one of neighbors
-        // check if a face already added to Shell shares E
-        Standard_Boolean bFound;
-        BOPCol_ListIteratorOfListOfShape aItLF;
-        BOPTools_ListOfCoupleOfShape aLCSOff;
-        //
-        aItLF.Initialize(aLF);
-        for (; aItLF.More(); aItLF.Next()) { 
-          const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
-          if (myShapesToAvoid.Contains(aFL)) {
-            continue;
-          }
-          if (aF.IsSame(aFL)) {
-            continue;
-          } 
-          if (AddedFacesMap.Contains(aFL)){
-            continue;
-          }
-          //
-          bFound=BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL);
-          if (!bFound) {
-            continue;
-          }
-          //
-          aCSOff.SetShape1(aEL);
-          aCSOff.SetShape2(aFL);
-          aLCSOff.Append(aCSOff);
-        }//for (; aItLF.More(); aItLF.Next()) { 
-        //
-        aNbOff=aLCSOff.Extent();
-        if (!aNbOff){
-          continue;
-        }
-        //
-        TopoDS_Face aSelF;
-        if (aNbOff==1) {
-          aSelF=(*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
-        }
-        else if (aNbOff>1){
-          BOPTools_AlgoTools::GetFaceOff(aE, aF, aLCSOff, aSelF, myContext);
-          }
-        //
-        if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) { 
-          aBB.Add(aShell, aSelF);
-          BOPTools::MapShapesAndAncestors(aSelF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
-        }
-      } // for (; aEdgeExp.More(); aEdgeExp.Next()) { 
-    } //for (; aItAddedF.More(); aItAddedF.Next()) {
-    //
-    if (IsClosedShell(aShell)) {
-      myLoops.Append(aShell);
-    }
-  } // for (; aItF.More(); aItF.Next()) {
-  
+  const BOPCol_ListOfShape& aLSh=aSSp.Shells();
+  aIt.Initialize (aLSh);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aSh=aIt.Value();
+    myLoops.Append(aSh);
+  }
+  //=================================================
   //
   //
-  // Post Treatment
+  // 2. Post Treatment
+  Standard_Integer aNbFA;
+  BRep_Builder aBB;
+  BOPCol_MapOfOrientedShape AddedFacesMap;
+  BOPCol_IndexedDataMapOfShapeListOfShape aEFMap;
   BOPCol_MapOfOrientedShape aMP;
   BOPCol_MapOfOrientedShape aMP;
-  // 
+  //
   // a. collect all edges that are in loops
   aIt.Initialize (myLoops);
   for (; aIt.More(); aIt.Next()) {
   // a. collect all edges that are in loops
   aIt.Initialize (myLoops);
   for (; aIt.More(); aIt.Next()) {
@@ -412,17 +369,20 @@ void BOPAlgo_BuilderSolid::PerformLoops()
   }
   //=================================================
   //
   }
   //=================================================
   //
-  // 2.Internal Shells
-  //
+  // 3.Internal Shells
   myLoopsInternal.Clear();
   //
   aEFMap.Clear();
   AddedFacesMap.Clear();
   //
   myLoopsInternal.Clear();
   //
   aEFMap.Clear();
   AddedFacesMap.Clear();
   //
+  aNbFA=myShapesToAvoid.Extent();
+  //
   aItM.Initialize(myShapesToAvoid);
   for (; aItM.More(); aItM.Next()) {
     const TopoDS_Shape& aFF=aItM.Key();
   aItM.Initialize(myShapesToAvoid);
   for (; aItM.More(); aItM.Next()) {
     const TopoDS_Shape& aFF=aItM.Key();
-    BOPTools::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
+    BOPTools::MapShapesAndAncestors(aFF, 
+                                   TopAbs_EDGE, TopAbs_FACE, 
+                                   aEFMap);
   }
   //
   aItM.Initialize(myShapesToAvoid);
   }
   //
   aItM.Initialize(myShapesToAvoid);
@@ -445,9 +405,9 @@ void BOPAlgo_BuilderSolid::PerformLoops()
       for (; aEdgeExp.More(); aEdgeExp.Next()) {
         const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aEdgeExp.Current()));
         const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
       for (; aEdgeExp.More(); aEdgeExp.Next()) {
         const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aEdgeExp.Current()));
         const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
-        aItF.Initialize(aLF);
-        for (; aItF.More(); aItF.Next()) { 
-          const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItF.Value()));
+        aIt.Initialize(aLF);
+        for (; aIt.More(); aIt.Next()) { 
+          const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aIt.Value()));
           if (AddedFacesMap.Add(aFL)){
             aBB.Add(aShell, aFL);
           }
           if (AddedFacesMap.Add(aFL)){
             aBB.Add(aShell, aFL);
           }
@@ -463,129 +423,182 @@ void BOPAlgo_BuilderSolid::PerformLoops()
 //=======================================================================
 void BOPAlgo_BuilderSolid::PerformAreas()
 {
 //=======================================================================
 void BOPAlgo_BuilderSolid::PerformAreas()
 {
-  myErrorStatus=0;
-  //
-  Standard_Boolean bIsGrowthShell, bIsHole;
+  Standard_Boolean bIsGrowth, bIsHole;
+  Standard_Integer k,aNbHoles;
   BRep_Builder aBB; 
   BRep_Builder aBB; 
-  TopoDS_Shape anInfinitePointShape;
-  BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
-  BOPCol_ListIteratorOfListOfShape aShellIt, aSolidIt;
-  //
+  BOPCol_ListIteratorOfListOfShape aItLS;
   BOPCol_ListOfShape aNewSolids, aHoleShells; 
   BOPCol_DataMapOfShapeShape aInOutMap;
   BOPCol_ListOfShape aNewSolids, aHoleShells; 
   BOPCol_DataMapOfShapeShape aInOutMap;
-  BOPCol_DataMapOfShapeListOfShape aMSH;
   BOPCol_IndexedMapOfShape aMHF;
   BOPCol_IndexedMapOfShape aMHF;
+  BOPCol_ListIteratorOfListOfInteger aItLI;
+  BOPCol_BoxBndTreeSelector aSelector;
+  BOPCol_BoxBndTree aBBTree;
+  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
+  BOPAlgo_DataMapOfIntegerBSSB aDMISB(100);
+  BOPAlgo_DataMapIteratorOfDataMapOfIntegerBSSB aItDMISB;
+  BOPCol_DataMapOfShapeListOfShape aMSH;
+  BOPCol_DataMapIteratorOfDataMapOfShapeShape aItDMSS;
+  BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
+  //
+  myErrorStatus=0;
   //
   myAreas.Clear();
   //
   //  Draft solids [aNewSolids]
   //
   myAreas.Clear();
   //
   //  Draft solids [aNewSolids]
-  aShellIt.Initialize(myLoops);
-  for ( ; aShellIt.More(); aShellIt.Next()) {
-    const TopoDS_Shape& aShell = aShellIt.Value();
+  aItLS.Initialize(myLoops);
+  for (k=0; aItLS.More(); aItLS.Next(), ++k) {
+    TopoDS_Solid aSolid;
+    Bnd_Box aBox;
+    BOPAlgo_BuilderSolid_ShapeBox aSB;
+    //
+    const TopoDS_Shape& aShell = aItLS.Value();
+    aSB.SetShape(aShell);
+    //
+    BRepBndLib::Add(aShell, aBox);
+    bIsHole=Standard_False;
     //
     //
-    bIsGrowthShell=IsGrowthShell(aShell, aMHF);
-    if (bIsGrowthShell) {
+    bIsGrowth=IsGrowthShell(aShell, aMHF);
+    if (bIsGrowth) {
       // make a growth solid from a shell
       // make a growth solid from a shell
-      TopoDS_Solid Solid;
-      aBB.MakeSolid(Solid);
-      aBB.Add (Solid, aShell);
+      aBB.MakeSolid(aSolid);
+      aBB.Add (aSolid, aShell);
       //
       //
-      aNewSolids.Append (Solid);
+      aNewSolids.Append (aSolid);
+      aSB.SetShape(aSolid);
     }
     else{
       // check if a shell is a hole
     }
     else{
       // check if a shell is a hole
-      //XX
       bIsHole=IsHole(aShell, myContext);
       bIsHole=IsHole(aShell, myContext);
-      //XX
       if (bIsHole) {
         aHoleShells.Append(aShell);
         BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF);
       if (bIsHole) {
         aHoleShells.Append(aShell);
         BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF);
+       aSB.SetShape(aShell);
       }
       else {
         // make a growth solid from a shell
       }
       else {
         // make a growth solid from a shell
-        TopoDS_Solid Solid;
-        aBB.MakeSolid(Solid);
-        aBB.Add (Solid, aShell);
+        aBB.MakeSolid(aSolid);
+        aBB.Add (aSolid, aShell);
         //
         //
-        aNewSolids.Append (Solid);
+        aNewSolids.Append (aSolid);
+       aSB.SetShape(aSolid);
       }
     }
       }
     }
+    //
+    aSB.SetBox(aBox);
+    aSB.SetIsHole(bIsHole);
+    aDMISB.Bind(k, aSB);
+  }  
+  //
+  // 2. Prepare TreeFiller
+  aItDMISB.Initialize(aDMISB);
+  for (; aItDMISB.More(); aItDMISB.Next()) {
+    k=aItDMISB.Key();
+    const BOPAlgo_BuilderSolid_ShapeBox& aSB=aItDMISB.Value();
+    //
+    bIsHole=aSB.IsHole();
+    if (bIsHole) {
+      const Bnd_Box& aBox=aSB.Box();
+      aTreeFiller.Add(k, aBox);
+    }
   }
   //
   }
   //
-  // 2. Find outer growth shell that is most close to each hole shell
-  aShellIt.Initialize(aHoleShells);
-  for (; aShellIt.More(); aShellIt.Next()) {
-    const TopoDS_Shape& aHole = aShellIt.Value();
+  // 3. Shake TreeFiller
+  aTreeFiller.Fill();
+  //
+  // 4. Find outer growth shell that is most close 
+  //    to each hole shell
+  aItDMISB.Initialize(aDMISB);
+  for (; aItDMISB.More(); aItDMISB.Next()) {
+    k=aItDMISB.Key();
+    const BOPAlgo_BuilderSolid_ShapeBox& aSB=aItDMISB.Value();
+    bIsHole=aSB.IsHole();
+    if (bIsHole) {
+      continue;
+    }
+    //
+    const TopoDS_Shape aSolid=aSB.Shape();
+    const Bnd_Box& aBoxSolid=aSB.Box();
     //
     //
-    aSolidIt.Initialize(aNewSolids);
-    for ( ; aSolidIt.More(); aSolidIt.Next())    {
-      const TopoDS_Shape& aSolid = aSolidIt.Value();
+    aSelector.Clear();
+    aSelector.SetBox(aBoxSolid);
+    //
+    aNbHoles=aBBTree.Select(aSelector);
+    //
+    const BOPCol_ListOfInteger& aLI=aSelector.Indices();
+    //
+    aItLI.Initialize(aLI);
+    for (; aItLI.More(); aItLI.Next()) {
+      k=aItLI.Value();
+      const BOPAlgo_BuilderSolid_ShapeBox& aSBk=aDMISB.Find(k);
+      const TopoDS_Shape& aHole=aSBk.Shape();
       //
       if (!IsInside(aHole, aSolid, myContext)){
         continue;
       }
       //
       //
       if (!IsInside(aHole, aSolid, myContext)){
         continue;
       }
       //
-      if ( aInOutMap.IsBound (aHole)){
-        const TopoDS_Shape& aSolid2 = aInOutMap(aHole);
-        if (IsInside(aSolid, aSolid2, myContext)) {
+      if (aInOutMap.IsBound (aHole)){
+       const TopoDS_Shape& aHole2=aInOutMap(aHole);
+       if (IsInside(aHole, aHole2, myContext)) {
           aInOutMap.UnBind(aHole);
           aInOutMap.Bind (aHole, aSolid);
         }
       }
       else{
           aInOutMap.UnBind(aHole);
           aInOutMap.Bind (aHole, aSolid);
         }
       }
       else{
-        aInOutMap.Bind (aHole, aSolid);
+        aInOutMap.Bind(aHole, aSolid);
       }
     }
       }
     }
+  }//for (; aItDMISB.More(); aItDMISB.Next()) {
+  //
+  // 5. Map [Solid/Holes] -> aMSH 
+  aItDMSS.Initialize(aInOutMap);
+  for (; aItDMSS.More(); aItDMSS.Next()) {
+    const TopoDS_Shape& aHole=aItDMSS.Key();
+    const TopoDS_Shape& aSolid=aItDMSS.Value();
     //
     //
-    // Add aHole to a map Solid/ListOfHoles [aMSH]
-    if (aInOutMap.IsBound(aHole)){
-      const TopoDS_Shape& aSolid=aInOutMap(aHole);
-      if (aMSH.IsBound(aSolid)) {
-        BOPCol_ListOfShape& aLH=aMSH.ChangeFind(aSolid);
-        aLH.Append(aHole);
-      }
-      else {
-        BOPCol_ListOfShape aLH;
-        aLH.Append(aHole);
-        aMSH.Bind(aSolid, aLH);
-      }
-      //aBB.Add (aSolid, aHole);
+    if (aMSH.IsBound(aSolid)) {
+      BOPCol_ListOfShape& aLH=aMSH.ChangeFind(aSolid);
+      aLH.Append(aHole);
+    }
+    else {
+      BOPCol_ListOfShape aLH;
+      aLH.Append(aHole);
+      aMSH.Bind(aSolid, aLH);
     }
     }
-  }// for (; aShellIt.More(); aShellIt.Next()) {
+  }
   //
   //
-  // 3. Add aHoles to Solids
+  // 6. Add aHoles to Solids
   aItMSH.Initialize(aMSH);
   for (; aItMSH.More(); aItMSH.Next()) {
     TopoDS_Solid aSolid=(*(TopoDS_Solid*)(&aItMSH.Key()));
     //
     const BOPCol_ListOfShape& aLH=aItMSH.Value();
   aItMSH.Initialize(aMSH);
   for (; aItMSH.More(); aItMSH.Next()) {
     TopoDS_Solid aSolid=(*(TopoDS_Solid*)(&aItMSH.Key()));
     //
     const BOPCol_ListOfShape& aLH=aItMSH.Value();
-    aShellIt.Initialize(aLH);
-    for (; aShellIt.More(); aShellIt.Next()) {
-      const TopoDS_Shape& aHole = aShellIt.Value();
+    aItLS.Initialize(aLH);
+    for (; aItLS.More(); aItLS.Next()) {
+      const TopoDS_Shape& aHole = aItLS.Value();
       aBB.Add (aSolid, aHole);
     }
     //
     // update classifier
       aBB.Add (aSolid, aHole);
     }
     //
     // update classifier
-    BRepClass3d_SolidClassifier& aSC=myContext->SolidClassifier(aSolid);
+    BRepClass3d_SolidClassifier& aSC=
+      myContext->SolidClassifier(aSolid);
     aSC.Load(aSolid);
     //
   }
   //
     aSC.Load(aSolid);
     //
   }
   //
-  // These aNewSolids are draft solids that 
+  // 7. These aNewSolids are draft solids that 
   // do not contain any internal shapes
   // do not contain any internal shapes
-  //
-  aShellIt.Initialize(aNewSolids);
-  for ( ; aShellIt.More(); aShellIt.Next()) {
-    const TopoDS_Shape& aSx = aShellIt.Value();
+  aItLS.Initialize(aNewSolids);
+  for ( ; aItLS.More(); aItLS.Next()) {
+    const TopoDS_Shape& aSx=aItLS.Value();
     myAreas.Append(aSx);
   }
     myAreas.Append(aSx);
   }
-
   // Add holes that outside the solids to myAreas
   // Add holes that outside the solids to myAreas
-  aShellIt.Initialize(aHoleShells);
-  for (; aShellIt.More(); aShellIt.Next()) {
-    const TopoDS_Shape& aHole = aShellIt.Value();
+  aItLS.Initialize(aHoleShells);
+  for (; aItLS.More(); aItLS.Next()) {
+    const TopoDS_Shape& aHole = aItLS.Value();
     if (!aInOutMap.IsBound(aHole)){
       TopoDS_Solid aSolid;
     if (!aInOutMap.IsBound(aHole)){
       TopoDS_Solid aSolid;
+      //
       aBB.MakeSolid(aSolid);
       aBB.Add (aSolid, aHole);
       //
       aBB.MakeSolid(aSolid);
       aBB.Add (aSolid, aHole);
       //
@@ -643,7 +656,9 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes()
       aMFx.Add(aFF);
     }
     aMEF.Clear();
       aMFx.Add(aFF);
     }
     aMEF.Clear();
-    BOPTools::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMEF);
+    BOPTools::MapShapesAndAncestors(aSolid, 
+                                   TopAbs_EDGE, TopAbs_FACE, 
+                                   aMEF);
     //
     // 2.1 Separate faces to process aMFP
     aMFP.Clear();
     //
     // 2.1 Separate faces to process aMFP
     aMFP.Clear();
@@ -651,7 +666,11 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes()
     for (; aItMF.More(); aItMF.Next()) {
       const TopoDS_Face& aF=(*(TopoDS_Face*)(&aItMF.Key()));
       if (!aMFx.Contains(aF)) {
     for (; aItMF.More(); aItMF.Next()) {
       const TopoDS_Face& aF=(*(TopoDS_Face*)(&aItMF.Key()));
       if (!aMFx.Contains(aF)) {
-        if (BOPTools_AlgoTools::IsInternalFace(aF, aSolid, aMEF, 1.e-14, myContext)) {
+        if (BOPTools_AlgoTools::IsInternalFace(aF, 
+                                              aSolid, 
+                                              aMEF, 
+                                              1.e-14, 
+                                              myContext)) {
           aMFP.Add(aF);
         }
       }
           aMFP.Add(aF);
         }
       }
@@ -712,7 +731,9 @@ void MakeInternalShells(const BOPCol_MapOfShape& theMF,
   aItM.Initialize(theMF);
   for (; aItM.More(); aItM.Next()) {
     const TopoDS_Shape& aF=aItM.Key();
   aItM.Initialize(theMF);
   for (; aItM.More(); aItM.Next()) {
     const TopoDS_Shape& aF=aItM.Key();
-    BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
+    BOPTools::MapShapesAndAncestors(aF, 
+                                   TopAbs_EDGE, TopAbs_FACE, 
+                                   aMEF);
   }
   //
   aItM.Initialize(theMF);
   }
   //
   aItM.Initialize(theMF);
@@ -786,7 +807,8 @@ Standard_Boolean IsInside(const TopoDS_Shape& theS1,
     BOPCol_IndexedMapOfShape aBounds;
     BOPTools::MapShapes(*pS2, TopAbs_EDGE, aBounds);
     const TopoDS_Face& aF = (*(TopoDS_Face*)(&aExp.Current()));
     BOPCol_IndexedMapOfShape aBounds;
     BOPTools::MapShapes(*pS2, TopAbs_EDGE, aBounds);
     const TopoDS_Face& aF = (*(TopoDS_Face*)(&aExp.Current()));
-    aState=BOPTools_AlgoTools::ComputeState(aF, *pS2, 1.e-14, aBounds, theContext);
+    aState=BOPTools_AlgoTools::ComputeState(aF, *pS2, 1.e-14, 
+                                           aBounds, theContext);
   }
   return (aState==TopAbs_IN);
 }
   }
   return (aState==TopAbs_IN);
 }
@@ -812,42 +834,3 @@ Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell,
   }
   return bRet;
 }
   }
   return bRet;
 }
-//=======================================================================
-//function : IsClosedShell
-//purpose  : 
-//=======================================================================
-Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell)
-{
-  Standard_Integer aNbE;
-  Standard_Boolean bRet;
-  TopoDS_Iterator aIt;
-  TopExp_Explorer aExp;
-  //
-  BOPCol_MapOfShape aM;
-  // 
-  bRet=Standard_False;
-  aIt.Initialize(theShell);
-  for(; aIt.More(); aIt.Next()) {
-    const TopoDS_Face& aF=(*(TopoDS_Face*)(&aIt.Value()));
-    aExp.Init(aF, TopAbs_EDGE);
-    for (; aExp.More(); aExp.Next()) {
-      const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
-      if (BRep_Tool::Degenerated(aE)) {
-        continue;
-      }
-      //
-      if (aE.Orientation()==TopAbs_INTERNAL) {
-        continue;
-      }
-      if (!aM.Add(aE)) {
-        aM.Remove(aE);
-      }
-    }
-  }
-  //
-  aNbE=aM.Extent();
-  if (!aNbE) {
-    bRet=!bRet;
-  }
-  return bRet;
-}
diff --git a/src/BOPAlgo/BOPAlgo_ShellSplitter.cdl b/src/BOPAlgo/BOPAlgo_ShellSplitter.cdl
new file mode 100644 (file)
index 0000000..4cddcfa
--- /dev/null
@@ -0,0 +1,73 @@
+-- Created by: Peter KURNEV
+-- Copyright (c) 1999-2014 OPEN CASCADE SAS
+--
+-- This file is part of Open CASCADE Technology software library.
+--
+-- This library is free software; you can redistribute it and / or modify it
+-- under the terms of the GNU Lesser General Public 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.
+--
+-- Alternatively, this file may be used under the terms of Open CASCADE
+-- commercial license or contractual agreement.
+
+class ShellSplitter from BOPAlgo 
+       inherits Algo from BOPAlgo 
+        
+       ---Purpose:  
+        -- The class provides the splitting of the set of connected faces 
+       -- on separate loops    
+uses   
+    BaseAllocator from BOPCol, 
+    Shape from TopoDS,
+    ListOfShape from BOPCol, 
+    ConnexityBlock from BOPTools, 
+    ListOfConnexityBlock from BOPTools 
+    
+    
+--raises
+
+is 
+    Create 
+       returns ShellSplitter from BOPAlgo; 
+    ---C++: alias "Standard_EXPORT virtual ~BOPAlgo_ShellSplitter();" 
+    ---Purpose: empty constructor
+     
+    Create(theAllocator: BaseAllocator from BOPCol)  
+       returns ShellSplitter from BOPAlgo; 
+    ---Purpose:  constructor 
+    
+    AddStartElement(me:out; 
+           theS: Shape from TopoDS); 
+    ---Purpose: adds a face <theS> to process             
+    
+    StartElements(me)  
+       returns ListOfShape from BOPCol;
+    ---C++: return const & 
+    ---Purpose: return the faces to process 
+    
+    Perform(me:out) 
+       is redefined;  
+    ---Purpose: performs the algorithm         
+         
+    Shells(me) 
+       returns ListOfShape from BOPCol; 
+    ---C++: return const &      
+    ---Purpose: returns the loops 
+     
+    MakeConnexityBlocks(me:out)  
+       is protected;  
+     
+    MakeShells (me:out)  
+       is protected;   
+       
+    SplitBlock(myclass; 
+           theCB:out ConnexityBlock from BOPTools);  
+        
+fields  
+    myStartShapes: ListOfShape from BOPCol is protected; 
+    myShells: ListOfShape from BOPCol is protected; 
+    myLCB   : ListOfConnexityBlock from BOPTools is protected; 
+   
+end ShellSplitter;
diff --git a/src/BOPAlgo/BOPAlgo_ShellSplitter.cxx b/src/BOPAlgo/BOPAlgo_ShellSplitter.cxx
new file mode 100644 (file)
index 0000000..c6ddb1e
--- /dev/null
@@ -0,0 +1,555 @@
+// Created by: Peter KURNEV
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and / or modify it
+// under the terms of the GNU Lesser General Public 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.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+// File:       BOPAlgo_ShellSplitter.cxx
+// Created:    Thu Jan 16 08:33:50 2014
+//             <pkv@PETREX>
+
+#include <BOPAlgo_ShellSplitter.ixx>
+//
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Edge.hxx>
+
+#include <BRep_Builder.hxx>
+#include <TopExp_Explorer.hxx>
+//
+#include <BOPCol_TBB.hxx>
+#include <BOPCol_IndexedMapOfShape.hxx>
+#include <BOPCol_MapOfShape.hxx>
+#include <BOPCol_MapOfOrientedShape.hxx>
+#include <BOPCol_NCVector.hxx>
+#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
+//
+#include <BOPInt_Context.hxx>
+//
+#include <BOPTools.hxx>
+#include <BOPTools_AlgoTools.hxx>
+#include <BOPTools_CoupleOfShape.hxx>
+//
+typedef BOPCol_NCVector<BOPTools_ConnexityBlock> \
+  BOPAlgo_ShellSplitter_VectorOfConnexityBlock;
+//
+static
+  Standard_Boolean IsClosedShell(const TopoDS_Shell& );
+static
+  void MakeShell(const BOPCol_ListOfShape& , 
+                TopoDS_Shell& );
+
+//=======================================================================
+//function : 
+//purpose  : 
+//=======================================================================
+BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter()
+:
+  BOPAlgo_Algo(),
+  myStartShapes(myAllocator),
+  myShells(myAllocator),
+  myLCB(myAllocator)
+{
+}
+//=======================================================================
+//function : 
+//purpose  : 
+//=======================================================================
+BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter
+  (const Handle(NCollection_BaseAllocator)& theAllocator)
+:
+  BOPAlgo_Algo(theAllocator),
+  myStartShapes(theAllocator),
+  myShells(theAllocator),
+  myLCB(myAllocator)
+{
+}
+//=======================================================================
+//function : ~
+//purpose  : 
+//=======================================================================
+BOPAlgo_ShellSplitter::~BOPAlgo_ShellSplitter()
+{
+}
+//=======================================================================
+//function : AddStartElement
+//purpose  : 
+//=======================================================================
+void BOPAlgo_ShellSplitter::AddStartElement(const TopoDS_Shape& aE)
+{
+  myStartShapes.Append(aE);
+}
+//=======================================================================
+//function : StartElements
+//purpose  : 
+//=======================================================================
+const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::StartElements()const
+{
+  return myStartShapes;
+}
+//=======================================================================
+//function : Loops
+//purpose  : 
+//=======================================================================
+const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::Shells()const
+{
+  return myShells;
+}
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+void BOPAlgo_ShellSplitter::Perform()
+{
+  myErrorStatus=0;
+  //
+  MakeConnexityBlocks();
+  if (myErrorStatus) {
+    return;
+  }
+  //
+  MakeShells();
+}
+//=======================================================================
+//function : MakeConnexityBlocks
+//purpose  : 
+//=======================================================================
+void BOPAlgo_ShellSplitter::MakeConnexityBlocks()
+{
+  Standard_Boolean bRegular;
+  Standard_Integer i, j, aNbE, aNbES, aNbEP, k, aNbCB;
+  TopoDS_Shape aFR;
+  TopExp_Explorer aExpF;
+  BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, myAllocator);
+  BOPCol_IndexedMapOfShape aMEP(100, myAllocator);
+  BOPCol_IndexedMapOfShape aMFC(100, myAllocator);
+  BOPCol_MapOfShape aMER(100, myAllocator);
+  BOPCol_MapOfShape aMFP(100, myAllocator);
+  BOPCol_IndexedMapOfShape aMEAdd(100, myAllocator);
+  BOPCol_MapOfShape aMES(100, myAllocator);
+  BOPCol_ListIteratorOfListOfShape aIt;
+  //
+  myErrorStatus=0;
+  //
+  myLCB.Clear();
+  //
+  const BOPCol_ListOfShape& aLSE=myStartShapes;
+  aIt.Initialize(aLSE);
+  for (i=1; aIt.More(); aIt.Next(), ++i) {
+    const TopoDS_Shape& aSE=aIt.Value();
+    if (!aMEP.Contains(aSE)) {
+      aMEP.Add(aSE);
+      BOPTools::MapShapesAndAncestors(aSE, 
+                                     TopAbs_EDGE, TopAbs_FACE, 
+                                     aMEF);
+    }
+    else {
+      aMER.Add(aSE);
+    }
+  }
+  //
+  // 2
+  aNbE=aMEF.Extent();
+  for (i=1; i<=aNbE; ++i) {
+    aNbES=aMES.Extent();
+    if (aNbES==aNbE) {
+      break;
+    }
+    //
+    const TopoDS_Shape& aE=aMEF.FindKey(i);
+    //
+    if (!aMES.Add(aE)) {
+      continue;
+    }
+    // aMES - globally processed edges
+    //
+    //------------------------------------- goal: aMEC
+    aMFC.Clear();    // aMEC - edges of CB
+    aMEP.Clear();    // aMVP - edges to process right now 
+    aMEAdd.Clear();  // aMVAdd edges to process on next step of for(;;) {
+    //
+    aMEP.Add(aE);
+    //
+    for(;;) {
+      aNbEP=aMEP.Extent();
+      for (k=1; k<=aNbEP; ++k) {
+        const TopoDS_Shape& aEP=aMEP(k);
+        const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aEP);
+        aIt.Initialize(aLF);
+        for (; aIt.More(); aIt.Next()) {
+          const TopoDS_Shape& aF=aIt.Value();
+          if (aMFC.Add(aF)) {
+           aExpF.Init(aF, TopAbs_EDGE);
+            for (; aExpF.More(); aExpF.Next()) {
+              const TopoDS_Shape& aEF=aExpF.Current();
+              if (aMES.Add(aEF)) {
+                aMEAdd.Add(aEF);
+              }
+            }
+          }
+        }
+      }
+      //
+      aNbEP=aMEAdd.Extent();
+      if (!aNbEP) {
+        break; // from for(;;) {
+      }
+      //
+      aMEP.Clear();
+      //
+      for (k=1; k<=aNbEP; ++k) {
+        const TopoDS_Shape& aEF=aMEAdd(k);
+        aMEP.Add(aEF);
+      }
+      aMEAdd.Clear();
+    }// for(;;) {
+    //
+    //-------------------------------------
+    BOPTools_ConnexityBlock aCB(myAllocator);
+    //
+    BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
+    BOPCol_IndexedDataMapOfShapeListOfShape aMEFR(100, myAllocator);
+    //
+    bRegular=Standard_True;
+    aNbCB = aMFC.Extent();
+    for (j=1; j<=aNbCB; ++j) {
+      aFR = aMFC(j);
+      //
+      if (aMER.Contains(aFR)) {
+        aFR.Orientation(TopAbs_FORWARD);
+        aLECB.Append(aFR);
+        aFR.Orientation(TopAbs_REVERSED);
+        aLECB.Append(aFR);
+        bRegular=Standard_False;
+      }
+      else {
+        aLECB.Append(aFR);
+      }
+      //
+      if (bRegular) {
+        BOPTools::MapShapesAndAncestors(aFR,
+                                       TopAbs_EDGE, TopAbs_FACE, 
+                                       aMEFR);
+      }
+    }
+    //
+    if (bRegular) {
+      Standard_Integer aNbER, aNbFR; 
+      //
+      aNbER=aMEFR.Extent();
+      for (k=1; k<=aNbER; ++k) {
+        const BOPCol_ListOfShape& aLFR=aMEFR(k);
+        aNbFR=aLFR.Extent();
+        if (aNbFR>2) {
+          bRegular=!bRegular;
+          break;
+        }
+      }
+    }
+    //
+    aCB.SetRegular(bRegular);
+    myLCB.Append(aCB);
+  }
+}
+//=======================================================================
+//function : SplitBlock
+//purpose  : 
+//=======================================================================
+void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
+{
+  Standard_Integer aNbLF, aNbOff, aNbFP;
+  Standard_Integer i;
+  TopAbs_Orientation anOr;
+  TopoDS_Edge aEL;
+  BRep_Builder aBB;
+  TopoDS_Iterator aItS;
+  TopExp_Explorer aExp;
+  BOPCol_ListIteratorOfListOfShape aItF;
+  BOPTools_CoupleOfShape aCSOff;
+  BOPCol_MapOfOrientedShape AddedFacesMap;
+  BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
+  // 
+  Handle (BOPInt_Context) aContext=new BOPInt_Context;
+  //
+  const BOPCol_ListOfShape& myShapes=aCB.Shapes();
+  //
+  BOPCol_ListOfShape& myLoops=aCB.ChangeLoops();
+  myLoops.Clear();
+  //
+  // 1. Shells Usual
+  aItF.Initialize (myShapes);
+  for (; aItF.More(); aItF.Next()) {
+    const TopoDS_Shape& aFF = aItF.Value();
+    BOPTools::MapShapesAndAncestors
+      (aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
+  }
+  //
+  aItF.Initialize (myShapes);
+  for (i=1; aItF.More(); aItF.Next(), ++i) {
+    const TopoDS_Shape& aFF = aItF.Value();
+    if (!AddedFacesMap.Add(aFF)) {
+      continue;
+    }
+    //
+    // make a new shell
+    TopoDS_Shell aShell;
+    aBB.MakeShell(aShell);
+    aBB.Add(aShell, aFF);
+    //
+    aMEFP.Clear();
+    BOPTools::MapShapesAndAncestors(aFF, 
+                                   TopAbs_EDGE, TopAbs_FACE, 
+                                   aMEFP);
+    //
+    // loop on faces added to Shell; 
+    // add their neighbor faces to Shell and so on
+    aItS.Initialize (aShell);
+    for (; aItS.More(); aItS.Next()) {
+      const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
+      //
+      // loop on edges of aF; find a good neighbor face of aF by aE
+      aExp.Init(aF, TopAbs_EDGE);
+      for (; aExp.More(); aExp.Next()) {
+        const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
+        //
+        //1
+        if (aMEFP.Contains(aE)) {
+          const BOPCol_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
+          aNbFP=aLFP.Extent();
+          if (aNbFP>1) { 
+            continue;
+          }
+        }
+        //2
+        anOr=aE.Orientation();
+        if (anOr==TopAbs_INTERNAL) {
+          continue;
+        }
+        //3
+        if (BRep_Tool::Degenerated(aE)) {
+          continue;
+        }
+        //
+        // candidate faces list
+        const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
+        aNbLF=aLF.Extent();
+        if (!aNbLF) {
+          continue;
+        }
+        //
+        // try to select one of neighbors
+        // check if a face already added to Shell shares E
+        Standard_Boolean bFound;
+        BOPCol_ListIteratorOfListOfShape aItLF;
+        BOPTools_ListOfCoupleOfShape aLCSOff;
+        //
+        aItLF.Initialize(aLF);
+        for (; aItLF.More(); aItLF.Next()) { 
+          const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
+          if (aF.IsSame(aFL)) {
+            continue;
+          } 
+          if (AddedFacesMap.Contains(aFL)){
+            continue;
+          }
+          //
+          bFound=BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL);
+          if (!bFound) {
+            continue;
+          }
+          //
+          aCSOff.SetShape1(aEL);
+          aCSOff.SetShape2(aFL);
+          aLCSOff.Append(aCSOff);
+        }//for (; aItLF.More(); aItLF.Next()) { 
+        //
+        aNbOff=aLCSOff.Extent();
+        if (!aNbOff){
+          continue;
+        }
+        //
+        TopoDS_Face aSelF;
+        if (aNbOff==1) {
+          aSelF=(*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
+        }
+        else if (aNbOff>1){
+          BOPTools_AlgoTools::GetFaceOff(aE, aF, 
+                                        aLCSOff, aSelF, aContext);
+        }
+        //
+        if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) { 
+          aBB.Add(aShell, aSelF);
+          BOPTools::MapShapesAndAncestors(aSelF, 
+                                         TopAbs_EDGE, TopAbs_FACE, 
+                                         aMEFP);
+        }
+      } // for (; aEdgeExp.More(); aEdgeExp.Next()) { 
+    } //for (; aItAddedF.More(); aItAddedF.Next()) {
+    //
+    if (IsClosedShell(aShell)) {
+      myLoops.Append(aShell);
+    }
+  } // for (; aItF.More(); aItF.Next()) {
+}
+//=======================================================================
+//class    : ShellSplitterFunctor
+//purpose  : Auxiliary class
+//=======================================================================
+class BOPAlgo_ShellSplitterFunctor {
+ protected:
+  TopoDS_Face myFace;
+  BOPAlgo_ShellSplitter_VectorOfConnexityBlock* myPVCB;
+  //
+ public:
+  BOPAlgo_ShellSplitterFunctor
+    (BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB) 
+      : myPVCB(&aVCB) {
+  }
+  //
+  void operator()( const flexible_range<Standard_Size>& aBR ) const{
+    Standard_Size i, iBeg, iEnd;
+    //
+    BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB=*myPVCB;
+    //
+    iBeg=aBR.begin();
+    iEnd=aBR.end();
+    for(i=iBeg; i!=iEnd; ++i) {
+      BOPTools_ConnexityBlock& aCB=aVCB((Standard_Integer)i);
+      //
+      BOPAlgo_ShellSplitter::SplitBlock(aCB);
+    }
+  }
+};
+//=======================================================================
+//class    : BOPAlgo_ShellSplitterCnt
+//purpose  : Auxiliary class
+//=======================================================================
+class BOPAlgo_ShellSplitterCnt {
+ public:
+  //-------------------------------
+  // Perform
+  Standard_EXPORT 
+    static void Perform
+      (const Standard_Boolean bRunParallel,
+       BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB) {
+    //
+    BOPAlgo_ShellSplitterFunctor aSSF(aVCB);
+    Standard_Size aNbVCB=aVCB.Extent();
+    //
+    if (bRunParallel) {
+      flexible_for(flexible_range<Standard_Size>(0,aNbVCB), aSSF);
+    }
+    else {
+      aSSF.operator()(flexible_range<Standard_Size>(0,aNbVCB));
+    }
+  }
+};
+//=======================================================================
+//function : MMakeShells
+//purpose  : 
+//=======================================================================
+void BOPAlgo_ShellSplitter::MakeShells()
+{
+  Standard_Boolean bIsRegular;
+  Standard_Integer aNbVCB, k;
+  BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
+  BOPCol_ListIteratorOfListOfShape aIt;
+  BOPAlgo_ShellSplitter_VectorOfConnexityBlock aVCB;
+  //
+  myErrorStatus=0;
+  myShells.Clear();
+  //
+  aItCB.Initialize(myLCB);
+  for (; aItCB.More(); aItCB.Next()) {
+    BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
+    bIsRegular=aCB.IsRegular();
+    if (bIsRegular) {
+      TopoDS_Shell aShell;
+      //
+      const BOPCol_ListOfShape& aLF=aCB.Shapes();
+      MakeShell(aLF, aShell);
+      myShells.Append(aShell);
+    }
+    else {
+      aVCB.Append(aCB);
+    }
+  }
+  //
+  aNbVCB=aVCB.Extent();
+  //===================================================
+  BOPAlgo_ShellSplitterCnt::Perform(myRunParallel, aVCB);
+  //===================================================
+  for (k=0; k<aNbVCB; ++k) {
+    const BOPTools_ConnexityBlock& aCB=aVCB(k);
+    const BOPCol_ListOfShape& aLS=aCB.Loops();
+    aIt.Initialize(aLS);
+    for (; aIt.More(); aIt.Next()) {
+      const TopoDS_Shape& aShell=aIt.Value();
+      myShells.Append(aShell);
+    }
+  }
+}
+//=======================================================================
+//function : IsClosedShell
+//purpose  : 
+//=======================================================================
+Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell)
+{
+  Standard_Integer aNbE;
+  Standard_Boolean bRet;
+  TopoDS_Iterator aIt;
+  TopExp_Explorer aExp;
+  BOPCol_MapOfShape aM;
+  // 
+  bRet=Standard_False;
+  aIt.Initialize(theShell);
+  for(; aIt.More(); aIt.Next()) {
+    const TopoDS_Face& aF=(*(TopoDS_Face*)(&aIt.Value()));
+    aExp.Init(aF, TopAbs_EDGE);
+    for (; aExp.More(); aExp.Next()) {
+      const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
+      if (BRep_Tool::Degenerated(aE)) {
+        continue;
+      }
+      //
+      if (aE.Orientation()==TopAbs_INTERNAL) {
+        continue;
+      }
+      if (!aM.Add(aE)) {
+        aM.Remove(aE);
+      }
+    }
+  }
+  //
+  aNbE=aM.Extent();
+  if (!aNbE) {
+    bRet=!bRet;
+  }
+  return bRet;
+}
+//=======================================================================
+//function : MakeShell
+//purpose  : 
+//=======================================================================
+void MakeShell(const BOPCol_ListOfShape& aLS, 
+              TopoDS_Shell& aShell)
+{
+  BRep_Builder aBB;
+  BOPCol_ListIteratorOfListOfShape aIt;
+  //
+  aBB.MakeShell(aShell);
+  //
+  aIt.Initialize(aLS);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aF=aIt.Value();
+    aBB.Add(aShell, aF);
+  }
+}