Salome HOME
PAL0023627: [IMACS] ASERIS: project point to the mesh
[modules/smesh.git] / src / SMESH / SMESH_MeshEditor.cxx
index b86d7f5e0d270e71075857179eb6294365413b65..cea314220460932062e7b7bd972eeced069adae7 100644 (file)
@@ -162,7 +162,7 @@ SMESH_MeshEditor::ElemFeatures::Init( const SMDS_MeshElement* elem, bool basicOn
         myIsQuad = elem->IsQuadratic();
         if ( myType == SMDSAbs_Volume && !basicOnly )
         {
-          vector<int > quant = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
+          vector<int> quant = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
           myPolyhedQuantities.swap( quant );
         }
       }
@@ -682,16 +682,16 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
 {
   ClearLastCreated();
 
-  if (!theTria1 || !theTria2)
+  if ( !theTria1 || !theTria2 ||
+       !dynamic_cast<const SMDS_MeshCell*>( theTria1 ) ||
+       !dynamic_cast<const SMDS_MeshCell*>( theTria2 ) ||
+       theTria1->GetType() != SMDSAbs_Face ||
+       theTria2->GetType() != SMDSAbs_Face )
     return false;
 
-  const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( theTria1 );
-  if (!F1) return false;
-  const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( theTria2 );
-  if (!F2) return false;
   if ((theTria1->GetEntityType() == SMDSEntity_Triangle) &&
-      (theTria2->GetEntityType() == SMDSEntity_Triangle)) {
-
+      (theTria2->GetEntityType() == SMDSEntity_Triangle))
+  {
     //  1 +--+ A  theTria1: ( 1 A B ) A->2 ( 1 2 B ) 1 +--+ A
     //    | /|    theTria2: ( B A 2 ) B->1 ( 1 A 2 )   |\ |
     //    |/ |                                         | \|
@@ -805,9 +805,9 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshElement * theTria1,
     gp_Pnt xyz;
     if ( F.IsNull() )
     {
-      xyz = ( SMESH_TNodeXYZ( nodes[3] ) +
-              SMESH_TNodeXYZ( nodes[4] ) +
-              SMESH_TNodeXYZ( nodes[5] )) / 3.;
+      xyz = ( SMESH_NodeXYZ( nodes[3] ) +
+              SMESH_NodeXYZ( nodes[4] ) +
+              SMESH_NodeXYZ( nodes[5] )) / 3.;
     }
     else
     {
@@ -886,10 +886,10 @@ bool SMESH_MeshEditor::InverseDiag (const SMDS_MeshNode * theNode1,
   if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
     return false;
 
-  const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
-  if (!F1) return false;
-  const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
-  if (!F2) return false;
+  if ( !dynamic_cast<const SMDS_MeshCell*>( tr1 ) ||
+       !dynamic_cast<const SMDS_MeshCell*>( tr2 ))
+    return false;
+
   if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
       (tr2->GetEntityType() == SMDSEntity_Triangle)) {
 
@@ -1006,15 +1006,15 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
   if ( !findTriangles( theNode1, theNode2, tr1, tr2 ))
     return false;
 
-  const SMDS_VtkFace* F1 = dynamic_cast<const SMDS_VtkFace*>( tr1 );
-  if (!F1) return false;
-  const SMDS_VtkFace* F2 = dynamic_cast<const SMDS_VtkFace*>( tr2 );
-  if (!F2) return false;
+  if ( !dynamic_cast<const SMDS_MeshCell*>( tr1 ) ||
+       !dynamic_cast<const SMDS_MeshCell*>( tr2 ))
+    return false;
+
   SMESHDS_Mesh * aMesh = GetMeshDS();
 
   if ((tr1->GetEntityType() == SMDSEntity_Triangle) &&
-      (tr2->GetEntityType() == SMDSEntity_Triangle)) {
-
+      (tr2->GetEntityType() == SMDSEntity_Triangle))
+  {
     const SMDS_MeshNode* aNodes [ 4 ];
     if ( ! getQuadrangleNodes( aNodes, theNode1, theNode2, tr1, tr2 ))
       return false;
@@ -1025,9 +1025,8 @@ bool SMESH_MeshEditor::DeleteDiag (const SMDS_MeshNode * theNode1,
     AddToSameGroups( newElem, tr1, aMesh );
     int aShapeId = tr1->getshapeId();
     if ( aShapeId )
-    {
       aMesh->SetMeshElementOnShape( newElem, aShapeId );
-    }
+
     aMesh->RemoveElement( tr1 );
     aMesh->RemoveElement( tr2 );
 
@@ -1109,8 +1108,7 @@ bool SMESH_MeshEditor::Reorient (const SMDS_MeshElement * theElem)
   const SMDSAbs_EntityType geomType = theElem->GetEntityType();
   if ( geomType == SMDSEntity_Polyhedra ) // polyhedron
   {
-    const SMDS_VtkVolume* aPolyedre =
-      dynamic_cast<const SMDS_VtkVolume*>( theElem );
+    const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( theElem );
     if (!aPolyedre) {
       MESSAGE("Warning: bad volumic element");
       return false;
@@ -1168,7 +1166,7 @@ int SMESH_MeshEditor::Reorient2D (TIDSortedElemSet &       theFaces,
 
   if ( theFaces.empty() )
   {
-    SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=*/true);
+    SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=true*/);
     while ( fIt->more() )
       theFaces.insert( theFaces.end(), fIt->next() );
   }
@@ -1425,7 +1423,7 @@ bool SMESH_MeshEditor::QuadToTri (TIDSortedElemSet &                   theElems,
     const SMDS_MeshElement* newElem1 = 0;
     const SMDS_MeshElement* newElem2 = 0;
 
-    if ( !elem->IsQuadratic() ) // split liner quadrangle
+    if ( !elem->IsQuadratic() ) // split linear quadrangle
     {
       // for MaxElementLength2D functor we return minimum diagonal for splitting,
       // because aBadRate1=2*len(diagonal 1-3); aBadRate2=2*len(diagonal 2-4)
@@ -1556,7 +1554,7 @@ void SMESH_MeshEditor::QuadTo4Tri (TIDSortedElemSet & theElems)
       if ( F.IsNull() )
       {
         for ( ; iN < nodes.size(); ++iN )
-          xyz[ iN ] = SMESH_TNodeXYZ( nodes[ iN ] );
+          xyz[ iN ] = SMESH_NodeXYZ( nodes[ iN ] );
 
         for ( ; iN < 8; ++iN ) // mid-side points of a linear qudrangle
           xyz[ iN ] = 0.5 * ( xyz[ iN - 4 ] + xyz[( iN - 3 )%4 ] );
@@ -2361,7 +2359,7 @@ void SMESH_MeshEditor::SplitVolumes (const TFacetOfElem & theElems,
           if ( fSubMesh ) // update position of the bary node on geometry
           {
             if ( subMesh )
-              subMesh->RemoveNode( baryNode, false );
+              subMesh->RemoveNode( baryNode );
             GetMeshDS()->SetNodeOnFace( baryNode, fSubMesh->GetID() );
             const TopoDS_Shape& s = GetMeshDS()->IndexToShape( fSubMesh->GetID() );
             if ( !s.IsNull() && s.ShapeType() == TopAbs_FACE )
@@ -3830,7 +3828,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
         // }
         if ( project ) { // compute new UV
           gp_XY newUV;
-          gp_Pnt pNode = SMESH_TNodeXYZ( node );
+          gp_Pnt pNode = SMESH_NodeXYZ( node );
           if ( !getClosestUV( projector, pNode, newUV )) {
             MESSAGE("Node Projection Failed " << node);
           }
@@ -4085,7 +4083,7 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
         const SMDS_MeshElement* QF = *elemIt;
         if ( QF->IsQuadratic() )
         {
-          nodes.assign( SMDS_MeshElement::iterator( QF->interlacedNodesElemIterator() ),
+          nodes.assign( SMDS_MeshElement::iterator( QF->interlacedNodesIterator() ),
                         SMDS_MeshElement::iterator() );
           nodes.push_back( nodes[0] );
           gp_Pnt xyz;
@@ -4099,9 +4097,9 @@ void SMESH_MeshEditor::Smooth (TIDSortedElemSet &          theElems,
               xyz = surface->Value( uv.X(), uv.Y() );
             }
             else {
-              xyz = 0.5 * ( SMESH_TNodeXYZ( nodes[i-1] ) + SMESH_TNodeXYZ( nodes[i+1] ));
+              xyz = 0.5 * ( SMESH_NodeXYZ( nodes[i-1] ) + SMESH_NodeXYZ( nodes[i+1] ));
             }
-            if (( SMESH_TNodeXYZ( nodes[i] ) - xyz.XYZ() ).Modulus() > disttol )
+            if (( SMESH_NodeXYZ( nodes[i] ) - xyz.XYZ() ).Modulus() > disttol )
               // we have to move a medium node
               aMesh->MoveNode( nodes[i], xyz.X(), xyz.Y(), xyz.Z() );
           }
@@ -4129,8 +4127,8 @@ namespace
                  const int                           iNotSame)
   {
 
-    SMESH_TNodeXYZ pP = prevNodes[ iNotSame ];
-    SMESH_TNodeXYZ pN = nextNodes[ iNotSame ];
+    SMESH_NodeXYZ pP = prevNodes[ iNotSame ];
+    SMESH_NodeXYZ pN = nextNodes[ iNotSame ];
     gp_XYZ extrDir( pN - pP ), faceNorm;
     SMESH_MeshAlgos::FaceNormal( face, faceNorm, /*normalized=*/false );
 
@@ -4834,9 +4832,9 @@ void SMESH_MeshEditor::makeWalls (TNodeOfNodeListMap &     mapNewNodes,
         SMDS_VolumeTool vTool( *v, /*ignoreCentralNodes=*/false );
         int iF, nbF = vTool.NbFaces();
         for ( iF = 0; iF < nbF; iF ++ ) {
-          if (vTool.IsFreeFace( iF ) &&
-              vTool.GetFaceNodes( iF, faceNodeSet ) &&
-              initNodeSet != faceNodeSet) // except an initial face
+          if ( vTool.IsFreeFace( iF ) &&
+               vTool.GetFaceNodes( iF, faceNodeSet ) &&
+               initNodeSet != faceNodeSet) // except an initial face
           {
             if ( nbSteps == 1 && faceNodeSet == topNodeSet )
               continue;
@@ -5325,7 +5323,7 @@ void SMESH_MeshEditor::ExtrusParam::SetElementsToUse( const TIDSortedElemSet& el
         while ( itN->more() ) {
           const SMDS_MeshElement* node = itN->next();
           if ( newNodes.insert( node ).second )
-            myBaseP += SMESH_TNodeXYZ( node );
+            myBaseP += SMESH_NodeXYZ( node );
         }
       }
     }
@@ -5391,7 +5389,7 @@ makeNodesByDir( SMESHDS_Mesh*                     mesh,
                 std::list<const SMDS_MeshNode*> & newNodes,
                 const bool                        makeMediumNodes)
 {
-  gp_XYZ p = SMESH_TNodeXYZ( srcNode );
+  gp_XYZ p = SMESH_NodeXYZ( srcNode );
 
   int nbNodes = 0;
   for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
@@ -5428,7 +5426,7 @@ makeNodesByDir( SMESHDS_Mesh*                     mesh,
       iSc += int( makeMediumNodes );
       ScaleIt& scale = scales[ iSc % 2 ];
       
-      gp_XYZ xyz = SMESH_TNodeXYZ( *nIt );
+      gp_XYZ xyz = SMESH_NodeXYZ( *nIt );
       xyz = ( *scale * ( xyz - center )) + center;
       mesh->MoveNode( *nIt, xyz.X(), xyz.Y(), xyz.Z() );
 
@@ -5449,7 +5447,7 @@ makeNodesByDirAndSew( SMESHDS_Mesh*                     mesh,
                       std::list<const SMDS_MeshNode*> & newNodes,
                       const bool                        makeMediumNodes)
 {
-  gp_XYZ P1 = SMESH_TNodeXYZ( srcNode );
+  gp_XYZ P1 = SMESH_NodeXYZ( srcNode );
 
   int nbNodes = 0;
   for ( beginStepIter( makeMediumNodes ); moreSteps(); ++nbNodes ) // loop on steps
@@ -5460,10 +5458,11 @@ makeNodesByDirAndSew( SMESHDS_Mesh*                     mesh,
     // if myNodes.size()>0 we 'nave to use given sequence
     // else - use all nodes of mesh
     const SMDS_MeshNode * node = 0;
-    if ( myNodes.Length() > 0 ) {
-      int i;
-      for ( i = 1; i <= myNodes.Length(); i++ ) {
-        gp_XYZ P2 = SMESH_TNodeXYZ( myNodes.Value(i) );
+    if ( myNodes.Length() > 0 )
+    {
+      for ( int i = 1; i <= myNodes.Length(); i++ )
+      {
+        SMESH_NodeXYZ P2 = myNodes.Value(i);
         if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
         {
           node = myNodes.Value(i);
@@ -5471,10 +5470,12 @@ makeNodesByDirAndSew( SMESHDS_Mesh*                     mesh,
         }
       }
     }
-    else {
+    else
+    {
       SMDS_NodeIteratorPtr itn = mesh->nodesIterator();
-      while(itn->more()) {
-        SMESH_TNodeXYZ P2( itn->next() );
+      while(itn->more())
+      {
+        SMESH_NodeXYZ P2 = itn->next();
         if (( P1 - P2 ).SquareModulus() < myTolerance * myTolerance )
         {
           node = P2._node;
@@ -5506,7 +5507,7 @@ makeNodesByNormal2D( SMESHDS_Mesh*                     mesh,
 {
   const bool alongAvgNorm = ( myFlags & EXTRUSION_FLAG_BY_AVG_NORMAL );
 
-  gp_XYZ p = SMESH_TNodeXYZ( srcNode );
+  gp_XYZ p = SMESH_NodeXYZ( srcNode );
 
   // get normals to faces sharing srcNode
   vector< gp_XYZ > norms, baryCenters;
@@ -5526,7 +5527,7 @@ makeNodesByNormal2D( SMESHDS_Mesh*                     mesh,
         gp_XYZ bc(0,0,0);
         int nbN = 0;
         for ( SMDS_ElemIteratorPtr nIt = face->nodesIterator(); nIt->more(); ++nbN )
-          bc += SMESH_TNodeXYZ( nIt->next() );
+          bc += SMESH_NodeXYZ( nIt->next() );
         baryCenters.push_back( bc / nbN );
       }
     }
@@ -5794,9 +5795,8 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
       return EXTR_BAD_STARTING_NODE;
     aItN = pSubMeshDS->GetNodes();
     while ( aItN->more() ) {
-      const SMDS_MeshNode* pNode = aItN->next();
-      const SMDS_EdgePosition* pEPos =
-        static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
+      const SMDS_MeshNode*  pNode = aItN->next();
+      SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
       double aT = pEPos->GetUParameter();
       aPrms.push_back( aT );
     }
@@ -5839,8 +5839,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
         aItN = locMeshDS->GetNodes();
         while ( aItN->more() ) {
           const SMDS_MeshNode* pNode = aItN->next();
-          const SMDS_EdgePosition* pEPos =
-            static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
+          SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
           double aT = pEPos->GetUParameter();
           aPrms.push_back( aT );
         }
@@ -5962,7 +5961,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
     SMDS_ElemIteratorPtr nIt;
 
     //check start node
-    if( !theTrack->GetMeshDS()->Contains(theN1) ) {
+    if( !theTrack->GetMeshDS()->Contains( theN1 )) {
       return EXTR_BAD_STARTING_NODE;
     }
 
@@ -6022,8 +6021,8 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
     int startNid = theN1->GetID();
     for ( size_t i = 1; i < aNodesList.size(); i++ )
     {
-      gp_Pnt     p1 = SMESH_TNodeXYZ( aNodesList[i-1] );
-      gp_Pnt     p2 = SMESH_TNodeXYZ( aNodesList[i] );
+      gp_Pnt     p1 = SMESH_NodeXYZ( aNodesList[i-1] );
+      gp_Pnt     p2 = SMESH_NodeXYZ( aNodesList[i] );
       TopoDS_Edge e = BRepBuilderAPI_MakeEdge( p1, p2 );
       list<SMESH_MeshEditor_PathPoint> LPP;
       aPrms.clear();
@@ -6079,8 +6078,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
     while ( aItN->more() ) {
       const SMDS_MeshNode* pNode = aItN->next();
       if( pNode==aN1 || pNode==aN2 ) continue;
-      const SMDS_EdgePosition* pEPos =
-        static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
+      SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
       double aT = pEPos->GetUParameter();
       aPrms.push_back( aT );
     }
@@ -6136,9 +6134,8 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet     theElements[2],
         aPrms.clear();
         aItN = locMeshDS->GetNodes();
         while ( aItN->more() ) {
-          const SMDS_MeshNode*     pNode = aItN->next();
-          const SMDS_EdgePosition* pEPos =
-            static_cast<const SMDS_EdgePosition*>( pNode->GetPosition() );
+          const SMDS_MeshNode*  pNode = aItN->next();
+          SMDS_EdgePositionPtr pEPos = pNode->GetPosition();
           double aT = pEPos->GetUParameter();
           aPrms.push_back( aT );
         }
@@ -6296,7 +6293,7 @@ SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets
         while ( itN->more() ) {
           const SMDS_MeshElement* node = itN->next();
           if ( newNodes.insert( node ).second )
-            aGC += SMESH_TNodeXYZ( node );
+            aGC += SMESH_NodeXYZ( node );
         }
       }
     }
@@ -6340,7 +6337,7 @@ SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets
           aTolAng=1.e-4;
 
           aV0x = aV0;
-          aPN0 = SMESH_TNodeXYZ( node );
+          aPN0 = SMESH_NodeXYZ( node );
 
           const SMESH_MeshEditor_PathPoint& aPP0 = aPPs[0];
           aP0x = aPP0.Pnt();
@@ -6357,7 +6354,7 @@ SMESH_MeshEditor::makeExtrElements(TIDSortedElemSet                  theElemSets
             gp_Vec aV01x( aP0x, aP1x );
             aTrsf.SetTranslation( aV01x );
 
-            // traslated point
+            // translated point
             aV1x = aV0x.Transformed( aTrsf );
             aPN1 = aPN0.Transformed( aTrsf );
 
@@ -6660,8 +6657,8 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 
     if ( geomType == SMDSGeom_POLYHEDRA )  // ------------------ polyhedral volume
     {
-      const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem );
-      if (!aPolyedre)
+      const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem );
+      if ( !aPolyedre )
         continue;
       nodes.clear();
       bool allTransformed = true;
@@ -6744,6 +6741,7 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem
                                                       const double       theValue,
                                                       SMESH_Mesh*        theTgtMesh,
                                                       const bool         theMakeGroups,
+                                                      const bool         theCopyElements,
                                                       const bool         theFixSelfIntersection)
 {
   SMESHDS_Mesh*    meshDS = GetMeshDS();
@@ -6760,9 +6758,21 @@ SMESH_MeshEditor::PGroupIDs SMESH_MeshEditor::Offset( TIDSortedElemSet & theElem
     ( SMESH_MeshAlgos::MakeOffset( eIt, *meshDS, theValue,
                                    theFixSelfIntersection,
                                    new2OldFaces, new2OldNodes ));
+  if ( offsetMesh->NbElements() == 0 )
+    return PGroupIDs(); // MakeOffset() failed
+
+
+  if ( theTgtMesh == myMesh && !theCopyElements )
+  {
+    // clear the source elements
+    if ( theElements.empty() ) eIt = meshDS->elementsIterator( SMDSAbs_Face );
+    else                       eIt = SMESHUtils::elemSetIterator( theElements );
+    while ( eIt->more() )
+      meshDS->RemoveFreeElement( eIt->next(), 0 );
+  }
 
-  offsetMesh->Modified();
-  offsetMesh->CompactMesh(); // make IDs start from 1
+  // offsetMesh->Modified();
+  // offsetMesh->CompactMesh(); // make IDs start from 1
 
   // source elements for each generated one
   SMESH_SequenceOfElemPtr srcElems, srcNodes;
@@ -7035,7 +7045,7 @@ void SMESH_MeshEditor::FindCoincidentNodes (TIDSortedNodeSet &   theNodes,
   if ( theNodes.empty() ) // get all nodes in the mesh
   {
     TIDSortedNodeSet* nodes[2] = { &corners, &medium };
-    SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator(/*idInceasingOrder=*/true);
+    SMDS_NodeIteratorPtr nIt = GetMeshDS()->nodesIterator();
     if ( theSeparateCornersAndMedium )
       while ( nIt->more() )
       {
@@ -7171,8 +7181,11 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
     const SMDS_MeshNode* nToKeep = nnIt->second;
     TNodeNodeMap::iterator nnIt_i = nodeNodeMap.find( nToKeep );
     while ( nnIt_i != nodeNodeMap.end() && nnIt_i->second != nnIt->second )
+    {
       nToKeep = nnIt_i->second;
-    nnIt->second = nToKeep;
+      nnIt->second = nToKeep;
+      nnIt_i = nodeNodeMap.find( nToKeep );
+    }
   }
 
   if ( theAvoidMakingHoles )
@@ -7223,7 +7236,7 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes,
       AddToSameGroups( nToKeep, nToRemove, mesh );
       // set _alwaysComputed to a sub-mesh of VERTEX to enable further mesh computing
       // w/o creating node in place of merged ones.
-      const SMDS_PositionPtr& pos = nToRemove->GetPosition();
+      SMDS_PositionPtr pos = nToRemove->GetPosition();
       if ( pos && pos->GetTypeOfPosition() == SMDS_TOP_VERTEX )
         if ( SMESH_subMesh* sm = myMesh->GetSubMeshContaining( nToRemove->getshapeId() ))
           sm->SetIsAlwaysComputed( true );
@@ -7411,7 +7424,7 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem,
       if ( nbUniqueNodes >= 4 )
       {
         // each face has to be analyzed in order to check volume validity
-        if ( const SMDS_VtkVolume* aPolyedre = dynamic_cast<const SMDS_VtkVolume*>( elem ))
+        if ( const SMDS_MeshVolume* aPolyedre = SMDS_Mesh::DownCast< SMDS_MeshVolume >( elem ))
         {
           int nbFaces = aPolyedre->NbFaces();
 
@@ -7729,26 +7742,55 @@ bool SMESH_MeshEditor::applyMerge( const SMDS_MeshElement* elem,
 
 
 // ========================================================
-// class   : SortableElement
-// purpose : allow sorting elements basing on their nodes
+// class   : ComparableElement
+// purpose : allow comparing elements basing on their nodes
 // ========================================================
-class SortableElement : public set <const SMDS_MeshElement*>
+
+class ComparableElement : public boost::container::flat_set< int >
 {
+  typedef boost::container::flat_set< int >  int_set;
+
+  const SMDS_MeshElement* myElem;
+  int                     mySumID;
+  mutable int             myGroupID;
+
 public:
 
-  SortableElement( const SMDS_MeshElement* theElem )
+  ComparableElement( const SMDS_MeshElement* theElem ):
+    myElem ( theElem ), mySumID( 0 ), myGroupID( -1 )
   {
-    myElem = theElem;
-    SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator();
-    while ( nodeIt->more() )
-      this->insert( nodeIt->next() );
+    this->reserve( theElem->NbNodes() );
+    for ( SMDS_ElemIteratorPtr nodeIt = theElem->nodesIterator(); nodeIt->more(); )
+    {
+      int id = nodeIt->next()->GetID();
+      mySumID += id;
+      this->insert( id );
+    }
   }
 
-  const SMDS_MeshElement* Get() const
-  { return myElem; }
+  const SMDS_MeshElement* GetElem() const { return myElem; }
+
+  int& GroupID() const { return myGroupID; }
+  //int& GroupID() const { return const_cast< int& >( myGroupID ); }
+
+  ComparableElement( const ComparableElement& theSource ) // move copy
+  {
+    ComparableElement& src = const_cast< ComparableElement& >( theSource );
+    (int_set&) (*this ) = boost::move( src );
+    myElem    = src.myElem;
+    mySumID   = src.mySumID;
+    myGroupID = src.myGroupID;
+  }
+
+  static int HashCode(const ComparableElement& se, int limit )
+  {
+    return ::HashCode( se.mySumID, limit );
+  }
+  static Standard_Boolean IsEqual(const ComparableElement& se1, const ComparableElement& se2 )
+  {
+    return ( se1 == se2 );
+  }
 
-private:
-  mutable const SMDS_MeshElement* myElem;
 };
 
 //=======================================================================
@@ -7757,48 +7799,47 @@ private:
 //           Search among theElements or in the whole mesh if theElements is empty
 //=======================================================================
 
-void SMESH_MeshEditor::FindEqualElements(TIDSortedElemSet &        theElements,
-                                         TListOfListOfElementsID & theGroupsOfElementsID)
+void SMESH_MeshEditor::FindEqualElements( TIDSortedElemSet &        theElements,
+                                          TListOfListOfElementsID & theGroupsOfElementsID )
 {
   ClearLastCreated();
 
-  typedef map< SortableElement, int > TMapOfNodeSet;
-  typedef list<int> TGroupOfElems;
-
   SMDS_ElemIteratorPtr elemIt;
   if ( theElements.empty() ) elemIt = GetMeshDS()->elementsIterator();
   else                       elemIt = SMESHUtils::elemSetIterator( theElements );
 
-  vector< TGroupOfElems > arrayOfGroups;
-  TGroupOfElems groupOfElems;
-  TMapOfNodeSet mapOfNodeSet;
+  typedef NCollection_Map< ComparableElement, ComparableElement > TMapOfElements;
+  typedef std::list<int>                                          TGroupOfElems;
+  TMapOfElements               mapOfElements;
+  std::vector< TGroupOfElems > arrayOfGroups;
+  TGroupOfElems                groupOfElems;
 
-  for ( int iGroup = 0; elemIt->more(); )
+  while ( elemIt->more() )
   {
     const SMDS_MeshElement* curElem = elemIt->next();
-    SortableElement SE(curElem);
+    ComparableElement      compElem = curElem;
     // check uniqueness
-    pair< TMapOfNodeSet::iterator, bool> pp = mapOfNodeSet.insert(make_pair(SE, iGroup));
-    if ( !pp.second ) { // one more coincident elem
-      TMapOfNodeSet::iterator& itSE = pp.first;
-      int iG = itSE->second;
+    const ComparableElement& elemInSet = mapOfElements.Added( compElem );
+    if ( elemInSet.GetElem() != curElem ) // coincident elem
+    {
+      int& iG = elemInSet.GroupID();
+      if ( iG < 0 )
+      {
+        iG = arrayOfGroups.size();
+        arrayOfGroups.push_back( groupOfElems );
+        arrayOfGroups[ iG ].push_back( elemInSet.GetElem()->GetID() );
+      }
       arrayOfGroups[ iG ].push_back( curElem->GetID() );
     }
-    else {
-      arrayOfGroups.push_back( groupOfElems );
-      arrayOfGroups.back().push_back( curElem->GetID() );
-      iGroup++;
-    }
   }
 
   groupOfElems.clear();
-  vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
+  std::vector< TGroupOfElems >::iterator groupIt = arrayOfGroups.begin();
   for ( ; groupIt != arrayOfGroups.end(); ++groupIt )
   {
     if ( groupIt->size() > 1 ) {
-      //groupOfElems.sort(); -- theElements is sorted already
-      theGroupsOfElementsID.push_back( groupOfElems );
-      theGroupsOfElementsID.back().splice( theGroupsOfElementsID.back().end(), *groupIt );
+      //groupOfElems.sort(); -- theElements are sorted already
+      theGroupsOfElementsID.emplace_back( *groupIt );
     }
   }
 }
@@ -7849,8 +7890,8 @@ void SMESH_MeshEditor::MergeEqualElements()
   TIDSortedElemSet aMeshElements; /* empty input ==
                                      to merge equal elements in the whole mesh */
   TListOfListOfElementsID aGroupsOfElementsID;
-  FindEqualElements(aMeshElements, aGroupsOfElementsID);
-  MergeElements(aGroupsOfElementsID);
+  FindEqualElements( aMeshElements, aGroupsOfElementsID );
+  MergeElements( aGroupsOfElementsID );
 }
 
 //=======================================================================
@@ -7928,24 +7969,11 @@ bool SMESH_MeshEditor::FindFreeBorder (const SMDS_MeshNode*             theFirst
       if ( e == curElem || foundElems.insert( e ).second ) {
         // get nodes
         int iNode = 0, nbNodes = e->NbNodes();
-        vector<const SMDS_MeshNode*> nodes(nbNodes+1);
-
-        if ( e->IsQuadratic() ) {
-          const SMDS_VtkFace* F =
-            dynamic_cast<const SMDS_VtkFace*>(e);
-          if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-          // use special nodes iterator
-          SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-          while( anIter->more() ) {
-            nodes[ iNode++ ] = cast2Node(anIter->next());
-          }
-        }
-        else {
-          SMDS_ElemIteratorPtr nIt = e->nodesIterator();
-          while ( nIt->more() )
-            nodes[ iNode++ ] = static_cast<const SMDS_MeshNode*>( nIt->next() );
-        }
-        nodes[ iNode ] = nodes[ 0 ];
+        vector<const SMDS_MeshNode*> nodes( nbNodes+1 );
+        nodes.assign( SMDS_MeshElement::iterator( e->interlacedNodesIterator() ),
+                      SMDS_MeshElement::iterator() );
+        nodes.push_back( nodes[ 0 ]);
+
         // check 2 links
         for ( iNode = 0; iNode < nbNodes; iNode++ )
           if (((nodes[ iNode ] == nStart && nodes[ iNode + 1] != nIgnore ) ||
@@ -8202,27 +8230,13 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
         const SMDS_MeshNode** nodes = isVolume ? volume.GetNodes() : & faceNodes[0];
         if ( isVolume ) // --volume
           hasVolumes = true;
-        else if ( elem->GetType()==SMDSAbs_Face ) { // --face
+        else if ( elem->GetType() == SMDSAbs_Face ) { // --face
           // retrieve all face nodes and find iPrevNode - an index of the prevSideNode
-          if(elem->IsQuadratic()) {
-            const SMDS_VtkFace* F =
-              dynamic_cast<const SMDS_VtkFace*>(elem);
-            if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-            // use special nodes iterator
-            SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-            while( anIter->more() ) {
-              nodes[ iNode ] = cast2Node(anIter->next());
-              if ( nodes[ iNode++ ] == prevSideNode )
-                iPrevNode = iNode - 1;
-            }
-          }
-          else {
-            SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
-            while ( nIt->more() ) {
-              nodes[ iNode ] = cast2Node( nIt->next() );
-              if ( nodes[ iNode++ ] == prevSideNode )
-                iPrevNode = iNode - 1;
-            }
+          SMDS_NodeIteratorPtr nIt = elem->interlacedNodesIterator();
+          while ( nIt->more() ) {
+            nodes[ iNode ] = cast2Node( nIt->next() );
+            if ( nodes[ iNode++ ] == prevSideNode )
+              iPrevNode = iNode - 1;
           }
           // there are 2 links to check
           nbNodes = 2;
@@ -8528,6 +8542,7 @@ SMESH_MeshEditor::SewFreeBorder (const SMDS_MeshNode* theBordFirstNode,
   for ( ; groupIt != nodeGroupsToMerge.end(); groupIt++ )
   {
     const list<const SMDS_MeshNode*>& nodes = *groupIt;
+    if ( nodes.front()->IsNull() ) continue;
     SMDS_ElemIteratorPtr segIt = nodes.front()->GetInverseElementIterator( SMDSAbs_Edge );
     while ( segIt->more() )
       segments.insert( segIt->next() );
@@ -8682,48 +8697,21 @@ void SMESH_MeshEditor::InsertNodesIntoLink(const SMDS_MeshElement*     theElemen
 
     // add nodes of face up to first node of link
     bool isFLN = false;
-
-    if ( theFace->IsQuadratic() ) {
-      const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>(theFace);
-      if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-      // use special nodes iterator
-      SMDS_ElemIteratorPtr anIter = F->interlacedNodesElemIterator();
-      while( anIter->more()  && !isFLN ) {
-        const SMDS_MeshNode* n = cast2Node(anIter->next());
-        poly_nodes[iNode++] = n;
-        if (n == nodes[il1]) {
-          isFLN = true;
-        }
-      }
-      // add nodes to insert
-      list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
-      for (; nIt != aNodesToInsert.end(); nIt++) {
-        poly_nodes[iNode++] = *nIt;
-      }
-      // add nodes of face starting from last node of link
-      while ( anIter->more() ) {
-        poly_nodes[iNode++] = cast2Node(anIter->next());
-      }
+    SMDS_NodeIteratorPtr nodeIt = theFace->interlacedNodesIterator();
+    while ( nodeIt->more() && !isFLN ) {
+      const SMDS_MeshNode* n = nodeIt->next();
+      poly_nodes[iNode++] = n;
+      isFLN = ( n == nodes[il1] );
     }
-    else {
-      SMDS_ElemIteratorPtr nodeIt = theFace->nodesIterator();
-      while ( nodeIt->more() && !isFLN ) {
-        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-        poly_nodes[iNode++] = n;
-        if (n == nodes[il1]) {
-          isFLN = true;
-        }
-      }
-      // add nodes to insert
-      list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
-      for (; nIt != aNodesToInsert.end(); nIt++) {
-        poly_nodes[iNode++] = *nIt;
-      }
-      // add nodes of face starting from last node of link
-      while ( nodeIt->more() ) {
-        const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
-        poly_nodes[iNode++] = n;
-      }
+    // add nodes to insert
+    list<const SMDS_MeshNode*>::iterator nIt = aNodesToInsert.begin();
+    for (; nIt != aNodesToInsert.end(); nIt++) {
+      poly_nodes[iNode++] = *nIt;
+    }
+    // add nodes of face starting from last node of link
+    while ( nodeIt->more() ) {
+      const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
+      poly_nodes[iNode++] = n;
     }
 
     // make a new face
@@ -9065,7 +9053,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
     const int nbNodes = elem->NbCornerNodes();
     nodes.assign(elem->begin_nodes(), elem->end_nodes());
     if ( aGeomType == SMDSEntity_Polyhedra )
-      nbNodeInFaces = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
+      nbNodeInFaces = static_cast<const SMDS_MeshVolume* >( elem )->GetQuantities();
     else if ( aGeomType == SMDSEntity_Hexagonal_Prism )
       volumeToPolyhedron( elem, nodes, nbNodeInFaces );
 
@@ -9286,7 +9274,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d, const bool theT
       const int id = volume->GetID();
       vector<const SMDS_MeshNode *> nodes (volume->begin_nodes(), volume->end_nodes());
       if ( type == SMDSEntity_Polyhedra )
-        nbNodeInFaces = static_cast<const SMDS_VtkVolume* >(volume)->GetQuantities();
+        nbNodeInFaces = static_cast<const SMDS_MeshVolume* >(volume)->GetQuantities();
       else if ( type == SMDSEntity_Hexagonal_Prism )
         volumeToPolyhedron( volume, nodes, nbNodeInFaces );
 
@@ -10048,20 +10036,8 @@ SMESH_MeshEditor::SewSideElements (TIDSortedElemSet&    theSide1,
         //cout << " F " << face[ iSide]->GetID() <<endl;
         faceSetPtr[ iSide ]->erase( face[ iSide ]);
         // put face nodes to fnodes
-        if ( face[ iSide ]->IsQuadratic() )
-        {
-          // use interlaced nodes iterator
-          const SMDS_VtkFace* F = dynamic_cast<const SMDS_VtkFace*>( face[ iSide ]);
-          if (!F) throw SALOME_Exception(LOCALIZED("not an SMDS_VtkFace"));
-          SMDS_ElemIteratorPtr nIter = F->interlacedNodesElemIterator();
-          while ( nIter->more() )
-            fnodes[ iSide ].push_back( cast2Node( nIter->next() ));
-        }
-        else
-        {
-          fnodes[ iSide ].assign( face[ iSide ]->begin_nodes(),
-                                  face[ iSide ]->end_nodes() );
-        }
+        SMDS_MeshElement::iterator nIt( face[ iSide ]->interlacedNodesIterator() ), nEnd;
+        fnodes[ iSide ].assign( nIt, nEnd );
         fnodes[ iSide ].push_back( fnodes[ iSide ].front());
       }
     }
@@ -10957,9 +10933,9 @@ void SMESH_MeshEditor::DoubleElements( const TIDSortedElemSet& theElements )
       if ( mesh->GetMeshInfo().NbElements( types[i] ))
       {
         type = types[i];
+        elemIt = mesh->elementsIterator( type );
         break;
       }
-    elemIt = mesh->elementsIterator( type );
   }
   else
   {
@@ -11178,8 +11154,7 @@ namespace {
                 const double            theTol)
   {
     gp_XYZ centerXYZ (0, 0, 0);
-    SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator();
-    while ( aNodeItr->more() )
+    for ( SMDS_ElemIteratorPtr aNodeItr = theElem->nodesIterator(); aNodeItr->more(); )
       centerXYZ += SMESH_NodeXYZ( aNodeItr->next() );
 
     gp_Pnt aPnt = centerXYZ / theElem->NbNodes();
@@ -11404,7 +11379,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
   meshDS->BuildDownWardConnectivity(true);
   CHRONO(50);
-  SMDS_UnstructuredGrid *grid = meshDS->getGrid();
+  SMDS_UnstructuredGrid *grid = meshDS->GetGrid();
 
   // --- build the list of faces shared by 2 domains (group of elements), with their domain and volume indexes
   //     build the list of cells with only a node or an edge on the border, with their domain and volume indexes
@@ -11470,7 +11445,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       const SMDS_MeshElement* anElem = *elemItr;
       if (!anElem)
         continue;
-      int vtkId = anElem->getVtkId();
+      int vtkId = anElem->GetVtkID();
       //MESSAGE("  vtkId " << vtkId << " smdsId " << anElem->GetID());
       int neighborsVtkIds[NBMAXNEIGHBORS];
       int downIds[NBMAXNEIGHBORS];
@@ -11478,7 +11453,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       int nbNeighbors = grid->GetNeighbors(neighborsVtkIds, downIds, downTypes, vtkId);
       for (int n = 0; n < nbNeighbors; n++)
       {
-        int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
+        int smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]);
         const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
         if (elem && ! domain.count(elem)) // neighbor is in another domain : face is shared
         {
@@ -11541,7 +11516,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
         for (int i=0; i<l.ncells; i++)
         {
           int vtkId = l.cells[i];
-          const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->fromVtkToSmds(vtkId));
+          const SMDS_MeshElement* anElem = GetMeshDS()->FindElement(GetMeshDS()->FromVtkToSmds(vtkId));
           if (!domain.count(anElem))
             continue;
           int vtkType = grid->GetCellType(vtkId);
@@ -11625,7 +11600,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
             double *coords = grid->GetPoint(oldId);
             SMDS_MeshNode *newNode = meshDS->AddNode(coords[0], coords[1], coords[2]);
             copyPosition( meshDS->FindNodeVtk( oldId ), newNode );
-            int newId = newNode->getVtkId();
+            int newId = newNode->GetVtkID();
             nodeDomains[oldId][idom] = newId; // cloned node for other domains
             //MESSAGE("-+-+-c     oldNode " << oldId << " domain " << idomain << " newNode " << newId << " domain " << idom << " size=" <<nodeDomains[oldId].size());
           }
@@ -11698,7 +11673,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                 gp_Pnt p1(coords[0], coords[1], coords[2]);
                 gp_Pnt gref;
                 int vtkVolIds[1000];  // an edge can belong to a lot of volumes
-                map<int, SMDS_VtkVolume*> domvol; // domain --> a volume with the edge
+                map<int, SMDS_MeshVolume*> domvol; // domain --> a volume with the edge
                 map<int, double> angleDom; // oriented angles between planes defined by edge and volume centers
                 int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
                 for ( size_t id = 0; id < doms.size(); id++ )
@@ -11707,26 +11682,31 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                   const TIDSortedElemSet& domain = (idom == iRestDom) ? theRestDomElems : theElems[idom];
                   for ( int ivol = 0; ivol < nbvol; ivol++ )
                   {
-                    int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
-                    SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
+                    int smdsId = meshDS->FromVtkToSmds(vtkVolIds[ivol]);
+                    const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
                     if (domain.count(elem))
                     {
-                      SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
-                      domvol[idom] = svol;
+                      const SMDS_MeshVolume* svol = SMDS_Mesh::DownCast<SMDS_MeshVolume>(elem);
+                      domvol[idom] = (SMDS_MeshVolume*) svol;
                       //MESSAGE("  domain " << idom << " volume " << elem->GetID());
-                      double values[3];
+                      double values[3] = { 0,0,0 };
                       vtkIdType npts = 0;
                       vtkIdType* pts = 0;
                       grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
-                      SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
-                      if (id ==0)
+                      for ( vtkIdType i = 0; i < npts; ++i )
+                      {
+                        double *coords = grid->GetPoint( pts[i] );
+                        for ( int j = 0; j < 3; ++j )
+                          values[j] += coords[j] / npts;
+                      }
+                      if ( id == 0 )
                       {
-                        gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
+                        gref.SetCoord( values[0], values[1], values[2] );
                         angleDom[idom] = 0;
                       }
                       else
                       {
-                        gp_Pnt g(values[0], values[1], values[2]);
+                        gp_Pnt g( values[0], values[1], values[2] );
                         angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pi<angle<+pi
                         //MESSAGE("  angle=" << angleDom[idom]);
                       }
@@ -11915,7 +11895,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
               feDom[vtkId] = idomain;
               faceOrEdgeDom[aCell] = emptyMap;
               faceOrEdgeDom[aCell][idomain] = vtkId; // affect face or edge to the first domain only
-              //MESSAGE("affect cell " << this->GetMeshDS()->fromVtkToSmds(vtkId) << " domain " << idomain
+              //MESSAGE("affect cell " << this->GetMeshDS()->FromVtkToSmds(vtkId) << " domain " << idomain
               //        << " type " << vtkType << " downId " << downId);
             }
       }
@@ -11947,7 +11927,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       {
         int idom = itdom->first;
         int vtkVolId = itdom->second;
-        //MESSAGE("modify nodes of cell " << this->GetMeshDS()->fromVtkToSmds(vtkVolId) << " domain " << idom);
+        //MESSAGE("modify nodes of cell " << this->GetMeshDS()->FromVtkToSmds(vtkVolId) << " domain " << idom);
         localClonedNodeIds.clear();
         for (itn = oldNodes.begin(); itn != oldNodes.end(); ++itn)
         {
@@ -12014,8 +11994,7 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
     TIDSortedElemSet::const_iterator elemItr = domain.begin();
     for ( ; elemItr != domain.end(); ++elemItr )
     {
-      SMDS_MeshElement* anElem = (SMDS_MeshElement*) *elemItr;
-      SMDS_MeshFace* aFace = dynamic_cast<SMDS_MeshFace*> (anElem);
+      const SMDS_MeshFace* aFace = meshDS->DownCast<SMDS_MeshFace> ( *elemItr );
       if (!aFace)
         continue;
       // MESSAGE("aFace=" << aFace->GetID());
@@ -12024,11 +12003,11 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
 
       // --- clone the nodes, create intermediate nodes for non medium nodes of a quad face
 
-      SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
+      SMDS_NodeIteratorPtr nodeIt = aFace->nodeIterator();
       while (nodeIt->more())
       {
-        const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*> (nodeIt->next());
-        bool isMedium = isQuad && (aFace->IsMediumNode(node));
+        const SMDS_MeshNode* node = nodeIt->next();
+        bool isMedium = ( isQuad && aFace->IsMediumNode( node ));
         if (isMedium)
           ln2.push_back(node);
         else
@@ -12136,7 +12115,7 @@ bool SMESH_MeshEditor::CreateFlatElementsOnFacesGroups(const std::vector<TIDSort
 
       // --- modify the face
 
-      aFace->ChangeNodes(&ln[0], ln.size());
+      const_cast<SMDS_MeshFace*>( aFace )->ChangeNodes( &ln[0], ln.size() );
     }
   }
   return true;
@@ -12247,7 +12226,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
 
   SMESHDS_Mesh *meshDS = this->myMesh->GetMeshDS();
   meshDS->BuildDownWardConnectivity(true);
-  SMDS_UnstructuredGrid* grid = meshDS->getGrid();
+  SMDS_UnstructuredGrid* grid = meshDS->GetGrid();
 
   // --- set of volumes detected inside
 
@@ -12274,7 +12253,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       while (volItr->more())
       {
         vol = (SMDS_MeshElement*)volItr->next();
-        setOfInsideVol.insert(vol->getVtkId());
+        setOfInsideVol.insert(vol->GetVtkID());
         sgrp->Add(vol->GetID());
       }
     }
@@ -12329,7 +12308,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
     while (volItr->more())
     {
       startVol = (SMDS_MeshElement*)volItr->next();
-      setOfVolToCheck.insert(startVol->getVtkId());
+      setOfVolToCheck.insert(startVol->GetVtkID());
     }
     if (setOfVolToCheck.empty())
     {
@@ -12348,7 +12327,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
     {
       std::set<int>::iterator it = setOfVolToCheck.begin();
       int vtkId = *it;
-      //MESSAGE("volume to check,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+      //MESSAGE("volume to check,  vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
       bool volInside = false;
       vtkIdType npts = 0;
       vtkIdType* pts = 0;
@@ -12382,14 +12361,14 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         if (distance2 < radius2)
         {
           volInside = true; // one or more nodes inside the domain
-          sgrp->Add(meshDS->fromVtkToSmds(vtkId));
+          sgrp->Add(meshDS->FromVtkToSmds(vtkId));
           break;
         }
       }
       if (volInside)
       {
         setOfInsideVol.insert(vtkId);
-        //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
         int neighborsVtkIds[NBMAXNEIGHBORS];
         int downIds[NBMAXNEIGHBORS];
         unsigned char downTypes[NBMAXNEIGHBORS];
@@ -12401,7 +12380,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       else
       {
         setOfOutsideVol.insert(vtkId);
-        //MESSAGE("  volume outside, vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("  volume outside, vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
       }
       setOfVolToCheck.erase(vtkId);
     }
@@ -12436,7 +12415,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       int vtkId = *it;
       if (grid->GetCellType(vtkId) == VTK_HEXAHEDRON)
       {
-        //MESSAGE("volume to recheck,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+        //MESSAGE("volume to recheck,  vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
         int countInside = 0;
         int neighborsVtkIds[NBMAXNEIGHBORS];
         int downIds[NBMAXNEIGHBORS];
@@ -12448,9 +12427,9 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         //MESSAGE("countInside " << countInside);
         if (countInside > 1)
         {
-          //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+          //MESSAGE("  volume inside,  vtkId " << vtkId << " smdsId " << meshDS->FromVtkToSmds(vtkId));
           setOfInsideVol.insert(vtkId);
-          sgrp->Add(meshDS->fromVtkToSmds(vtkId));
+          sgrp->Add(meshDS->FromVtkToSmds(vtkId));
           addedInside = true;
         }
         else
@@ -12471,7 +12450,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   for (; it != setOfInsideVol.end(); ++it)
   {
     int vtkId = *it;
-    //MESSAGE("  vtkId " << vtkId  << " smdsId " << meshDS->fromVtkToSmds(vtkId));
+    //MESSAGE("  vtkId " << vtkId  << " smdsId " << meshDS->FromVtkToSmds(vtkId));
     int neighborsVtkIds[NBMAXNEIGHBORS];
     int downIds[NBMAXNEIGHBORS];
     unsigned char downTypes[NBMAXNEIGHBORS];
@@ -12490,7 +12469,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]);
         if (vtkFaceId >= 0)
         {
-          sgrpi->Add(meshDS->fromVtkToSmds(vtkFaceId));
+          sgrpi->Add(meshDS->FromVtkToSmds(vtkFaceId));
           // find also the smds edges on this face
           int nbEdges = grid->getDownArray(downTypes[n])->getNumberOfDownCells(downIds[n]);
           const int* dEdges = grid->getDownArray(downTypes[n])->getDownCells(downIds[n]);
@@ -12499,7 +12478,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
           {
             int vtkEdgeId = grid->getDownArray(dTypes[i])->getVtkCellId(dEdges[i]);
             if (vtkEdgeId >= 0)
-              sgrpei->Add(meshDS->fromVtkToSmds(vtkEdgeId));
+              sgrpei->Add(meshDS->FromVtkToSmds(vtkEdgeId));
           }
         }
       }
@@ -12509,7 +12488,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
         skinFaces[face] = vtkId;
         int vtkFaceId = grid->getDownArray(downTypes[n])->getVtkCellId(downIds[n]);
         if (vtkFaceId >= 0)
-          sgrps->Add(meshDS->fromVtkToSmds(vtkFaceId));
+          sgrps->Add(meshDS->FromVtkToSmds(vtkFaceId));
       }
     }
   }
@@ -12528,7 +12507,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
   {
     const SMDS_MeshElement *elem = itelem->next();
     int shapeId = elem->getshapeId();
-    int vtkId = elem->getVtkId();
+    int   vtkId = elem->GetVtkID();
     if (!shapeIdToVtkIdSet.count(shapeId))
     {
       shapeIdToVtkIdSet[shapeId] = emptySet;
@@ -12563,7 +12542,7 @@ void SMESH_MeshEditor::CreateHoleSkin(double                          radius,
       {
         if (neighborsVtkIds[n]<0) // only smds faces are considered as neighbors here
           continue;
-        int smdsId = meshDS->fromVtkToSmds(neighborsVtkIds[n]);
+        int smdsId = meshDS->FromVtkToSmds(neighborsVtkIds[n]);
         const SMDS_MeshElement* elem = meshDS->FindElement(smdsId);
         if ( shapeIds.count(elem->getshapeId()) && !sgrps->Contains(elem)) // edge : neighbor in the set of shape, not in the group
         {
@@ -12717,7 +12696,7 @@ bool SMESH_MeshEditor::Make2DMeshFrom3D()
       // add new face based on volume nodes
       if (aMesh->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/false) )
       {
-        nbExisted++; // face already exsist
+        nbExisted++; // face already exists
       }
       else
       {
@@ -12803,7 +12782,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   if (elements.empty()) eIt = aMesh->elementsIterator(elemType);
   else                  eIt = SMESHUtils::elemSetIterator( elements );
 
-  while (eIt->more())
+  while ( eIt->more() )
   {
     const SMDS_MeshElement* elem = eIt->next();
     const int              iQuad = elem->IsQuadratic();
@@ -12884,7 +12863,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
     else if ( elem->GetType() == SMDSAbs_Face ) // elem is a face ------------------------
     {
       avoidSet.clear(), avoidSet.insert( elem );
-      elemNodes.assign( SMDS_MeshElement::iterator( elem->interlacedNodesElemIterator() ),
+      elemNodes.assign( SMDS_MeshElement::iterator( elem->interlacedNodesIterator() ),
                         SMDS_MeshElement::iterator() );
       elemNodes.push_back( elemNodes[0] );
       nodes.resize( 2 + iQuad );
@@ -12917,7 +12896,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
         tgtNodes.resize( srcNodes.size() );
         for ( inode = 0; inode < srcNodes.size(); ++inode )
           tgtNodes[inode] = getNodeWithSameID( tgtMeshDS, srcNodes[inode] );
-        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( tgtNodes,
+        if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( tgtNodes,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
@@ -12928,7 +12907,7 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
       for ( size_t i = 0; i < missingBndElems.size(); ++i )
       {
         TConnectivity& nodes = missingBndElems[ i ];
-        if ( aroundElements && tgtEditor.GetMeshDS()->FindElement( nodes,
+        if ( /*aroundElements && */tgtEditor.GetMeshDS()->FindElement( nodes,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
@@ -13038,7 +13017,7 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from,
 
   case SMDS_TOP_FACE:
   {
-    const SMDS_FacePosition* fPos = static_cast< const SMDS_FacePosition* >( pos );
+    SMDS_FacePositionPtr fPos = pos;
     GetMeshDS()->SetNodeOnFace( to, from->getshapeId(),
                                 fPos->GetUParameter(), fPos->GetVParameter() );
     break;
@@ -13046,7 +13025,7 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from,
   case SMDS_TOP_EDGE:
   {
     // WARNING: it is dangerous to set equal nodes on one EDGE!!!!!!!!
-    const SMDS_EdgePosition* ePos = static_cast< const SMDS_EdgePosition* >( pos );
+    SMDS_EdgePositionPtr ePos = pos;
     GetMeshDS()->SetNodeOnEdge( to, from->getshapeId(), ePos->GetUParameter() );
     break;
   }
@@ -13071,14 +13050,15 @@ namespace // utils for MakePolyLine
     std::vector< gp_XYZ >   myPoints;
     double                  myLength;
 
-    int                     mySrcPntInd; //!< start point index
     const SMDS_MeshElement* myFace;
-    SMESH_NodeXYZ           myNode1;
+    SMESH_NodeXYZ           myNode1; // nodes of the edge the path entered myFace
     SMESH_NodeXYZ           myNode2;
     int                     myNodeInd1;
     int                     myNodeInd2;
     double                  myDot1;
     double                  myDot2;
+
+    int                     mySrcPntInd; //!< start point index
     TIDSortedElemSet        myElemSet, myAvoidSet;
 
     Path(): myLength(0.0), myFace(0) {}
@@ -13271,6 +13251,7 @@ namespace // utils for MakePolyLine
       myErrors( theSegments.size() )
     {
     }
+
 #undef SMESH_CAUGHT
 #define SMESH_CAUGHT myErrors[i] =
     void operator() ( const int i ) const
@@ -13280,6 +13261,7 @@ namespace // utils for MakePolyLine
       SMESH_CATCH( SMESH::returnError );
     }
 #undef SMESH_CAUGHT
+
     //================================================================================
     /*!
      * \brief Compute a path of a given segment
@@ -13290,21 +13272,15 @@ namespace // utils for MakePolyLine
     {
       SMESH_MeshEditor::PolySegment& polySeg = mySegments[ iSeg ];
 
-      // get a cutting plane
-
-      gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
-      gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
-      if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
-      if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
-
-      gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
-      gp_XYZ plnOrig = p2;
+      // the cutting plane
+      gp_XYZ plnNorm = ( polySeg.myXYZ[0] - polySeg.myXYZ[1] ) ^ polySeg.myVector.XYZ();
+      gp_XYZ plnOrig = polySeg.myXYZ[1];
 
-      // find paths connecting the 2 end points of polySeg
+      // Find paths connecting the 2 end points of polySeg
 
       std::vector< Path > paths; paths.reserve(10);
 
-      // initialize paths
+      // 1) initialize paths; two paths starts at each end point
 
       for ( int iP = 0; iP < 2; ++iP ) // loop on the polySeg end points
       {
@@ -13312,8 +13288,76 @@ namespace // utils for MakePolyLine
         path.mySrcPntInd = iP;
         size_t nbPaths = paths.size();
 
+        if ( polySeg.myFace[ iP ]) // the end point lies on polySeg.myFace[ iP ]
+        {
+          // check coincidence of polySeg.myXYZ[ iP ] with nodes
+          const double tol = 1e-20;
+          SMESH_NodeXYZ nodes[4];
+          for ( int i = 0; i < 3 &&  !polySeg.myNode1[ iP ]; ++i )
+          {
+            nodes[ i ] = polySeg.myFace[ iP ]->GetNode( i );
+            if (( nodes[ i ] - polySeg.myXYZ[ iP ]).SquareModulus() < tol*tol )
+              polySeg.myNode1[ iP ] = nodes[ i ].Node();
+          }
+          nodes[ 3 ] = nodes[ 0 ];
+
+          // check coincidence of polySeg.myXYZ[ iP ] with edges
+          for ( int i = 0; i < 3 &&  !polySeg.myNode1[ iP ]; ++i )
+          {
+            SMDS_LinearEdge edge( nodes[i].Node(), nodes[i+1].Node() );
+            if ( SMESH_MeshAlgos::GetDistance( &edge, polySeg.myXYZ[ iP ]) < tol )
+            {
+              polySeg.myNode1[ iP ] = nodes[ i     ].Node();
+              polySeg.myNode2[ iP ] = nodes[ i + 1 ].Node();
+            }
+          }
+
+          if ( !polySeg.myNode1[ iP ] ) // polySeg.myXYZ[ iP ] is within polySeg.myFace[ iP ]
+          {
+            double dot[ 4 ];
+            for ( int i = 0; i < 3; ++i )
+              dot[ i ] = plnNorm * ( nodes[ i ] - plnOrig );
+            dot[ 3 ] = dot[ 0 ];
+
+            int iCut = 0; // index of a cut edge
+            if      ( dot[ 1 ] * dot[ 2 ] < 0. ) iCut = 1;
+            else if ( dot[ 2 ] * dot[ 3 ] < 0. ) iCut = 2;
+
+            // initialize path so as if it entered the face via iCut-th edge
+            path.myFace = polySeg.myFace[ iP ];
+            path.myNodeInd1 = iCut;
+            path.myNodeInd2 = iCut + 1;
+            path.myNode1.Set( nodes[ iCut     ].Node() );
+            path.myNode2.Set( nodes[ iCut + 1 ].Node() );
+            path.myDot1 = dot[ iCut ];
+            path.myDot2 = dot[ iCut + 1 ];
+            path.myPoints.clear();
+            path.AddPoint( polySeg.myXYZ[ iP ]);
+            paths.push_back( path );
+
+            path.Extend( plnNorm, plnOrig ); // to get another edge cut
+            path.myFace = polySeg.myFace[ iP ];
+            if ( path.myDot1 == 0. ) // cut at a node
+            {
+              path.myNodeInd1 = ( iCut + 2 ) % 3;
+              path.myNodeInd2 = ( iCut + 3 ) % 3;
+              path.myNode2.Set( path.myFace->GetNode( path.myNodeInd2 ));
+              path.myDot2 = dot[ path.myNodeInd2 ];
+            }
+            else
+            {
+              path.myNodeInd1 = path.myFace->GetNodeIndex( path.myNode1.Node() );
+              path.myNodeInd2 = path.myFace->GetNodeIndex( path.myNode2.Node() );
+            }
+            path.myPoints.clear();
+            path.AddPoint( polySeg.myXYZ[ iP ]);
+            paths.push_back( path );
+          }
+        }
+
         if ( polySeg.myNode2[ iP ] && polySeg.myNode2[ iP ] != polySeg.myNode1[ iP ] )
         {
+          // the end point is on an edge
           while (( path.myFace = SMESH_MeshAlgos::FindFaceInSet( polySeg.myNode1[ iP ],
                                                                  polySeg.myNode2[ iP ],
                                                                  path.myElemSet,
@@ -13326,7 +13370,7 @@ namespace // utils for MakePolyLine
             path.myDot1 = plnNorm * ( path.myNode1 - plnOrig );
             path.myDot2 = plnNorm * ( path.myNode2 - plnOrig );
             path.myPoints.clear();
-            path.AddPoint( 0.5 * ( path.myNode1 + path.myNode2 ));
+            path.AddPoint( polySeg.myXYZ[ iP ]);
             path.myAvoidSet.insert( path.myFace );
             paths.push_back( path );
           }
@@ -13334,7 +13378,7 @@ namespace // utils for MakePolyLine
             throw SALOME_Exception ( SMESH_Comment("No face edge found by point ") << iP+1
                                      << " in a PolySegment " << iSeg );
         }
-        else // an end point is at node
+        else if ( polySeg.myNode1[ iP ] ) // the end point is at a node
         {
           std::set<const SMDS_MeshNode* > nodes;
           SMDS_ElemIteratorPtr fIt = polySeg.myNode1[ iP ]->GetInverseElementIterator(SMDSAbs_Face);
@@ -13361,7 +13405,7 @@ namespace // utils for MakePolyLine
             }
       }
 
-      // extend paths
+      // 2) extend paths and compose the shortest one connecting the two points
 
       myPaths[ iSeg ].myLength = 1e100;
 
@@ -13370,7 +13414,7 @@ namespace // utils for MakePolyLine
         for ( size_t i = 0; i < paths.size(); ++i )
         {
           Path& path = paths[ i ];
-          if ( !path.Extend( plnNorm, plnOrig ) ||         // path reached a mesh boundary
+          if ( !path.Extend( plnNorm, plnOrig ) ||        // path reached a mesh boundary
                path.myLength > myPaths[ iSeg ].myLength ) // path is longer than others
           {
             Path::Remove( paths, i );
@@ -13445,6 +13489,18 @@ void SMESH_MeshEditor::MakePolyLine( TListOfPolySegments&   theSegments,
     if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
     if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
 
+    polySeg.myFace[0] = polySeg.myFace[1] = 0;
+    if ( !polySeg.myNode1[0] && !polySeg.myNode2[0] )
+    {
+      p1 = searcher->Project( polySeg.myXYZ[0], SMDSAbs_Face, &polySeg.myFace[0] );
+    }
+    if ( !polySeg.myNode1[1] && !polySeg.myNode2[1] )
+    {
+      p2 = searcher->Project( polySeg.myXYZ[1], SMDSAbs_Face, &polySeg.myFace[1] );
+    }
+    polySeg.myXYZ[0] = p1;
+    polySeg.myXYZ[1] = p2;
+
     gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
 
     isVectorOK[ iSeg ] = ( plnNorm.Modulus() > std::numeric_limits<double>::min() );