0030670: Modeling Algorithms - Performance improvement of Boolean Operations algorithm
authoremv <emv@opencascade.com>
Tue, 23 Apr 2019 09:31:23 +0000 (12:31 +0300)
committerbugmaster <bugmaster@opencascade.com>
Fri, 24 May 2019 07:33:23 +0000 (10:33 +0300)
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.

src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
src/BOPDS/BOPDS_DS.cxx
src/BOPDS/BOPDS_DS.hxx
src/BRepClass/BRepClass_FaceClassifier.cxx
src/BRepClass/BRepClass_FaceExplorer.cxx
src/BRepClass/BRepClass_FaceExplorer.hxx
src/BRepClass/BRepClass_Intersector.cxx
src/IntTools/IntTools_FClass2d.cxx
src/IntTools/IntTools_FClass2d.hxx
tests/perf/modalg/bug30670 [new file with mode: 0644]

index 5a8aa81..c6b43cf 100644 (file)
@@ -469,12 +469,8 @@ void BOPAlgo_PaveFiller::PerformEF()
   PerformNewVertices(aMVCPB, aAllocator, Standard_False);
   //
   // Update FaceInfoIn for all faces having EF common parts
-  TColStd_MapIteratorOfMapOfInteger aItMI;
-  aItMI.Initialize(aMIEFC);
-  for (; aItMI.More(); aItMI.Next()) {
-    nF=aItMI.Value();
-    myDS->UpdateFaceInfoIn(nF);
-  }
+  myDS->UpdateFaceInfoIn (aMIEFC);
+
   //-----------------------------------------------------scope t
   aMIEFC.Clear();
   aMVCPB.Clear();
index 7cfdeea..871d738 100644 (file)
@@ -200,36 +200,18 @@ void BOPAlgo_PaveFiller::PerformFF()
   for (; myIterator->More(); myIterator->Next()) {
     myIterator->Value(nF1, nF2);
 
-    // Update/Initialize FaceInfo structure for first face
-    if (myDS->HasFaceInfo(nF1))
-    {
-      if (aMIFence.Add(nF1))
-      {
-        myDS->UpdateFaceInfoOn(nF1);
-        myDS->UpdateFaceInfoIn(nF1);
-      }
-    }
-    else if (myDS->HasInterfShapeSubShapes(nF2, nF1))
-    {
-      myDS->ChangeFaceInfo(nF1);
-      aMIFence.Add(nF1);
-    }
+    aMIFence.Add (nF1);
+    aMIFence.Add (nF2);
+  }
+  // Update face info
+  myDS->UpdateFaceInfoOn (aMIFence);
+  myDS->UpdateFaceInfoIn (aMIFence);
+
+  // Initialize interferences
+  myIterator->Initialize(TopAbs_FACE, TopAbs_FACE);
+  for (; myIterator->More(); myIterator->Next()) {
+    myIterator->Value(nF1, nF2);
 
-    // 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)
     {
       const TopoDS_Face& aF1 = (*(TopoDS_Face *)(&myDS->Shape(nF1)));
index b547175..aefaeee 100644 (file)
@@ -1203,10 +1203,34 @@ void BOPDS_DS::InitFaceInfo(const Standard_Integer theI)
   aSI.SetReference(iRef);
   //
   aFI.SetIndex(theI);
-  UpdateFaceInfoIn(theI);
+  InitFaceInfoIn(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
 //purpose  : 
 //=======================================================================
@@ -1357,6 +1381,105 @@ void BOPDS_DS::FaceInfoIn(const Standard_Integer theF,
 }
 
 //=======================================================================
+//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
 //purpose  : 
 //=======================================================================
index d51d775..418a4b9 100644 (file)
@@ -274,10 +274,14 @@ Standard_EXPORT virtual ~BOPDS_DS();
   //! Update the state In of face with index 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
   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
   //! Returns the state On
@@ -479,6 +483,10 @@ protected:
 
   //! Initializes the state of face with index 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);
   
index 8d1ba8c..b593eb0 100644 (file)
@@ -97,7 +97,7 @@ void  BRepClass_FaceClassifier::Perform(const TopoDS_Face& aF,
   aMaxDist=RealLast();
   aIndice=0;
   //
-  BRepAdaptor_Surface aSurf(aF);
+  BRepAdaptor_Surface aSurf(aF, Standard_False);
   BRepTools::UVBounds(aF, aU1, aU2, aV1, aV2);
   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);
   }
 }
-
-
-
-
-
-
-
index 3fb9b5b..b2255c4 100644 (file)
@@ -40,45 +40,61 @@ static const Standard_Real Probing_Step = 0.2111;
 BRepClass_FaceExplorer::BRepClass_FaceExplorer(const TopoDS_Face& F) :
        myFace(F),
        myCurEdgeInd(1),
-       myCurEdgePar(Probing_Start)
+       myCurEdgePar(Probing_Start),
+       myUMin (Precision::Infinite()),
+       myUMax (-Precision::Infinite()),
+       myVMin (Precision::Infinite()),
+       myVMax (-Precision::Infinite())
 {
   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
 //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;
-  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))
+  if (myUMin > myUMax)
   {
-    BRepTools::UVBounds(myFace, anUMin, anUMax, aVMin, aVMax);
-    if (Precision::IsInfinite(anUMin) || Precision::IsInfinite(anUMax) ||
-        Precision::IsInfinite(aVMin) || Precision::IsInfinite(aVMax))
-    {
-      return Standard_True;
-    }
+    ComputeFaceBounds();
+  }
+
+  if (Precision::IsInfinite(myUMin) || Precision::IsInfinite(myUMax) ||
+      Precision::IsInfinite(myVMin) || Precision::IsInfinite(myVMax))
+  {
+    return Standard_True;
   }
 
-  gp_Pnt2d aCenterPnt(( anUMin + anUMax ) / 2, ( aVMin + aVMax ) / 2);
+  gp_Pnt2d aCenterPnt(( myUMin + myUMax ) / 2, ( myVMin + myVMax ) / 2);
   Standard_Real aDistance = aCenterPnt.Distance(thePoint);
   if (Precision::IsInfinite(aDistance))
   {
-    thePoint.SetCoord(anUMin - ( anUMax - anUMin ),
-                       aVMin - ( aVMax - aVMin ));
+    thePoint.SetCoord (myUMin - (myUMax - myUMin ),
+                       myVMin - (myVMax - myVMin ));
     return Standard_False;
   }
   else
   {
     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_Dir2d aLinDir(aLinVec);
index 3e404b8..bdb14b1 100644 (file)
@@ -99,8 +99,8 @@ public:
 
 protected:
 
-
-
+  //! Computes UV bounds of a face
+  Standard_EXPORT void ComputeFaceBounds();
 
 
 private:
@@ -113,7 +113,10 @@ private:
   Standard_Integer myCurEdgeInd;
   Standard_Real myCurEdgePar;
 
-
+  Standard_Real myUMin;
+  Standard_Real myUMax;
+  Standard_Real myVMin;
+  Standard_Real myVMax;
 };
 
 
index 847d877..a141f56 100644 (file)
@@ -37,7 +37,7 @@
 
 static 
 void RefineTolerance(const TopoDS_Face& aF,
-                     const BRepAdaptor_Curve2d& aC,
+                     const Geom2dAdaptor_Curve& aC,
                      const Standard_Real aT,
                      Standard_Real& aTolZ);
 
@@ -72,7 +72,7 @@ void  BRepClass_Intersector::Perform(const gp_Lin2d& L,
     return;
   }
   //
-  BRepAdaptor_Curve2d C(EE, F);
+  Geom2dAdaptor_Curve C(aC2D, deb, fin);
   //
   deb = C.FirstParameter();
   fin = C.LastParameter();
@@ -185,7 +185,7 @@ void  BRepClass_Intersector::LocalGeometry(const BRepClass_Edge& E,
 //purpose  : 
 //=======================================================================
 void RefineTolerance(const TopoDS_Face& aF,
-                     const BRepAdaptor_Curve2d& aC,
+                     const Geom2dAdaptor_Curve& aC,
                      const Standard_Real aT,
                      Standard_Real& aTolZ)
 {
index 33833d9..49dd72b 100644 (file)
@@ -67,7 +67,7 @@ IntTools_FClass2d::IntTools_FClass2d()
 //=======================================================================
 IntTools_FClass2d::IntTools_FClass2d(const TopoDS_Face& aFace,
                                     const Standard_Real TolUV) 
-: Toluv(TolUV), Face(aFace)  
+: Toluv(TolUV), Face(aFace)
 {
   Init(Face, Toluv);
 }
@@ -662,8 +662,12 @@ TopAbs_State IntTools_FClass2d::Perform
        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();
     }
     
@@ -779,8 +783,12 @@ TopAbs_State IntTools_FClass2d::TestOnRestriction
       }
     }
     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();
     }
     
index 1d0b0a4..bc838fd 100644 (file)
 #include <Standard_DefineAlloc.hxx>
 #include <Standard_Handle.hxx>
 
+#include <BRepClass_FaceExplorer.hxx>
 #include <BRepTopAdaptor_SeqOfPtr.hxx>
 #include <TColStd_SequenceOfInteger.hxx>
 #include <Standard_Real.hxx>
 #include <TopoDS_Face.hxx>
 #include <Standard_Boolean.hxx>
 #include <TopAbs_State.hxx>
+#include <memory>
+
 class TopoDS_Face;
 class gp_Pnt2d;
 
-
 //! Class provides an algorithm to classify a 2d Point
 //! in 2d space of face using boundaries of the face.
 class IntTools_FClass2d 
@@ -108,6 +110,15 @@ private:
   Standard_Real Vmax;
   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
 
 };
 
diff --git a/tests/perf/modalg/bug30670 b/tests/perf/modalg/bug30670
new file mode 100644 (file)
index 0000000..ab2d39e
--- /dev/null
@@ -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