From 9324aa2d0db76088d01531a879d0eb5633d9d0fd Mon Sep 17 00:00:00 2001 From: emv Date: Thu, 18 Apr 2019 15:34:37 +0300 Subject: [PATCH] 0030656: Modeling Algorithms - Change Boolean Operations algorithm to use BVH tree instead of UBTree Switching the Boolean Operations algorithm to use the BVH tree instead of UB tree as selection of the elements from BVH tree is usually faster. --- dox/dev_guides/upgrade/upgrade.md | 10 + samples/tcl/ANC101.tcl | 4 +- src/BOPAlgo/BOPAlgo_BuilderFace.cxx | 42 ++-- src/BOPAlgo/BOPAlgo_BuilderSolid.cxx | 24 +- src/BOPAlgo/BOPAlgo_PaveFiller.cxx | 4 +- src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx | 2 +- src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx | 17 +- src/BOPAlgo/BOPAlgo_Tools.cxx | 260 ++++++++++---------- src/BOPAlgo/BOPAlgo_Tools.hxx | 1 - src/BOPDS/BOPDS_Iterator.cxx | 270 +++++++++------------ src/BOPDS/BOPDS_Iterator.hxx | 11 +- src/BOPDS/BOPDS_IteratorSI.cxx | 133 +++++----- src/BOPDS/BOPDS_ShapeInfo.lxx | 13 +- src/BOPDS/BOPDS_SubIterator.cxx | 112 ++++----- src/BOPTools/BOPTools_BoxBndTree.hxx | 26 -- src/BOPTools/BOPTools_BoxSelector.hxx | 76 ++++-- src/BOPTools/BOPTools_BoxTree.hxx | 47 ++++ src/BOPTools/BOPTools_PairSelector.hxx | 131 ++++++++++ src/BOPTools/FILES | 3 +- src/BRepOffset/BRepOffset_Inter3d.cxx | 60 ++--- src/IntPolyh/IntPolyh_MaillageAffinage.cxx | 212 +++++++++------- 21 files changed, 805 insertions(+), 653 deletions(-) delete mode 100644 src/BOPTools/BOPTools_BoxBndTree.hxx create mode 100644 src/BOPTools/BOPTools_BoxTree.hxx create mode 100644 src/BOPTools/BOPTools_PairSelector.hxx diff --git a/dox/dev_guides/upgrade/upgrade.md b/dox/dev_guides/upgrade/upgrade.md index c67248800f..e4c78255c5 100644 --- a/dox/dev_guides/upgrade/upgrade.md +++ b/dox/dev_guides/upgrade/upgrade.md @@ -1751,3 +1751,13 @@ Proxy classes *SelectBasics_SensitiveEntity* and *SelectBasics_EntityOwner* have *env.bat* produced by Visual Studio project generator *genproj.bat* has been modified so that *%CSF_DEFINES%* variable is reset to initial state. Custom building environment relying on old behavior and setting extra macros within *%CSF_DEFINES%* before env.bat should be updated to either modify custom.bat or setup new variable *%CSF_DEFINES_EXTRA%* instead. + +@subsection upgrade_740_BVH_in_BOP Switching Boolean Operations algorithm to use BVH tree instead of UB tree + +Since OCCT 7.4.0 Boolean Operations algorithm uses BVH tree instead of UBTree to find the pairs of entities with interfering bounding boxes. +The following API changes have been made: +* BOPTools_BoxBndTree and BOPTools_BoxBndTreeSelector have been removed. Use the BOPTools_BoxTree and BOPTools_BoxTreeSelector instead. +* BOPTools_BoxSelector::SetBox() method now accepts the BVH_Box instead of Bnd_Box. +* Methods BOPTools_BoxSelector::Reject and BOPTools_BoxSelector::Accept have been removed as unused. +* The RunParallel flag has been removed from the list of parameters of BOPAlgo_Tools::IntersectVertices method. Earlier, it performed selection from the UB tree in parallel mode. Now all interfering pairs are found in one pass, using pair traverse of the same BVH tree. + diff --git a/samples/tcl/ANC101.tcl b/samples/tcl/ANC101.tcl index 818f3eb6c8..42852ebb92 100644 --- a/samples/tcl/ANC101.tcl +++ b/samples/tcl/ANC101.tcl @@ -264,11 +264,11 @@ bfuse _model _model t_s explode _model e # Make a weld at joint edges of platform and wedge -blend _model _model 2 _model_26 blend _model _model 2 _model_27 blend _model _model 2 _model_28 blend _model _model 2 _model_29 -blend _model _model 2 _model_31 +blend _model _model 2 _model_30 +blend _model _model 2 _model_32 # Cylinder on wedge blend result _model 2 _model_161 diff --git a/src/BOPAlgo/BOPAlgo_BuilderFace.cxx b/src/BOPAlgo/BOPAlgo_BuilderFace.cxx index d75aad1f11..8fe38f13ff 100644 --- a/src/BOPAlgo/BOPAlgo_BuilderFace.cxx +++ b/src/BOPAlgo/BOPAlgo_BuilderFace.cxx @@ -24,7 +24,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -448,28 +448,28 @@ void BOPAlgo_BuilderFace::PerformAreas() // Classify holes relatively faces - // Prepare tree filler with the boxes of the hole faces - NCollection_UBTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); - + // Prepare tree with the boxes of the hole faces + BOPTools_Box2dTree aBoxTree; Standard_Integer i, aNbH = aHoleFaces.Extent(); + aBoxTree.SetSize (aNbH); for (i = 1; i <= aNbH; ++i) { const TopoDS_Face& aHFace = TopoDS::Face(aHoleFaces(i)); // Bnd_Box2d aBox; BRepTools::AddUVBounds(aHFace, aBox); - aTreeFiller.Add(i, aBox); + aBoxTree.Add(i, Bnd_Tools::Bnd2BVH (aBox)); } - // Shake TreeFiller - aTreeFiller.Fill(); + // Build BVH + aBoxTree.Build(); // Find outer growth face that is most close to each hole face TopTools_IndexedDataMapOfShapeShape aHoleFaceMap; // Selector - BOPTools_BoxSelector aSelector; + BOPTools_Box2dTreeSelector aSelector; + aSelector.SetBVHSet (&aBoxTree); TopTools_ListIteratorOfListOfShape aItLS(aNewFaces); for (; aItLS.More(); aItLS.Next()) @@ -481,8 +481,8 @@ void BOPAlgo_BuilderFace::PerformAreas() BRepTools::AddUVBounds(aFace, aBox); aSelector.Clear(); - aSelector.SetBox(aBox); - aBBTree.Select(aSelector); + aSelector.SetBox(Bnd_Tools::Bnd2BVH (aBox)); + aSelector.Select(); const TColStd_ListOfInteger& aLI = aSelector.Indices(); TColStd_ListIteratorOfListOfInteger aItLI(aLI); @@ -590,9 +590,8 @@ void BOPAlgo_BuilderFace::PerformInternalShapes() // No edges left for classification return; - // Prepare tree filler with the boxes of the edges to classify - NCollection_UBTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); + // Prepare tree with the boxes of the edges to classify + BOPTools_Box2dTree aBoxTree; // Map of edges to classify TopTools_IndexedMapOfShape anEdgesMap; @@ -611,13 +610,13 @@ void BOPAlgo_BuilderFace::PerformInternalShapes() BRepTools::AddUVBounds(myFace, aE, aBoxE); // Make sure the index of edge in the map and // of the box in the tree is the same - aTreeFiller.Add(anEdgesMap.Add(aE), aBoxE); + aBoxTree.Add(anEdgesMap.Add(aE), Bnd_Tools::Bnd2BVH (aBoxE)); } } } - // Shake the tree - aTreeFiller.Fill(); + // Build BVH + aBoxTree.Build(); // Fence map TColStd_MapOfInteger aMEDone; @@ -633,9 +632,10 @@ void BOPAlgo_BuilderFace::PerformInternalShapes() BRepTools::AddUVBounds(aF, aBoxF); // Select edges for the classification - BOPTools_BoxSelector aSelector; - aSelector.SetBox(aBoxF); - if (!aBBTree.Select(aSelector)) + BOPTools_Box2dTreeSelector aSelector; + aSelector.SetBVHSet (&aBoxTree); + aSelector.SetBox(Bnd_Tools::Bnd2BVH (aBoxF)); + if (!aSelector.Select()) continue; // Collect edges inside the face diff --git a/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx b/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx index 29cc5a610d..a024a4f2ca 100644 --- a/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx +++ b/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx @@ -21,9 +21,10 @@ #include #include #include -#include +#include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -443,24 +443,23 @@ void BOPAlgo_BuilderSolid::PerformAreas() // Classify holes relatively solids - // Prepare tree filler with the boxes of the hole shells - BOPTools_BoxBndTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); - + // Prepare tree with the boxes of the hole shells + BOPTools_BoxTree aBBTree; Standard_Integer i, aNbH = aHoleShells.Extent(); + aBBTree.SetSize (aNbH); for (i = 1; i <= aNbH; ++i) { const TopoDS_Shape& aHShell = aHoleShells(i); // Bnd_Box aBox; BRepBndLib::Add(aHShell, aBox); - aTreeFiller.Add(i, aBox); + aBBTree.Add(i, Bnd_Tools::Bnd2BVH(aBox)); myBoxes.Bind(aHShell, aBox); } - // Shake TreeFiller - aTreeFiller.Fill(); + // Build BVH + aBBTree.Build(); // Find outer growth shell that is most close to each hole shell TopTools_IndexedDataMapOfShapeShape aHoleSolidMap; @@ -476,9 +475,10 @@ void BOPAlgo_BuilderSolid::PerformAreas() myBoxes.Bind(aSolid, aBox); - BOPTools_BoxBndTreeSelector aSelector; - aSelector.SetBox(aBox); - aBBTree.Select(aSelector); + BOPTools_BoxTreeSelector aSelector; + aSelector.SetBox(Bnd_Tools::Bnd2BVH(aBox)); + aSelector.SetBVHSet (&aBBTree); + aSelector.Select(); const TColStd_ListOfInteger& aLI = aSelector.Indices(); TColStd_ListIteratorOfListOfInteger aItLI(aLI); diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller.cxx index d03fac1ac0..a12e527c4d 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller.cxx @@ -298,7 +298,7 @@ void BOPAlgo_PaveFiller::PerformInternal() // MakeSplitEdges(); if (HasErrors()) { - return; + return; } // UpdatePaveBlocksWithSDVertices(); @@ -361,7 +361,7 @@ void BOPAlgo_PaveFiller::RepeatIntersection() return; // Update iterator of pairs of shapes with interfering boxes - myIterator->PrepareExt(anExtraInterfMap); + myIterator->IntersectExt(anExtraInterfMap); // Perform intersections with vertices PerformVV(); diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx index 4171cc90d7..6994be6fcd 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx @@ -595,7 +595,7 @@ void BOPAlgo_PaveFiller::TreatNewVertices // // Perform intersection TopTools_ListOfListOfShape aChains; - BOPAlgo_Tools::IntersectVertices(aVerts, myRunParallel, myFuzzyValue, aChains); + BOPAlgo_Tools::IntersectVertices(aVerts, myFuzzyValue, aChains); // // Treat the results - make new vertices for each chain TopTools_ListOfListOfShape::Iterator aItC(aChains); diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx index c6b43cfc9a..7248bf994b 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -31,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -729,8 +729,7 @@ void BOPAlgo_PaveFiller::ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB return; // Fill the tree with bounding boxes of the pave blocks - NCollection_UBTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); + BOPTools_BoxTree aBBTree; Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; BOPDS_IndexedMapOfPaveBlock aPBMap(1, anAlloc); @@ -751,11 +750,11 @@ void BOPAlgo_PaveFiller::ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB Standard_Boolean isSplit; aPB->ShrunkData(f, l, aPBBox, isSplit); - aTreeFiller.Add(aPBMap.Add(aPB), aPBBox); + aBBTree.Add(aPBMap.Add(aPB), Bnd_Tools::Bnd2BVH(aPBBox)); } // Shake the tree - aTreeFiller.Fill(); + aBBTree.Build(); // Find pairs of Face/PaveBlock containing the same vertices // and prepare those pairs for intersection. @@ -774,10 +773,10 @@ void BOPAlgo_PaveFiller::ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB continue; const Bnd_Box& aBoxF = aSI.Box(); - BOPTools_BoxSelector aSelector; - aSelector.SetBox(aBoxF); - - if (!aBBTree.Select(aSelector)) + BOPTools_BoxTreeSelector aSelector; + aSelector.SetBox(Bnd_Tools::Bnd2BVH(aBoxF)); + aSelector.SetBVHSet (&aBBTree); + if (!aSelector.Select()) continue; const TopoDS_Face& aF = TopoDS::Face(aSI.Shape()); diff --git a/src/BOPAlgo/BOPAlgo_Tools.cxx b/src/BOPAlgo/BOPAlgo_Tools.cxx index fa93d31291..b5b7625e87 100644 --- a/src/BOPAlgo/BOPAlgo_Tools.cxx +++ b/src/BOPAlgo/BOPAlgo_Tools.cxx @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -954,78 +954,66 @@ Standard_Boolean FindPlane(const TopoDS_Shape& theWire, ///////////////////////////////////////////////////////////////////////// //======================================================================= -//class : BOPAlgo_TNV +//class : BOPAlgo_PairVerticesSelector //purpose : //======================================================================= -class BOPAlgo_TNV; -typedef NCollection_Vector BOPAlgo_VectorOfTNV; +class BOPAlgo_PairVerticesSelector : public BOPTools_BoxPairSelector +{ +public: -//======================================================================= -class BOPAlgo_TNV : public BOPTools_BoxBndTreeSelector{ - public: - BOPAlgo_TNV() - : BOPTools_BoxBndTreeSelector(), - myTol (0.), myFuzzyValue(0.), myTree(NULL), myVecTNV(NULL) { - }; - // - ~BOPAlgo_TNV(){ - }; - // - void SetVertex(const TopoDS_Vertex& aV) { - myV=aV; - myPnt = BRep_Tool::Pnt(myV); + BOPAlgo_PairVerticesSelector() + : myVertices(NULL), + myFuzzyValue(Precision::Confusion()) + {} + + //! Sets the map of vertices with tolerances + void SetMapOfVerticesTolerances (const TopTools_IndexedDataMapOfShapeReal& theVertices) + { + myVertices = &theVertices; } - // - const TopoDS_Vertex& Vertex()const { - return myV; - } - // - void SetTree(BOPTools_BoxBndTree& aTree) { - myTree=&aTree; - } - // - void SetTolerance(const Standard_Real theTol) { - myTol = theTol; - } - // - Standard_Real Tolerance() const { - return myTol; - } - // - const gp_Pnt& Pnt() const { - return myPnt; - } - // - void SetFuzzyValue(const Standard_Real theFuzzyValue) { + + //! Sets the fuzzy value + void SetFuzzyValue (const Standard_Real theFuzzyValue) + { myFuzzyValue = theFuzzyValue; } - // - void SetVectorOfTNV(const BOPAlgo_VectorOfTNV& theVec) { - myVecTNV = &theVec; - } - // - virtual Standard_Boolean Accept(const Standard_Integer& theIndex) + + //! Checks and accepts the pair of elements. + virtual Standard_Boolean Accept (const Standard_Integer theID1, + const Standard_Integer theID2) Standard_OVERRIDE { - const BOPAlgo_TNV& aTNV = myVecTNV->Value(theIndex - 1); - Standard_Real aTolSum2 = myTol + aTNV.Tolerance() + myFuzzyValue; - aTolSum2 *= aTolSum2; - Standard_Real aD2 = myPnt.SquareDistance(aTNV.Pnt()); - if (aD2 < aTolSum2) - return BOPTools_BoxBndTreeSelector::Accept(theIndex); + if (!RejectElement (theID1, theID2)) + { + const Standard_Integer anID1 = this->myBVHSet1->Element (theID1); + const TopoDS_Vertex& aV1 = TopoDS::Vertex (myVertices->FindKey (anID1)); + Standard_Real aTolV1 = BRep_Tool::Tolerance (aV1); + if (aTolV1 < myVertices->FindFromIndex (anID1)) + aTolV1 = myVertices->FindFromIndex (anID1); + gp_Pnt aP1 = BRep_Tool::Pnt (aV1); + + const Standard_Integer anID2 = this->myBVHSet1->Element (theID2); + const TopoDS_Vertex& aV2 = TopoDS::Vertex (myVertices->FindKey (anID2)); + Standard_Real aTolV2 = BRep_Tool::Tolerance (aV2); + if (aTolV2 < myVertices->FindFromIndex (anID2)) + aTolV2 = myVertices->FindFromIndex (anID2); + gp_Pnt aP2 = BRep_Tool::Pnt (aV2); + + Standard_Real aTolSum2 = aTolV1 + aTolV2 + myFuzzyValue; + aTolSum2 *= aTolSum2; + + Standard_Real aD2 = aP1.SquareDistance (aP2); + if (aD2 < aTolSum2) + { + myPairs.push_back (PairIDs (anID1, anID2)); + return Standard_True; + } + } return Standard_False; } - // - void Perform() { - myTree->Select(*this); - } - // - protected: - Standard_Real myTol; + +protected: + const TopTools_IndexedDataMapOfShapeReal * myVertices; Standard_Real myFuzzyValue; - gp_Pnt myPnt; - TopoDS_Vertex myV; - BOPTools_BoxBndTree *myTree; - const BOPAlgo_VectorOfTNV *myVecTNV; }; // ///////////////////////////////////////////////////////////////////////// @@ -1035,84 +1023,82 @@ class BOPAlgo_TNV : public BOPTools_BoxBndTreeSelector{ //purpose : Builds the chains of intersecting vertices //======================================================================= void BOPAlgo_Tools::IntersectVertices(const TopTools_IndexedDataMapOfShapeReal& theVertices, - const Standard_Boolean theRunParallel, const Standard_Real theFuzzyValue, TopTools_ListOfListOfShape& theChains) { - Standard_Integer i, j, aNbV = theVertices.Extent(); + Standard_Integer aNbV = theVertices.Extent(); if (aNbV <= 1) { if (aNbV == 1) { theChains.Append(TopTools_ListOfShape()).Append(theVertices.FindKey(1)); } return; } - // - // Use unbalanced binary tree of bounding boxes for sorting of the vertices. - BOPTools_BoxBndTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); - // Perform intersection of the vertices - BOPAlgo_VectorOfTNV aVTNV; - // - // Use additional tolerance for intersection + + // Additional tolerance for intersection Standard_Real aTolAdd = theFuzzyValue / 2.; - // Prepare the tree - for (i = 1; i <= aNbV; ++i) { + + // Use BVH Tree for sorting the vertices + BOPTools_BoxTree aBBTree; + aBBTree.SetSize (aNbV); + + for (Standard_Integer i = 1; i <= aNbV; ++i) + { const TopoDS_Vertex& aV = TopoDS::Vertex(theVertices.FindKey(i)); Standard_Real aTol = BRep_Tool::Tolerance(aV); - if (aTol < theVertices(i)) { + if (aTol < theVertices(i)) aTol = theVertices(i); - } + // Build bnd box for vertex Bnd_Box aBox; aBox.Add(BRep_Tool::Pnt(aV)); aBox.SetGap(aTol + aTolAdd); - // - aTreeFiller.Add(i, aBox); - // - BOPAlgo_TNV& aTNV=aVTNV.Appended(); - aTNV.SetTree(aBBTree); - aTNV.SetBox(aBox); - aTNV.SetVertex(aV); - aTNV.SetTolerance(aTol); - aTNV.SetFuzzyValue(theFuzzyValue); - aTNV.SetVectorOfTNV(aVTNV); + aBBTree.Add(i, Bnd_Tools::Bnd2BVH(aBox)); } - // Shake the tree - aTreeFiller.Fill(); - // - // Perform intersection - BOPTools_Parallel::Perform (theRunParallel, aVTNV); - // - // Fence map - TColStd_MapOfInteger aMFence; - // Build chains of intersecting vertices - for (i = 1; i <= aNbV; ++i) { - if (!aMFence.Add(i)) { - continue; - } - // Start the chain - TColStd_IndexedMapOfInteger aMChain; - aMChain.Add(i); - // - for (j = 1; j <= aMChain.Extent(); ++j) { - BOPAlgo_TNV& aTNV = aVTNV(aMChain(j) - 1); - const TColStd_ListOfInteger& aLI = aTNV.Indices(); - // Add these vertices into the chain - for (TColStd_ListIteratorOfListOfInteger aItLI(aLI); aItLI.More(); aItLI.Next()) { - if (aMFence.Add(aItLI.Value())) { - aMChain.Add(aItLI.Value()); - } - } - } - // - // Put vertices of the chain into the list - TopTools_ListOfShape& aChain = theChains.Append(TopTools_ListOfShape()); - // - Standard_Integer aNbVChain = aMChain.Extent(); - for (j = 1; j <= aNbVChain; ++j) { - const TopoDS_Vertex& aVP = aVTNV(aMChain(j) - 1).Vertex(); - aChain.Append(aVP); + + aBBTree.Build(); + + // Perform selection of the interfering vertices + BOPAlgo_PairVerticesSelector aPairSelector; + aPairSelector.SetBVHSets (&aBBTree, &aBBTree); + aPairSelector.SetSame (Standard_True); + aPairSelector.SetMapOfVerticesTolerances (theVertices); + aPairSelector.SetFuzzyValue (theFuzzyValue); + aPairSelector.Select(); + + // Treat the selected pairs + const std::vector& aPairs = aPairSelector.Pairs(); + const Standard_Integer aNbPairs = static_cast (aPairs.size()); + + // Collect interfering pairs + Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; + NCollection_IndexedDataMap aMILI (1, anAlloc); + + for (Standard_Integer iPair = 0; iPair < aNbPairs; ++iPair) + { + const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair]; + BOPAlgo_Tools::FillMap (aPair.ID1, aPair.ID2, aMILI, anAlloc); + } + + NCollection_List aBlocks (anAlloc); + BOPAlgo_Tools::MakeBlocks (aMILI, aBlocks, anAlloc); + + NCollection_List::Iterator itLI (aBlocks); + for (; itLI.More(); itLI.Next()) + { + const TColStd_ListOfInteger& aLI = itLI.Value(); + TopTools_ListOfShape &aChain = theChains.Append (TopTools_ListOfShape()); + + for (TColStd_ListOfInteger::Iterator itI (aLI); itI.More(); itI.Next()) + aChain.Append (theVertices.FindKey (itI.Value())); + } + + // Add not interfered vertices as a chain of 1 element + for (Standard_Integer i = 1; i <= aNbV; ++i) + { + if (!aMILI.Contains (i)) + { + TopTools_ListOfShape &aChain = theChains.Append (TopTools_ListOfShape()); + aChain.Append (theVertices.FindKey(i)); } } } @@ -1236,9 +1222,9 @@ public: }; //! Sets the Bounding Box tree - void SetBBTree(const BOPTools_BoxBndTree& theBBTree) + void SetBBTree(BOPTools_BoxTree* theBBTree) { - myBBTree = (BOPTools_BoxBndTree*)&theBBTree; + myBBTree = theBBTree; }; //! Sets the ShapeBox structure @@ -1288,7 +1274,7 @@ private: TopTools_ListOfShape myOwnIF; //! Own INTERNAL faces of the solid TopTools_ListOfShape myInFaces; //! Faces classified as IN - BOPTools_BoxBndTree* myBBTree; //! UB tree of bounding boxes + BOPTools_BoxTree* myBBTree; //! BVH tree of bounding boxes BOPAlgo_VectorOfShapeBox* myVShapeBox; //! ShapeBoxMap TopoDS_Iterator myItF; //! Iterators @@ -1308,10 +1294,11 @@ void BOPAlgo_FillIn3DParts::Perform() myInFaces.Clear(); // 1. Select boxes of faces that are not out of aBoxS - BOPTools_BoxBndTreeSelector aSelector; - aSelector.SetBox(myBoxS); + BOPTools_BoxTreeSelector aSelector; + aSelector.SetBox(Bnd_Tools::Bnd2BVH(myBoxS)); + aSelector.SetBVHSet (myBBTree); // - if (!myBBTree->Select(aSelector)) + if (!aSelector.Select()) return; const TColStd_ListOfInteger& aLIFP = aSelector.Indices(); @@ -1559,19 +1546,18 @@ void BOPAlgo_Tools::ClassifyFaces(const TopTools_ListOfShape& theFaces, } } - // Prepare UB tree of bounding boxes of the faces to classify + // Prepare BVH tree of bounding boxes of the faces to classify // taking the bounding boxes from the just prepared vector - BOPTools_BoxBndTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); - + BOPTools_BoxTree aBBTree; Standard_Integer aNbF = aVSB.Length(); + aBBTree.SetSize (aNbF); for (Standard_Integer i = 0; i < aNbF; ++i) { - aTreeFiller.Add(i, aVSB(i).Box()); + aBBTree.Add(i, Bnd_Tools::Bnd2BVH(aVSB(i).Box())); } // Shake tree filler - aTreeFiller.Fill(); + aBBTree.Build(); // Prepare vector of solids to classify BOPAlgo_VectorOfFillIn3DParts aVFIP; @@ -1605,7 +1591,7 @@ void BOPAlgo_Tools::ClassifyFaces(const TopTools_ListOfShape& theFaces, if (pLIF) aFIP.SetOwnIF(*pLIF); - aFIP.SetBBTree(aBBTree); + aFIP.SetBBTree(&aBBTree); aFIP.SetShapeBoxVector(aVSB); } diff --git a/src/BOPAlgo/BOPAlgo_Tools.hxx b/src/BOPAlgo/BOPAlgo_Tools.hxx index 50492e9b55..9d20dd3b26 100644 --- a/src/BOPAlgo/BOPAlgo_Tools.hxx +++ b/src/BOPAlgo/BOPAlgo_Tools.hxx @@ -162,7 +162,6 @@ public: //! Finds chains of intersecting vertices Standard_EXPORT static void IntersectVertices(const TopTools_IndexedDataMapOfShapeReal& theVertices, - const Standard_Boolean theRunParallel, const Standard_Real theFuzzyValue, TopTools_ListOfListOfShape& theChains); diff --git a/src/BOPDS/BOPDS_Iterator.cxx b/src/BOPDS/BOPDS_Iterator.cxx index 03228384c0..a685c02aee 100644 --- a/src/BOPDS/BOPDS_Iterator.cxx +++ b/src/BOPDS/BOPDS_Iterator.cxx @@ -18,16 +18,16 @@ #include #include +#include #include #include #include #include #include #include -#include +#include #include #include -#include #include #include #include @@ -37,12 +37,12 @@ //class : BOPDS_TreeSelector //purpose : //======================================================================= -class BOPDS_TSR : public BOPTools_BoxBndTreeSelector{ +class BOPDS_TSR : public BOPTools_BoxTreeSelector +{ public: BOPDS_TSR() : - BOPTools_BoxBndTreeSelector(), + BOPTools_BoxTreeSelector(), myHasBRep(Standard_False), - myTree(NULL), myIndex(-1) {} // virtual ~BOPDS_TSR() { @@ -52,23 +52,18 @@ class BOPDS_TSR : public BOPTools_BoxBndTreeSelector{ myHasBRep=bFlag; } // - void SetTree(BOPTools_BoxBndTree& aTree) { - myTree=&aTree; - } - // void SetIndex(const Standard_Integer theIndex) { myIndex = theIndex; } // Standard_Integer Index() const { return myIndex; } // void Perform() { if (myHasBRep) { - myTree->Select(*this); + Select(); } } // protected: Standard_Boolean myHasBRep; - BOPTools_BoxBndTree *myTree; Standard_Integer myIndex; }; // @@ -76,7 +71,6 @@ class BOPDS_TSR : public BOPTools_BoxBndTreeSelector{ typedef NCollection_Vector BOPDS_VectorOfTSR; ///////////////////////////////////////////////////////////////////////// - //======================================================================= //function : //purpose : @@ -289,142 +283,81 @@ void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx, const Standard_Boolean theCheckOBB, const Standard_Real theFuzzyValue) { - Standard_Integer i, j, iX, i1, i2, iR, aNb, aNbR; - Standard_Integer iTi, iTj; - TopAbs_ShapeEnum aTi, aTj; - // - myBoxTree.Clear(); - NCollection_UBTreeFiller aTreeFiller(myBoxTree); - // - aNb = myDS->NbSourceShapes(); - BOPDS_VectorOfTSR aVTSR(aNb); - // - for (i=0; iShapeInfo(i); - Standard_Boolean bHasBrep = aSI.IsInterfering() && !(aSI.ShapeType() == TopAbs_SOLID); - // - BOPDS_TSR& aTSR=aVTSR.Appended(); - // - aTSR.SetHasBRep(bHasBrep); - if (!bHasBrep) { - continue; - } - // - const Bnd_Box& aBoxEx=aSI.Box(); - aTSR.SetTree(myBoxTree); - aTSR.SetBox(aBoxEx); - aTSR.SetIndex(i); - // - aTreeFiller.Add(i, aBoxEx); - } - // - aTreeFiller.Fill(); - // - //=========================================== - BOPTools_Parallel::Perform (myRunParallel, aVTSR); - //=========================================== - // - BOPDS_MapOfPair aMPFence; - // - aNbR = myDS->NbRanges() - 1; - for (iR = 0; iR < aNbR; ++iR) { - const BOPDS_IndexRange& aR = myDS->Range(iR); - i1 = aR.First(); - i2 = aR.Last(); - for (i = i1; i <= i2; ++i) { - const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); - // - if (!aSI.IsInterfering() || (aSI.ShapeType() == TopAbs_SOLID)) { - continue; - } - // - BOPDS_TSR& aTSRi = aVTSR(i); - const TColStd_ListOfInteger& aLI = aTSRi.Indices(); - Standard_Integer aNbSD = aLI.Extent(); - if (!aNbSD) { - continue; - } - // - aTi = aSI.ShapeType(); - iTi = BOPDS_Tools::TypeToInteger(aTi); - // - TColStd_ListIteratorOfListOfInteger aIt(aLI); - for (; aIt.More(); aIt.Next()) { - j = aIt.Value(); // DS index - if (j >= i1 && j <= i2) { - continue;// same range - } - // - const BOPDS_ShapeInfo& aSJ = myDS->ShapeInfo(j); - aTj = aSJ.ShapeType(); - iTj = BOPDS_Tools::TypeToInteger(aTj); - // - // avoid interfering of the same shapes and shape with its sub-shapes - if (((iTi < iTj) && aSI.HasSubShape(j)) || - ((iTi > iTj) && aSJ.HasSubShape(i))) { - continue; - } - // - BOPDS_Pair aPair(i, j); - if (aMPFence.Add(aPair)) { - if (theCheckOBB) - { - // Check intersection of Oriented bounding boxes of the shapes - Bnd_OBB& anOBBi = theCtx->OBB(aSI.Shape(), theFuzzyValue); - Bnd_OBB& anOBBj = theCtx->OBB(aSJ.Shape(), theFuzzyValue); + const Standard_Integer aNb = myDS->NbSourceShapes(); - if (anOBBi.IsOut(anOBBj)) - continue; - } - - iX = BOPDS_Tools::TypeToInteger(aTi, aTj); - myLists(iX).Append(aPair); - }// if (aMPFence.Add(aPair)) { - }// for (; aIt.More(); aIt.Next()) { - }//for (i=i1; i<=i2; ++i) { - }//for (iR=1; iRHasShapeSD(nV, nVSD); - const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nVSD); + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); + if (!aSI.HasBRep()) + continue; const Bnd_Box& aBox = aSI.Box(); - myBoxTree.Add(nV, aBox); + aBoxTree.Add (i, Bnd_Tools::Bnd2BVH (aBox)); } - // Clear the extra lists - const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs(); - myLength = 0; - for (Standard_Integer i = 0; i < aNbExt; ++i) - myExtLists(i).Clear(); + // Build BVH + aBoxTree.Build(); - IntersectExt(theIndices); + // Select pairs of shapes with interfering bounding boxes + BOPTools_BoxPairSelector aPairSelector; + aPairSelector.SetBVHSets (&aBoxTree, &aBoxTree); + aPairSelector.SetSame (Standard_True); + aPairSelector.Select(); + aPairSelector.Sort(); - myUseExt = Standard_True; + // Treat the selected pairs + const std::vector& aPairs = aPairSelector.Pairs(); + const Standard_Integer aNbPairs = static_cast (aPairs.size()); + + Standard_Integer iPair = 0; + + const Standard_Integer aNbR = myDS->NbRanges(); + for (Standard_Integer iR = 0; iR < aNbR; ++iR) + { + const BOPDS_IndexRange& aRange = myDS->Range(iR); + + for (; iPair < aNbPairs; ++iPair) + { + const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair]; + if (!aRange.Contains (aPair.ID1)) + // Go to the next range + break; + + if (aRange.Contains (aPair.ID2)) + // Go to the next pair + continue; + + const BOPDS_ShapeInfo& aSI1 = myDS->ShapeInfo (aPair.ID1); + const BOPDS_ShapeInfo& aSI2 = myDS->ShapeInfo (aPair.ID2); + + const TopAbs_ShapeEnum aType1 = aSI1.ShapeType(); + const TopAbs_ShapeEnum aType2 = aSI2.ShapeType(); + + Standard_Integer iType1 = BOPDS_Tools::TypeToInteger (aType1); + Standard_Integer iType2 = BOPDS_Tools::TypeToInteger (aType2); + + // avoid interfering of the shape with its sub-shapes + if (((iType1 < iType2) && aSI1.HasSubShape (aPair.ID2)) || + ((iType1 > iType2) && aSI2.HasSubShape (aPair.ID1))) + continue; + + if (theCheckOBB) + { + // Check intersection of Oriented bounding boxes of the shapes + const Bnd_OBB& anOBB1 = theCtx->OBB (aSI1.Shape(), theFuzzyValue); + const Bnd_OBB& anOBB2 = theCtx->OBB (aSI2.Shape(), theFuzzyValue); + + if (anOBB1.IsOut (anOBB2)) + continue; + } + + Standard_Integer iX = BOPDS_Tools::TypeToInteger (aType1, aType2); + myLists(iX).Append (BOPDS_Pair (Min (aPair.ID1, aPair.ID2), + Max (aPair.ID1, aPair.ID2))); + } + } } //======================================================================= @@ -433,24 +366,43 @@ void BOPDS_Iterator::PrepareExt(const TColStd_MapOfInteger& theIndices) //======================================================================= void BOPDS_Iterator::IntersectExt(const TColStd_MapOfInteger& theIndices) { - // Prepare vector for parallel selection - BOPDS_VectorOfTSR aVTSR(theIndices.Extent()); + if (!myDS) + return; - TColStd_MapIteratorOfMapOfInteger itM(theIndices); - for (; itM.More(); itM.Next()) + const Standard_Integer aNb = myDS->NbSourceShapes(); + + BOPTools_BoxTree aBoxTree; + aBoxTree.SetSize (aNb); + BOPDS_VectorOfTSR aVTSR(theIndices.Extent()); + // + for (Standard_Integer i = 0; i < aNb; ++i) { - Standard_Integer nV = itM.Value(); - Standard_Integer nVSD = nV; - myDS->HasShapeSD(nV, nVSD); - const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nVSD); - const Bnd_Box& aBox = aSI.Box(); - BOPDS_TSR& aTSR = aVTSR.Appended(); - aTSR.SetHasBRep(Standard_True); - aTSR.SetTree(myBoxTree); - aTSR.SetBox(aBox); - aTSR.SetIndex(nV); + const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i); + if (!aSI.IsInterfering() || (aSI.ShapeType() == TopAbs_SOLID)) + continue; + // + if (theIndices.Contains (i)) + { + Standard_Integer nVSD = i; + myDS->HasShapeSD (i, nVSD); + const BOPDS_ShapeInfo& aSISD = myDS->ShapeInfo (nVSD); + const Bnd_Box& aBox = aSISD.Box (); + aBoxTree.Add (i, Bnd_Tools::Bnd2BVH(aBox)); + + BOPDS_TSR& aTSR=aVTSR.Appended(); + aTSR.SetHasBRep(Standard_True); + aTSR.SetBVHSet (&aBoxTree); + aTSR.SetBox (Bnd_Tools::Bnd2BVH (aBox)); + aTSR.SetIndex (i); + } + else + { + aBoxTree.Add (i, Bnd_Tools::Bnd2BVH (aSI.Box ())); + } } + aBoxTree.Build(); + // Perform selection BOPTools_Parallel::Perform (myRunParallel, aVTSR); @@ -459,8 +411,8 @@ void BOPDS_Iterator::IntersectExt(const TColStd_MapOfInteger& theIndices) // Fence map to avoid duplicating pairs BOPDS_MapOfPair aMPFence; - const Standard_Integer aNb = aVTSR.Length(); - for (Standard_Integer k = 0; k < aNb; ++k) + const Standard_Integer aNbV = aVTSR.Length(); + for (Standard_Integer k = 0; k < aNbV; ++k) { BOPDS_TSR& aTSRi = aVTSR(k); const TColStd_ListOfInteger& aLI = aTSRi.Indices(); @@ -485,7 +437,7 @@ void BOPDS_Iterator::IntersectExt(const TColStd_MapOfInteger& theIndices) const TopAbs_ShapeEnum aTJ = aSJ.ShapeType(); const Standard_Integer iTJ = BOPDS_Tools::TypeToInteger(aTJ); - // avoid interfering of the same shapes and shape with its sub-shapes + // avoid interfering of the shape with its sub-shapes if (((iTI < iTJ) && aSI.HasSubShape(j)) || ((iTI > iTJ) && aSJ.HasSubShape(i))) continue; @@ -499,4 +451,6 @@ void BOPDS_Iterator::IntersectExt(const TColStd_MapOfInteger& theIndices) } } } + + myUseExt = Standard_True; } diff --git a/src/BOPDS/BOPDS_Iterator.hxx b/src/BOPDS/BOPDS_Iterator.hxx index 04b339a5af..9faf534c49 100644 --- a/src/BOPDS/BOPDS_Iterator.hxx +++ b/src/BOPDS/BOPDS_Iterator.hxx @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include @@ -88,7 +88,7 @@ public: //! Updates the tree of Bounding Boxes with increased boxes and //! intersects such elements with the tree. - Standard_EXPORT void PrepareExt(const TColStd_MapOfInteger& theIndicies); + Standard_EXPORT void IntersectExt(const TColStd_MapOfInteger& theIndicies); //! Returns the number of intersections founded Standard_EXPORT Standard_Integer ExpectedLength() const; @@ -119,12 +119,6 @@ protected: //! @name Protected methods for bounding boxes intersection const Standard_Boolean theCheckOBB = Standard_False, const Standard_Real theFuzzyValue = Precision::Confusion()); - //! Intersects the bounding boxes of the shapes with given indices in DS - //! with the tree of bounding boxes and saves the interfering pairs in - //! extra lists for further geometrical intersection. - Standard_EXPORT void IntersectExt(const TColStd_MapOfInteger& theIndices); - - protected: //! @name Fields Handle(NCollection_BaseAllocator) myAllocator; //!< Allocator @@ -134,7 +128,6 @@ protected: //! @name Fields BOPDS_VectorOfVectorOfPair myLists; //!< Pairs with interfering bounding boxes BOPDS_VectorOfPair::Iterator myIterator; //!< Iterator on each interfering type Standard_Boolean myRunParallel; //!< Flag for parallel processing - BOPTools_BoxBndTree myBoxTree; //!< Unbalanced tree of bounding boxes BOPDS_VectorOfVectorOfPair myExtLists; //!< Extra pairs of sub-shapes found after //! intersection of increased sub-shapes Standard_Boolean myUseExt; //!< Information flag for using the extra lists diff --git a/src/BOPDS/BOPDS_IteratorSI.cxx b/src/BOPDS/BOPDS_IteratorSI.cxx index 3b824010eb..13f0926ead 100644 --- a/src/BOPDS/BOPDS_IteratorSI.cxx +++ b/src/BOPDS/BOPDS_IteratorSI.cxx @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -21,11 +22,10 @@ #include #include #include -#include +#include #include #include #include -#include #include #include #include @@ -79,83 +79,68 @@ void BOPDS_IteratorSI::UpdateByLevelOfCheck(const Standard_Integer theLevel) // function: Intersect // purpose: //======================================================================= -void BOPDS_IteratorSI::Intersect(const Handle(IntTools_Context)& theCtx, - const Standard_Boolean theCheckOBB, - const Standard_Real theFuzzyValue) +void BOPDS_IteratorSI::Intersect (const Handle(IntTools_Context)& theCtx, + const Standard_Boolean theCheckOBB, + const Standard_Real theFuzzyValue) { - Standard_Integer i, j, iX, aNbS; - Standard_Integer iTi, iTj; - TopAbs_ShapeEnum aTi, aTj; - // - BOPTools_BoxBndTreeSelector aSelector; - BOPTools_BoxBndTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); - // - aNbS = myDS->NbSourceShapes(); - for (i=0; iShapeInfo(i); - if (!aSI.IsInterfering()) { + const Standard_Integer aNbS = myDS->NbSourceShapes(); + + BOPTools_BoxTree aBBTree; + aBBTree.SetSize (aNbS); + + for (Standard_Integer i = 0; i < aNbS; ++i) + { + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo (i); + if (!aSI.IsInterfering()) continue; - } - // + const Bnd_Box& aBoxEx = aSI.Box(); - aTreeFiller.Add(i, aBoxEx); + aBBTree.Add (i, Bnd_Tools::Bnd2BVH (aBoxEx)); } - // - aTreeFiller.Fill(); - // - BOPDS_MapOfPair aMPFence; - // - for (i = 0; i < aNbS; ++i) { - const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); - if (!aSI.IsInterfering()){ + + aBBTree.Build(); + + // Select pairs of shapes with interfering bounding boxes + BOPTools_BoxPairSelector aPairSelector; + aPairSelector.SetBVHSets (&aBBTree, &aBBTree); + aPairSelector.SetSame (Standard_True); + aPairSelector.Select(); + aPairSelector.Sort(); + + // Treat the selected pairs + const std::vector& aPairs = aPairSelector.Pairs(); + const Standard_Integer aNbPairs = static_cast (aPairs.size()); + + for (Standard_Integer iPair = 0; iPair < aNbPairs; ++iPair) + { + const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair]; + + const BOPDS_ShapeInfo& aSI1 = myDS->ShapeInfo (aPair.ID1); + const BOPDS_ShapeInfo& aSI2 = myDS->ShapeInfo (aPair.ID2); + + const TopAbs_ShapeEnum aType1 = aSI1.ShapeType(); + const TopAbs_ShapeEnum aType2 = aSI2.ShapeType(); + + Standard_Integer iType1 = BOPDS_Tools::TypeToInteger (aType1); + Standard_Integer iType2 = BOPDS_Tools::TypeToInteger (aType2); + + // avoid interfering of the shape with its sub-shapes + if (((iType1 < iType2) && aSI1.HasSubShape (aPair.ID2)) || + ((iType1 > iType2) && aSI2.HasSubShape (aPair.ID1))) continue; - } - // - const Bnd_Box& aBoxEx = aSI.Box(); - // - aSelector.Clear(); - aSelector.SetBox(aBoxEx); - // - Standard_Integer aNbSD = aBBTree.Select(aSelector); - if (!aNbSD) { - continue; - } - // - aTi = aSI.ShapeType(); - iTi = BOPDS_Tools::TypeToInteger(aTi); - // - const TColStd_ListOfInteger& aLI = aSelector.Indices(); - TColStd_ListIteratorOfListOfInteger aIt(aLI); - for (; aIt.More(); aIt.Next()) { - j = aIt.Value(); - const BOPDS_ShapeInfo& aSJ = myDS->ShapeInfo(j); - aTj = aSJ.ShapeType(); - iTj = BOPDS_Tools::TypeToInteger(aTj); - // - // avoid interfering of the same shapes and shape with its sub-shapes - if ((i == j) || ((iTi < iTj) && aSI.HasSubShape(j)) || - ((iTi > iTj) && aSJ.HasSubShape(i))) { + + if (theCheckOBB) + { + // Check intersection of Oriented bounding boxes of the shapes + const Bnd_OBB& anOBB1 = theCtx->OBB (aSI1.Shape (), theFuzzyValue); + const Bnd_OBB& anOBB2 = theCtx->OBB (aSI2.Shape (), theFuzzyValue); + + if (anOBB1.IsOut (anOBB2)) continue; - } - // - BOPDS_Pair aPair(i, j); - if (aMPFence.Add(aPair)) { - if (theCheckOBB) - { - // Check intersection of Oriented bounding boxes of the shapes - Bnd_OBB& anOBBi = theCtx->OBB(aSI.Shape(), theFuzzyValue); - Bnd_OBB& anOBBj = theCtx->OBB(aSJ.Shape(), theFuzzyValue); + } - if (anOBBi.IsOut(anOBBj)) - continue; - } - - iX = BOPDS_Tools::TypeToInteger(aTi, aTj); - myLists(iX).Append(aPair); - }// if (aMPKXB.Add(aPKXB)) { - }// for (; aIt.More(); aIt.Next()) { - }//for (i=1; i<=aNbS; ++i) { - // - aMPFence.Clear(); + Standard_Integer iX = BOPDS_Tools::TypeToInteger (aType1, aType2); + myLists(iX).Append (BOPDS_Pair (Min (aPair.ID1, aPair.ID2), + Max (aPair.ID1, aPair.ID2))); + } } diff --git a/src/BOPDS/BOPDS_ShapeInfo.lxx b/src/BOPDS/BOPDS_ShapeInfo.lxx index f528d35ac1..3acaa2b6e2 100644 --- a/src/BOPDS/BOPDS_ShapeInfo.lxx +++ b/src/BOPDS/BOPDS_ShapeInfo.lxx @@ -126,18 +126,7 @@ inline TColStd_ListOfInteger& BOPDS_ShapeInfo::ChangeSubShapes() inline Standard_Boolean BOPDS_ShapeInfo::HasSubShape (const Standard_Integer theI)const { - Standard_Boolean bRet; - TColStd_ListIteratorOfListOfInteger aIt; - // - bRet=Standard_False; - aIt.Initialize(mySubShapes); - for (; aIt.More(); aIt.Next()) { - bRet=(theI==aIt.Value()); - if (bRet) { - return bRet; - } - } - return bRet; + return mySubShapes.Contains (theI); } //======================================================================= //function : HasReference diff --git a/src/BOPDS/BOPDS_SubIterator.cxx b/src/BOPDS/BOPDS_SubIterator.cxx index 18ec0e5d2e..5105fa3e9a 100644 --- a/src/BOPDS/BOPDS_SubIterator.cxx +++ b/src/BOPDS/BOPDS_SubIterator.cxx @@ -16,14 +16,13 @@ #include #include +#include #include #include #include -#include - -#include +#include #include @@ -115,60 +114,65 @@ void BOPDS_SubIterator::Initialize() // function: Intersect // purpose: //======================================================================= - void BOPDS_SubIterator::Intersect() +void BOPDS_SubIterator::Intersect() { - Standard_Integer i, j, iTi, iTj; - BOPTools_BoxBndTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); - // - TColStd_ListIteratorOfListOfInteger aIt(*mySubSet1); - for (; aIt.More(); aIt.Next()) { - i = aIt.Value(); - // - const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); - const Bnd_Box& aBoxEx = aSI.Box(); - // - aTreeFiller.Add(i, aBoxEx); + if (!mySubSet1->Extent() || !mySubSet2->Extent()) + return; + + // Construct BVH tree for each sub-set + BOPTools_BoxTree aBBTree[2]; + for (Standard_Integer i = 0; i < 2; ++i) + { + const TColStd_ListOfInteger* aSubSet = !i ? mySubSet1 : mySubSet2; + aBBTree[i].SetSize (aSubSet->Extent()); + for (TColStd_ListOfInteger::Iterator it (*aSubSet); it.More(); it.Next()) + { + const Standard_Integer nS = it.Value(); + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nS); + const Bnd_Box& aBoxEx = aSI.Box(); + aBBTree[i].Add(nS, Bnd_Tools::Bnd2BVH (aBoxEx)); + } + aBBTree[i].Build(); } - // - aTreeFiller.Fill(); - // + + // Perform selection of the interfering pairs + BOPTools_BoxPairSelector aPairSelector; + aPairSelector.SetBVHSets (&aBBTree[0], &aBBTree[1]); + aPairSelector.Select(); + aPairSelector.Sort(); + + // Treat the selected pairs + const std::vector& aPairs = aPairSelector.Pairs(); + const Standard_Integer aNbPairs = static_cast (aPairs.size()); + + // Fence map BOPDS_MapOfPair aMPKFence; - // - aIt.Initialize(*mySubSet2); - for (; aIt.More(); aIt.Next()) { - i = aIt.Value(); - // - const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); - const Bnd_Box& aBoxEx = aSI.Box(); - // - BOPTools_BoxBndTreeSelector aSelector; - aSelector.SetBox(aBoxEx); - Standard_Integer aNbSD = aBBTree.Select(aSelector); - if (!aNbSD) { + + for (Standard_Integer iPair = 0; iPair < aNbPairs; ++iPair) + { + const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair]; + if (aPair.ID1 == aPair.ID2) continue; - } - // - iTi = BOPDS_Tools::TypeToInteger(aSI.ShapeType()); - // - const TColStd_ListOfInteger& aLI = aSelector.Indices(); - TColStd_ListIteratorOfListOfInteger aItLI(aLI); - for (; aItLI.More(); aItLI.Next()) { - j = aItLI.Value(); - // - const BOPDS_ShapeInfo& aSJ = myDS->ShapeInfo(j); - iTj = BOPDS_Tools::TypeToInteger(aSJ.ShapeType()); - // - // avoid interfering of the same shapes and shape with its sub-shapes - if ((i == j) || ((iTi < iTj) && aSI.HasSubShape(j)) || - ((iTi > iTj) && aSJ.HasSubShape(i))) { - continue; - } - // - BOPDS_Pair aPair(j, i); - if (aMPKFence.Add(aPair)) { - myList.Append(aPair); - } - } + + BOPDS_Pair aDSPair (Min(aPair.ID1, aPair.ID2), + Max(aPair.ID1, aPair.ID2)); + if (!aMPKFence.Add(aDSPair)) + continue; + + const BOPDS_ShapeInfo& aSI1 = myDS->ShapeInfo (aPair.ID1); + const BOPDS_ShapeInfo& aSI2 = myDS->ShapeInfo (aPair.ID2); + + const TopAbs_ShapeEnum aType1 = aSI1.ShapeType(); + const TopAbs_ShapeEnum aType2 = aSI2.ShapeType(); + + Standard_Integer iType1 = BOPDS_Tools::TypeToInteger (aType1); + Standard_Integer iType2 = BOPDS_Tools::TypeToInteger (aType2); + + // avoid interfering of the shape with its sub-shapes + if (((iType1 < iType2) && aSI1.HasSubShape (aPair.ID2)) || + ((iType1 > iType2) && aSI2.HasSubShape (aPair.ID1))) + continue; + + myList.Append(aDSPair); } } diff --git a/src/BOPTools/BOPTools_BoxBndTree.hxx b/src/BOPTools/BOPTools_BoxBndTree.hxx deleted file mode 100644 index 6ed2ea0963..0000000000 --- a/src/BOPTools/BOPTools_BoxBndTree.hxx +++ /dev/null @@ -1,26 +0,0 @@ -// Created by: Eugeny MALTCHIKOV -// Copyright (c) 2017 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 License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef BOPTools_BoxBndTree_HeaderFile -#define BOPTools_BoxBndTree_HeaderFile - -#include -#include -#include -#include - -typedef NCollection_EBTree BOPTools_BoxBndTree; -typedef BOPTools_BoxSelector BOPTools_BoxBndTreeSelector; - -#endif diff --git a/src/BOPTools/BOPTools_BoxSelector.hxx b/src/BOPTools/BOPTools_BoxSelector.hxx index e8bf2683f4..c29012e04d 100644 --- a/src/BOPTools/BOPTools_BoxSelector.hxx +++ b/src/BOPTools/BOPTools_BoxSelector.hxx @@ -15,32 +15,27 @@ #ifndef BOPTools_BoxSelector_HeaderFile #define BOPTools_BoxSelector_HeaderFile -#include -#include -#include +#include +#include -//! Template Selector for the unbalanced binary tree -//! of overlapped bounding boxes. -template class BOPTools_BoxSelector : - public NCollection_UBTree::Selector +#include +#include + +//! Template Selector for elements selection from BVH tree. +template +class BOPTools_BoxSelector : + public BVH_Traverse , Standard_Boolean> { public: + typedef typename BVH::VectorType::Type BVH_VecNd; + +public: //! @name Constructor + //! Empty constructor BOPTools_BoxSelector() {}; - //! Checks if the box should be rejected - virtual Standard_Boolean Reject(const BoxType& theOther) const - { - return myBox.IsOut(theOther); - } - - //! Accepts the index - virtual Standard_Boolean Accept(const Standard_Integer& theIndex) - { - myIndices.Append(theIndex); - return Standard_True; - } +public: //! @name public interfaces //! Clears the indices void Clear() @@ -49,7 +44,7 @@ public: } //! Sets the box - void SetBox(const BoxType& theBox) + void SetBox (const BVH_Box & theBox) { myBox = theBox; } @@ -60,11 +55,46 @@ public: return myIndices; } -private: +public: //! @name Rejection/Acceptance rules - BoxType myBox; - TColStd_ListOfInteger myIndices; + //! Checks if the box should be rejected + virtual Standard_Boolean RejectNode (const BVH_VecNd& theCMin, + const BVH_VecNd& theCMax, + Standard_Boolean& theIsInside) const Standard_OVERRIDE + { + Standard_Boolean hasOverlap; + theIsInside = myBox.Contains (theCMin, theCMax, hasOverlap); + return !hasOverlap; + } + //! Checks if the element should be rejected + Standard_Boolean RejectElement (const Standard_Integer theIndex) + { + return myBox.IsOut (this->myBVHSet->Box (theIndex)); + } + + //! Checks if the metric of the node may be accepted + virtual Standard_Boolean AcceptMetric (const Standard_Boolean& theIsInside) const Standard_OVERRIDE + { + return theIsInside; + } + + //! Accepts the element with the index in BVH tree + virtual Standard_Boolean Accept (const Standard_Integer theIndex, + const Standard_Boolean& theIsInside) Standard_OVERRIDE + { + if (theIsInside || !RejectElement (theIndex)) + { + myIndices.Append (this->myBVHSet->Element (theIndex)); + return Standard_True; + } + return Standard_False; + } + +protected: //! @name Fields + + BVH_Box myBox; //!< Selection box + TColStd_ListOfInteger myIndices; //!< Selected indices }; #endif diff --git a/src/BOPTools/BOPTools_BoxTree.hxx b/src/BOPTools/BOPTools_BoxTree.hxx new file mode 100644 index 0000000000..7477139f3b --- /dev/null +++ b/src/BOPTools/BOPTools_BoxTree.hxx @@ -0,0 +1,47 @@ +// Created by: Eugeny MALTCHIKOV +// Copyright (c) 2017 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 License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef BOPTools_BoxTree_HeaderFile +#define BOPTools_BoxTree_HeaderFile + +#include +#include +#include +#include +#include +#include + +//! Redefines BoxSet to use the Linear builder by default + +template +class BOPTools_BoxSet : public BVH_BoxSet +{ +public: //! @name Constructors + //! Empty constructor for use the default BVH_Builder + BOPTools_BoxSet (const opencascade::handle >& theBuilder = NULL) + : BVH_BoxSet (theBuilder.IsNull() ? new BVH_LinearBuilder() : theBuilder) + {} +}; + +//! 2D definitions +typedef BOPTools_BoxSet BOPTools_Box2dTree; +typedef BOPTools_BoxSelector<2> BOPTools_Box2dTreeSelector; +typedef BOPTools_PairSelector<2> BOPTools_Box2dPairSelector; + +//! 3D definitions +typedef BOPTools_BoxSet BOPTools_BoxTree; +typedef BOPTools_BoxSelector<3> BOPTools_BoxTreeSelector; +typedef BOPTools_PairSelector<3> BOPTools_BoxPairSelector; + +#endif diff --git a/src/BOPTools/BOPTools_PairSelector.hxx b/src/BOPTools/BOPTools_PairSelector.hxx new file mode 100644 index 0000000000..19a22740be --- /dev/null +++ b/src/BOPTools/BOPTools_PairSelector.hxx @@ -0,0 +1,131 @@ +// Created by: Eugeny MALTCHIKOV +// Copyright (c) 2017 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 License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef BOPTools_PairSelector_HeaderFile +#define BOPTools_PairSelector_HeaderFile + +#include +#include + +#include +#include +#include + +//! Template Selector for selection of the elements from two BVH trees. +template +class BOPTools_PairSelector : + public BVH_PairTraverse > +{ +public: //! @name public types + + //! Auxiliary structure to keep the pair of indices + struct PairIDs + { + PairIDs (const Standard_Integer theId1 = -1, + const Standard_Integer theId2 = -1) + : ID1 (theId1), ID2 (theId2) + {} + + Standard_Boolean operator< (const PairIDs& theOther) const + { + return ID1 < theOther.ID1 || + (ID1 == theOther.ID1 && ID2 < theOther.ID2); + } + + Standard_Integer ID1; + Standard_Integer ID2; + }; + + typedef typename BVH::VectorType::Type BVH_VecNd; + +public: //! @name Constructor + + //! Empty constructor + BOPTools_PairSelector() + : mySameBVHs (Standard_False) + {} + +public: //! @name public interfaces + + //! Clears the indices + void Clear() + { + myPairs.Clear(); + } + + //! Sorts the indices + void Sort() + { + std::sort (myPairs.begin(), myPairs.end()); + } + + //! Tells to selector that BVH trees are the same. + //! If the flag is set to true the resulting vector will contain + //! only unique pairs (mirrored pairs will be rejected, + //! e.g. (1, 2) will be taken, (2, 1) will be rejected) and will + //! not contain pairs in which IDs are the same (pair (1, 1) will be rejected). + //! If it is required to have a full vector of pairs even + //! for the same BVH trees, just keep the false value of this flag. + void SetSame (const Standard_Boolean theIsSame) + { + mySameBVHs = theIsSame; + } + + //! Returns the list of accepted indices + const std::vector& Pairs() const + { + return myPairs; + } + +public: //! @name Rejection/Acceptance rules + + //! Basing on the bounding boxes of the nodes checks if the pair of nodes should be rejected. + virtual Standard_Boolean RejectNode (const BVH_VecNd& theCMin1, + const BVH_VecNd& theCMax1, + const BVH_VecNd& theCMin2, + const BVH_VecNd& theCMax2, + Standard_Real&) const Standard_OVERRIDE + { + return BVH_Box (theCMin1, theCMax1).IsOut (theCMin2, theCMax2); + } + + //! Checks if the pair of elements should be rejected. + Standard_Boolean RejectElement (const Standard_Integer theID1, + const Standard_Integer theID2) + { + return (mySameBVHs && theID1 >= theID2) || + this->myBVHSet1->Box (theID1).IsOut( + this->myBVHSet2->Box (theID2)); + } + + //! Checks and accepts the pair of elements. + virtual Standard_Boolean Accept (const Standard_Integer theID1, + const Standard_Integer theID2) Standard_OVERRIDE + { + if (!RejectElement (theID1, theID2)) + { + myPairs.push_back (PairIDs (this->myBVHSet1->Element (theID1), + this->myBVHSet2->Element (theID2))); + return Standard_True; + } + return Standard_False; + } + +protected: //! @name Fields + + std::vector myPairs; //!< Selected pairs of indices + Standard_Boolean mySameBVHs; //!< Selection is performed from the same BVH trees +}; + +#endif diff --git a/src/BOPTools/FILES b/src/BOPTools/FILES index 26526d0a30..26ade9a944 100755 --- a/src/BOPTools/FILES +++ b/src/BOPTools/FILES @@ -8,13 +8,14 @@ BOPTools_AlgoTools3D.hxx BOPTools_AlgoTools_1.cxx BOPTools_AlgoTools_2.cxx BOPTools_BoxSelector.hxx -BOPTools_BoxBndTree.hxx +BOPTools_BoxTree.hxx BOPTools_ConnexityBlock.hxx BOPTools_CoupleOfShape.hxx BOPTools_IndexedDataMapOfSetShape.hxx BOPTools_ListOfConnexityBlock.hxx BOPTools_ListOfCoupleOfShape.hxx BOPTools_MapOfSet.hxx +BOPTools_PairSelector.hxx BOPTools_Parallel.hxx BOPTools_Set.cxx BOPTools_Set.hxx diff --git a/src/BRepOffset/BRepOffset_Inter3d.cxx b/src/BRepOffset/BRepOffset_Inter3d.cxx index adbaa2dd6a..0019a4f013 100644 --- a/src/BRepOffset/BRepOffset_Inter3d.cxx +++ b/src/BRepOffset/BRepOffset_Inter3d.cxx @@ -16,6 +16,7 @@ // Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 +#include #include #include #include @@ -46,8 +47,7 @@ #include // #include -#include -#include +#include // #include @@ -114,8 +114,8 @@ void BRepOffset_Inter3d::CompletInt(const TopTools_ListOfShape& SetOfFaces, //--------------------------------------------------------------- // Prepare tools for sorting the bounding boxes - BOPTools_BoxBndTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); + BOPTools_BoxTree aBBTree; + aBBTree.SetSize (SetOfFaces.Extent()); // NCollection_IndexedDataMap aMFaces; // Construct bounding boxes for faces and add them to the tree @@ -127,37 +127,37 @@ void BRepOffset_Inter3d::CompletInt(const TopTools_ListOfShape& SetOfFaces, Bnd_Box aBoxF; BRepBndLib::Add(aF, aBoxF); // - Standard_Integer i = aMFaces.Add(aF, aBoxF); + Standard_Integer i = aMFaces.Add (aF, aBoxF); // - aTreeFiller.Add(i, aBoxF); + aBBTree.Add(i, Bnd_Tools::Bnd2BVH(aBoxF)); } - // - // shake tree filler - aTreeFiller.Fill(); - // - // get faces with interfering bounding boxes - aItL.Initialize(SetOfFaces); - for (; aItL.More(); aItL.Next()) { - const TopoDS_Face& aF1 = TopoDS::Face(aItL.Value()); - const Bnd_Box& aBoxF1 = aMFaces.FindFromKey(aF1); - // - BOPTools_BoxBndTreeSelector aSelector; - aSelector.SetBox(aBoxF1); - aBBTree.Select(aSelector); - // - const TColStd_ListOfInteger& aLI = aSelector.Indices(); - TColStd_ListIteratorOfListOfInteger aItLI(aLI); - for (; aItLI.More(); aItLI.Next()) { - Standard_Integer i = aItLI.Value(); - const TopoDS_Face& aF2 = TopoDS::Face(aMFaces.FindKey(i)); - // - // intersect faces - FaceInter(aF1, aF2, InitOffsetFace); - } + + // Build BVH + aBBTree.Build(); + + // Perform selection of the pairs + BOPTools_BoxPairSelector aSelector; + aSelector.SetBVHSets (&aBBTree, &aBBTree); + aSelector.SetSame (Standard_True); + aSelector.Select(); + aSelector.Sort(); + + // Treat the selected pairs + const std::vector& aPairs = aSelector.Pairs(); + const Standard_Integer aNbPairs = static_cast (aPairs.size()); + + for (Standard_Integer iPair = 0; iPair < aNbPairs; ++iPair) + { + const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair]; + + const TopoDS_Face& aF1 = TopoDS::Face (aMFaces.FindKey (Min (aPair.ID1, aPair.ID2))); + const TopoDS_Face& aF2 = TopoDS::Face (aMFaces.FindKey (Max (aPair.ID1, aPair.ID2))); + + // intersect faces + FaceInter(aF1, aF2, InitOffsetFace); } } - //======================================================================= //function : FaceInter //purpose : Performs intersection of the given faces diff --git a/src/IntPolyh/IntPolyh_MaillageAffinage.cxx b/src/IntPolyh/IntPolyh_MaillageAffinage.cxx index a0f7958673..bcc580f34a 100644 --- a/src/IntPolyh/IntPolyh_MaillageAffinage.cxx +++ b/src/IntPolyh/IntPolyh_MaillageAffinage.cxx @@ -27,6 +27,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -42,16 +46,14 @@ #include #include #include -#include -#include #include #include typedef NCollection_Array1 IntPolyh_ArrayOfInteger; typedef NCollection_IndexedDataMap IntPolyh_IndexedDataMapOfIntegerArrayOfInteger; + TColStd_ListOfInteger, + TColStd_MapIntegerHasher> IntPolyh_IndexedDataMapOfIntegerListOfInteger; static Standard_Real MyTolerance=10.0e-7; @@ -133,32 +135,82 @@ static Standard_Integer& aI2); //======================================================================= -//class : IntPolyh_BoxBndTreeSelector -//purpose : Select interfering bounding boxes +//class : IntPolyh_BoxBndTree +//purpose : BVH structure to contain the boxes of triangles //======================================================================= -typedef NCollection_UBTree IntPolyh_BoxBndTree; -class IntPolyh_BoxBndTreeSelector : public IntPolyh_BoxBndTree::Selector { - public: - IntPolyh_BoxBndTreeSelector(const Bnd_Box& theBox) : myBox(theBox) {} - // - virtual Standard_Boolean Reject(const Bnd_Box& theOther) const +typedef BVH_BoxSet IntPolyh_BoxBndTree; + +//======================================================================= +//class : IntPolyh_BoxBndTreeSelector +//purpose : Selector of interfering boxes +//======================================================================= +class IntPolyh_BoxBndTreeSelector : + public BVH_PairTraverse +{ +public: + typedef BVH_Box::BVH_VecNt BVH_Vec3d; + + //! Auxiliary structure to keep the pair of indices + struct PairIDs { - return myBox.IsOut(theOther); - } - // - virtual Standard_Boolean Accept(const Standard_Integer &theInd) + PairIDs (const Standard_Integer theId1 = -1, + const Standard_Integer theId2 = -1) + : ID1 (theId1), ID2 (theId2) + {} + + Standard_Boolean operator< (const PairIDs& theOther) const + { + return ID1 < theOther.ID1 || + (ID1 == theOther.ID1 && ID2 < theOther.ID2); + } + + Standard_Integer ID1; + Standard_Integer ID2; + }; + +public: + + //! Constructor + IntPolyh_BoxBndTreeSelector () + {} + + //! Rejects the node + virtual Standard_Boolean RejectNode (const BVH_Vec3d& theCMin1, + const BVH_Vec3d& theCMax1, + const BVH_Vec3d& theCMin2, + const BVH_Vec3d& theCMax2, + Standard_Real&) const Standard_OVERRIDE { - myIndices.Append(theInd); - return Standard_True; + return BVH_Box (theCMin1, theCMax1).IsOut (theCMin2, theCMax2); } - // - const TColStd_ListOfInteger& Indices() const + + //! Accepts the element + virtual Standard_Boolean Accept (const Standard_Integer theID1, + const Standard_Integer theID2) Standard_OVERRIDE { - return myIndices; + if (!myBVHSet1->Box (theID1).IsOut (myBVHSet2->Box (theID2))) + { + myPairs.push_back (PairIDs (myBVHSet1->Element (theID1), myBVHSet2->Element (theID2))); + return Standard_True; + } + return Standard_False; } - private: - Bnd_Box myBox; - TColStd_ListOfInteger myIndices; + + //! Returns indices + const std::vector& Pairs() const + { + return myPairs; + } + + //! Sorts the resulting indices + void Sort() + { + std::sort (myPairs.begin(), myPairs.end()); + } + +private: + + std::vector myPairs; }; //======================================================================= @@ -170,59 +222,57 @@ static const IntPolyh_ArrayOfPoints& thePoints1, IntPolyh_ArrayOfTriangles& theTriangles2, const IntPolyh_ArrayOfPoints& thePoints2, - IntPolyh_IndexedDataMapOfIntegerArrayOfInteger& theCouples) + IntPolyh_IndexedDataMapOfIntegerListOfInteger& theCouples) { - // To find the triangles with interfering bounding boxes - // use the algorithm of unbalanced binary tree of overlapping bounding boxes - IntPolyh_BoxBndTree aBBTree; - NCollection_UBTreeFiller aTreeFiller(aBBTree); - // 1. Fill the tree with the boxes of the triangles from second surface - Standard_Integer i, aNbT2 = theTriangles2.NbItems(); - Standard_Boolean bAdded = Standard_False; - for (i = 0; i < aNbT2; ++i) { - IntPolyh_Triangle& aT = theTriangles2[i]; - if (!aT.IsIntersectionPossible() || aT.IsDegenerated()) { - continue; - } - // - const Bnd_Box& aBox = aT.BoundingBox(thePoints2); - aTreeFiller.Add(i, aBox); - bAdded = Standard_True; - } - // - if (!bAdded) - // Intersection is not possible for all triangles in theTriangles2 - return; + // Use linear builder for BVH construction + opencascade::handle> aLBuilder = + new BVH_LinearBuilder (10); - // 2. Shake the tree filler - aTreeFiller.Fill(); - // - // 3. Find boxes interfering with the first triangles - Standard_Integer aNbT1 = theTriangles1.NbItems(); - for (i = 0; i < aNbT1; ++i) { - IntPolyh_Triangle& aT = theTriangles1[i]; - if (!aT.IsIntersectionPossible() || aT.IsDegenerated()) { - continue; + // To find the triangles with interfering bounding boxes + // use the BVH structure + IntPolyh_BoxBndTree aBBTree1 (aLBuilder), aBBTree2 (aLBuilder); + + // 1. Fill the trees with the boxes of the surfaces triangles + for (Standard_Integer i = 0; i < 2; ++i) + { + IntPolyh_BoxBndTree &aBBTree = !i ? aBBTree1 : aBBTree2; + IntPolyh_ArrayOfTriangles& aTriangles = !i ? theTriangles1 : theTriangles2; + const IntPolyh_ArrayOfPoints& aPoints = !i ? thePoints1 : thePoints2; + + const Standard_Integer aNbT = aTriangles.NbItems(); + aBBTree.SetSize (aNbT); + for (Standard_Integer j = 0; j < aNbT; ++j) + { + IntPolyh_Triangle& aT = aTriangles[j]; + if (!aT.IsIntersectionPossible() || aT.IsDegenerated()) + continue; + + aBBTree.Add (j, Bnd_Tools::Bnd2BVH (aT.BoundingBox(aPoints))); } - // - const Bnd_Box& aBox = aT.BoundingBox(thePoints1); - // - IntPolyh_BoxBndTreeSelector aSelector(aBox); - if (!aBBTree.Select(aSelector)) { - continue; - } - // - const TColStd_ListOfInteger& aLI = aSelector.Indices(); - // Sort the indices - IntPolyh_ArrayOfInteger anArr(1, aLI.Extent()); - TColStd_ListIteratorOfListOfInteger aItLI(aLI); - for (Standard_Integer j = 1; aItLI.More(); aItLI.Next(), ++j) { - anArr(j) = aItLI.Value(); - } - // - std::sort(anArr.begin(), anArr.end()); - // - theCouples.Add(i, anArr); + + if (!aBBTree.Size()) + return; + } + // 2. Construct BVH trees + aBBTree1.Build(); + aBBTree2.Build(); + + // 3. Perform selection of the interfering triangles + IntPolyh_BoxBndTreeSelector aSelector; + aSelector.SetBVHSets (&aBBTree1, &aBBTree2); + aSelector.Select(); + aSelector.Sort(); + + const std::vector& aPairs = aSelector.Pairs(); + const Standard_Integer aNbPairs = static_cast(aPairs.size()); + + for (Standard_Integer i = 0; i < aNbPairs; ++i) + { + const IntPolyh_BoxBndTreeSelector::PairIDs& aPair = aPairs[i]; + TColStd_ListOfInteger* pTriangles2 = theCouples.ChangeSeek (aPair.ID1); + if (!pTriangles2) + pTriangles2 = &theCouples( theCouples.Add (aPair.ID1, TColStd_ListOfInteger())); + pTriangles2->Append (aPair.ID2); } } @@ -921,7 +971,7 @@ static const Standard_Real theFlecheCritique2) { // Find the intersecting triangles - IntPolyh_IndexedDataMapOfIntegerArrayOfInteger aDMILI; + IntPolyh_IndexedDataMapOfIntegerListOfInteger aDMILI; GetInterferingTriangles(theTriangles1, thePoints1, theTriangles2, thePoints2, aDMILI); // // Interfering triangles of second surface @@ -938,8 +988,8 @@ static continue; } // - const IntPolyh_ArrayOfInteger *pLI = aDMILI.Seek(i_S1); - if (!pLI || !pLI->Length()) { + const TColStd_ListOfInteger *pLI = aDMILI.Seek(i_S1); + if (!pLI || pLI->IsEmpty()) { // Mark non-interfering triangles of S1 to avoid their repeated usage aTriangle1.SetIntersectionPossible(Standard_False); continue; @@ -949,7 +999,7 @@ static aTriangle1.MiddleRefinement(i_S1, theS1, thePoints1, theTriangles1, theEdges1); } // - IntPolyh_ArrayOfInteger::Iterator Iter(*pLI); + TColStd_ListOfInteger::Iterator Iter(*pLI); for (; Iter.More(); Iter.Next()) { Standard_Integer i_S2 = Iter.Value(); if (aMIntS2.Add(i_S2)) { @@ -2295,7 +2345,7 @@ Standard_Integer IntPolyh_MaillageAffinage::TriangleEdgeContact Standard_Integer IntPolyh_MaillageAffinage::TriangleCompare () { // Find couples with interfering bounding boxes - IntPolyh_IndexedDataMapOfIntegerArrayOfInteger aDMILI; + IntPolyh_IndexedDataMapOfIntegerListOfInteger aDMILI; GetInterferingTriangles(TTriangles1, TPoints1, TTriangles2, TPoints2, aDMILI); @@ -2314,8 +2364,8 @@ Standard_Integer IntPolyh_MaillageAffinage::TriangleCompare () const IntPolyh_Point& P2 = TPoints1[Triangle1.SecondPoint()]; const IntPolyh_Point& P3 = TPoints1[Triangle1.ThirdPoint()]; // - const IntPolyh_ArrayOfInteger& aLI2 = aDMILI(i); - IntPolyh_ArrayOfInteger::Iterator aItLI(aLI2); + const TColStd_ListOfInteger& aLI2 = aDMILI(i); + TColStd_ListOfInteger::Iterator aItLI(aLI2); for (; aItLI.More(); aItLI.Next()) { const Standard_Integer i_S2 = aItLI.Value(); IntPolyh_Triangle &Triangle2 = TTriangles2[i_S2];