From 682c9d06824cdb947c2506a3f015a23d1d90f2a0 Mon Sep 17 00:00:00 2001 From: pkv Date: Tue, 28 Jan 2014 11:09:54 +0400 Subject: [PATCH] 0024157: Parallelization of assembly part of BO 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 | 3 +- src/BOPAlgo/BOPAlgo_BuilderSolid.cxx | 509 ++++++++++++----------- src/BOPAlgo/BOPAlgo_ShellSplitter.cdl | 73 ++++ src/BOPAlgo/BOPAlgo_ShellSplitter.cxx | 555 ++++++++++++++++++++++++++ 4 files changed, 876 insertions(+), 264 deletions(-) create mode 100644 src/BOPAlgo/BOPAlgo_ShellSplitter.cdl create mode 100644 src/BOPAlgo/BOPAlgo_ShellSplitter.cxx diff --git a/src/BOPAlgo/BOPAlgo.cdl b/src/BOPAlgo/BOPAlgo.cdl index f4097cd6fc..08b283e4eb 100644 --- a/src/BOPAlgo/BOPAlgo.cdl +++ b/src/BOPAlgo/BOPAlgo.cdl @@ -67,7 +67,8 @@ is deferred class BuilderArea; class BuilderFace; class WireEdgeSet; - class WireSplitter; + class WireSplitter; + class ShellSplitter; class BuilderSolid; class Tools; class SectionAttribute; diff --git a/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx b/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx index bf6213797a..04c9fb430d 100644 --- a/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx +++ b/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx @@ -16,19 +16,25 @@ // commercial license or contractual agreement. #include - +// +#include +#include +#include +// #include #include #include #include #include - +// +#include +// #include #include #include - +// #include - +// #include #include #include @@ -40,25 +46,29 @@ #include #include -#include -#include - +// #include #include // -#include +#include +#include +// #include -#include #include #include -// -#include -// #include #include -#include -#include #include +#include +#include +// +#include +#include +#include +// +#include +// +#include static Standard_Boolean IsGrowthShell(const TopoDS_Shape& , @@ -74,14 +84,61 @@ static 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\ + \ + BOPAlgo_DataMapOfIntegerBSSB; +// +typedef BOPAlgo_DataMapOfIntegerBSSB::Iterator \ + BOPAlgo_DataMapIteratorOfDataMapOfIntegerBSSB; +// //======================================================================= //function : //purpose : //======================================================================= - BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid() +BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid() : BOPAlgo_BuilderArea() { @@ -90,7 +147,8 @@ static //function : //purpose : //======================================================================= -BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid(const Handle(NCollection_BaseAllocator)& theAllocator) +BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid + (const Handle(NCollection_BaseAllocator)& theAllocator) : BOPAlgo_BuilderArea(theAllocator) { @@ -127,8 +185,6 @@ void BOPAlgo_BuilderSolid::Perform() myErrorStatus=0; // if (myContext.IsNull()) { - //myErrorStatus=11;// Null Context - //return; myContext=new BOPInt_Context; } // @@ -237,7 +293,7 @@ void BOPAlgo_BuilderSolid::PerformShapesToAvoid() break; } // - }//while (1) + }//for(;;) { } //======================================================================= //function : PerformLoops @@ -245,145 +301,46 @@ void BOPAlgo_BuilderSolid::PerformShapesToAvoid() //======================================================================= 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; - // - BOPCol_ListIteratorOfListOfShape aItF, aIt; BOPCol_MapIteratorOfMapOfOrientedShape aItM; - BOPTools_CoupleOfShape aCSOff; - // - BOPCol_MapOfOrientedShape AddedFacesMap; - BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP; - // - //================================================= + BOPAlgo_ShellSplitter aSSp; + // + myErrorStatus=0; + myLoops.Clear(); // // 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; - // + // // 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(); // + aNbFA=myShapesToAvoid.Extent(); + // 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); @@ -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); - 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); } @@ -463,129 +423,182 @@ void BOPAlgo_BuilderSolid::PerformLoops() //======================================================================= void BOPAlgo_BuilderSolid::PerformAreas() { - myErrorStatus=0; - // - Standard_Boolean bIsGrowthShell, bIsHole; + Standard_Boolean bIsGrowth, bIsHole; + Standard_Integer k,aNbHoles; BRep_Builder aBB; - TopoDS_Shape anInfinitePointShape; - BOPCol_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH; - BOPCol_ListIteratorOfListOfShape aShellIt, aSolidIt; - // + BOPCol_ListIteratorOfListOfShape aItLS; BOPCol_ListOfShape aNewSolids, aHoleShells; BOPCol_DataMapOfShapeShape aInOutMap; - BOPCol_DataMapOfShapeListOfShape aMSH; BOPCol_IndexedMapOfShape aMHF; + BOPCol_ListIteratorOfListOfInteger aItLI; + BOPCol_BoxBndTreeSelector aSelector; + BOPCol_BoxBndTree aBBTree; + NCollection_UBTreeFiller 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] - 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 - 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 - //XX bIsHole=IsHole(aShell, myContext); - //XX if (bIsHole) { aHoleShells.Append(aShell); BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF); + aSB.SetShape(aShell); } 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 ( 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.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(); - 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 - BRepClass3d_SolidClassifier& aSC=myContext->SolidClassifier(aSolid); + BRepClass3d_SolidClassifier& aSC= + myContext->SolidClassifier(aSolid); aSC.Load(aSolid); // } // - // These aNewSolids are draft solids that + // 7. These aNewSolids are draft solids that // 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); } - // 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; + // aBB.MakeSolid(aSolid); aBB.Add (aSolid, aHole); // @@ -643,7 +656,9 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes() 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(); @@ -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)) { - 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); } } @@ -712,7 +731,9 @@ void MakeInternalShells(const BOPCol_MapOfShape& theMF, 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); @@ -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())); - 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); } @@ -812,42 +834,3 @@ Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell, } 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 index 0000000000..4cddcfae1a --- /dev/null +++ b/src/BOPAlgo/BOPAlgo_ShellSplitter.cdl @@ -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 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 index 0000000000..c6ddb1e929 --- /dev/null +++ b/src/BOPAlgo/BOPAlgo_ShellSplitter.cxx @@ -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 +// + +#include +// +#include +#include +#include + +#include +#include +// +#include +#include +#include +#include +#include +#include +// +#include +// +#include +#include +#include +// +typedef BOPCol_NCVector \ + 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& 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(0,aNbVCB), aSSF); + } + else { + aSSF.operator()(flexible_range(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