// 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 <TColStd_MapIntegerHasher.hxx>
+//
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <Geom2d_Curve.hxx>
-
+//
#include <TopAbs.hxx>
-
+//
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
-#include <BRepTools.hxx>
-#include <BRepClass3d_SolidClassifier.hxx>
-
+//
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
//
-#include <BOPTools_AlgoTools.hxx>
+#include <BRepBndLib.hxx>
+#include <BRepClass3d_SolidClassifier.hxx>
+//
#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
-#include <BOPTools.hxx>
#include <BOPCol_ListOfShape.hxx>
#include <BOPCol_MapOfOrientedShape.hxx>
-//
-#include <NCollection_List.hxx>
-//
#include <BOPCol_DataMapOfShapeShape.hxx>
#include <BOPCol_DataMapOfShapeListOfShape.hxx>
-#include <BOPInt_Context.hxx>
-#include <BOPTools_CoupleOfShape.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& ,
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 :
//=======================================================================
- BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid()
+BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid()
:
BOPAlgo_BuilderArea()
{
//function :
//purpose :
//=======================================================================
-BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid(const Handle(NCollection_BaseAllocator)& theAllocator)
+BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid
+ (const Handle(NCollection_BaseAllocator)& theAllocator)
:
BOPAlgo_BuilderArea(theAllocator)
{
myErrorStatus=0;
//
if (myContext.IsNull()) {
- //myErrorStatus=11;// Null Context
- //return;
myContext=new BOPInt_Context;
}
//
break;
}
//
- }//while (1)
+ }//for(;;) {
}
//=======================================================================
//function : 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;
- //
- 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()) {
}
//=================================================
//
- // 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);
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);
}
//=======================================================================
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 <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]
- 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);
//
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();
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);
}
}
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);
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 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;
-}
--- /dev/null
+// 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);
+ }
+}