1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-06-30 12:14:08 +03:00

0030670: Modeling Algorithms - Performance improvement of Boolean Operations algorithm

The following improvements have been made in Boolean operations algorithm:
1. Added possibility to update FaceInfo structure for many faces at once which helps to avoid nested loops.
2. Improve Point-Face classification procedure by caching the FaceExplorer for a face.
This commit is contained in:
emv 2019-04-23 12:31:23 +03:00 committed by bugmaster
parent a4d594cbda
commit 47cd8af2d2
11 changed files with 246 additions and 74 deletions

View File

@ -469,12 +469,8 @@ void BOPAlgo_PaveFiller::PerformEF()
PerformNewVertices(aMVCPB, aAllocator, Standard_False); PerformNewVertices(aMVCPB, aAllocator, Standard_False);
// //
// Update FaceInfoIn for all faces having EF common parts // Update FaceInfoIn for all faces having EF common parts
TColStd_MapIteratorOfMapOfInteger aItMI; myDS->UpdateFaceInfoIn (aMIEFC);
aItMI.Initialize(aMIEFC);
for (; aItMI.More(); aItMI.Next()) {
nF=aItMI.Value();
myDS->UpdateFaceInfoIn(nF);
}
//-----------------------------------------------------scope t //-----------------------------------------------------scope t
aMIEFC.Clear(); aMIEFC.Clear();
aMVCPB.Clear(); aMVCPB.Clear();

View File

@ -200,36 +200,18 @@ void BOPAlgo_PaveFiller::PerformFF()
for (; myIterator->More(); myIterator->Next()) { for (; myIterator->More(); myIterator->Next()) {
myIterator->Value(nF1, nF2); myIterator->Value(nF1, nF2);
// Update/Initialize FaceInfo structure for first face aMIFence.Add (nF1);
if (myDS->HasFaceInfo(nF1)) aMIFence.Add (nF2);
{ }
if (aMIFence.Add(nF1)) // Update face info
{ myDS->UpdateFaceInfoOn (aMIFence);
myDS->UpdateFaceInfoOn(nF1); myDS->UpdateFaceInfoIn (aMIFence);
myDS->UpdateFaceInfoIn(nF1);
} // Initialize interferences
} myIterator->Initialize(TopAbs_FACE, TopAbs_FACE);
else if (myDS->HasInterfShapeSubShapes(nF2, nF1)) for (; myIterator->More(); myIterator->Next()) {
{ myIterator->Value(nF1, nF2);
myDS->ChangeFaceInfo(nF1);
aMIFence.Add(nF1);
}
// Update/Initialize FaceInfo structure for second face
if (myDS->HasFaceInfo(nF2))
{
if (aMIFence.Add(nF2))
{
myDS->UpdateFaceInfoOn(nF2);
myDS->UpdateFaceInfoIn(nF2);
}
}
else if (myDS->HasInterfShapeSubShapes(nF1, nF2))
{
myDS->ChangeFaceInfo(nF2);
aMIFence.Add(nF2);
}
//
if (myGlue == BOPAlgo_GlueOff) if (myGlue == BOPAlgo_GlueOff)
{ {
const TopoDS_Face& aF1 = (*(TopoDS_Face *)(&myDS->Shape(nF1))); const TopoDS_Face& aF1 = (*(TopoDS_Face *)(&myDS->Shape(nF1)));

View File

@ -1203,9 +1203,33 @@ void BOPDS_DS::InitFaceInfo(const Standard_Integer theI)
aSI.SetReference(iRef); aSI.SetReference(iRef);
// //
aFI.SetIndex(theI); aFI.SetIndex(theI);
UpdateFaceInfoIn(theI); InitFaceInfoIn(theI);
UpdateFaceInfoOn(theI); UpdateFaceInfoOn(theI);
} }
//=======================================================================
//function : InitFaceInfoIn
//purpose :
//=======================================================================
void BOPDS_DS::InitFaceInfoIn (const Standard_Integer theI)
{
BOPDS_ShapeInfo& aSI = ChangeShapeInfo (theI);
if (aSI.HasReference())
{
BOPDS_FaceInfo& aFI = myFaceInfoPool (aSI.Reference());
const TopoDS_Shape& aF = Shape (theI);
for (TopoDS_Iterator itS (aF); itS.More(); itS.Next())
{
const TopoDS_Shape& aV = itS.Value();
if (aV.ShapeType() == TopAbs_VERTEX)
{
Standard_Integer nV = Index (aV);
HasShapeSD (nV, nV);
aFI.ChangeVerticesIn().Add (nV);
}
}
}
}
//======================================================================= //=======================================================================
//function : UpdateFaceInfoIn //function : UpdateFaceInfoIn
//purpose : //purpose :
@ -1356,6 +1380,105 @@ void BOPDS_DS::FaceInfoIn(const Standard_Integer theF,
}// for (i=0; i<aNbEF; ++i) { }// for (i=0; i<aNbEF; ++i) {
} }
//=======================================================================
//function : UpdateFaceInfoIn
//purpose :
//=======================================================================
void BOPDS_DS::UpdateFaceInfoIn (const TColStd_MapOfInteger& theFaces)
{
for (TColStd_MapOfInteger::Iterator itM (theFaces); itM.More(); itM.Next())
{
const Standard_Integer nF = itM.Value();
BOPDS_ShapeInfo& aSI = ChangeShapeInfo (nF);
if (!aSI.HasReference())
{
myFaceInfoPool.Appended().SetIndex (nF);
aSI.SetReference (myFaceInfoPool.Length() - 1);
}
BOPDS_FaceInfo& aFI = myFaceInfoPool (aSI.Reference());
aFI.ChangePaveBlocksIn().Clear();
aFI.ChangeVerticesIn().Clear();
// 1. Add pure internal vertices on the face
InitFaceInfoIn (nF);
}
// 2. Analyze Vertex-Face interferences
BOPDS_VectorOfInterfVF& aVFs = InterfVF();
const Standard_Integer aNbVF = aVFs.Length();
for (Standard_Integer iVF = 0; iVF < aNbVF; ++iVF)
{
BOPDS_InterfVF& aVF = aVFs (iVF);
const Standard_Integer nF = aVF.Index2();
if (theFaces.Contains (nF))
{
Standard_Integer nV = aVF.Index1();
HasShapeSD (nV, nV);
myFaceInfoPool (ShapeInfo (nF).Reference()).ChangeVerticesIn().Add (nV);
}
}
//
// 3. Analyze Edge-Face interferences
BOPDS_VectorOfInterfEF& aEFs = InterfEF();
const Standard_Integer aNbEF = aEFs.Length();
for (Standard_Integer iEF = 0; iEF < aNbEF; ++iEF)
{
BOPDS_InterfEF& aEF = aEFs (iEF);
const Standard_Integer nF = aEF.Index2();
if (theFaces.Contains (nF))
{
BOPDS_FaceInfo& aFI = myFaceInfoPool (ShapeInfo (nF).Reference());
Standard_Integer nVNew;
if (aEF.HasIndexNew (nVNew))
{
HasShapeSD (nVNew, nVNew);
aFI.ChangeVerticesIn().Add (nVNew);
}
else
{
const Standard_Integer nE = aEF.Index1();
const BOPDS_ListOfPaveBlock& aLPB = PaveBlocks (nE);
for (BOPDS_ListOfPaveBlock::Iterator itPB (aLPB); itPB.More(); itPB.Next())
{
const Handle(BOPDS_PaveBlock)& aPB = itPB.Value();
const Handle(BOPDS_CommonBlock)& aCB = CommonBlock (aPB);
if (!aCB.IsNull())
{
if (aCB->Contains (nF))
{
const Handle(BOPDS_PaveBlock)& aPBR = aCB->PaveBlock1();
aFI.ChangePaveBlocksIn().Add(aPBR);
}
}
}
}
}
}
}
//=======================================================================
//function : UpdateFaceInfoOn
//purpose :
//=======================================================================
void BOPDS_DS::UpdateFaceInfoOn (const TColStd_MapOfInteger& theFaces)
{
for (TColStd_MapOfInteger::Iterator itM (theFaces); itM.More(); itM.Next())
{
const Standard_Integer nF = itM.Value();
BOPDS_ShapeInfo& aSI = ChangeShapeInfo (nF);
if (!aSI.HasReference())
{
myFaceInfoPool.Appended().SetIndex (nF);
aSI.SetReference (myFaceInfoPool.Length() - 1);
}
BOPDS_FaceInfo& aFI = myFaceInfoPool (aSI.Reference());
aFI.ChangePaveBlocksOn().Clear();
aFI.ChangeVerticesOn().Clear();
FaceInfoOn (nF, aFI.ChangePaveBlocksOn(), aFI.ChangeVerticesOn());
}
}
//======================================================================= //=======================================================================
//function : RefineFaceInfoOn //function : RefineFaceInfoOn
//purpose : //purpose :

View File

@ -274,10 +274,14 @@ Standard_EXPORT virtual ~BOPDS_DS();
//! Update the state In of face with index theIndex //! Update the state In of face with index theIndex
Standard_EXPORT void UpdateFaceInfoIn (const Standard_Integer theIndex); Standard_EXPORT void UpdateFaceInfoIn (const Standard_Integer theIndex);
//! Update the state IN for all faces in the given map
Standard_EXPORT void UpdateFaceInfoIn (const TColStd_MapOfInteger& theFaces);
//! Update the state On of face with index theIndex //! Update the state On of face with index theIndex
Standard_EXPORT void UpdateFaceInfoOn (const Standard_Integer theIndex); Standard_EXPORT void UpdateFaceInfoOn (const Standard_Integer theIndex);
//! Update the state ON for all faces in the given map
Standard_EXPORT void UpdateFaceInfoOn (const TColStd_MapOfInteger& theFaces);
//! Selector //! Selector
//! Returns the state On //! Returns the state On
@ -479,6 +483,10 @@ protected:
//! Initializes the state of face with index theIndex //! Initializes the state of face with index theIndex
Standard_EXPORT void InitFaceInfo (const Standard_Integer theIndex); Standard_EXPORT void InitFaceInfo (const Standard_Integer theIndex);
//! Initializes the FaceInfo structure for face with index theIndex with elements
//! having IN state for the face
Standard_EXPORT void InitFaceInfoIn (const Standard_Integer theIndex);
Standard_EXPORT void InitShape (const Standard_Integer theIndex, const TopoDS_Shape& theS); Standard_EXPORT void InitShape (const Standard_Integer theIndex, const TopoDS_Shape& theS);

View File

@ -97,7 +97,7 @@ void BRepClass_FaceClassifier::Perform(const TopoDS_Face& aF,
aMaxDist=RealLast(); aMaxDist=RealLast();
aIndice=0; aIndice=0;
// //
BRepAdaptor_Surface aSurf(aF); BRepAdaptor_Surface aSurf(aF, Standard_False);
BRepTools::UVBounds(aF, aU1, aU2, aV1, aV2); BRepTools::UVBounds(aF, aU1, aU2, aV1, aV2);
aExtrema.Initialize(aSurf, aU1, aU2, aV1, aV2, aTol, aTol); aExtrema.Initialize(aSurf, aU1, aU2, aV1, aV2, aTol, aTol);
// //
@ -128,10 +128,3 @@ void BRepClass_FaceClassifier::Perform(const TopoDS_Face& aF,
Perform(aF, aPuv, aTol); Perform(aF, aPuv, aTol);
} }
} }

View File

@ -40,45 +40,61 @@ static const Standard_Real Probing_Step = 0.2111;
BRepClass_FaceExplorer::BRepClass_FaceExplorer(const TopoDS_Face& F) : BRepClass_FaceExplorer::BRepClass_FaceExplorer(const TopoDS_Face& F) :
myFace(F), myFace(F),
myCurEdgeInd(1), myCurEdgeInd(1),
myCurEdgePar(Probing_Start) myCurEdgePar(Probing_Start),
myUMin (Precision::Infinite()),
myUMax (-Precision::Infinite()),
myVMin (Precision::Infinite()),
myVMax (-Precision::Infinite())
{ {
myFace.Orientation(TopAbs_FORWARD); myFace.Orientation(TopAbs_FORWARD);
} }
//=======================================================================
//function : ComputeFaceBounds
//purpose :
//=======================================================================
void BRepClass_FaceExplorer::ComputeFaceBounds()
{
TopLoc_Location aLocation;
const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface (myFace, aLocation);
aSurface->Bounds (myUMin, myUMax, myVMin, myVMax);
if (Precision::IsInfinite (myUMin) || Precision::IsInfinite (myUMax) ||
Precision::IsInfinite (myVMin) || Precision::IsInfinite (myVMax))
{
BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax);
}
}
//======================================================================= //=======================================================================
//function : CheckPoint //function : CheckPoint
//purpose : //purpose :
//======================================================================= //=======================================================================
Standard_Boolean BRepClass_FaceExplorer::CheckPoint(gp_Pnt2d& thePoint) Standard_Boolean BRepClass_FaceExplorer::CheckPoint(gp_Pnt2d& thePoint)
{ {
Standard_Real anUMin = 0.0, anUMax = 0.0, aVMin = 0.0, aVMax = 0.0; if (myUMin > myUMax)
TopLoc_Location aLocation;
const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(myFace, aLocation);
aSurface->Bounds(anUMin, anUMax, aVMin, aVMax);
if (Precision::IsInfinite(anUMin) || Precision::IsInfinite(anUMax) ||
Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
{ {
BRepTools::UVBounds(myFace, anUMin, anUMax, aVMin, aVMax); ComputeFaceBounds();
if (Precision::IsInfinite(anUMin) || Precision::IsInfinite(anUMax) ||
Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
{
return Standard_True;
}
} }
gp_Pnt2d aCenterPnt(( anUMin + anUMax ) / 2, ( aVMin + aVMax ) / 2); if (Precision::IsInfinite(myUMin) || Precision::IsInfinite(myUMax) ||
Precision::IsInfinite(myVMin) || Precision::IsInfinite(myVMax))
{
return Standard_True;
}
gp_Pnt2d aCenterPnt(( myUMin + myUMax ) / 2, ( myVMin + myVMax ) / 2);
Standard_Real aDistance = aCenterPnt.Distance(thePoint); Standard_Real aDistance = aCenterPnt.Distance(thePoint);
if (Precision::IsInfinite(aDistance)) if (Precision::IsInfinite(aDistance))
{ {
thePoint.SetCoord(anUMin - ( anUMax - anUMin ), thePoint.SetCoord (myUMin - (myUMax - myUMin ),
aVMin - ( aVMax - aVMin )); myVMin - (myVMax - myVMin ));
return Standard_False; return Standard_False;
} }
else else
{ {
Standard_Real anEpsilon = Epsilon(aDistance); Standard_Real anEpsilon = Epsilon(aDistance);
if (anEpsilon > Max(anUMax - anUMin, aVMax - aVMin)) if (anEpsilon > Max (myUMax - myUMin, myVMax - myVMin))
{ {
gp_Vec2d aLinVec(aCenterPnt, thePoint); gp_Vec2d aLinVec(aCenterPnt, thePoint);
gp_Dir2d aLinDir(aLinVec); gp_Dir2d aLinDir(aLinVec);

View File

@ -99,8 +99,8 @@ public:
protected: protected:
//! Computes UV bounds of a face
Standard_EXPORT void ComputeFaceBounds();
private: private:
@ -113,7 +113,10 @@ private:
Standard_Integer myCurEdgeInd; Standard_Integer myCurEdgeInd;
Standard_Real myCurEdgePar; Standard_Real myCurEdgePar;
Standard_Real myUMin;
Standard_Real myUMax;
Standard_Real myVMin;
Standard_Real myVMax;
}; };

View File

@ -37,7 +37,7 @@
static static
void RefineTolerance(const TopoDS_Face& aF, void RefineTolerance(const TopoDS_Face& aF,
const BRepAdaptor_Curve2d& aC, const Geom2dAdaptor_Curve& aC,
const Standard_Real aT, const Standard_Real aT,
Standard_Real& aTolZ); Standard_Real& aTolZ);
@ -72,7 +72,7 @@ void BRepClass_Intersector::Perform(const gp_Lin2d& L,
return; return;
} }
// //
BRepAdaptor_Curve2d C(EE, F); Geom2dAdaptor_Curve C(aC2D, deb, fin);
// //
deb = C.FirstParameter(); deb = C.FirstParameter();
fin = C.LastParameter(); fin = C.LastParameter();
@ -185,7 +185,7 @@ void BRepClass_Intersector::LocalGeometry(const BRepClass_Edge& E,
//purpose : //purpose :
//======================================================================= //=======================================================================
void RefineTolerance(const TopoDS_Face& aF, void RefineTolerance(const TopoDS_Face& aF,
const BRepAdaptor_Curve2d& aC, const Geom2dAdaptor_Curve& aC,
const Standard_Real aT, const Standard_Real aT,
Standard_Real& aTolZ) Standard_Real& aTolZ)
{ {

View File

@ -67,7 +67,7 @@ IntTools_FClass2d::IntTools_FClass2d()
//======================================================================= //=======================================================================
IntTools_FClass2d::IntTools_FClass2d(const TopoDS_Face& aFace, IntTools_FClass2d::IntTools_FClass2d(const TopoDS_Face& aFace,
const Standard_Real TolUV) const Standard_Real TolUV)
: Toluv(TolUV), Face(aFace) : Toluv(TolUV), Face(aFace)
{ {
Init(Face, Toluv); Init(Face, Toluv);
} }
@ -662,8 +662,12 @@ TopAbs_State IntTools_FClass2d::Perform
aFCTol = (!bUIn) ? aURes : aVRes; aFCTol = (!bUIn) ? aURes : aVRes;
} }
// //
BRepClass_FaceClassifier aClassifier;
aClassifier.Perform(Face,Puv,aFCTol); if (myFExplorer.get() == NULL)
myFExplorer.reset (new BRepClass_FaceExplorer (Face));
BRepClass_FClassifier aClassifier;
aClassifier.Perform(*myFExplorer, Puv, aFCTol);
aStatus = aClassifier.State(); aStatus = aClassifier.State();
} }
@ -779,8 +783,12 @@ TopAbs_State IntTools_FClass2d::TestOnRestriction
} }
} }
else { //-- TabOrien(1)=-1 Wrong Wire else { //-- TabOrien(1)=-1 Wrong Wire
BRepClass_FaceClassifier aClassifier;
aClassifier.Perform(Face,Puv,Tol); if (myFExplorer.get() == NULL)
myFExplorer.reset (new BRepClass_FaceExplorer (Face));
BRepClass_FClassifier aClassifier;
aClassifier.Perform(*myFExplorer, Puv, Tol);
aStatus = aClassifier.State(); aStatus = aClassifier.State();
} }

View File

@ -21,16 +21,18 @@
#include <Standard_DefineAlloc.hxx> #include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx> #include <Standard_Handle.hxx>
#include <BRepClass_FaceExplorer.hxx>
#include <BRepTopAdaptor_SeqOfPtr.hxx> #include <BRepTopAdaptor_SeqOfPtr.hxx>
#include <TColStd_SequenceOfInteger.hxx> #include <TColStd_SequenceOfInteger.hxx>
#include <Standard_Real.hxx> #include <Standard_Real.hxx>
#include <TopoDS_Face.hxx> #include <TopoDS_Face.hxx>
#include <Standard_Boolean.hxx> #include <Standard_Boolean.hxx>
#include <TopAbs_State.hxx> #include <TopAbs_State.hxx>
#include <memory>
class TopoDS_Face; class TopoDS_Face;
class gp_Pnt2d; class gp_Pnt2d;
//! Class provides an algorithm to classify a 2d Point //! Class provides an algorithm to classify a 2d Point
//! in 2d space of face using boundaries of the face. //! in 2d space of face using boundaries of the face.
class IntTools_FClass2d class IntTools_FClass2d
@ -108,6 +110,15 @@ private:
Standard_Real Vmax; Standard_Real Vmax;
Standard_Boolean myIsHole; Standard_Boolean myIsHole;
#ifdef _MSC_VER
#if _MSC_VER < 1600
mutable std::auto_ptr<BRepClass_FaceExplorer> myFExplorer;
#else
mutable std::unique_ptr<BRepClass_FaceExplorer> myFExplorer;
#endif
#else
mutable std::unique_ptr<BRepClass_FaceExplorer> myFExplorer;
#endif
}; };

View File

@ -0,0 +1,32 @@
puts "==============================================================="
puts "0030670: Modeling Algorithms - Performance improvement of Boolean Operations algorithm"
puts "==============================================================="
puts ""
autodisplay 0
restore [locate_data_file bug30670_prisms.brep] c
bglue 1
bfuzzyvalue 0
set exp [explode c]
bclearobjects
bcleartools
baddobjects c_1
eval baddtools [lrange $exp 1 end]
dchrono fillds reset
dchrono fillds start
bfillds
dchrono fillds stop counter FILLER
dchrono fuse reset
dchrono fuse start
bbop result 1
dchrono fuse stop counter BUILDER
bglue 0
checknbshapes result -wire 12686 -face 12598 -shell 1 -solid 1 -t
checkprops result -s 1.34932e+06 -v 2.60155e+07
checkview -display result -2d -path ${imagedir}/${test_image}.png