Salome HOME
Regression of bugs/F9
[modules/smesh.git] / src / SMESH / SMESH_MeshEditor.cxx
index 140c974086bf8b59861809b42eaf4c0911e809f4..30d762efca12c6e33327a4efd41a3b2d190a1996 100644 (file)
@@ -120,6 +120,19 @@ SMESH_MeshEditor::SMESH_MeshEditor( SMESH_Mesh* theMesh )
 {
 }
 
+//================================================================================
+/*!
+ * \brief Clears myLastCreatedNodes and myLastCreatedElems
+ */
+//================================================================================
+
+void SMESH_MeshEditor::CrearLastCreated()
+{
+  myLastCreatedNodes.Clear();
+  myLastCreatedElems.Clear();
+}
+
+
 //=======================================================================
 /*!
  * \brief Add element
@@ -389,6 +402,44 @@ int SMESH_MeshEditor::Remove (const list< int >& theIDs,
   return removed;
 }
 
+//================================================================================
+/*!
+ * \brief Create 0D elements on all nodes of the given object except those
+ *        nodes on which a 0D element already exists.
+ *  \param elements - Elements on whose nodes to create 0D elements; if empty, 
+ *                    the all mesh is treated
+ *  \param all0DElems - returns all 0D elements found or created on nodes of \a elements
+ */
+//================================================================================
+
+void SMESH_MeshEditor::Create0DElementsOnAllNodes( const TIDSortedElemSet& elements,
+                                                   TIDSortedElemSet&       all0DElems )
+{
+  typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator> TSetIterator;
+  SMDS_ElemIteratorPtr elemIt;
+  if ( elements.empty() )
+    elemIt = GetMeshDS()->elementsIterator( SMDSAbs_Node );
+  else
+    elemIt = SMDS_ElemIteratorPtr( new TSetIterator( elements.begin(), elements.end() ));
+
+  while ( elemIt->more() )
+  {
+    const SMDS_MeshElement* e = elemIt->next();
+    SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
+    while ( nodeIt->more() )
+    {
+      const SMDS_MeshNode* n = cast2Node( nodeIt->next() );
+      SMDS_ElemIteratorPtr it0D = n->GetInverseElementIterator( SMDSAbs_0DElement );
+      if ( it0D->more() )
+        all0DElems.insert( it0D->next() );
+      else {
+        myLastCreatedElems.Append( GetMeshDS()->Add0DElement( n ));
+        all0DElems.insert( myLastCreatedElems.Last() );
+      }
+    }
+  }
+}
+
 //=======================================================================
 //function : FindShape
 //purpose  : Return an index of the shape theElem is on
@@ -1065,7 +1116,7 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
  * \brief Reorient faces.
  * \param theFaces - the faces to reorient. If empty the whole mesh is meant
  * \param theDirection - desired direction of normal of \a theFace
- * \param theFace - one of \a theFaces that sould be orientated according to
+ * \param theFace - one of \a theFaces that sould be oriented according to
  *        \a theDirection and whose orientation defines orientation of other faces
  * \return number of reoriented faces.
  */
@@ -1102,6 +1153,11 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet &       theFaces,
     theFaces.erase( theFace );
   startFaces.insert( theFace );
 
+  int nodeInd1, nodeInd2;
+  const SMDS_MeshElement*           otherFace;
+  vector< const SMDS_MeshElement* > facesNearLink;
+  vector< std::pair< int, int > >   nodeIndsOfFace;
+
   set< const SMDS_MeshElement* >::iterator startFace = startFaces.begin();
   while ( startFace != startFaces.end() )
   {
@@ -1124,13 +1180,40 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet &       theFaces,
       }
       else
       {
-        int nodeInd1, nodeInd2;
-        const SMDS_MeshElement* otherFace = FindFaceInSet( link.first, link.second,
-                                                           theFaces, avoidSet,
-                                                           & nodeInd1, & nodeInd2);
+        facesNearLink.clear();
+        nodeIndsOfFace.clear();
+        while (( otherFace = FindFaceInSet( link.first, link.second,
+                                            theFaces, avoidSet, &nodeInd1, &nodeInd2 )))
+          if ( otherFace != theFace)
+          {
+            facesNearLink.push_back( otherFace );
+            nodeIndsOfFace.push_back( make_pair( nodeInd1, nodeInd2 ));
+            avoidSet.insert( otherFace );
+          }
+        if ( facesNearLink.size() > 1 )
+        {
+          // select a face most co-directed with theFace,
+          // other faces won't be visited this time
+          gp_XYZ NF, NOF;
+          SMESH_Algo::FaceNormal( theFace, NF, /*normalized=*/false );
+          double proj, maxProj = 0;
+          for ( size_t i = 0; i < facesNearLink.size(); ++i ) {
+            SMESH_Algo::FaceNormal( facesNearLink[i], NOF, /*normalized=*/false );
+            if (( proj = Abs( NF * NOF )) > maxProj ) {
+              maxProj = proj;
+              otherFace = facesNearLink[i];
+              nodeInd1  = nodeIndsOfFace[i].first;
+              nodeInd2  = nodeIndsOfFace[i].second;
+            }
+          }
+        }
+        else if ( facesNearLink.size() == 1 )
+        {
+          otherFace = facesNearLink[0];
+        }
         if ( otherFace && otherFace != theFace)
         {
-          // link must be reversed in otherFace if orientation ot otherFace
+          // link must be reverse in otherFace if orientation ot otherFace
           // is same as that of theFace
           if ( abs(nodeInd2-nodeInd1) == 1 ? nodeInd2 > nodeInd1 : nodeInd1 > nodeInd2 )
           {
@@ -1143,7 +1226,7 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet &       theFaces,
             theFaces.erase( otherFace );
         }
       }
-      std::swap( link.first, link.second );
+      std::swap( link.first, link.second ); // reverse the link
     }
     startFaces.erase( startFace );
     startFace = startFaces.begin();
@@ -1216,7 +1299,8 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
     if( !elem->IsQuadratic() ) {
 
       // split liner quadrangle
-
+      // for MaxElementLength2D functor we return minimum diagonal for splitting,
+      // because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
       if ( aBadRate1 <= aBadRate2 ) {
         // tr1 + tr2 is better
         newElem1 = aMesh->AddFace( aNodes[2], aNodes[3], aNodes[0] );
@@ -1350,7 +1434,8 @@ int SMESH_MeshEditor::BestSplit (const SMDS_MeshElement*              theQuad,
     SMDS_FaceOfNodes tr3 ( aNodes[1], aNodes[2], aNodes[3] );
     SMDS_FaceOfNodes tr4 ( aNodes[3], aNodes[0], aNodes[1] );
     aBadRate2 = getBadRate( &tr3, theCrit ) + getBadRate( &tr4, theCrit );
-
+    // for MaxElementLength2D functor we return minimum diagonal for splitting,
+    // because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
     if (aBadRate1 <= aBadRate2) // tr1 + tr2 is better
       return 1; // diagonal 1-3
 
@@ -3062,7 +3147,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
     SMDS_FaceIteratorPtr fIt = aMesh->facesIterator();
     while ( fIt->more() ) {
       const SMDS_MeshElement* face = fIt->next();
-      theElems.insert( face );
+      theElems.insert( theElems.end(), face );
     }
   }
   // get all face ids theElems are on
@@ -5709,7 +5794,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 
     SMDSAbs_GeometryType geomType = elem->GetGeomType();
     int                  nbNodes  = elem->NbNodes();
-    if ( geomType == SMDSGeom_POINT ) continue; // node
+    if ( geomType == SMDSGeom_NONE ) continue; // node
 
     switch ( geomType ) {
 
@@ -5891,7 +5976,7 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
   vector< TOldNewGroup* > orderedOldNewGroups; // in order of old groups
   // group names
   set< string > groupNames;
-  
+
   SMESH_Mesh::GroupIteratorPtr groupIt = GetMesh()->GetGroups();
   if ( !groupIt->more() ) return newGroupIDs;
 
@@ -6103,7 +6188,7 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
         }
         else if ( tree->NbNodes() ) // put a tree to the treeMap
         {
-          const Bnd_B3d& box = tree->getBox();
+          const Bnd_B3d& box = *tree->getBox();
           double sqDist = thePnt.SquareDistance( 0.5 * ( box.CornerMin() + box.CornerMax() ));
           pair<TDistTreeMap::iterator,bool> it_in = treeMap.insert( make_pair( sqDist, tree ));
           if ( !it_in.second ) // not unique distance to box center
@@ -6115,7 +6200,7 @@ struct SMESH_NodeSearcherImpl: public SMESH_NodeSearcher
       TDistTreeMap::iterator sqDist_tree = treeMap.begin();
       if ( treeMap.size() > 5 ) {
         SMESH_OctreeNode* closestTree = sqDist_tree->second;
-        const Bnd_B3d& box = closestTree->getBox();
+        const Bnd_B3d& box = *closestTree->getBox();
         double limit = sqrt( sqDist_tree->first ) + sqrt ( box.SquareExtent() );
         sqLimit = limit * limit;
       }
@@ -6200,7 +6285,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
 
   protected:
     ElementBndBoxTree():_size(0) {}
-    SMESH_Octree* allocateOctreeChild() const { return new ElementBndBoxTree; }
+    SMESH_Octree* newChild() const { return new ElementBndBoxTree; }
     void          buildChildrenData();
     Bnd_B3d*      buildRootBox();
   private:
@@ -6222,7 +6307,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
   //================================================================================
 
   ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt, double tolerance)
-    :SMESH_Octree( new SMESH_Octree::Limit( MaxLevel, /*minSize=*/0. ))
+    :SMESH_Octree( new SMESH_TreeLimit( MaxLevel, /*minSize=*/0. ))
   {
     int nbElems = mesh.GetMeshInfo().NbElements( elemType );
     _elements.reserve( nbElems );
@@ -6273,7 +6358,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
     {
       for (int j = 0; j < 8; j++)
       {
-        if ( !_elements[i]->IsOut( myChildren[j]->getBox() ))
+        if ( !_elements[i]->IsOut( *myChildren[j]->getBox() ))
         {
           _elements[i]->_refCount++;
           ((ElementBndBoxTree*)myChildren[j])->_elements.push_back( _elements[i]);
@@ -6304,7 +6389,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
   void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt&     point,
                                                 TIDSortedElemSet& foundElems)
   {
-    if ( getBox().IsOut( point.XYZ() ))
+    if ( getBox()->IsOut( point.XYZ() ))
       return;
 
     if ( isLeaf() )
@@ -6329,7 +6414,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
   void ElementBndBoxTree::getElementsNearLine( const gp_Ax1&     line,
                                                TIDSortedElemSet& foundElems)
   {
-    if ( getBox().IsOut( line ))
+    if ( getBox()->IsOut( line ))
       return;
 
     if ( isLeaf() )
@@ -6355,7 +6440,7 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
                                                 const double      radius,
                                                 TIDSortedElemSet& foundElems)
   {
-    if ( getBox().IsOut( center, radius ))
+    if ( getBox()->IsOut( center, radius ))
       return;
 
     if ( isLeaf() )
@@ -6657,7 +6742,7 @@ void SMESH_ElementSearcherImpl::findOuterBoundary(const SMDS_MeshElement* outerF
  * \brief Find elements of given type where the given point is IN or ON.
  *        Returns nb of found elements and elements them-selves.
  *
- * 'ALL' type means elements of any type excluding nodes, balls and 0D elements 
+ * 'ALL' type means elements of any type excluding nodes, balls and 0D elements
  */
 //=======================================================================
 
@@ -6734,13 +6819,13 @@ SMESH_ElementSearcherImpl::FindClosestTo( const gp_Pnt&       point,
     }
     TIDSortedElemSet suspectElems;
     _ebbTree->getElementsNearPoint( point, suspectElems );
-    
+
     if ( suspectElems.empty() && _ebbTree->maxSize() > 0 )
     {
-      gp_Pnt boxCenter = 0.5 * ( _ebbTree->getBox().CornerMin() +
-                                 _ebbTree->getBox().CornerMax() );
+      gp_Pnt boxCenter = 0.5 * ( _ebbTree->getBox()->CornerMin() +
+                                 _ebbTree->getBox()->CornerMax() );
       double radius;
-      if ( _ebbTree->getBox().IsOut( point.XYZ() ))
+      if ( _ebbTree->getBox()->IsOut( point.XYZ() ))
         radius = point.Distance( boxCenter ) - 0.5 * _ebbTree->maxSize();
       else
         radius = _ebbTree->maxSize() / pow( 2., _ebbTree->getHeight()) / 2;
@@ -7242,7 +7327,7 @@ namespace
                       POS_ALL = POS_LEFT | POS_RIGHT | POS_VERTEX };
   struct PointPos
   {
-    PositionName _name; 
+    PositionName _name;
     int          _index; // index of vertex or segment
 
     PointPos( PositionName n, int i=-1 ): _name(n), _index(i) {}
@@ -8156,32 +8241,29 @@ private:
 //purpose  : Return list of group of elements built on the same nodes.
 //           Search among theElements or in the whole mesh if theElements is empty
 //=======================================================================
-void SMESH_MeshEditor::FindEqualElements(set<const SMDS_MeshElement*> & theElements,
-                                         TListOfListOfElementsID &      theGroupsOfElementsID)
+
+void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet &        theElements,
+                                         TListOfListOfElementsID & theGroupsOfElementsID)
 {
   myLastCreatedElems.Clear();
   myLastCreatedNodes.Clear();
 
-  typedef set<const SMDS_MeshElement*> TElemsSet;
   typedef map< SortableElement, int > TMapOfNodeSet;
   typedef list<int> TGroupOfElems;
 
-  TElemsSet elems;
   if ( theElements.empty() )
   { // get all elements in the mesh
     SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator();
     while ( eIt->more() )
-      elems.insert( elems.end(), eIt->next());
+      theElements.insert( theElements.end(), eIt->next());
   }
-  else
-    elems = theElements;
 
   vector< TGroupOfElems > arrayOfGroups;
   TGroupOfElems groupOfElems;
   TMapOfNodeSet mapOfNodeSet;
 
-  TElemsSet::iterator elemIt = elems.begin();
-  for ( int i = 0, j=0; elemIt != elems.end(); ++elemIt, ++j ) {
+  TIDSortedElemSet::iterator elemIt = theElements.begin();
+  for ( int i = 0, j=0; elemIt != theElements.end(); ++elemIt, ++j ) {
     const SMDS_MeshElement* curElem = *elemIt;
     SortableElement SE(curElem);
     int ind = -1;
@@ -8254,8 +8336,8 @@ void SMESH_MeshEditor::MergeElements(TListOfListOfElementsID & theGroupsOfElemen
 
 void SMESH_MeshEditor::MergeEqualElements()
 {
-  set<const SMDS_MeshElement*> aMeshElements; /* empty input -
-                                                 to merge equal elements in the whole mesh */
+  TIDSortedElemSet aMeshElements; /* empty input ==
+                                     to merge equal elements in the whole mesh */
   TListOfListOfElementsID aGroupsOfElementsID;
   FindEqualElements(aMeshElements, aGroupsOfElementsID);
   MergeElements(aGroupsOfElementsID);
@@ -9635,7 +9717,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
   if ( !theForce3d )
   { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
     aHelper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh
-    aHelper.FixQuadraticElements();
+    aHelper.FixQuadraticElements(myError);
   }
 }
 
@@ -9775,7 +9857,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
   if ( !theForce3d  && !getenv("NO_FixQuadraticElements"))
   { // setenv NO_FixQuadraticElements to know if FixQuadraticElements() is guilty of bad conversion
     helper.SetSubShape(0); // apply FixQuadraticElements() to the whole mesh
-    helper.FixQuadraticElements();
+    helper.FixQuadraticElements( myError );
   }
 }
 
@@ -11151,8 +11233,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
             {
               int oldId = *itn;
               //MESSAGE("     node " << oldId);
-              std::set<int> cells;
-              cells.clear();
               vtkCellLinks::Link l = grid->GetCellLinks()->GetLink(oldId);
               for (int i=0; i<l.ncells; i++)
                 {
@@ -11169,8 +11249,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                                 //no cells created after BuildDownWardConnectivity
                     }
                   DownIdType aCell(downId, vtkType);
-                  if (celldom.count(vtkId))
-                    continue;
+                  if (!cellDomains.count(aCell))
+                    cellDomains[aCell] = emptyMap; // create an empty entry for cell
                   cellDomains[aCell][idomain] = vtkId;
                   celldom[vtkId] = idomain;
                   //MESSAGE("       cell " << vtkId << " domain " << idomain);
@@ -11204,16 +11284,18 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
           std::set<int> oldNodes;
           oldNodes.clear();
           grid->GetNodeIds(oldNodes, face.cellId, face.cellType);
-//          bool isMultipleDetected = false;
           std::set<int>::iterator itn = oldNodes.begin();
           for (; itn != oldNodes.end(); ++itn)
             {
               int oldId = *itn;
-              //MESSAGE("     node " << oldId);
+              //MESSAGE("-+-+-a node " << oldId);
               if (!nodeDomains.count(oldId))
                 nodeDomains[oldId] = emptyMap; // create an empty entry for node
               if (nodeDomains[oldId].empty())
-                nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain
+                {
+                  nodeDomains[oldId][idomain] = oldId; // keep the old node in the first domain
+                  //MESSAGE("-+-+-b     oldNode " << oldId << " domain " << idomain);
+                }
               std::map<int, int>::iterator itdom = domvol.begin();
               for (; itdom != domvol.end(); ++itdom)
                 {
@@ -11225,7 +11307,6 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                         {
                           vector<int> orderedDoms;
                           //MESSAGE("multiple node " << oldId);
-//                          isMultipleDetected =true;
                           if (mutipleNodes.count(oldId))
                             orderedDoms = mutipleNodes[oldId];
                           else
@@ -11245,13 +11326,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                       SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
                       int newId = newNode->getVtkId();
                       nodeDomains[oldId][idom] = newId; // cloned node for other domains
-                      //MESSAGE("   newNode " << newId << " oldNode " << oldId << " size=" <<nodeDomains[oldId].size());
+                      //MESSAGE("-+-+-c     oldNode " << oldId << " domain " << idomain << " newNode " << newId << " domain " << idom << " size=" <<nodeDomains[oldId].size());
                     }
-//                  if (nodeDomains[oldId].size() >= 3)
-//                    {
-//                      //MESSAGE("confirm multiple node " << oldId);
-//                      isMultipleDetected =true;
-//                    }
                 }
             }
         }
@@ -11388,6 +11464,14 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
 
   if (createJointElems)
     {
+      int idg;
+      string joints2DName = "joints2D";
+      mapOfJunctionGroups[joints2DName] = this->myMesh->AddGroup(SMDSAbs_Face, joints2DName.c_str(), idg);
+      SMESHDS_Group *joints2DGrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[joints2DName]->GetGroupDS());
+      string joints3DName = "joints3D";
+      mapOfJunctionGroups[joints3DName] = this->myMesh->AddGroup(SMDSAbs_Volume, joints3DName.c_str(), idg);
+      SMESHDS_Group *joints3DGrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[joints3DName]->GetGroupDS());
+
       itface = faceDomains.begin();
       for (; itface != faceDomains.end(); ++itface)
         {
@@ -11411,13 +11495,16 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
             grpname << dom1 << "_" << dom2;
           else
             grpname << dom2 << "_" << dom1;
-          int idg;
           string namegrp = grpname.str();
           if (!mapOfJunctionGroups.count(namegrp))
             mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg);
           SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
           if (sgrp)
             sgrp->Add(vol->GetID());
+          if (vol->GetType() == SMDSAbs_Volume)
+            joints3DGrp->Add(vol->GetID());
+          else if (vol->GetType() == SMDSAbs_Face)
+            joints2DGrp->Add(vol->GetID());
         }
     }
 
@@ -11471,11 +11558,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                     orderedNodes.push_back( nodeDomains[nodes[ino]][orderDom[idom]] );
               SMDS_MeshVolume* vol = this->GetMeshDS()->AddVolumeFromVtkIds(orderedNodes);
 
-              stringstream grpname;
-              grpname << "mj_";
-              grpname << 0 << "_" << 0;
               int idg;
-              string namegrp = grpname.str();
+              string namegrp = "jointsMultiples";
               if (!mapOfJunctionGroups.count(namegrp))
                 mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
               SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
@@ -11484,7 +11568,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
             }
           else
             {
-              MESSAGE("Quadratic multiple joints not implemented");
+              INFOS("Quadratic multiple joints not implemented");
               // TODO quadratic nodes
             }
         }
@@ -11777,8 +11861,11 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius,
       groupDS = group->GetGroupDS();
       if ( !groupDS || groupDS->IsEmpty() ) continue;
       std::string grpName = group->GetName();
+      //MESSAGE("grpName=" << grpName);
       if (grpName == groupName)
         break;
+      else
+        groupDS = 0;
     }
 
   bool isNodeGroup = false;
@@ -11792,6 +11879,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double radius,
 
   if (nodesCoords.size() > 0)
     isNodeCoords = true; // a list o nodes given by their coordinates
+  //MESSAGE("---" << isNodeGroup << " " << isNodeCoords);
 
   // --- define groups to build