Salome HOME
Quality Info: tolerance change does not influence on Nb double nodes
[modules/smesh.git] / src / Controls / SMESH_Controls.cxx
index f18cadd34e8b27efae988682a905489a7b505afc..06c40dae2ad9c8b21d5ec8098df9528899d990c8 100644 (file)
@@ -2436,6 +2436,15 @@ SMDSAbs_ElementType CoincidentNodes::GetType() const
   return SMDSAbs_Node;
 }
 
+void CoincidentNodes::SetTolerance( const double theToler )
+{
+  if ( myToler != theToler )
+  {
+    SetMesh(0);
+    myToler = theToler;
+  }
+}
+
 void CoincidentNodes::SetMesh( const SMDS_Mesh* theMesh )
 {
   myMeshModifTracer.SetMesh( theMesh );
@@ -2565,18 +2574,14 @@ void FreeEdges::SetMesh( const SMDS_Mesh* theMesh )
 
 bool FreeEdges::IsFreeEdge( const SMDS_MeshNode** theNodes, const int theFaceId  )
 {
-  TColStd_MapOfInteger aMap;
-  for ( int i = 0; i < 2; i++ )
+  SMDS_ElemIteratorPtr anElemIter = theNodes[ 0 ]->GetInverseElementIterator(SMDSAbs_Face);
+  while( anElemIter->more() )
   {
-    SMDS_ElemIteratorPtr anElemIter = theNodes[ i ]->GetInverseElementIterator(SMDSAbs_Face);
-    while( anElemIter->more() )
+    if ( const SMDS_MeshElement* anElem = anElemIter->next())
     {
-      if ( const SMDS_MeshElement* anElem = anElemIter->next())
-      {
-        const int anId = anElem->GetID();
-        if ( anId != theFaceId && !aMap.Add( anId ))
-          return false;
-      }
+      const int anId = anElem->GetID();
+      if ( anId != theFaceId && anElem->GetNodeIndex( theNodes[1] ) >= 0 )
+        return false;
     }
   }
   return true;
@@ -4242,6 +4247,7 @@ struct ElementsOnShape::Classifier
   TopAbs_ShapeEnum ShapeType() const { return myShape.ShapeType(); }
   const TopoDS_Shape& Shape() const  { return myShape; }
   const Bnd_B3d* GetBndBox() const   { return & myBox; }
+  double Tolerance() const           { return myTol; }
   bool IsChecked()                   { return myFlags & theIsCheckedFlag; }
   bool IsSetFlag( int flag ) const   { return myFlags & flag; }
   void SetChecked( bool is ) { is ? SetFlag( theIsCheckedFlag ) : UnsetFlag( theIsCheckedFlag ); }
@@ -4275,6 +4281,8 @@ struct ElementsOnShape::OctreeClassifier : public SMESH_Octree
                     std::vector< ElementsOnShape::Classifier >&       cls );
   void GetClassifiersAtPoint( const gp_XYZ& p,
                               std::vector< ElementsOnShape::Classifier* >& classifiers );
+  size_t GetSize();
+
 protected:
   OctreeClassifier() {}
   SMESH_Octree* newChild() const { return new OctreeClassifier; }
@@ -4300,6 +4308,21 @@ ElementsOnShape::~ElementsOnShape()
 
 Predicate* ElementsOnShape::clone() const
 {
+  size_t size = sizeof( *this );
+  if ( myOctree )
+    size += myOctree->GetSize();
+  if ( !myClassifiers.empty() )
+    size += sizeof( myClassifiers[0] ) * myClassifiers.size();
+  if ( !myWorkClassifiers.empty() )
+    size += sizeof( myWorkClassifiers[0] ) * myWorkClassifiers.size();
+  if ( size > 1e+9 ) // 1G
+  {
+#ifdef _DEBUG_
+    std::cout << "Avoid ElementsOnShape::clone(), too large: " << size << " bytes " << std::endl;
+#endif
+    return 0;
+  }
+
   ElementsOnShape* cln = new ElementsOnShape();
   cln->SetAllNodes ( myAllNodesFlag );
   cln->SetTolerance( myToler );
@@ -4456,12 +4479,13 @@ bool ElementsOnShape::IsSatisfy (const SMDS_MeshElement* elem)
     for ( size_t i = 0; i < myClassifiers.size(); ++i )
       myWorkClassifiers[ i ] = & myClassifiers[ i ];
     myOctree = new OctreeClassifier( myWorkClassifiers );
+
+    SMESHUtils::FreeVector( myWorkClassifiers );
   }
 
-  SMDS_ElemIteratorPtr aNodeItr = elem->nodesIterator();
-  while (aNodeItr->more() && (isSatisfy == myAllNodesFlag))
+  for ( int i = 0, nb = elem->NbNodes(); i < nb  && (isSatisfy == myAllNodesFlag); ++i )
   {
-    SMESH_TNodeXYZ aPnt( aNodeItr->next() );
+    SMESH_TNodeXYZ aPnt( elem->GetNode( i ));
     centerXYZ += aPnt;
 
     isNodeOut = true;
@@ -4627,7 +4651,15 @@ void ElementsOnShape::Classifier::Init( const TopoDS_Shape& theShape,
     else
     {
       Bnd_Box box;
-      BRepBndLib::Add( myShape, box );
+      if ( myShape.ShapeType() == TopAbs_FACE )
+      {
+        BRepAdaptor_Surface SA( TopoDS::Face( myShape ), /*useBoundaries=*/false );
+        if ( SA.GetType() == GeomAbs_BSplineSurface )
+          BRepBndLib::AddOptimal( myShape, box,
+                                  /*useTriangulation=*/true, /*useShapeTolerance=*/true );
+      }
+      if ( box.IsVoid() )
+        BRepBndLib::Add( myShape, box );
       myBox.Clear();
       myBox.Add( box.CornerMin() );
       myBox.Add( box.CornerMax() );
@@ -4647,19 +4679,19 @@ ElementsOnShape::Classifier::~Classifier()
   delete mySolidClfr; mySolidClfr = 0;
 }
 
-bool ElementsOnShape::Classifier::isOutOfSolid (const gp_Pnt& p)
+bool ElementsOnShape::Classifier::isOutOfSolid( const gp_Pnt& p )
 {
   if ( isOutOfBox( p )) return true;
   mySolidClfr->Perform( p, myTol );
   return ( mySolidClfr->State() != TopAbs_IN && mySolidClfr->State() != TopAbs_ON );
 }
 
-bool ElementsOnShape::Classifier::isOutOfBox (const gp_Pnt& p)
+bool ElementsOnShape::Classifier::isOutOfBox( const gp_Pnt& p )
 {
   return myBox.IsOut( p.XYZ() );
 }
 
-bool ElementsOnShape::Classifier::isOutOfFace  (const gp_Pnt& p)
+bool ElementsOnShape::Classifier::isOutOfFace( const gp_Pnt& p )
 {
   if ( isOutOfBox( p )) return true;
   myProjFace.Perform( p );
@@ -4676,19 +4708,19 @@ bool ElementsOnShape::Classifier::isOutOfFace  (const gp_Pnt& p)
   return true;
 }
 
-bool ElementsOnShape::Classifier::isOutOfEdge  (const gp_Pnt& p)
+bool ElementsOnShape::Classifier::isOutOfEdge( const gp_Pnt& p )
 {
   if ( isOutOfBox( p )) return true;
   myProjEdge.Perform( p );
   return ! ( myProjEdge.NbPoints() > 0 && myProjEdge.LowerDistance() <= myTol );
 }
 
-bool ElementsOnShape::Classifier::isOutOfVertex(const gp_Pnt& p)
+bool ElementsOnShape::Classifier::isOutOfVertex( const gp_Pnt& p )
 {
   return ( myVertexXYZ.Distance( p ) > myTol );
 }
 
-bool ElementsOnShape::Classifier::isBox (const TopoDS_Shape& theShape)
+bool ElementsOnShape::Classifier::isBox(const TopoDS_Shape& theShape )
 {
   TopTools_IndexedMapOfShape vMap;
   TopExp::MapShapes( theShape, TopAbs_VERTEX, vMap );
@@ -4770,6 +4802,19 @@ OctreeClassifier::GetClassifiersAtPoint( const gp_XYZ& point,
   }
 }
 
+size_t ElementsOnShape::OctreeClassifier::GetSize()
+{
+  size_t res = sizeof( *this );
+  if ( !myClassifiers.empty() )
+    res += sizeof( myClassifiers[0] ) * myClassifiers.size();
+
+  if ( !isLeaf() )
+    for (int i = 0; i < nbChildren(); i++)
+      res += ((OctreeClassifier*) myChildren[i])->GetSize();
+
+  return res;
+}
+
 void ElementsOnShape::OctreeClassifier::buildChildrenData()
 {
   // distribute myClassifiers among myChildren
@@ -4816,7 +4861,8 @@ void ElementsOnShape::OctreeClassifier::buildChildrenData()
   for ( int i = 0; i < nbChildren(); i++ )
   {
     OctreeClassifier* child = static_cast<OctreeClassifier*>( myChildren[ i ]);
-    child->myIsLeaf = ( child->myClassifiers.size() <= 5  );
+    child->myIsLeaf = ( child->myClassifiers.size() <= 5  ||
+                        child->maxSize() < child->myClassifiers[0]->Tolerance() );
   }
 }
 
@@ -4843,8 +4889,13 @@ BelongToGeom::BelongToGeom()
 
 Predicate* BelongToGeom::clone() const
 {
-  BelongToGeom* cln = new BelongToGeom( *this );
-  cln->myElementsOnShapePtr.reset( static_cast<ElementsOnShape*>( myElementsOnShapePtr->clone() ));
+  BelongToGeom* cln = 0;
+  if ( myElementsOnShapePtr )
+    if ( ElementsOnShape* eos = static_cast<ElementsOnShape*>( myElementsOnShapePtr->clone() ))
+    {
+      cln = new BelongToGeom( *this );
+      cln->myElementsOnShapePtr.reset( eos );
+    }
   return cln;
 }
 
@@ -4855,6 +4906,8 @@ void BelongToGeom::SetMesh( const SMDS_Mesh* theMesh )
     myMeshDS = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
     init();
   }
+  if ( myElementsOnShapePtr )
+    myElementsOnShapePtr->SetMesh( myMeshDS );
 }
 
 void BelongToGeom::SetGeom( const TopoDS_Shape& theShape )
@@ -5014,8 +5067,13 @@ LyingOnGeom::LyingOnGeom()
 
 Predicate* LyingOnGeom::clone() const
 {
-  LyingOnGeom* cln = new LyingOnGeom( *this );
-  cln->myElementsOnShapePtr.reset( static_cast<ElementsOnShape*>( myElementsOnShapePtr->clone() ));
+  LyingOnGeom* cln = 0;
+  if ( myElementsOnShapePtr )
+    if ( ElementsOnShape* eos = static_cast<ElementsOnShape*>( myElementsOnShapePtr->clone() ))
+    {
+      cln = new LyingOnGeom( *this );
+      cln->myElementsOnShapePtr.reset( eos );
+    }
   return cln;
 }
 
@@ -5026,6 +5084,8 @@ void LyingOnGeom::SetMesh( const SMDS_Mesh* theMesh )
     myMeshDS = dynamic_cast<const SMESHDS_Mesh*>(theMesh);
     init();
   }
+  if ( myElementsOnShapePtr )
+    myElementsOnShapePtr->SetMesh( myMeshDS );
 }
 
 void LyingOnGeom::SetGeom( const TopoDS_Shape& theShape )