1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-09-03 14:10:33 +03:00

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.
This commit is contained in:
emv
2019-04-18 15:34:37 +03:00
committed by bugmaster
parent 0616aa9ecf
commit 9324aa2d0d
21 changed files with 805 additions and 653 deletions

View File

@@ -25,7 +25,7 @@
#include <BOPDS_PaveBlock.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_AlgoTools2D.hxx>
#include <BOPTools_BoxBndTree.hxx>
#include <BOPTools_BoxTree.hxx>
#include <BOPTools_Parallel.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
@@ -33,6 +33,7 @@
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepLib.hxx>
#include <Bnd_Tools.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <gp_Circ.hxx>
@@ -45,7 +46,6 @@
#include <gp_Vec.hxx>
#include <IntTools_Context.hxx>
#include <NCollection_IncAllocator.hxx>
#include <NCollection_UBTreeFiller.hxx>
#include <NCollection_Vector.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
@@ -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_TNV> 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 <Standard_Integer,
Bnd_Box> 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<BOPTools_BoxPairSelector::PairIDs>& aPairs = aPairSelector.Pairs();
const Standard_Integer aNbPairs = static_cast<Standard_Integer> (aPairs.size());
// Collect interfering pairs
Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
NCollection_IndexedDataMap<Standard_Integer, TColStd_ListOfInteger> aMILI (1, anAlloc);
for (Standard_Integer iPair = 0; iPair < aNbPairs; ++iPair)
{
const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair];
BOPAlgo_Tools::FillMap<Standard_Integer, TColStd_MapIntegerHasher> (aPair.ID1, aPair.ID2, aMILI, anAlloc);
}
NCollection_List<TColStd_ListOfInteger> aBlocks (anAlloc);
BOPAlgo_Tools::MakeBlocks<Standard_Integer, TColStd_MapIntegerHasher> (aMILI, aBlocks, anAlloc);
NCollection_List<TColStd_ListOfInteger>::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 <Standard_Integer, Bnd_Box> 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);
}