Salome HOME
0021468]: EDF 2073 SMESH: Body-fitting algo creates elements in hole
[modules/smesh.git] / src / Controls / SMESH_Controls.cxx
index 072aea8e195915201162f2d336b484262ecb5075..26348e012c76e895c5526dc3f2bc8884188d2038 100644 (file)
@@ -18,7 +18,6 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
 
 #include "SMESH_ControlsDef.hxx"
 
@@ -66,6 +65,8 @@
 #include "SMESHDS_Mesh.hxx"
 #include "SMESHDS_GroupBase.hxx"
 
+#include "SMESH_OctreeNode.hxx"
+
 #include <vtkMeshQuality.h>
 
 /*
@@ -693,7 +694,7 @@ double MinimumAngle::GetValue( const TSequenceOfXYZ& P )
     aMin = Min(aMin,A0);
   }
 
-  return aMin * 180.0 / PI;
+  return aMin * 180.0 / M_PI;
 }
 
 double MinimumAngle::GetBadRate( double Value, int nbNodes ) const
@@ -1278,12 +1279,12 @@ double Warping::ComputeA( const gp_XYZ& thePnt1,
   gp_XYZ N  = GI.Crossed( GJ );
 
   if ( N.Modulus() < gp::Resolution() )
-    return PI / 2;
+    return M_PI / 2;
 
   N.Normalize();
 
   double H = ( thePnt2 - theG ).Dot( N );
-  return asin( fabs( H / L ) ) * 180. / PI;
+  return asin( fabs( H / L ) ) * 180. / M_PI;
 }
 
 double Warping::GetBadRate( double Value, int /*nbNodes*/ ) const
@@ -1362,14 +1363,14 @@ double Skew::GetValue( const TSequenceOfXYZ& P )
     return 0.;
 
   // Compute skew
-  static double PI2 = PI / 2.;
+  static double PI2 = M_PI / 2.;
   if ( P.size() == 3 )
   {
     double A0 = fabs( PI2 - skewAngle( P( 3 ), P( 1 ), P( 2 ) ) );
     double A1 = fabs( PI2 - skewAngle( P( 1 ), P( 2 ), P( 3 ) ) );
     double A2 = fabs( PI2 - skewAngle( P( 2 ), P( 3 ), P( 1 ) ) );
 
-    return Max( A0, Max( A1, A2 ) ) * 180. / PI;
+    return Max( A0, Max( A1, A2 ) ) * 180. / M_PI;
   }
   else
   {
@@ -1386,7 +1387,7 @@ double Skew::GetValue( const TSequenceOfXYZ& P )
     if ( A < Precision::Angular() )
       return 0.;
 
-    return A * 180. / PI;
+    return A * 180. / M_PI;
   }
 }
 
@@ -2024,10 +2025,11 @@ bool BareBorderFace::IsSatisfy(long theElementId )
         }
         if ( !isShared )
         {
-          myLinkNodes.resize( 2 + face->IsQuadratic());
+          const int iQuad = face->IsQuadratic();
+          myLinkNodes.resize( 2 + iQuad);
           myLinkNodes[0] = n1;
           myLinkNodes[1] = n2;
-          if ( face->IsQuadratic() )
+          if ( iQuad )
             myLinkNodes[2] = face->GetNode( i+nbN );
           ok = !myMesh->FindElement( myLinkNodes, SMDSAbs_Edge, /*noMedium=*/false);
         }
@@ -2090,6 +2092,106 @@ bool OverConstrainedFace::IsSatisfy(long theElementId )
   return false;
 }
 
+/*
+  Class       : CoincidentNodes
+  Description : Predicate of Coincident nodes
+*/
+
+CoincidentNodes::CoincidentNodes()
+{
+  myToler = 1e-5;
+}
+
+bool CoincidentNodes::IsSatisfy( long theElementId )
+{
+  return myCoincidentIDs.Contains( theElementId );
+}
+
+SMDSAbs_ElementType CoincidentNodes::GetType() const
+{
+  return SMDSAbs_Node;
+}
+
+void CoincidentNodes::SetMesh( const SMDS_Mesh* theMesh )
+{
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified() )
+  {
+    TIDSortedNodeSet nodesToCheck;
+    SMDS_NodeIteratorPtr nIt = theMesh->nodesIterator(/*idInceasingOrder=*/true);
+    while ( nIt->more() )
+      nodesToCheck.insert( nodesToCheck.end(), nIt->next() );
+
+    list< list< const SMDS_MeshNode*> > nodeGroups;
+    SMESH_OctreeNode::FindCoincidentNodes ( nodesToCheck, &nodeGroups, myToler );
+
+    myCoincidentIDs.Clear();
+    list< list< const SMDS_MeshNode*> >::iterator groupIt = nodeGroups.begin();
+    for ( ; groupIt != nodeGroups.end(); ++groupIt )
+    {
+      list< const SMDS_MeshNode*>& coincNodes = *groupIt;
+      list< const SMDS_MeshNode*>::iterator n = coincNodes.begin();
+      for ( ; n != coincNodes.end(); ++n )
+        myCoincidentIDs.Add( (*n)->GetID() );
+    }
+  }
+}
+
+/*
+  Class       : CoincidentElements
+  Description : Predicate of Coincident Elements
+  Note        : This class is suitable only for visualization of Coincident Elements
+*/
+
+CoincidentElements::CoincidentElements()
+{
+  myMesh = 0;
+}
+
+void CoincidentElements::SetMesh( const SMDS_Mesh* theMesh )
+{
+  myMesh = theMesh;
+}
+
+bool CoincidentElements::IsSatisfy( long theElementId )
+{
+  if ( !myMesh ) return false;
+
+  if ( const SMDS_MeshElement* e = myMesh->FindElement( theElementId ))
+  {
+    if ( e->GetType() != GetType() ) return false;
+    set< const SMDS_MeshNode* > elemNodes( e->begin_nodes(), e->end_nodes() );
+    const int nbNodes = e->NbNodes();
+    SMDS_ElemIteratorPtr invIt = (*elemNodes.begin())->GetInverseElementIterator( GetType() );
+    while ( invIt->more() )
+    {
+      const SMDS_MeshElement* e2 = invIt->next();
+      if ( e2 == e || e2->NbNodes() != nbNodes ) continue;
+
+      bool sameNodes = true;
+      for ( size_t i = 0; i < elemNodes.size() && sameNodes; ++i )
+        sameNodes = ( elemNodes.count( e2->GetNode( i )));
+      if ( sameNodes )
+        return true;
+    }
+  }
+  return false;
+}
+
+SMDSAbs_ElementType CoincidentElements1D::GetType() const
+{
+  return SMDSAbs_Edge;
+}
+SMDSAbs_ElementType CoincidentElements2D::GetType() const
+{
+  return SMDSAbs_Face;
+}
+SMDSAbs_ElementType CoincidentElements3D::GetType() const
+{
+  return SMDSAbs_Volume;
+}
+
+
 /*
   Class       : FreeBorders
   Description : Predicate for free borders
@@ -2565,28 +2667,31 @@ SMDSAbs_GeometryType ElemGeomType::GetGeomType() const
 //================================================================================
 
 CoplanarFaces::CoplanarFaces()
-  : myMesh(0), myFaceID(0), myToler(0)
+  : myFaceID(0), myToler(0)
 {
 }
-bool CoplanarFaces::IsSatisfy( long theElementId )
+void CoplanarFaces::SetMesh( const SMDS_Mesh* theMesh )
 {
-  if ( myCoplanarIDs.empty() )
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified() )
   {
     // Build a set of coplanar face ids
 
-    if ( !myMesh || !myFaceID || !myToler )
-      return false;
+    myCoplanarIDs.clear();
+
+    if ( !myMeshModifTracer.GetMesh() || !myFaceID || !myToler )
+      return;
 
-    const SMDS_MeshElement* face = myMesh->FindElement( myFaceID );
+    const SMDS_MeshElement* face = myMeshModifTracer.GetMesh()->FindElement( myFaceID );
     if ( !face || face->GetType() != SMDSAbs_Face )
-      return false;
+      return;
 
     bool normOK;
     gp_Vec myNorm = getNormale( static_cast<const SMDS_MeshFace*>(face), &normOK );
     if (!normOK)
-      return false;
+      return;
 
-    const double radianTol = myToler * PI180;
+    const double radianTol = myToler * M_PI / 180.;
     typedef SMDS_StdIterator< const SMDS_MeshElement*, SMDS_ElemIteratorPtr > TFaceIt;
     std::set<const SMDS_MeshElement*> checkedFaces, checkedNodes;
     std::list<const SMDS_MeshElement*> faceQueue( 1, face );
@@ -2613,6 +2718,9 @@ bool CoplanarFaces::IsSatisfy( long theElementId )
       faceQueue.pop_front();
     }
   }
+}
+bool CoplanarFaces::IsSatisfy( long theElementId )
+{
   return myCoplanarIDs.count( theElementId );
 }
 
@@ -3590,7 +3698,7 @@ bool ElementsOnSurface::isOnSurface( const SMDS_MeshNode* theNode )
 */
 
 ElementsOnShape::ElementsOnShape()
-  : myMesh(0),
+  : //myMesh(0),
     myType(SMDSAbs_All),
     myToler(Precision::Confusion()),
     myAllNodesFlag(false)
@@ -3604,10 +3712,9 @@ ElementsOnShape::~ElementsOnShape()
 
 void ElementsOnShape::SetMesh (const SMDS_Mesh* theMesh)
 {
-  if (myMesh != theMesh) {
-    myMesh = theMesh;
+  myMeshModifTracer.SetMesh( theMesh );
+  if ( myMeshModifTracer.IsMeshModified())
     SetShape(myShape, myType);
-  }
 }
 
 bool ElementsOnShape::IsSatisfy (long theElementId)
@@ -3648,7 +3755,9 @@ void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
   myShape = theShape;
   myIds.Clear();
 
-  if (myMesh == 0) return;
+  const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
+  
+  if ( !myMesh ) return;
 
   switch (myType)
   {
@@ -3677,7 +3786,7 @@ void ElementsOnShape::SetShape (const TopoDS_Shape&       theShape,
 
 void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
 {
-  if (theShape.IsNull() || myMesh == 0)
+  if (theShape.IsNull() || myMeshModifTracer.GetMesh() == 0)
     return;
 
   if (!myShapesMap.Add(theShape)) return;
@@ -3738,6 +3847,7 @@ void ElementsOnShape::addShape (const TopoDS_Shape& theShape)
 
 void ElementsOnShape::process()
 {
+  const SMDS_Mesh* myMesh = myMeshModifTracer.GetMesh();
   if (myShape.IsNull() || myMesh == 0)
     return;
 
@@ -3896,3 +4006,24 @@ TSequenceOfXYZ::size_type TSequenceOfXYZ::size() const
 {
   return myArray.size();
 }
+
+TMeshModifTracer::TMeshModifTracer():
+  myMeshModifTime(0), myMesh(0)
+{
+}
+void TMeshModifTracer::SetMesh( const SMDS_Mesh* theMesh )
+{
+  if ( theMesh != myMesh )
+    myMeshModifTime = 0;
+  myMesh = theMesh;
+}
+bool TMeshModifTracer::IsMeshModified()
+{
+  bool modified = false;
+  if ( myMesh )
+  {
+    modified = ( myMeshModifTime != myMesh->GetMTime() );
+    myMeshModifTime = myMesh->GetMTime();
+  }
+  return modified;
+}