Salome HOME
Fix regressions caused by improvements
authoreap <eap@opencascade.com>
Wed, 5 Aug 2015 17:59:31 +0000 (20:59 +0300)
committereap <eap@opencascade.com>
Wed, 5 Aug 2015 17:59:31 +0000 (20:59 +0300)
doc/salome/gui/SMESH/images/sew_after_merge.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/sew_using_merge.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/sewing_meshes.doc
src/SMESHDS/SMESHDS_SubMesh.cxx
src/SMESHDS/SMESHDS_SubMesh.hxx
src/SMESH_SWIG/smesh_algorithm.py
src/StdMeshers/StdMeshers_FaceSide.cxx
src/StdMeshers/StdMeshers_Projection_2D.cxx
src/StdMeshers/StdMeshers_Quadrangle_2D.cxx

diff --git a/doc/salome/gui/SMESH/images/sew_after_merge.png b/doc/salome/gui/SMESH/images/sew_after_merge.png
new file mode 100644 (file)
index 0000000..43d6869
Binary files /dev/null and b/doc/salome/gui/SMESH/images/sew_after_merge.png differ
diff --git a/doc/salome/gui/SMESH/images/sew_using_merge.png b/doc/salome/gui/SMESH/images/sew_using_merge.png
new file mode 100644 (file)
index 0000000..80cc44c
Binary files /dev/null and b/doc/salome/gui/SMESH/images/sew_using_merge.png differ
index ad5f15e..b7640f3 100644 (file)
@@ -53,8 +53,12 @@ the opposite border.
 In practice the borders to sew often coincide and in this case it is
 difficult to specify the first and the last nodes of a border since
 they coincide with the first and the last nodes of the other
-border. To cope with this, manually \ref merging_nodes_page to fuse
-each pair of coincident nodes into one.
+border. To cope with this,
+\ref merging_nodes_page "merge" coincident nodes into one
+beforehand. Two figures below illustrate this approach.
+\image html sew_using_merge.png "Merge coincident nodes which are difficult to distinguish"
+<br>
+\image html sew_after_merge.png "After merging nodes it is easy to specify border nodes"
 
 The sewing algorithm is as follows:
 <ol>
index f06ec6e..04a0021 100644 (file)
@@ -46,8 +46,6 @@ using namespace std;
 SMESHDS_SubMesh::SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index)
 {
   myParent = parent;
-  myElements.clear();
-  myNodes.clear();
   myIndex = index;
   myUnusedIdNodes = 0;
   myUnusedIdElements = 0;
@@ -65,61 +63,54 @@ SMESHDS_SubMesh::~SMESHDS_SubMesh()
 
 //=======================================================================
 //function : AddElement
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMESHDS_SubMesh::AddElement(const SMDS_MeshElement * ME)
 {
   if (!IsComplexSubmesh())
+  {
+    if ( ME->GetType() == SMDSAbs_Node )
+    {
+      AddNode( static_cast< const SMDS_MeshNode* >( ME ));
+      return;
+    }
+    int oldShapeId = ME->getshapeId();
+    if ( oldShapeId > 0 )
     {
-      if ( ME->GetType() == SMDSAbs_Node )
+      if (oldShapeId != myIndex)
       {
-        AddNode( static_cast< const SMDS_MeshNode* >( ME ));
-        return;
+        throw SALOME_Exception
+          (LOCALIZED("add element in subshape already belonging to a subshape"));
       }
-      int oldShapeId = ME->getshapeId();
-      if ( oldShapeId > 0 )
+      int idInSubShape = ME->getIdInShape();
+      if (idInSubShape >= 0)
+      {
+        MESSAGE("add element in subshape already belonging to that subshape "
+                << ME->GetID() << " " << oldShapeId << " " << idInSubShape);
+        // check if ok: do nothing if ok
+        if (idInSubShape >= myElements.size())
         {
-          if (oldShapeId != myIndex)
-            {
-              MESSAGE("add element in subshape already belonging to another subshape "
-                << ME->GetID() << " " << oldShapeId << " " << myIndex);
-              throw SALOME_Exception(LOCALIZED("add element in subshape already belonging to a subshape"));
-            }
-          else
-            {
-              int idInSubShape = ME->getIdInShape();
-              if (idInSubShape >= 0)
-                {
-                  MESSAGE("add element in subshape already belonging to that subshape "
-                      << ME->GetID() << " " << oldShapeId << " " << idInSubShape);
-                  // check if ok: do nothing if ok
-                  if (idInSubShape >= myElements.size())
-                    {
-                      MESSAGE("out of bounds " << idInSubShape << " " << myElements.size());
-                      throw SALOME_Exception(LOCALIZED("out of bounds"));
-                    }
-                  if (ME != myElements[idInSubShape])
-                    {
-                      MESSAGE("not the same element");
-                      throw SALOME_Exception(LOCALIZED("not the same element"));
-                    }
-                  MESSAGE("already done, OK, nothing to do");
-                  return;
-                }
-            }
+          throw SALOME_Exception(LOCALIZED("out of bounds"));
         }
-
-      SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
-      elem->setShapeId(myIndex);
-      elem->setIdInShape(myElements.size());
-      myElements.push_back(ME);
+        if (ME != myElements[idInSubShape])
+        {
+          throw SALOME_Exception(LOCALIZED("not the same element"));
+        }
+        return;
+      }
     }
+
+    SMDS_MeshElement* elem = (SMDS_MeshElement*) (ME);
+    elem->setShapeId(myIndex);
+    elem->setIdInShape(myElements.size());
+    myElements.push_back(ME);
+  }
 }
 
 //=======================================================================
 //function : RemoveElement
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool SMESHDS_SubMesh::RemoveElement(const SMDS_MeshElement * ME, bool isElemDeleted)
@@ -183,7 +174,7 @@ void SMESHDS_SubMesh::AddNode(const SMDS_MeshNode * N)
 
 //=======================================================================
 //function : RemoveNode
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool SMESHDS_SubMesh::RemoveNode(const SMDS_MeshNode * N, bool isNodeDeleted)
@@ -385,29 +376,52 @@ bool SMESHDS_SubMesh::Contains(const SMDS_MeshElement * ME) const
   if (!ME)
     return false;
 
-  if (IsComplexSubmesh())
-    {
-      set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
-      for (; aSubIt != mySubMeshes.end(); aSubIt++)
-        if ((*aSubIt)->Contains(ME))
-          return true;
-      return false;
-    }
+  if ( IsComplexSubmesh() )
+  {
+    set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
+    for (; aSubIt != mySubMeshes.end(); aSubIt++)
+      if ((*aSubIt)->Contains(ME))
+        return true;
+    return false;
+  }
 
   if (ME->GetType() == SMDSAbs_Node)
-    {
-      int idInShape = ME->getIdInShape();
-      if ((idInShape >= 0) && (idInShape < myNodes.size()))
-        if (myNodes[idInShape] == ME)
-          return true;
-    }
+  {
+    int idInShape = ME->getIdInShape();
+    if ((idInShape >= 0) && (idInShape < myNodes.size()))
+      if (myNodes[idInShape] == ME)
+        return true;
+  }
   else
-    {
-      int idInShape = ME->getIdInShape();
-      if ((idInShape >= 0) && (idInShape < myElements.size()))
-        if (myElements[idInShape] == ME)
-          return true;
-    }
+  {
+    int idInShape = ME->getIdInShape();
+    if ((idInShape >= 0) && (idInShape < myElements.size()))
+      if (myElements[idInShape] == ME)
+        return true;
+  }
+  return false;
+}
+
+//=======================================================================
+//function : IsQuadratic
+//purpose  : Return true if my 1st element is quadratic
+//=======================================================================
+
+bool SMESHDS_SubMesh::IsQuadratic() const
+{
+  if ( IsComplexSubmesh() )
+  {
+    set<const SMESHDS_SubMesh*>::const_iterator aSubIt = mySubMeshes.begin();
+    for (; aSubIt != mySubMeshes.end(); aSubIt++)
+      if ((*aSubIt)->IsQuadratic())
+        return true;
+    return false;
+  }
+
+  for ( size_t i = 0; i < myElements.size(); ++i )
+    if ( myElements[i] )
+      return myElements[i]->IsQuadratic();
+
   return false;
 }
 
index 3460b8c..c70857c 100644 (file)
@@ -67,19 +67,20 @@ class SMESHDS_EXPORT SMESHDS_SubMesh
   virtual int NbNodes() const;
   virtual SMDS_NodeIteratorPtr GetNodes() const;
   virtual bool Contains(const SMDS_MeshElement * ME) const;      // check if elem or node is in
+  virtual bool IsQuadratic() const;
 
   // clear the contents
   virtual void Clear();
-  int getSize();
+  int  getSize();
   void compactList();
 
   SMESHDS_Mesh* GetParent() const { return const_cast< SMESHDS_Mesh*>( myParent ); }
   int           GetID()     const { return myIndex; }
 
  private:
-  SMESHDS_Mesh * myParent;
+  SMESHDS_Mesh *                       myParent;
   std::vector<const SMDS_MeshElement*> myElements;
-  std::vector<const SMDS_MeshNode*> myNodes;
+  std::vector<const SMDS_MeshNode*>    myNodes;
 
   int myUnusedIdNodes;
   int myUnusedIdElements;
index df02724..9481ff1 100644 (file)
@@ -287,8 +287,11 @@ class Mesh_Algorithm:
         if not "ViscousLayers" in self.GetCompatibleHypothesis():
             raise TypeError, "ViscousLayers are not supported by %s"%self.algo.GetName()
         if faces and isinstance( faces[0], geomBuilder.GEOM._objref_GEOM_Object ):
-            import GEOM
-            faceIDs = [self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in faces]
+            faceIDs = []
+            for shape in faces:
+                ff = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["FACE"] )
+                for f in ff:
+                    faceIDs.append( self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f))
             faces = faceIDs
         hyp = self.Hypothesis("ViscousLayers",
                               [thickness, numberOfLayers, stretchFactor, faces, isFacesToIgnore],
@@ -320,7 +323,12 @@ class Mesh_Algorithm:
         if not "ViscousLayers2D" in self.GetCompatibleHypothesis():
             raise TypeError, "ViscousLayers2D are not supported by %s"%self.algo.GetName()
         if edges and isinstance( edges[0], geomBuilder.GEOM._objref_GEOM_Object ):
-            edges = [ self.mesh.geompyD.GetSubShapeID(self.mesh.geom, f) for f in edges ]
+            edgeIDs = []
+            for shape in edges:
+                ee = self.mesh.geompyD.SubShapeAll( shape, self.mesh.geompyD.ShapeType["EDGE"])
+                for e in ee:
+                    edgeIDs.append( self.mesh.geompyD.GetSubShapeID( self.mesh.geom, e ))
+            edges = edgeIDs
         hyp = self.Hypothesis("ViscousLayers2D",
                               [thickness, numberOfLayers, stretchFactor, edges, isEdgesToIgnore],
                               toAdd=False)
index 377a79c..d1d2024 100644 (file)
@@ -311,7 +311,9 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
 
     StdMeshers_FaceSide* me = const_cast< StdMeshers_FaceSide* >( this );
     SMESHDS_Mesh*    meshDS = myProxyMesh->GetMeshDS();
-    SMESH_MesherHelper helper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
+    fHelper.SetSubShape( myFace );
     bool paramOK;
     double eps = 1e-100;
 
@@ -346,7 +348,8 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
       const double  prevNormPar = ( iE == 0 ? 0 : myNormPar[ iE-1 ]); // normalized param
       if ( node ) // nodes on internal vertices may be missing
       {
-        if ( vertexNodes.insert( node ).second )
+        if ( vertexNodes.insert( node ).second ||
+             fHelper.IsRealSeam( node->getshapeId() ))
           u2node.insert( u2node.end(), make_pair( prevNormPar, node ));
       }
       else if ( iE == 0 )
@@ -373,12 +376,12 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
         u2nodeVec.clear();
         double paramSize = myLast[iE] - myFirst[iE];
         double r         = myNormPar[iE] - prevNormPar;
-        helper.SetSubShape( myEdge[iE] );
-        helper.ToFixNodeParameters( true );
+        eHelper.SetSubShape( myEdge[iE] );
+        eHelper.ToFixNodeParameters( true );
         if ( !myIsUniform[iE] )
           for ( size_t i = 0; i < nodes.size(); ++i )
           {
-            double     u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
+            double     u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
             double aLenU = GCPnts_AbscissaPoint::Length( me->myC3dAdaptor[iE], myFirst[iE], u );
             if ( myEdgeLength[iE] < aLenU ) // nonregression test "3D_mesh_NETGEN/G6"
             {
@@ -391,7 +394,7 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
         if ( u2nodeVec.empty() )
           for ( size_t i = 0; i < nodes.size(); ++i )
           {
-            double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
+            double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
             // paramSize is signed so orientation is taken into account
             double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize;
             u2nodeVec.push_back( make_pair( normPar, nodes[i] ));
@@ -401,10 +404,11 @@ const vector<UVPtStruct>& StdMeshers_FaceSide::GetUVPtStruct(bool   isXConst,
       }
     } // loop on myEdge's
 
-    if ( u2node.empty() ) return myPoints;
-
     // Add 2nd VERTEX node for a last EDGE
+    if ( !proxySubMesh.back() )
     {
+      if ( u2node.empty() ) return myPoints;
+
       const SMDS_MeshNode* node;
       if ( IsClosed() )
         node = u2node.begin()->second;
@@ -576,7 +580,9 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
     if ( NbEdges() == 0 ) return resultNodes;
 
     SMESHDS_Mesh* meshDS = myProxyMesh->GetMeshDS();
-    SMESH_MesherHelper helper(*myProxyMesh->GetMesh());
+    SMESH_MesherHelper eHelper( *myProxyMesh->GetMesh() );
+    SMESH_MesherHelper fHelper( *myProxyMesh->GetMesh() );
+    fHelper.SetSubShape( myFace );
     bool paramOK = true;
 
     // Sort nodes of all edges putting them into a map
@@ -606,7 +612,8 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
       // Add 1st vertex node of a current EDGE
       const SMDS_MeshNode* node = VertexNode( iE );
       if ( node ) { // nodes on internal vertices may be missing
-        if ( vertexNodes.insert( node ).second )
+        if ( vertexNodes.insert( node ).second ||
+             fHelper.IsRealSeam( node->getshapeId() ))
           u2node.insert( make_pair( prevNormPar, node ));
       }
       else if ( iE == 0 )
@@ -632,11 +639,11 @@ std::vector<const SMDS_MeshNode*> StdMeshers_FaceSide::GetOrderedNodes(int theEd
       {
         double paramSize = myLast[iE] - myFirst[iE];
         double r         = myNormPar[iE] - prevNormPar;
-        helper.SetSubShape( myEdge[iE] );
-        helper.ToFixNodeParameters( true );
+        eHelper.SetSubShape( myEdge[iE] );
+        eHelper.ToFixNodeParameters( true );
         for ( size_t i = 0; i < nodes.size(); ++i )
         {
-          double u = helper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
+          double u = eHelper.GetNodeU( myEdge[iE], nodes[i], 0, &paramOK );
           // paramSize is signed so orientation is taken into account
           double normPar = prevNormPar + r * ( u - myFirst[iE] ) / paramSize;
           u2node.insert( u2node.end(), make_pair( normPar, nodes[i] ));
@@ -707,9 +714,8 @@ bool StdMeshers_FaceSide::GetEdgeNodes(size_t                        i,
 
   if ( inlude1stVertex )
   {
-    const SMDS_MeshNode* n0 = VertexNode( i );
-    if ( !n0 ) return false;
-    nodes.push_back( n0 );
+    if ( const SMDS_MeshNode* n0 = VertexNode( i ))
+      nodes.push_back( n0 );
   }
 
   if ( sm && ( sm->NbElements() > 0 || sm->NbNodes() > 0 ))
@@ -764,9 +770,8 @@ bool StdMeshers_FaceSide::GetEdgeNodes(size_t                        i,
 
   if ( inludeLastVertex )
   {
-    const SMDS_MeshNode* n1 = VertexNode( i+1 );
-    if ( !n1 ) return false;
-    nodes.push_back( n1 );
+    if ( const SMDS_MeshNode* n1 = VertexNode( i+1 ))
+      nodes.push_back( n1 );
   }
   return true;
 }
@@ -943,27 +948,43 @@ int StdMeshers_FaceSide::NbPoints(const bool update) const
     me->myNbSegments = 0;
     me->myMissingVertexNodes = false;
 
+    vector<const SMDS_MeshNode*> nodes;
     for ( int i = 0; i < NbEdges(); ++i )
     {
-      if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) )) {
-        int nbN = sm->NbNodes();
-        if ( sm->NbElements() > 0 ) {
-          nbN = sm->NbElements() - 1; // nodes can be moved to other shapes by MergeNodes()
-          if ( !myIgnoreMediumNodes &&
-               sm->GetElements()->next()->IsQuadratic() )
-            nbN += sm->NbElements();
+      if ( const SMESHDS_SubMesh* sm = myProxyMesh->GetSubMesh( Edge(i) ))
+      {
+        if ( sm->NbNodes() == sm->NbElements() - 1 )
+        {
+          me->myNbPonits += sm->NbNodes();
+          if ( myIgnoreMediumNodes && sm->IsQuadratic() )
+            me->myNbPonits -= sm->NbElements();
+        }
+        else // nodes can be moved to other shapes by MergeNodes()
+        {
+          nodes.clear();
+          GetEdgeNodes( i, nodes, /*v1=*/false, /*v2=*/false );
+          me->myNbPonits += nodes.size();
         }
-        me->myNbPonits   += nbN;
         me->myNbSegments += sm->NbElements();
       }
     }
 
+    SMESH_MesherHelper helper( *myProxyMesh->GetMesh() );
+    helper.SetSubShape( myFace );
+
     std::set< const SMDS_MeshNode* > vNodes;
-    for ( int i = 0; i <= NbEdges(); ++i )
+    for ( int i = 0; i <= NbEdges(); ++i ) // nb VERTEXes is more than NbEdges() if !IsClosed()
       if ( const SMDS_MeshNode* n = VertexNode( i ))
-        vNodes.insert( n );
+      {
+        if ( !vNodes.insert( n ).second &&
+             helper.IsRealSeam( n->getshapeId() ) &&
+             i < NbEdges())
+          me->myNbPonits++;
+      }
       else
+      {
         me->myMissingVertexNodes = true;
+      }
     me->myNbPonits += vNodes.size();
 
     if ( IsClosed() )
index d038ded..87572c1 100644 (file)
@@ -513,18 +513,18 @@ namespace {
           if ( !tgtNodes.empty() )
           {
             vector< const SMDS_MeshNode* >::iterator tn = tgtNodes.begin();
-            if ( srcWire->Edge(iE).Orientation() == tgtWire->Edge(iE).Orientation() )
+            //if ( srcWire->Edge(iE).Orientation() == tgtWire->Edge(iE).Orientation() )
             {
               vector< const SMDS_MeshNode* >::iterator sn = srcNodes.begin();
               for ( ; tn != tgtNodes.end(); ++tn, ++sn)
                 src2tgtNodes.insert( make_pair( *sn, *tn ));
             }
-            else
-            {
-              vector< const SMDS_MeshNode* >::reverse_iterator sn = srcNodes.rbegin();
-              for ( ; tn != tgtNodes.end(); ++tn, ++sn)
-                src2tgtNodes.insert( make_pair( *sn, *tn ));
-            }
+            // else
+            // {
+            //   vector< const SMDS_MeshNode* >::reverse_iterator sn = srcNodes.rbegin();
+            //   for ( ; tn != tgtNodes.end(); ++tn, ++sn)
+            //     src2tgtNodes.insert( make_pair( *sn, *tn ));
+            // }
             is1DComputed = true;
           }
         }
index 30c91c4..c173428 100644 (file)
@@ -4276,9 +4276,12 @@ int StdMeshers_Quadrangle_2D::getCorners(const TopoDS_Face&          theFace,
     return error(COMPERR_BAD_SHAPE,
                  TComm("Face must have 4 sides but not ") << faceSide.NbEdges() );
 
-  const int nbSegments = Max( faceSide.NbPoints()-1, faceSide.NbSegments() );
-  if ( nbSegments < nbCorners )
-    return error(COMPERR_BAD_INPUT_MESH, TComm("Too few boundary nodes: ") << nbSegments);
+  if ( theConsiderMesh )
+  {
+    const int nbSegments = Max( faceSide.NbPoints()-1, faceSide.NbSegments() );
+    if ( nbSegments < nbCorners )
+      return error(COMPERR_BAD_INPUT_MESH, TComm("Too few boundary nodes: ") << nbSegments);
+  }
 
   if ( nbCorners == 3 )
   {