Salome HOME
21948: EDF SMESH : Memory is not freed when deleting a mesh
authoreap <eap@opencascade.com>
Fri, 14 Dec 2012 13:36:23 +0000 (13:36 +0000)
committereap <eap@opencascade.com>
Fri, 14 Dec 2012 13:36:23 +0000 (13:36 +0000)
Optimize ElementsOnShape for large meshes

src/Controls/SMESH_Controls.cxx
src/Controls/SMESH_ControlsDef.hxx

index 3e44afe282f09f0a2c53c05b5466a46986c87f9d..0c33a0078df8b743219a24fed7a87b90d0621df9 100644 (file)
@@ -3671,23 +3671,11 @@ ElementsOnShape::ElementsOnShape()
     myToler(Precision::Confusion()),
     myAllNodesFlag(false)
 {
-  myCurShapeType = TopAbs_SHAPE;
 }
 
 ElementsOnShape::~ElementsOnShape()
 {
-}
-
-void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
-{
-  myMeshModifTracer.SetMesh( theMesh );
-  if ( myMeshModifTracer.IsMeshModified())
-    SetShape(myShape, myType);
-}
-
-bool ElementsOnShape::IsSatisfy (long theElementId)
-{
-  return myIds.Contains(theElementId);
+  clearClassifiers();
 }
 
 SMDSAbs_ElementType ElementsOnShape::GetType() const
@@ -3710,169 +3698,161 @@ double ElementsOnShape::GetTolerance() const
 
 void ElementsOnShape::SetAllNodes (bool theAllNodes)
 {
-  if (myAllNodesFlag != theAllNodes) {
-    myAllNodesFlag = theAllNodes;
-    SetShape(myShape, myType);
-  }
+  myAllNodesFlag = theAllNodes;
+}
+
+void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
+{
+  myMesh = theMesh;
 }
 
 void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
                                 const SMDSAbs_ElementType theType)
 {
-  myType = theType;
+  myType  = theType;
   myShape = theShape;
-  myIds.Clear();
-
-  const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
+  if ( myShape.IsNull() ) return;
   
-  if ( !myMesh ) return;
-
-  myIds.ReSize( myMeshModifTracer.GetMesh()->GetMeshInfo().NbElements( myType ));
+  TopTools_IndexedMapOfShape shapesMap;
+  TopAbs_ShapeEnum shapeTypes[4] = { TopAbs_SOLID, TopAbs_FACE, TopAbs_EDGE, TopAbs_VERTEX };
+  TopExp_Explorer sub;
+  for ( int i = 0; i < 4; ++i )
+  {
+    if ( shapesMap.IsEmpty() )
+      for ( sub.Init( myShape, shapeTypes[i] ); sub.More(); sub.Next() )
+        shapesMap.Add( sub.Current() );
+    if ( i > 0 )
+      for ( sub.Init( myShape, shapeTypes[i], shapeTypes[i-1] ); sub.More(); sub.Next() )
+        shapesMap.Add( sub.Current() );
+  }
 
-  myShapesMap.Clear();
-  addShape(myShape);
+  clearClassifiers();
+  myClassifiers.resize( shapesMap.Extent() );
+  for ( int i = 0; i < shapesMap.Extent(); ++i )
+    myClassifiers[ i ] = new TClassifier( shapesMap( i+1 ), myToler );
 }
 
-void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
+void ElementsOnShape::clearClassifiers()
 {
-  if (theShape.IsNull() || myMeshModifTracer.GetMesh() == 0)
-    return;
+  for ( size_t i = 0; i < myClassifiers.size(); ++i )
+    delete myClassifiers[ i ];
+  myClassifiers.clear();
+}
 
-  if (!myShapesMap.Add(theShape)) return;
+bool ElementsOnShape::IsSatisfy (long elemId)
+{
+  const SMDS_MeshElement* elem =
+    ( myType == SMDSAbs_Node ? myMesh->FindNode( elemId ) : myMesh->FindElement( elemId ));
+  if ( !elem || myClassifiers.empty() )
+    return false;
 
-  myCurShapeType = theShape.ShapeType();
-  switch (myCurShapeType)
+  for ( size_t i = 0; i < myClassifiers.size(); ++i )
   {
-  case TopAbs_COMPOUND:
-  case TopAbs_COMPSOLID:
-  case TopAbs_SHELL:
-  case TopAbs_WIRE:
+    SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator();
+    bool isSatisfy = myAllNodesFlag;
+    
+    gp_XYZ centerXYZ (0, 0, 0);
+
+    while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
     {
-      TopoDS_Iterator anIt (theShape, Standard_True, Standard_True);
-      for (; anIt.More(); anIt.Next()) addShape(anIt.Value());
+      SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
+      centerXYZ += aPnt;
+      isSatisfy = ! myClassifiers[i]->IsOut( aPnt );
     }
-    break;
-  case TopAbs_SOLID:
+
+    // Check the center point for volumes MantisBug 0020168
+    if (isSatisfy && myClassifiers[i]->ShapeType() == TopAbs_SOLID)
     {
-      myCurSC.Load(theShape);
-      process();
+      centerXYZ /= elem->NbNodes();
+      isSatisfy = ! myClassifiers[i]->IsOut( centerXYZ );
     }
+    if ( isSatisfy )
+      return true;
+  }
+
+  return false;
+}
+
+TopAbs_ShapeEnum ElementsOnShape::TClassifier::ShapeType() const
+{
+  return myShape.ShapeType();
+}
+
+bool ElementsOnShape::TClassifier::IsOut(const gp_Pnt& p)
+{
+  return (this->*myIsOutFun)( p );
+}
+
+void ElementsOnShape::TClassifier::Init (const TopoDS_Shape& theShape, double theTol)
+{
+  myShape = theShape;
+  myTol   = theTol;
+  switch ( myShape.ShapeType() )
+  {
+  case TopAbs_SOLID: {
+    mySolidClfr.Load(theShape);
+    myIsOutFun = & ElementsOnShape::TClassifier::isOutOfSolid;
     break;
-  case TopAbs_FACE:
-    {
-      TopoDS_Face aFace = TopoDS::Face(theShape);
-      BRepAdaptor_Surface SA (aFace, true);
-      Standard_Real
-        u1 = SA.FirstUParameter(),
-        u2 = SA.LastUParameter(),
-        v1 = SA.FirstVParameter(),
-        v2 = SA.LastVParameter();
-      Handle(Geom_Surface) surf = BRep_Tool::Surface(aFace);
-      myCurProjFace.Init(surf, u1,u2, v1,v2);
-      myCurFace = aFace;
-      process();
-    }
+  }
+  case TopAbs_FACE:  {
+    Standard_Real u1,u2,v1,v2;
+    Handle(Geom_Surface) surf = BRep_Tool::Surface( TopoDS::Face( theShape ));
+    surf->Bounds( u1,u2,v1,v2 );
+    myProjFace.Init(surf, u1,u2, v1,v2, myTol );
+    myIsOutFun = & ElementsOnShape::TClassifier::isOutOfFace;
     break;
-  case TopAbs_EDGE:
-    {
-      TopoDS_Edge anEdge = TopoDS::Edge(theShape);
-      Standard_Real u1, u2;
-      Handle(Geom_Curve) curve = BRep_Tool::Curve(anEdge, u1, u2);
-      myCurProjEdge.Init(curve, u1, u2);
-      process();
-    }
+  }
+  case TopAbs_EDGE:  {
+    Standard_Real u1, u2;
+    Handle(Geom_Curve) curve = BRep_Tool::Curve( TopoDS::Edge(theShape), u1, u2);
+    myProjEdge.Init(curve, u1, u2);
+    myIsOutFun = & ElementsOnShape::TClassifier::isOutOfEdge;
     break;
-  case TopAbs_VERTEX:
-    {
-      TopoDS_Vertex aV = TopoDS::Vertex(theShape);
-      myCurPnt = BRep_Tool::Pnt(aV);
-      process();
-    }
+  }
+  case TopAbs_VERTEX:{
+    myVertexXYZ = BRep_Tool::Pnt( TopoDS::Vertex( theShape ) );
+    myIsOutFun = & ElementsOnShape::TClassifier::isOutOfVertex;
     break;
+  }
   default:
-    break;
+    throw SALOME_Exception("Programmer error in usage of ElementsOnShape::TClassifier");
   }
 }
 
-void ElementsOnShape::process()
+bool ElementsOnShape::TClassifier::isOutOfSolid (const gp_Pnt& p)
 {
-  const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
-  if (myShape.IsNull() || myMesh == 0)
-    return;
-
-  SMDS_ElemIteratorPtr anIter = myMesh->elementsIterator(myType);
-  while (anIter->more())
-    process(anIter->next());
+  mySolidClfr.Perform( p, myTol );
+  return ( mySolidClfr.State() != TopAbs_IN && mySolidClfr.State() != TopAbs_ON );
 }
 
-void ElementsOnShape::process (const SMDS_MeshElement* theElemPtr)
+bool ElementsOnShape::TClassifier::isOutOfFace  (const gp_Pnt& p)
 {
-  if (myShape.IsNull())
-    return;
-
-  SMDS_ElemIteratorPtr aNodeItr = theElemPtr->nodesIterator();
-  bool isSatisfy = myAllNodesFlag;
-
-  gp_XYZ centerXYZ (0, 0, 0);
-
-  while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
+  myProjFace.Perform( p );
+  if ( myProjFace.IsDone() && myProjFace.LowerDistance() <= myTol );
   {
-    SMESH_TNodeXYZ aPnt ( aNodeItr->next() );
-    centerXYZ += aPnt;
-
-    switch (myCurShapeType)
-    {
-    case TopAbs_SOLID:
-      {
-        myCurSC.Perform(aPnt, myToler);
-        isSatisfy = (myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON);
-      }
-      break;
-    case TopAbs_FACE:
-      {
-        myCurProjFace.Perform(aPnt);
-        isSatisfy = (myCurProjFace.IsDone() && myCurProjFace.LowerDistance() <= myToler);
-        if (isSatisfy)
-        {
-          // check relatively the face
-          Quantity_Parameter u, v;
-          myCurProjFace.LowerDistanceParameters(u, v);
-          gp_Pnt2d aProjPnt (u, v);
-          BRepClass_FaceClassifier aClsf (myCurFace, aProjPnt, myToler);
-          isSatisfy = (aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON);
-        }
-      }
-      break;
-    case TopAbs_EDGE:
-      {
-        myCurProjEdge.Perform(aPnt);
-        isSatisfy = (myCurProjEdge.NbPoints() > 0 && myCurProjEdge.LowerDistance() <= myToler);
-      }
-      break;
-    case TopAbs_VERTEX:
-      {
-        isSatisfy = (myCurPnt.Distance(aPnt) <= myToler);
-      }
-      break;
-    default:
-      {
-        isSatisfy = false;
-      }
-    }
+    // check relatively to the face
+    Quantity_Parameter u, v;
+    myProjFace.LowerDistanceParameters(u, v);
+    gp_Pnt2d aProjPnt (u, v);
+    BRepClass_FaceClassifier aClsf ( TopoDS::Face( myShape ), aProjPnt, myTol );
+    if ( aClsf.State() == TopAbs_IN || aClsf.State() == TopAbs_ON )
+      return false;
   }
+  return true;
+}
 
-  if (isSatisfy && myCurShapeType == TopAbs_SOLID) { // Check the center point for volumes MantisBug 0020168
-    centerXYZ /= theElemPtr->NbNodes();
-    gp_Pnt aCenterPnt (centerXYZ);
-    myCurSC.Perform(aCenterPnt, myToler);
-    if ( !(myCurSC.State() == TopAbs_IN || myCurSC.State() == TopAbs_ON))
-      isSatisfy = false;
-  }
+bool ElementsOnShape::TClassifier::isOutOfEdge  (const gp_Pnt& p)
+{
+  myProjEdge.Perform( p );
+  return ! ( myProjEdge.NbPoints() > 0 && myProjEdge.LowerDistance() <= myTol );
+}
 
-  if (isSatisfy)
-    myIds.Add(theElemPtr->GetID());
+bool ElementsOnShape::TClassifier::isOutOfVertex(const gp_Pnt& p)
+{
+  return ( myVertexXYZ.Distance( p ) > myTol );
 }
 
+
 TSequenceOfXYZ::TSequenceOfXYZ()
 {}
 
index 587f5b6d609bf79b6c09b933764aaaf81758953b..a0e984cddc92adf1fb7227c9bbe7b213578d78d4 100644 (file)
@@ -820,25 +820,36 @@ namespace SMESH{
                         const SMDSAbs_ElementType theType);
 
     private:
-      void    addShape (const TopoDS_Shape& theShape);
-      void    process();
-      void    process (const SMDS_MeshElement* theElem);
 
-    private:
-      TMeshModifTracer      myMeshModifTracer;
-      TColStd_MapOfInteger  myIds;
-      SMDSAbs_ElementType   myType;
-      TopoDS_Shape          myShape;
-      double                myToler;
-      bool                  myAllNodesFlag;
-
-      TopTools_MapOfShape         myShapesMap;
-      TopAbs_ShapeEnum            myCurShapeType; // type of current sub-shape
-      BRepClass3d_SolidClassifier myCurSC;        // current SOLID
-      GeomAPI_ProjectPointOnSurf  myCurProjFace;  // current FACE
-      TopoDS_Face                 myCurFace;      // current FACE
-      GeomAPI_ProjectPointOnCurve myCurProjEdge;  // current EDGE
-      gp_Pnt                      myCurPnt;       // current VERTEX
+      struct TClassifier
+      {
+        TClassifier(const TopoDS_Shape& s, double tol) { Init(s,tol); }
+        void Init(const TopoDS_Shape& s, double tol);
+        bool IsOut(const gp_Pnt& p);
+        TopAbs_ShapeEnum ShapeType() const;
+      private:
+        bool isOutOfSolid (const gp_Pnt& p);
+        bool isOutOfFace  (const gp_Pnt& p);
+        bool isOutOfEdge  (const gp_Pnt& p);
+        bool isOutOfVertex(const gp_Pnt& p);
+
+        bool (TClassifier::* myIsOutFun)(const gp_Pnt& p);
+        BRepClass3d_SolidClassifier mySolidClfr;
+        GeomAPI_ProjectPointOnSurf  myProjFace;
+        GeomAPI_ProjectPointOnCurve myProjEdge;
+        gp_Pnt                      myVertexXYZ;
+        TopoDS_Shape                myShape;
+        double                      myTol;
+      };
+      void clearClassifiers();
+
+      std::vector< TClassifier* > myClassifiers;
+      const SMDS_Mesh*            myMesh;
+      SMDSAbs_ElementType         myType;
+      TopoDS_Shape                myShape;
+      double                      myToler;
+      bool                        myAllNodesFlag;
+
     };
 
     typedef boost::shared_ptr<ElementsOnShape> ElementsOnShapePtr;