Salome HOME
Fix of 20128 issue (EDF SMESH 926 : Quadratic conversion of BLSURF mesh).
[modules/smesh.git] / src / SMESH / SMESH_MesherHelper.cxx
index c3e420317ad626a35470b08c8dfd25b6d74c0384..292c29ecb7fc8964985f66f29ef4b03eaae0c53c 100644 (file)
@@ -1,28 +1,28 @@
-// Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
 //
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-// This library is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
 //
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
 //
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 // File:      SMESH_MesherHelper.cxx
 // Created:   15.02.06 15:22:41
 // Author:    Sergey KUUL
-// Copyright: Open CASCADE 2006
-
-
+//
 #include "SMESH_MesherHelper.hxx"
 
 #include "SMDS_FacePosition.hxx" 
 #include <BRepAdaptor_Surface.hxx>
 #include <BRepTools.hxx>
 #include <BRep_Tool.hxx>
+#include <BRepTools_WireExplorer.hxx>
 #include <Geom2d_Curve.hxx>
 #include <Geom_Curve.hxx>
 #include <Geom_Surface.hxx>
+#include <ShapeAnalysis.hxx>
+#include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <TopoDS.hxx>
 #include <gp_Pnt2d.hxx>
-#include <ShapeAnalysis.hxx>
+
+#include <Standard_Failure.hxx>
+#include <Standard_ErrorHandler.hxx>
 
 #include <utilities.h>
 
 #define RETURN_BAD_RESULT(msg) { MESSAGE(msg); return false; }
 
+//================================================================================
+/*!
+ * \brief Constructor
+ */
+//================================================================================
+
+SMESH_MesherHelper::SMESH_MesherHelper(SMESH_Mesh& theMesh)
+  : myMesh(&theMesh), myShapeID(-1), myCreateQuadratic(false)
+{
+  mySetElemOnShape = ( ! myMesh->HasShapeToMesh() );
+}
+
 //=======================================================================
 //function : CheckShape
 //purpose  : 
@@ -57,6 +76,7 @@ bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh)
   // also we have to fill myNLinkNodeMap
   myCreateQuadratic = true;
   mySeamShapeIds.clear();
+  myDegenShapeIds.clear();
   TopAbs_ShapeEnum subType( aSh.ShapeType()==TopAbs_FACE ? TopAbs_EDGE : TopAbs_FACE );
   SMDSAbs_ElementType elemType( subType==TopAbs_FACE ? SMDSAbs_Face : SMDSAbs_Edge );
 
@@ -115,7 +135,7 @@ void SMESH_MesherHelper::SetSubShape(const int aShID)
   if ( aShID == myShapeID )
     return;
   if ( aShID > 1 )
-    SetSubShape( GetMesh()->GetMeshDS()->IndexToShape( aShID ));
+    SetSubShape( GetMeshDS()->IndexToShape( aShID ));
   else
     SetSubShape( TopoDS_Shape() );
 }
@@ -134,6 +154,7 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
 
   myShape = aSh;
   mySeamShapeIds.clear();
+  myDegenShapeIds.clear();
 
   if ( myShape.IsNull() ) {
     myShapeID  = -1;
@@ -149,8 +170,9 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
     BRepAdaptor_Surface surface( face );
     if ( surface.IsUPeriodic() || surface.IsVPeriodic() )
     {
-      // look for a seam edge
-      for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next()) {
+      for (TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next())
+      {
+        // look for a seam edge
         const TopoDS_Edge& edge = TopoDS::Edge( exp.Current() );
         if ( BRep_Tool::IsClosed( edge, face )) {
           // initialize myPar1, myPar2 and myParIndex
@@ -169,10 +191,20 @@ void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
               myPar2 = surface.LastVParameter();
             }
           }
-          // store shapes indices
-          mySeamShapeIds.insert( meshDS->ShapeToIndex( exp.Current() ));
-          for ( TopExp_Explorer v( exp.Current(), TopAbs_VERTEX ); v.More(); v.Next() )
-            mySeamShapeIds.insert( meshDS->ShapeToIndex( v.Current() ));
+          // store seam shape indices, negative if shape encounters twice
+          int edgeID = meshDS->ShapeToIndex( edge );
+          mySeamShapeIds.insert( IsSeamShape( edgeID ) ? -edgeID : edgeID );
+          for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() ) {
+            int vertexID = meshDS->ShapeToIndex( v.Current() );
+            mySeamShapeIds.insert( IsSeamShape( vertexID ) ? -vertexID : vertexID );
+          }
+        }
+
+        // look for a degenerated edge
+        if ( BRep_Tool::Degenerated( edge )) {
+          myDegenShapeIds.insert( meshDS->ShapeToIndex( edge ));
+          for ( TopExp_Explorer v( edge, TopAbs_VERTEX ); v.More(); v.Next() )
+            myDegenShapeIds.insert( meshDS->ShapeToIndex( v.Current() ));
         }
       }
     }
@@ -282,24 +314,68 @@ gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face&   F,
     // edge and recieve value from this pcurve
     const SMDS_EdgePosition* epos =
       static_cast<const SMDS_EdgePosition*>(n->GetPosition().get());
-    SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS();
+    SMESHDS_Mesh* meshDS = GetMeshDS();
     int edgeID = Pos->GetShapeId();
     TopoDS_Edge E = TopoDS::Edge(meshDS->IndexToShape(edgeID));
     double f, l;
-    TopLoc_Location loc;
     Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
     uv = C2d->Value( epos->GetUParameter() );
     // for a node on a seam edge select one of UVs on 2 pcurves
-    if ( n2 && mySeamShapeIds.find( edgeID ) != mySeamShapeIds.end() )
+    if ( n2 && IsSeamShape( edgeID ) )
       uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
   }
   else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX)
   {
-    int vertexID = n->GetPosition()->GetShapeId();
-    const TopoDS_Vertex& V = TopoDS::Vertex(GetMeshDS()->IndexToShape(vertexID));
-    uv = BRep_Tool::Parameters( V, F );
-    if ( n2 && mySeamShapeIds.find( vertexID ) != mySeamShapeIds.end() )
-      uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
+    if ( int vertexID = n->GetPosition()->GetShapeId() ) {
+      bool ok = true;
+      const TopoDS_Vertex& V = TopoDS::Vertex(GetMeshDS()->IndexToShape(vertexID));
+      try {
+        uv = BRep_Tool::Parameters( V, F );
+      }
+      catch (Standard_Failure& exc) {
+        ok = false;
+      }
+      if ( !ok ) {
+        for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !ok && vert.More(); vert.Next() )
+          ok = ( V == vert.Current() );
+        if ( !ok ) {
+#ifdef _DEBUG_
+          MESSAGE ( "SMESH_MesherHelper::GetNodeUV(); Vertex " << vertexID
+               << " not in face " << GetMeshDS()->ShapeToIndex( F ) );
+#endif
+          // get UV of a vertex closest to the node
+          double dist = 1e100;
+          gp_Pnt pn ( n->X(),n->Y(),n->Z() );
+          for ( TopExp_Explorer vert(F,TopAbs_VERTEX); !ok && vert.More(); vert.Next() ) {
+            TopoDS_Vertex curV = TopoDS::Vertex( vert.Current() );
+            gp_Pnt p = BRep_Tool::Pnt( curV );
+            double curDist = p.SquareDistance( pn );
+            if ( curDist < dist ) {
+              dist = curDist;
+              uv = BRep_Tool::Parameters( curV, F );
+              if ( dist < DBL_MIN ) break;
+            }
+          }
+        }
+        else {
+          TopTools_ListIteratorOfListOfShape it( myMesh->GetAncestors( V ));
+          for ( ; it.More(); it.Next() ) {
+            if ( it.Value().ShapeType() == TopAbs_EDGE ) {
+              const TopoDS_Edge & edge = TopoDS::Edge( it.Value() );
+              double f,l;
+              Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edge, F, f, l);
+              if ( !C2d.IsNull() ) {
+                double u = ( V == TopExp::FirstVertex( edge ) ) ?  f : l;
+                uv = C2d->Value( u );
+                break;
+              }
+            }
+          }
+        }
+      }
+      if ( n2 && IsSeamShape( vertexID ) )
+        uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
+    }
   }
   return uv.XY();
 }
@@ -326,7 +402,7 @@ double SMESH_MesherHelper::GetNodeU(const TopoDS_Edge&   E,
     param =  epos->GetUParameter();
   }
   else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX) {
-    SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+    SMESHDS_Mesh * meshDS = GetMeshDS();
     int vertexID = n->GetPosition()->GetShapeId();
     const TopoDS_Vertex& V = TopoDS::Vertex(meshDS->IndexToShape(vertexID));
     param =  BRep_Tool::Parameter( V, E );
@@ -393,6 +469,11 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
        gp_XY p1 = GetNodeUV(F,n1,n2);
         gp_XY p2 = GetNodeUV(F,n2,n1);
 
+       if ( IsDegenShape( Pos1->GetShapeId() ))
+         p1.SetCoord( myParIndex, p2.Coord( myParIndex ));
+       else if ( IsDegenShape( Pos2->GetShapeId() ))
+         p2.SetCoord( myParIndex, p1.Coord( myParIndex ));
+
        //checking if surface is periodic
        Handle(Geom_Surface) S = BRep_Tool::Surface(F);
        Standard_Real UF,UL,VF,VL;
@@ -478,68 +559,108 @@ const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
 }
 
 //=======================================================================
-//function : AddQuadraticEdge
-//purpose  : 
+/*!
+ * Creates a node
+ */
 //=======================================================================
-/**
- * Special function for creation quadratic edge
+
+SMDS_MeshNode* SMESH_MesherHelper::AddNode(double x, double y, double z, int ID)
+{
+  SMESHDS_Mesh * meshDS = GetMeshDS();
+  SMDS_MeshNode* node = 0;
+  if ( ID )
+    node = meshDS->AddNodeWithID( x, y, z, ID );
+  else
+    node = meshDS->AddNode( x, y, z );
+  if ( mySetElemOnShape && myShapeID > 0 ) {
+    switch ( myShape.ShapeType() ) {
+    case TopAbs_SOLID:  meshDS->SetNodeInVolume( node, myShapeID); break;
+    case TopAbs_SHELL:  meshDS->SetNodeInVolume( node, myShapeID); break;
+    case TopAbs_FACE:   meshDS->SetNodeOnFace(   node, myShapeID); break;
+    case TopAbs_EDGE:   meshDS->SetNodeOnEdge(   node, myShapeID); break;
+    case TopAbs_VERTEX: meshDS->SetNodeOnVertex( node, myShapeID); break;
+    default: ;
+    }
+  }
+  return node;
+}
+
+//=======================================================================
+/*!
+ * Creates quadratic or linear edge
  */
-SMDS_QuadraticEdge* SMESH_MesherHelper::AddQuadraticEdge(const SMDS_MeshNode* n1,
-                                                         const SMDS_MeshNode* n2,
-                                                         const int id,
-                                                        const bool force3d)
+//=======================================================================
+
+SMDS_MeshEdge* SMESH_MesherHelper::AddEdge(const SMDS_MeshNode* n1,
+                                                const SMDS_MeshNode* n2,
+                                                const int id,
+                                                const bool force3d)
 {
-  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  SMESHDS_Mesh * meshDS = GetMeshDS();
   
-  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
-  
-  myCreateQuadratic = true;
+  SMDS_MeshEdge* edge = 0;
+  if (myCreateQuadratic) {
+    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
+    if(id)
+      edge = meshDS->AddEdgeWithID(n1, n2, n12, id);
+    else
+      edge = meshDS->AddEdge(n1, n2, n12);
+  }
+  else {
+    if(id)
+      edge = meshDS->AddEdgeWithID(n1, n2, id);
+    else
+      edge = meshDS->AddEdge(n1, n2);
+  }
 
-  if(id)
-    return  (SMDS_QuadraticEdge*)(meshDS->AddEdgeWithID(n1, n2, n12, id));
-  else
-    return  (SMDS_QuadraticEdge*)(meshDS->AddEdge(n1, n2, n12));
+  if ( mySetElemOnShape && myShapeID > 0 )
+    meshDS->SetMeshElementOnShape( edge, myShapeID );
+
+  return edge;
 }
 
-//=======================================================================
-//function : AddFace
-//purpose  : 
 //=======================================================================
 /*!
- * Special function for creation quadratic triangle
+ * Creates quadratic or linear triangle
  */
+//=======================================================================
+
 SMDS_MeshFace* SMESH_MesherHelper::AddFace(const SMDS_MeshNode* n1,
                                            const SMDS_MeshNode* n2,
                                            const SMDS_MeshNode* n3,
                                            const int id,
                                           const bool force3d)
 {
-  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  SMESHDS_Mesh * meshDS = GetMeshDS();
+  SMDS_MeshFace* elem = 0;
   if(!myCreateQuadratic) {
     if(id)
-      return  meshDS->AddFaceWithID(n1, n2, n3, id);
+      elem = meshDS->AddFaceWithID(n1, n2, n3, id);
     else
-      return  meshDS->AddFace(n1, n2, n3);
+      elem = meshDS->AddFace(n1, n2, n3);
   }
+  else {
+    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
+    const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
+    const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
 
-  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
-  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
-  const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
+    if(id)
+      elem = meshDS->AddFaceWithID(n1, n2, n3, n12, n23, n31, id);
+    else
+      elem = meshDS->AddFace(n1, n2, n3, n12, n23, n31);
+  }
+  if ( mySetElemOnShape && myShapeID > 0 )
+    meshDS->SetMeshElementOnShape( elem, myShapeID );
 
-  if(id)
-    return  meshDS->AddFaceWithID(n1, n2, n3, n12, n23, n31, id);
-  else
-    return  meshDS->AddFace(n1, n2, n3, n12, n23, n31);
+  return elem;
 }
 
-
-//=======================================================================
-//function : AddFace
-//purpose  : 
 //=======================================================================
 /*!
- * Special function for creation quadratic quadrangle
+ * Creates quadratic or linear quadrangle
  */
+//=======================================================================
+
 SMDS_MeshFace* SMESH_MesherHelper::AddFace(const SMDS_MeshNode* n1,
                                            const SMDS_MeshNode* n2,
                                            const SMDS_MeshNode* n3,
@@ -547,33 +668,37 @@ SMDS_MeshFace* SMESH_MesherHelper::AddFace(const SMDS_MeshNode* n1,
                                            const int id,
                                           const bool force3d)
 {
-  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  SMESHDS_Mesh * meshDS = GetMeshDS();
+  SMDS_MeshFace* elem = 0;
   if(!myCreateQuadratic) {
     if(id)
-      return  meshDS->AddFaceWithID(n1, n2, n3, n4, id);
+      elem = meshDS->AddFaceWithID(n1, n2, n3, n4, id);
     else
-      return  meshDS->AddFace(n1, n2, n3, n4);
+      elem = meshDS->AddFace(n1, n2, n3, n4);
   }
+  else {
+    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
+    const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
+    const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
+    const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);
 
-  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
-  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
-  const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
-  const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);
+    if(id)
+      elem = meshDS->AddFaceWithID(n1, n2, n3, n4, n12, n23, n34, n41, id);
+    else
+      elem = meshDS->AddFace(n1, n2, n3, n4, n12, n23, n34, n41);
+  }
+  if ( mySetElemOnShape && myShapeID > 0 )
+    meshDS->SetMeshElementOnShape( elem, myShapeID );
 
-  if(id)
-    return  meshDS->AddFaceWithID(n1, n2, n3, n4, n12, n23, n34, n41, id);
-  else
-    return  meshDS->AddFace(n1, n2, n3, n4, n12, n23, n34, n41);
+  return elem;
 }
 
-
-//=======================================================================
-//function : AddVolume
-//purpose  : 
 //=======================================================================
 /*!
- * Special function for creation quadratic volume
+ * Creates quadratic or linear volume
  */
+//=======================================================================
+
 SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
                                                const SMDS_MeshNode* n2,
                                                const SMDS_MeshNode* n3,
@@ -583,37 +708,43 @@ SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
                                                const int id,
                                               const bool force3d)
 {
-  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  SMESHDS_Mesh * meshDS = GetMeshDS();
+  SMDS_MeshVolume* elem = 0;
   if(!myCreateQuadratic) {
     if(id)
-      return meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, id);
+      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, id);
     else
-      return meshDS->AddVolume(n1, n2, n3, n4, n5, n6);
+      elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6);
   }
+  else {
+    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
+    const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
+    const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
 
-  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
-  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
-  const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
+    const SMDS_MeshNode* n45 = GetMediumNode(n4,n5,force3d);
+    const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,force3d);
+    const SMDS_MeshNode* n64 = GetMediumNode(n6,n4,force3d);
 
-  const SMDS_MeshNode* n45 = GetMediumNode(n4,n5,force3d);
-  const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,force3d);
-  const SMDS_MeshNode* n64 = GetMediumNode(n6,n4,force3d);
+    const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,force3d);
+    const SMDS_MeshNode* n25 = GetMediumNode(n2,n5,force3d);
+    const SMDS_MeshNode* n36 = GetMediumNode(n3,n6,force3d);
 
-  const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,force3d);
-  const SMDS_MeshNode* n25 = GetMediumNode(n2,n5,force3d);
-  const SMDS_MeshNode* n36 = GetMediumNode(n3,n6,force3d);
+    if(id)
+      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, 
+                                     n12, n23, n31, n45, n56, n64, n14, n25, n36, id);
+    else
+      elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6,
+                               n12, n23, n31, n45, n56, n64, n14, n25, n36);
+  }
+  if ( mySetElemOnShape && myShapeID > 0 )
+    meshDS->SetMeshElementOnShape( elem, myShapeID );
 
-  if(id)
-    return meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, 
-                                   n12, n23, n31, n45, n56, n64, n14, n25, n36, id);
-  else
-    return meshDS->AddVolume(n1, n2, n3, n4, n5, n6,
-                             n12, n23, n31, n45, n56, n64, n14, n25, n36);
+  return elem;
 }
 
 //=======================================================================
 /*!
- * Special function for creation quadratic volume
+ * Creates quadratic or linear volume
  */
 //=======================================================================
 
@@ -624,31 +755,37 @@ SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
                                                const int id, 
                                               const bool force3d)
 {
-  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  SMESHDS_Mesh * meshDS = GetMeshDS();
+  SMDS_MeshVolume* elem = 0;
   if(!myCreateQuadratic) {
     if(id)
-      return meshDS->AddVolumeWithID(n1, n2, n3, n4, id);
+      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, id);
     else
-      return meshDS->AddVolume(n1, n2, n3, n4);
+      elem = meshDS->AddVolume(n1, n2, n3, n4);
   }
+  else {
+    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
+    const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
+    const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
 
-  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
-  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
-  const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
+    const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,force3d);
+    const SMDS_MeshNode* n24 = GetMediumNode(n2,n4,force3d);
+    const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
 
-  const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,force3d);
-  const SMDS_MeshNode* n24 = GetMediumNode(n2,n4,force3d);
-  const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
+    if(id)
+      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34, id);
+    else
+      elem = meshDS->AddVolume(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34);
+  }
+  if ( mySetElemOnShape && myShapeID > 0 )
+    meshDS->SetMeshElementOnShape( elem, myShapeID );
 
-  if(id)
-    return meshDS->AddVolumeWithID(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34, id);
-  else
-    return meshDS->AddVolume(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34);
+  return elem;
 }
 
 //=======================================================================
 /*!
- * Special function for creation quadratic pyramid
+ * Creates quadratic or linear pyramid
  */
 //=======================================================================
 
@@ -660,37 +797,43 @@ SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
                                                const int id, 
                                               const bool force3d)
 {
+  SMDS_MeshVolume* elem = 0;
   if(!myCreateQuadratic) {
     if(id)
-      return GetMeshDS()->AddVolumeWithID(n1, n2, n3, n4, n5, id);
+      elem = GetMeshDS()->AddVolumeWithID(n1, n2, n3, n4, n5, id);
     else
-      return GetMeshDS()->AddVolume(n1, n2, n3, n4, n5);
+      elem = GetMeshDS()->AddVolume(n1, n2, n3, n4, n5);
   }
+  else {
+    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
+    const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
+    const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
+    const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);
 
-  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
-  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
-  const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
-  const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);
+    const SMDS_MeshNode* n15 = GetMediumNode(n1,n5,force3d);
+    const SMDS_MeshNode* n25 = GetMediumNode(n2,n5,force3d);
+    const SMDS_MeshNode* n35 = GetMediumNode(n3,n5,force3d);
+    const SMDS_MeshNode* n45 = GetMediumNode(n4,n5,force3d);
 
-  const SMDS_MeshNode* n15 = GetMediumNode(n1,n5,force3d);
-  const SMDS_MeshNode* n25 = GetMediumNode(n2,n5,force3d);
-  const SMDS_MeshNode* n35 = GetMediumNode(n3,n5,force3d);
-  const SMDS_MeshNode* n45 = GetMediumNode(n4,n5,force3d);
+    if(id)
+      elem = GetMeshDS()->AddVolumeWithID ( n1,  n2,  n3,  n4,  n5,
+                                            n12, n23, n34, n41,
+                                            n15, n25, n35, n45,
+                                            id);
+    else
+      elem = GetMeshDS()->AddVolume( n1,  n2,  n3,  n4,  n5,
+                                     n12, n23, n34, n41,
+                                     n15, n25, n35, n45);
+  }
+  if ( mySetElemOnShape && myShapeID > 0 )
+    GetMeshDS()->SetMeshElementOnShape( elem, myShapeID );
 
-  if(id)
-    return GetMeshDS()->AddVolumeWithID ( n1,  n2,  n3,  n4,  n5,
-                                          n12, n23, n34, n41,
-                                          n15, n25, n35, n45,
-                                          id);
-  else
-    return GetMeshDS()->AddVolume( n1,  n2,  n3,  n4,  n5,
-                                   n12, n23, n34, n41,
-                                   n15, n25, n35, n45);
+  return elem;
 }
 
 //=======================================================================
 /*!
- * Special function for creation of quadratic hexahedron
+ * Creates quadratic or linear hexahedron
  */
 //=======================================================================
 
@@ -705,53 +848,59 @@ SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
                                                const int id,
                                               const bool force3d)
 {
-  SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
+  SMESHDS_Mesh * meshDS = GetMeshDS();
+  SMDS_MeshVolume* elem = 0;
   if(!myCreateQuadratic) {
     if(id)
-      return meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, id);
+      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, id);
     else
-      return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8);
+      elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8);
   }
+  else {
+    const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
+    const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
+    const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
+    const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);
 
-  const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
-  const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
-  const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
-  const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);
+    const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,force3d);
+    const SMDS_MeshNode* n67 = GetMediumNode(n6,n7,force3d);
+    const SMDS_MeshNode* n78 = GetMediumNode(n7,n8,force3d);
+    const SMDS_MeshNode* n85 = GetMediumNode(n8,n5,force3d);
 
-  const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,force3d);
-  const SMDS_MeshNode* n67 = GetMediumNode(n6,n7,force3d);
-  const SMDS_MeshNode* n78 = GetMediumNode(n7,n8,force3d);
-  const SMDS_MeshNode* n85 = GetMediumNode(n8,n5,force3d);
+    const SMDS_MeshNode* n15 = GetMediumNode(n1,n5,force3d);
+    const SMDS_MeshNode* n26 = GetMediumNode(n2,n6,force3d);
+    const SMDS_MeshNode* n37 = GetMediumNode(n3,n7,force3d);
+    const SMDS_MeshNode* n48 = GetMediumNode(n4,n8,force3d);
 
-  const SMDS_MeshNode* n15 = GetMediumNode(n1,n5,force3d);
-  const SMDS_MeshNode* n26 = GetMediumNode(n2,n6,force3d);
-  const SMDS_MeshNode* n37 = GetMediumNode(n3,n7,force3d);
-  const SMDS_MeshNode* n48 = GetMediumNode(n4,n8,force3d);
+    if(id)
+      elem = meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8,
+                                     n12, n23, n34, n41, n56, n67,
+                                     n78, n85, n15, n26, n37, n48, id);
+    else
+      elem = meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8,
+                               n12, n23, n34, n41, n56, n67,
+                               n78, n85, n15, n26, n37, n48);
+  }
+  if ( mySetElemOnShape && myShapeID > 0 )
+    meshDS->SetMeshElementOnShape( elem, myShapeID );
 
-  if(id)
-    return meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8,
-                                   n12, n23, n34, n41, n56, n67,
-                                   n78, n85, n15, n26, n37, n48, id);
-  else
-    return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8,
-                             n12, n23, n34, n41, n56, n67,
-                             n78, n85, n15, n26, n37, n48);
+  return elem;
 }
 
 //=======================================================================
-  /*!
  * \brief Load nodes bound to face into a map of node columns
   * \param theParam2ColumnMap - map of node columns to fill
   * \param theFace - the face on which nodes are searched for
   * \param theBaseEdge - the edge nodes of which are columns' bases
   * \param theMesh - the mesh containing nodes
   * \retval bool - false if something is wrong
  
  * The key of the map is a normalized parameter of each
  * base node on theBaseEdge.
  * This method works in supposition that nodes on the face
  * forms a rectangular grid and elements can be quardrangles or triangles
  */
+/*!
+ * \brief Load nodes bound to face into a map of node columns
+ * \param theParam2ColumnMap - map of node columns to fill
+ * \param theFace - the face on which nodes are searched for
+ * \param theBaseEdge - the edge nodes of which are columns' bases
+ * \param theMesh - the mesh containing nodes
+ * \retval bool - false if something is wrong
+ * 
+ * The key of the map is a normalized parameter of each
+ * base node on theBaseEdge.
+ * This method works in supposition that nodes on the face
+ * forms a rectangular grid and elements can be quardrangles or triangles
+ */
 //=======================================================================
 
 bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
@@ -853,14 +1002,14 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
 
   // load nodes from theBaseEdge
 
-  set<const SMDS_MeshNode*> loadedNodes;
+  std::set<const SMDS_MeshNode*> loadedNodes;
   const SMDS_MeshNode* nullNode = 0;
 
-  vector<const SMDS_MeshNode*> & nVecf = theParam2ColumnMap[ 0.];
+  std::vector<const SMDS_MeshNode*> & nVecf = theParam2ColumnMap[ 0.];
   nVecf.resize( vsize, nullNode );
   loadedNodes.insert( nVecf[ 0 ] = smVfb->GetNodes()->next() );
 
-  vector<const SMDS_MeshNode*> & nVecl = theParam2ColumnMap[ 1.];
+  std::vector<const SMDS_MeshNode*> & nVecl = theParam2ColumnMap[ 1.];
   nVecl.resize( vsize, nullNode );
   loadedNodes.insert( nVecl[ 0 ] = smVlb->GetNodes()->next() );
 
@@ -871,7 +1020,7 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
   const SMDS_MeshNode* node;
   while ( nIt->more() ) {
     node = nIt->next();
-    if(IsMedium(node))
+    if(IsMedium(node, SMDSAbs_Edge))
       continue;
     const SMDS_EdgePosition* pos =
       dynamic_cast<const SMDS_EdgePosition*>( node->GetPosition().get() );
@@ -879,7 +1028,7 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
       return false;
     }
     double u = ( pos->GetUParameter() - f ) / range;
-    vector<const SMDS_MeshNode*> & nVec = theParam2ColumnMap[ u ];
+    std::vector<const SMDS_MeshNode*> & nVec = theParam2ColumnMap[ u ];
     nVec.resize( vsize, nullNode );
     loadedNodes.insert( nVec[ 0 ] = node );
   }
@@ -889,7 +1038,7 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
 
   // load nodes from e1
 
-  map< double, const SMDS_MeshNode*> sortedNodes; // sort by param on edge
+  std::map< double, const SMDS_MeshNode*> sortedNodes; // sort by param on edge
   nIt = sm1->GetNodes();
   while ( nIt->more() ) {
     node = nIt->next();
@@ -900,10 +1049,10 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
     if ( !pos ) {
       return false;
     }
-    sortedNodes.insert( make_pair( pos->GetUParameter(), node ));
+    sortedNodes.insert( std::make_pair( pos->GetUParameter(), node ));
   }
   loadedNodes.insert( nVecf[ vsize - 1 ] = smVft->GetNodes()->next() );
-  map< double, const SMDS_MeshNode*>::iterator u_n = sortedNodes.begin();
+  std::map< double, const SMDS_MeshNode*>::iterator u_n = sortedNodes.begin();
   int row  = rev1 ? vsize - 1 : 0;
   int dRow = rev1 ? -1 : +1;
   for ( ; u_n != sortedNodes.end(); u_n++ ) {
@@ -914,12 +1063,12 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
   // try to load the rest nodes
 
   // get all faces from theFace
-  map<int,const SMDS_MeshElement*> allFaces, foundFaces;
+  TIDSortedElemSet allFaces, foundFaces;
   eIt = smFace->GetElements();
   while ( eIt->more() ) {
     const SMDS_MeshElement* e = eIt->next();
     if ( e->GetType() == SMDSAbs_Face )
-      allFaces.insert( make_pair(e->GetID(),e) );
+      allFaces.insert( e );
   }
   // Starting from 2 neighbour nodes on theBaseEdge, look for a face
   // the nodes belong to, and between the nodes of the found face,
@@ -967,7 +1116,7 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
             RETURN_BAD_RESULT( "Too many nodes in column "<< col <<": "<< row+1);
           }
           par_nVec_2->second[ row ] = node;
-          foundFaces.insert( make_pair(face->GetID(),face) );
+          foundFaces.insert( face );
           n2 = node;
           if ( nbFaceNodes==4 ) {
             n1 = par_nVec_1->second[ row ];
@@ -999,3 +1148,49 @@ bool SMESH_MesherHelper::LoadNodeColumns(TParam2ColumnMap & theParam2ColumnMap,
 
   return true;
 }
+
+//=======================================================================
+/**
+ * Check mesh without geometry for: if all elements on this shape are quadratic,
+ * quadratic elements will be created.
+ * Used then generated 3D mesh without geometry.
+ */
+//=======================================================================
+
+SMESH_MesherHelper:: MType SMESH_MesherHelper::IsQuadraticMesh()
+{
+  int NbAllEdgsAndFaces=0;
+  int NbQuadFacesAndEdgs=0;
+  int NbFacesAndEdges=0;
+  //All faces and edges
+  NbAllEdgsAndFaces = myMesh->NbEdges() + myMesh->NbFaces();
+  
+  //Quadratic faces and edges
+  NbQuadFacesAndEdgs = myMesh->NbEdges(ORDER_QUADRATIC) + myMesh->NbFaces(ORDER_QUADRATIC);
+
+  //Linear faces and edges
+  NbFacesAndEdges = myMesh->NbEdges(ORDER_LINEAR) + myMesh->NbFaces(ORDER_LINEAR);
+  
+  if (NbAllEdgsAndFaces == NbQuadFacesAndEdgs) {
+    //Quadratic mesh
+    return SMESH_MesherHelper::QUADRATIC;
+  }
+  else if (NbAllEdgsAndFaces == NbFacesAndEdges) {
+    //Linear mesh
+    return SMESH_MesherHelper::LINEAR;
+  }
+  else
+    //Mesh with both type of elements
+    return SMESH_MesherHelper::COMP;
+}
+
+//=======================================================================
+/*!
+ * \brief Return an alternative parameter for a node on seam
+ */
+//=======================================================================
+
+double SMESH_MesherHelper::GetOtherParam(const double param) const
+{
+  return fabs(param-myPar1) < fabs(param-myPar2) ? myPar2 : myPar1;
+}