]> SALOME platform Git repositories - plugins/ghs3dplugin.git/commitdiff
Salome HOME
1st version of enforced mesh
authorgdd <gdd>
Fri, 4 Mar 2011 14:33:51 +0000 (14:33 +0000)
committergdd <gdd>
Fri, 4 Mar 2011 14:33:51 +0000 (14:33 +0000)
configure.ac
idl/GHS3DPlugin_Algorithm.idl
idl/Makefile.am
src/GHS3DPlugin/GHS3DPlugin_GHS3D.cxx
src/GHS3DPlugin/GHS3DPlugin_Hypothesis.cxx
src/GHS3DPlugin/GHS3DPlugin_Hypothesis.hxx
src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.cxx
src/GHS3DPlugin/GHS3DPlugin_Hypothesis_i.hxx
src/GHS3DPlugin/Makefile.am

index f0999ac0e8317ca9fb7a4c24b0a9e51634512e2b..ce67fd53146bea414b1f516053dfbfd4f54604cb 100644 (file)
@@ -352,6 +352,10 @@ echo ---------------------------------------------
 echo
 
 CHECK_GHS3D
+if test "${GHS3D_ok}" = "yes"; then
+        GHS3D_VERSION=`ghs3d --help |grep "TETMESH-GHS3D SOFTWARE"|awk '{print $3}'|awk -F- '{print $1}'|awk -F. '{print $1$2}'`
+        AC_DEFINE_UNQUOTED(GHS3D_VERSION,${GHS3D_VERSION})
+fi
 
 echo
 echo ---------------------------------------------
index 20bcf334a3178069fd17f53f308a8bdd2173019d..9c22a44d6e03caa38b8e7cff4f0c9caf69820396 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "SALOME_Exception.idl"
 #include "SMESH_Hypothesis.idl"
+#include "SMESH_Mesh.idl"
 
 /*!
  * GHS3DPlugin: interfaces to GHS3D related hypotheses and algorithms
@@ -134,6 +135,10 @@ module GHS3DPlugin
     void RemoveEnforcedVertex(in double x, in double y, in double z) raises (SALOME::SALOME_Exception);
     GHS3DEnforcedVertexList GetEnforcedVertices();
     void ClearEnforcedVertices();
+    
+    void SetEnforcedMesh(in SMESH::SMESH_IDSource theSource, in SMESH::ElementType elementType) raises (SALOME::SALOME_Exception);
+    void SetEnforcedMeshSize(in SMESH::SMESH_IDSource theSource, in SMESH::ElementType elementType, in double size) raises (SALOME::SALOME_Exception);
+    void ClearEnforcedMeshes();
   };
 };
 
index 8e265df928f845eac91acb52d7dd181a76bd05dd..2dc36979c430bc18d02f7c04a7a763c60266987a 100644 (file)
@@ -47,12 +47,14 @@ libSalomeIDLGHS3DPLUGIN_la_CPPFLAGS = \
        $(CORBA_INCLUDES) \
        $(KERNEL_CXXFLAGS) \
        $(GEOM_CXXFLAGS) \
+       $(MED_CXXFLAGS) \
        $(SMESH_CXXFLAGS)
 
 libSalomeIDLGHS3DPLUGIN_la_LDFLAGS = -no-undefined -version-info=0:0:0
 libSalomeIDLGHS3DPLUGIN_la_LIBADD  = \
        $(KERNEL_LDFLAGS) -lSalomeIDLKernel \
        $(GEOM_LDFLAGS) -lSalomeIDLGEOM \
+       $(MED_LDFLAGS) -lSalomeIDLMED \
        $(SMESH_LDFLAGS) -lSalomeIDLSMESH \
        @CORBA_LIBS@
 
@@ -64,6 +66,7 @@ OMNIORB_IDLPYFLAGS  = \
        -I$(top_builddir)/idl/salome \
        -I$(KERNEL_ROOT_DIR)/idl/salome \
        -I$(GEOM_ROOT_DIR)/idl/salome \
+       -I$(MED_ROOT_DIR)/idl/salome \
        -I$(SMESH_ROOT_DIR)/idl/salome
 
 IDLCXXFLAGS = \
@@ -72,11 +75,13 @@ IDLCXXFLAGS = \
        -I$(top_builddir)/idl/salome \
        -I$(KERNEL_ROOT_DIR)/idl/salome \
        -I$(GEOM_ROOT_DIR)/idl/salome \
+       -I$(MED_ROOT_DIR)/idl/salome \
        -I$(SMESH_ROOT_DIR)/idl/salome
 IDLPYFLAGS  = \
        @IDLPYFLAGS@ \
        -I$(KERNEL_ROOT_DIR)/idl/salome \
        -I$(GEOM_ROOT_DIR)/idl/salome \
+       -I$(MED_ROOT_DIR)/idl/salome \
        -I$(SMESH_ROOT_DIR)/idl/salome
 
 # potential problem on parallel make on the following - multiple outputs
@@ -108,7 +113,7 @@ mostlyclean-local:
        @for dep in $^ dummy; do \
          if [ $$dep != "dummy" ]; then \
            echo Building dependencies for $$dep; \
-           $(CPP) $(C_DEPEND_FLAG) -x c -I$(srcdir) -I$(KERNEL_ROOT_DIR)/idl/salome -I$(GEOM_ROOT_DIR)/idl/salome -I$(SMESH_ROOT_DIR)/idl/salome $$dep 2>/dev/null | \
+           $(CPP) $(C_DEPEND_FLAG) -x c -I$(srcdir) -I$(KERNEL_ROOT_DIR)/idl/salome -I$(GEOM_ROOT_DIR)/idl/salome -I$(MED_ROOT_DIR)/idl/salome -I$(SMESH_ROOT_DIR)/idl/salome $$dep 2>/dev/null | \
            sed 's/\.o/\SK.cc/' >>$@; \
          fi; \
        done ;
index 74f318637f34453d36a5797a182176333abd4524..64e1cddca43786149f2eba6e9b30a8db0196daac 100644 (file)
 //
 #include "GHS3DPlugin_GHS3D.hxx"
 #include "GHS3DPlugin_Hypothesis.hxx"
-
+extern "C"
+{
+  #include "libmesh5.h"
+}
 
 #include <Basics_Utils.hxx>
 
@@ -101,6 +104,10 @@ extern "C"
 
 #define HOLE_ID -1
 
+#ifndef GHS3D_VERSION
+#define GHS3D_VERSION 41
+#endif
+
 typedef const list<const SMDS_MeshFace*> TTriaList;
 
 static void removeFile( const TCollection_AsciiString& fileName )
@@ -232,23 +239,1167 @@ static char* readMapIntLine(char* ptr, int tab[]) {
     if ( i < 3 )
       tab[i] = intVal;
   }
-  return ptr;
-}
+  return ptr;
+}
+
+//=======================================================================
+//function : countShape
+//purpose  :
+//=======================================================================
+
+// template < class Mesh, class Shape >
+// static int countShape( Mesh* mesh, Shape shape ) {
+//   TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape );
+//   int nbShape = 0;
+//   for ( ; expShape.More(); expShape.Next() ) {
+//       nbShape++;
+//   }
+//   return nbShape;
+// }
+//     Ok = writeGMFFile(aGMFFileName, aRequiredVerticesFileName, aSolFileName, &theMesh, *proxyMesh, 
+//                       aNodeByGhs3dId,
+//                       enforcedNodes, enforcedEdges, enforcedTriangles, enforcedQuadrangles,
+//                       enforcedVertices);
+
+static bool writeGMFFile(const TCollection_AsciiString&   theMeshFileName,
+                         const TCollection_AsciiString&   theRequiredVerticesFileName,
+                         const TCollection_AsciiString&   theSolFileName,
+                         const SMESH_ProxyMesh&           theProxyMesh,
+                         SMESH_Mesh *                     theMesh,
+                         vector <const SMDS_MeshNode*> &  theNodeByGhs3dId,
+                         vector <const SMDS_MeshNode*> &  theEnforcedNodeByGhs3dId,
+                         TIDSortedNodeSet &               theEnforcedNodes,
+                         TIDSortedElemSet &               theEnforcedEdges,
+                         TIDSortedElemSet &               theEnforcedTriangles,
+                         TIDSortedElemSet &               theEnforcedQuadrangles,
+                         GHS3DPlugin_Hypothesis::TEnforcedVertexValues & theEnforcedVertices)
+{
+  MESSAGE("writeGMFFile");
+  int idx;
+  const int dummyint = 0;
+  GHS3DPlugin_Hypothesis::TEnforcedVertexValues::const_iterator vertexIt;
+  std::vector<double> enfVertexSizes;
+  const SMDS_MeshElement* elem;
+  TIDSortedElemSet anElemSet, anEnforcedEdgeSet, anEnforcedTriangleSet, anEnforcedQuadrangleSet;
+  SMDS_ElemIteratorPtr nodeIt;
+  map<const SMDS_MeshNode*,int> aNodeToGhs3dIdMap, anEnforcedNodeToGhs3dIdMap;
+  TIDSortedElemSet::iterator elemIt;
+  bool isOK;
+  auto_ptr< SMESH_ElementSearcher > pntCls ( SMESH_MeshEditor( theMesh ).GetElementSearcher());
+  
+  int nbEnforcedVertices = theEnforcedVertices.size();
+  int nbEnforcedNodes    = theEnforcedNodes.size();
+  int nbEnforcedEdges       = theEnforcedEdges.size();
+  int nbEnforcedTriangles   = theEnforcedTriangles.size();
+  int nbEnforcedQuadrangles = theEnforcedQuadrangles.size();
+  
+  // count faces
+  int nbFaces = theProxyMesh.NbFaces();
+
+  if ( nbFaces == 0 )
+    return false;
+  
+  idx = GmfOpenMesh(theMeshFileName.ToCString(), GmfWrite, 3, 3);
+  if (!idx)
+    return false;
+  
+  /* ========================== FACES ========================== */
+  /* TRIANGLES ========================== */
+  SMDS_ElemIteratorPtr eIt = theProxyMesh.GetFaces();
+  while ( eIt->more() )
+  {
+    elem = eIt->next();
+    anElemSet.insert(elem);
+    // NODE_NB_1 NODE_NB_2 ...
+    nodeIt = elem->nodesIterator();
+    while ( nodeIt->more() )
+    {
+      // find GHS3D ID
+      const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+      int newId = aNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
+      aNodeToGhs3dIdMap.insert( make_pair( node, newId ));
+    }
+  }
+  
+  /* EDGES ========================== */
+  
+  // Iterate over the enforced edges
+  for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
+    elem = (*elemIt);
+    isOK = true;
+    nodeIt = elem->nodesIterator();
+    
+    while ( nodeIt->more() ) {
+      // find GHS3D ID
+      const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(node->X(),node->Y(),node->Z());
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN ) {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      nodeIt = elem->nodesIterator();
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        int newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
+        anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
+      }
+      anEnforcedEdgeSet.insert(elem);
+    }
+  }
+  
+  /* ENFORCED TRIANGLES ========================== */
+  
+  // Iterate over the enforced triangles
+  for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
+    elem = (*elemIt);
+    isOK = true;
+    nodeIt = elem->nodesIterator();
+    while ( nodeIt->more() ) {
+      // find GHS3D ID
+      const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(node->X(),node->Y(),node->Z());
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN ) {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      nodeIt = elem->nodesIterator();
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        int newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
+        anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
+      }
+      anEnforcedTriangleSet.insert(elem);
+    }
+  }
+  
+  /* ENFORCED QUADRANGLES ========================== */
+  
+    // Iterate over the enforced quadrangles
+  for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) {
+    elem = (*elemIt);
+    isOK = true;
+    nodeIt = elem->nodesIterator();
+    while ( nodeIt->more() ) {
+      // find GHS3D ID
+      const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(node->X(),node->Y(),node->Z());
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN ) {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      nodeIt = elem->nodesIterator();
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        int newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
+        anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
+      }
+      anEnforcedQuadrangleSet.insert(elem);
+    }
+  }
+  
+  
+  // put nodes to theNodeByGhs3dId vector
+  std::cout << "aNodeToGhs3dIdMap.size(): "<<aNodeToGhs3dIdMap.size()<<std::endl;
+  theNodeByGhs3dId.resize( aNodeToGhs3dIdMap.size() );
+  map<const SMDS_MeshNode*,int>::const_iterator n2id = aNodeToGhs3dIdMap.begin();
+  for ( ; n2id != aNodeToGhs3dIdMap.end(); ++ n2id)
+  {
+//     std::cout << "n2id->first: "<<n2id->first<<std::endl;
+    theNodeByGhs3dId[ n2id->second - 1 ] = n2id->first; // ghs3d ids count from 1
+  }
+
+  // put nodes to anEnforcedNodeToGhs3dIdMap vector
+  std::cout << "anEnforcedNodeToGhs3dIdMap.size(): "<<anEnforcedNodeToGhs3dIdMap.size()<<std::endl;
+  theEnforcedNodeByGhs3dId.resize( anEnforcedNodeToGhs3dIdMap.size() );
+  n2id = anEnforcedNodeToGhs3dIdMap.begin();
+  for ( ; n2id != anEnforcedNodeToGhs3dIdMap.end(); ++ n2id)
+  {
+//     std::cout << "n2id->first: "<<n2id->first<<std::endl;
+    theEnforcedNodeByGhs3dId[ n2id->second - aNodeToGhs3dIdMap.size() - 1 ] = n2id->first; // ghs3d ids count from 1
+  }
+  
+  
+  /* ========================== NODES ========================== */
+  vector<const SMDS_MeshNode*> theOrderedNodes;
+  std::set< std::vector<double> > nodesCoords;
+  vector<const SMDS_MeshNode*>::const_iterator ghs3dNodeIt = theNodeByGhs3dId.begin();
+  vector<const SMDS_MeshNode*>::const_iterator after  = theNodeByGhs3dId.end();
+  
+  std::cout << theNodeByGhs3dId.size() << " nodes from mesh ..." << std::endl;
+  for ( ; ghs3dNodeIt != after; ++ghs3dNodeIt )
+  {
+    const SMDS_MeshNode* node = *ghs3dNodeIt;
+    std::vector<double> coords;
+    coords.push_back(node->X());
+    coords.push_back(node->Y());
+    coords.push_back(node->Z());
+    nodesCoords.insert(coords);
+    theOrderedNodes.push_back(node);
+  }
+  
+  // Iterate over the enforced nodes
+  TIDSortedNodeSet::const_iterator enfNodeIt;
+  std::cout << theEnforcedNodes.size() << " nodes from enforced nodes ..." << std::endl;
+  for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt)
+  {
+    const SMDS_MeshNode* node = *enfNodeIt;
+    std::vector<double> coords;
+    coords.push_back(node->X());
+    coords.push_back(node->Y());
+    coords.push_back(node->Z());
+    
+    if (nodesCoords.find(coords) != nodesCoords.end()) {
+      std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z() << " found" << std::endl;
+      continue;
+    }
+
+    if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
+      continue;
+    
+    // Test if point is inside shape to mesh
+    gp_Pnt myPoint(node->X(),node->Y(),node->Z());
+    TopAbs_State result = pntCls->GetPointState( myPoint );
+    if ( result != TopAbs_IN )
+      continue;
+    
+    nodesCoords.insert(coords);
+    theOrderedNodes.push_back(node);
+  }
+  // Iterate over the enforced nodes given by enforced elements
+  ghs3dNodeIt = theEnforcedNodeByGhs3dId.begin();
+  after  = theEnforcedNodeByGhs3dId.end();
+  std::cout << theEnforcedNodes.size() << " nodes from enforced elements ..." << std::endl;
+  for ( ; ghs3dNodeIt != after; ++ghs3dNodeIt )
+  {
+    const SMDS_MeshNode* node = *ghs3dNodeIt;
+    std::vector<double> coords;
+    coords.push_back(node->X());
+    coords.push_back(node->Y());
+    coords.push_back(node->Z());
+    
+    if (nodesCoords.find(coords) != nodesCoords.end()) {
+      std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z() << " found" << std::endl;
+      continue;
+    }
+    
+    if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
+      continue;
+    
+    nodesCoords.insert(coords);
+    theOrderedNodes.push_back(node);
+  }
+  
+  
+  GmfSetKwd(idx, GmfVertices, theOrderedNodes.size());
+//   std::set< std::vector<double> >::const_iterator coordsIt = nodesCoords.begin();
+  for (ghs3dNodeIt = theOrderedNodes.begin();ghs3dNodeIt != theOrderedNodes.end();++ghs3dNodeIt)
+    GmfSetLin(idx, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
+
+  int nedge[2], ntri[3], nquad[4];
+  
+  if (anEnforcedEdgeSet.size()) {
+    GmfSetKwd(idx, GmfEdges, anEnforcedEdgeSet.size());
+    for(elemIt = anEnforcedEdgeSet.begin() ; elemIt != anEnforcedEdgeSet.end() ; ++elemIt) {
+      elem = (*elemIt);
+      nodeIt = elem->nodesIterator();
+      int index=0;
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node);
+        if (it == anEnforcedNodeToGhs3dIdMap.end())
+          throw "Node not found";
+        nedge[index] = it->second;
+        index++;
+      }
+      GmfSetLin(idx, GmfEdges, nedge[0], nedge[1], dummyint);
+    }
+  }
+
+  if (anElemSet.size()+anEnforcedTriangleSet.size()) {
+    GmfSetKwd(idx, GmfTriangles, anElemSet.size()+anEnforcedTriangleSet.size());
+    for(elemIt = anElemSet.begin() ; elemIt != anElemSet.end() ; ++elemIt) {
+      elem = (*elemIt);
+      nodeIt = elem->nodesIterator();
+      int index=0;
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        map< const SMDS_MeshNode*,int >::iterator it = aNodeToGhs3dIdMap.find(node);
+        if (it == aNodeToGhs3dIdMap.end())
+          throw "Node not found";
+        ntri[index] = it->second;
+        index++;
+      }
+      GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
+    }
+    for(elemIt = anEnforcedTriangleSet.begin() ; elemIt != anEnforcedTriangleSet.end() ; ++elemIt) {
+      elem = (*elemIt);
+      nodeIt = elem->nodesIterator();
+      int index=0;
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node);
+        if (it == anEnforcedNodeToGhs3dIdMap.end())
+          throw "Node not found";
+        ntri[index] = it->second;
+        index++;
+      }
+      GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
+    }
+  }
+
+  if (anEnforcedQuadrangleSet.size()) {
+    GmfSetKwd(idx, GmfQuadrilaterals, anEnforcedQuadrangleSet.size());
+    for(elemIt = anEnforcedQuadrangleSet.begin() ; elemIt != anEnforcedQuadrangleSet.end() ; ++elemIt) {
+      elem = (*elemIt);
+      nodeIt = elem->nodesIterator();
+      int index=0;
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        map< const SMDS_MeshNode*,int >::iterator it = anEnforcedNodeToGhs3dIdMap.find(node);
+        if (it == anEnforcedNodeToGhs3dIdMap.end())
+          throw "Node not found";
+        nquad[index] = it->second;
+        index++;
+      }
+      GmfSetLin(idx, GmfQuadrilaterals, nquad[0], nquad[1], nquad[2], nquad[3], dummyint);
+    }
+  }
+  
+  GmfCloseMesh(idx);
+  
+  if (nbEnforcedVertices) {
+    std::vector<std::vector<double> > ReqVerTab;
+    ReqVerTab.clear();
+    std::vector<double> enfVertexSizes;
+    int solSize = 0;
+    std::cout << theEnforcedVertices.size() << " nodes from enforced vertices ..." << std::endl;
+    // Iterate over the enforced vertices
+    for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
+      double x = vertexIt->first[0];
+      double y = vertexIt->first[1];
+      double z = vertexIt->first[2];
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(x,y,z);
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN )
+        continue;
+      std::vector<double> coords;
+      coords.push_back(x);
+      coords.push_back(y);
+      coords.push_back(z);
+      ReqVerTab.push_back(coords);
+      enfVertexSizes.push_back(vertexIt->second);
+      solSize++;
+    }
+    
+    if (solSize) {
+      int idxRequired = GmfOpenMesh(theRequiredVerticesFileName.ToCString(), GmfWrite, 3, 3);
+      if (!idxRequired)
+        return false;
+      int idxSol = GmfOpenMesh(theSolFileName.ToCString(), GmfWrite, 3, 3);
+      if (!idxSol)
+        return false;
+      
+      int TypTab[] = {GmfSca};
+      GmfSetKwd(idxRequired, GmfVertices, solSize);
+      GmfSetKwd(idxSol, GmfSolAtVertices, solSize, 1, TypTab);
+      
+      for (int i=0;i<solSize;i++) {
+        double solTab[] = {enfVertexSizes.at(i)};
+        GmfSetLin(idxRequired, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
+        GmfSetLin(idxSol, GmfSolAtVertices, solTab);
+      }
+      GmfCloseMesh(idxRequired);
+      GmfCloseMesh(idxSol);
+    }
+  }
+  
+  
+  return true;
+  
+}
+
+static bool writeGMFFile(const TCollection_AsciiString&   theMeshFileName,
+                         const TCollection_AsciiString&   theRequiredVerticesFileName,
+                         const TCollection_AsciiString&   theSolFileName,
+                         SMESH_MesherHelper&              theHelper,
+                         const SMESH_ProxyMesh&           theProxyMesh,
+                         map <int,int> &                  theSmdsToGhs3dIdMap,
+                         map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap,
+                         TIDSortedNodeSet &               theEnforcedNodes,
+                         TIDSortedElemSet &               theEnforcedEdges,
+                         TIDSortedElemSet &               theEnforcedTriangles,
+                         TIDSortedElemSet &               theEnforcedQuadrangles,
+                         GHS3DPlugin_Hypothesis::TEnforcedVertexValues & theEnforcedVertices)
+{
+  int idx, nbv, nbev, nben, aGhs3dID = 0;
+  const int dummyint = 0;
+  GHS3DPlugin_Hypothesis::TEnforcedVertexValues::const_iterator vertexIt;
+  std::vector<double> enfVertexSizes;
+  TIDSortedNodeSet::const_iterator enfNodeIt;
+  const SMDS_MeshNode* node;
+  SMDS_NodeIteratorPtr nodeIt;
+  std::map<int,int> theNodeId2NodeIndexMap;
+
+  idx = GmfOpenMesh(theMeshFileName.ToCString(), GmfWrite, 3, 3);
+  if (!idx)
+    return false;
+  
+  SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS();
+  
+  /* ========================== NODES ========================== */
+  // NB_NODES
+  nbv = theMeshDS->NbNodes();
+  if ( nbv == 0 )
+    return false;
+  nbev = theEnforcedVertices.size();
+  nben = theEnforcedNodes.size();
+  
+  // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D
+  // The problem is in nodes on degenerated edges, we need to skip them
+  if ( theHelper.HasDegeneratedEdges() )
+  {
+    // here we decrease total nb of nodes by nb of nodes on degenerated edges
+    set<int> checkedSM;
+    for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next())
+    {
+      SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() );
+      if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() )) {
+        if ( sm->GetSubMeshDS() )
+          nbv -= sm->GetSubMeshDS()->NbNodes();
+      }
+    }
+  }
+  
+  std::vector<std::vector<double> > VerTab;
+  VerTab.clear();
+  std::vector<double> aVerTab;
+  nodeIt = theMeshDS->nodesIterator();
+  // Loop from 1 to NB_NODES
+
+  while ( nodeIt->more() )
+  {
+    node = nodeIt->next();
+    if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_EDGE &&
+         theHelper.IsDegenShape( node->getshapeId() )) // Issue 020674
+      continue;
+
+    aVerTab.clear();
+    aVerTab.push_back(node->X());
+    aVerTab.push_back(node->Y());
+    aVerTab.push_back(node->Z());
+    VerTab.push_back(aVerTab);
+    aGhs3dID++;
+    theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID ));
+    theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node ));
+  }
+  
+  /* ENFORCED NODES ========================== */
+  if (nben) {
+    for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt) {
+      double x = (*enfNodeIt)->X();
+      double y = (*enfNodeIt)->Y();
+      double z = (*enfNodeIt)->Z();
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(x,y,z);
+      BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
+      scl.Perform(myPoint, 1e-7);
+      TopAbs_State result = scl.State();
+      if ( result != TopAbs_IN )
+        continue;
+      std::vector<double> coords;
+      coords.push_back(x);
+      coords.push_back(y);
+      coords.push_back(z);
+      if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
+        continue;
+      aVerTab.clear();
+      aVerTab.push_back(x);
+      aVerTab.push_back(y);
+      aVerTab.push_back(z);
+      VerTab.push_back(aVerTab);
+      aGhs3dID++;
+      theNodeId2NodeIndexMap.insert( make_pair( (*enfNodeIt)->GetID(), aGhs3dID ));
+    }
+  }
+  
+  /* Write vertices number */
+  MESSAGE("Number of vertices: "<<aGhs3dID);
+  MESSAGE("Size of vector: "<<VerTab.size());
+  GmfSetKwd(idx, GmfVertices, aGhs3dID);
+  for (int i=0;i<aGhs3dID;i++)
+    GmfSetLin(idx, GmfVertices, VerTab[i][0], VerTab[i][1], VerTab[i][2], dummyint);
+  
+  
+  /* ENFORCED VERTICES ========================== */
+  if (nbev) {
+    std::vector<std::vector<double> > ReqVerTab;
+    ReqVerTab.clear();
+    std::vector<double> aReqVerTab;
+    int solSize = 0;
+    for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
+      double x = vertexIt->first[0];
+      double y = vertexIt->first[1];
+      double z = vertexIt->first[2];
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(x,y,z);
+      BRepClass3d_SolidClassifier scl(theMeshDS->ShapeToMesh());
+      scl.Perform(myPoint, 1e-7);
+      TopAbs_State result = scl.State();
+      if ( result != TopAbs_IN )
+        continue;
+      enfVertexSizes.push_back(vertexIt->second);
+      aReqVerTab.clear();
+      aReqVerTab.push_back(x);
+      aReqVerTab.push_back(y);
+      aReqVerTab.push_back(z);
+      ReqVerTab.push_back(aReqVerTab);
+      solSize++;
+    }
+
+    if (solSize) {
+      int idxRequired = GmfOpenMesh(theRequiredVerticesFileName.ToCString(), GmfWrite, 3, 3);
+      if (!idxRequired)
+        return false;
+      int idxSol = GmfOpenMesh(theSolFileName.ToCString(), GmfWrite, 3, 3);
+      if (!idxSol)
+        return false;
+      
+      int TypTab[] = {GmfSca};
+      GmfSetKwd(idxRequired, GmfVertices, solSize);
+      GmfSetKwd(idxSol, GmfSolAtVertices, solSize, 1, TypTab);
+      
+      for (int i=0;i<solSize;i++) {
+        double solTab[] = {enfVertexSizes.at(i)};
+        GmfSetLin(idxRequired, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
+        GmfSetLin(idxSol, GmfSolAtVertices, solTab);
+      }
+      GmfCloseMesh(idxRequired);
+      GmfCloseMesh(idxSol);
+    }
+  }
+  
+  /* ========================== EDGES ========================== */
+  
+  
+  
+  /* ========================== FACES ========================== */
+  
+  int nbTriangles = 0, nbQuadrangles = 0, aSmdsID;
+  TopTools_IndexedMapOfShape facesMap, trianglesMap, quadranglesMap;
+  TIDSortedElemSet::const_iterator elemIt;
+  const SMESHDS_SubMesh* theSubMesh;
+  TopoDS_Shape aShape;
+  SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace;
+  const SMDS_MeshElement* aFace;
+  map<int,int>::const_iterator itOnMap;
+  std::vector<std::vector<int> > tt, qt;
+  tt.clear();
+  qt.clear();
+  std::vector<int> att, aqt;
+  
+  TopExp::MapShapes( theMeshDS->ShapeToMesh(), TopAbs_FACE, facesMap );
+
+  for ( int i = 1; i <= facesMap.Extent(); ++i )
+    if (( theSubMesh  = theProxyMesh.GetSubMesh( facesMap(i))))
+    {
+      SMDS_ElemIteratorPtr it = theSubMesh->GetElements();
+      while (it->more())
+      {
+        const SMDS_MeshElement *elem = it->next();
+        if (elem->NbNodes() == 3)
+        {
+          trianglesMap.Add(facesMap(i));
+          nbTriangles ++;
+        }
+        else if (elem->NbNodes() == 4)
+        {
+          quadranglesMap.Add(facesMap(i));
+          nbQuadrangles ++;
+        }
+      }
+    }
+    
+  /* TRIANGLES ========================== */
+  if (nbTriangles) {
+    for ( int i = 1; i <= trianglesMap.Extent(); i++ )
+    {
+      aShape = trianglesMap(i);
+      theSubMesh = theProxyMesh.GetSubMesh(aShape);
+      if ( !theSubMesh ) continue;
+      itOnSubMesh = theSubMesh->GetElements();
+      while ( itOnSubMesh->more() )
+      {
+        aFace = itOnSubMesh->next();
+        itOnSubFace = aFace->nodesIterator();
+        att.clear();
+        while ( itOnSubFace->more() ) {
+          // find GHS3D ID
+          aSmdsID = itOnSubFace->next()->GetID();
+          itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
+          ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
+          att.push_back((*itOnMap).second);
+        }
+        tt.push_back(att);
+      }
+    }
+  }
+  
+  int nbEnforcedTriangles = theEnforcedTriangles.size();
+  if (nbEnforcedTriangles) {
+    // Iterate over the enforced triangles
+    for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
+      aFace = (*elemIt);
+      bool isOK = true;
+      itOnSubFace = aFace->nodesIterator();
+      att.clear();
+      while ( itOnSubFace->more() ) {
+        int aNodeID = itOnSubFace->next()->GetID();
+        itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
+        if (itOnMap != theNodeId2NodeIndexMap.end())
+          att.push_back((*itOnMap).second);
+        else {
+          isOK = false;
+          break;
+        }
+      }
+      if (isOK)
+        tt.push_back(att);
+    }
+  }
+  
+  if (tt.size()) {
+    GmfSetKwd(idx, GmfTriangles, tt.size());
+    for (int i=0;i<tt.size();i++)
+      GmfSetLin(idx, GmfTriangles, tt[i][0], tt[i][1], tt[i][2], dummyint);
+  }
+    
+  /* QUADRANGLES ========================== */
+  if (nbQuadrangles) {
+    for ( int i = 1; i <= quadranglesMap.Extent(); i++ )
+    {
+      aShape = quadranglesMap(i);
+      theSubMesh = theProxyMesh.GetSubMesh(aShape);
+      if ( !theSubMesh ) continue;
+      itOnSubMesh = theSubMesh->GetElements();
+      while ( itOnSubMesh->more() )
+      {
+        aFace = itOnSubMesh->next();
+        itOnSubFace = aFace->nodesIterator();
+        aqt.clear();
+        while ( itOnSubFace->more() ) {
+          // find GHS3D ID
+          aSmdsID = itOnSubFace->next()->GetID();
+          itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
+          ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
+          aqt.push_back((*itOnMap).second);
+        }
+        qt.push_back(aqt);
+      }
+    }
+  }
+  
+  int nbEnforcedQuadrangles = theEnforcedQuadrangles.size();
+  if (nbEnforcedQuadrangles) {
+    // Iterate over the enforced triangles
+    for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) {
+      aFace = (*elemIt);
+      bool isOK = true;
+      itOnSubFace = aFace->nodesIterator();
+      aqt.clear();
+      while ( itOnSubFace->more() ) {
+        int aNodeID = itOnSubFace->next()->GetID();
+        itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
+        if (itOnMap != theNodeId2NodeIndexMap.end())
+          aqt.push_back((*itOnMap).second);
+        else {
+          isOK = false;
+          break;
+        }
+      }
+      if (isOK)
+        qt.push_back(att);
+    }
+  }
+  
+  if (qt.size()) {
+    GmfSetKwd(idx, GmfQuadrilaterals, qt.size());
+    for (int i=0;i<qt.size();i++)
+      GmfSetLin(idx, GmfQuadrilaterals, qt[i][0], qt[i][1], qt[i][2], qt[i][3], dummyint);
+  }
+  
+  
+  GmfCloseMesh(idx);
+  return true;
+}
+
+/*
+static bool writeGMFHeader (ofstream &theFile,
+                            int       thePrecision)
+{
+  theFile << "MeshVersionFormatted " << thePrecision << std::endl;
+  theFile << std::endl;
+  theFile << "Dimension" << std::endl;
+  theFile << "3" << std::endl;
+  theFile << std::endl;
+  return true;
+}
+
+static bool writeGMFEnd (ofstream &theFile)
+{
+  theFile << std::endl;
+  theFile << "End" << std::endl;
+  return true;
+}
+  
+static bool writeGMFVertices (ofstream &                       theFile,
+                              ofstream &                       theSolFile,
+                              SMESH_MesherHelper&              theHelper,
+                              map <int,int> &                  theSmdsToGhs3dIdMap,
+                              map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap,
+                              GHS3DPlugin_Hypothesis::TEnforcedVertexValues & theEnforcedVertices,
+                              TIDSortedNodeSet & theEnforcedNodes,
+                              std::map <int,int>& theNodeId2NodeIndexMap)
+{
+  SMESHDS_Mesh * theMeshDS = theHelper.GetMeshDS();
+  // NB_NODES
+  int nbNodes = theMeshDS->NbNodes();
+  if ( nbNodes == 0 )
+    return false;
+  int nbEnforcedVertices = theEnforcedVertices.size();
+  int nbEnforcedNodes    = theEnforcedNodes.size();
+  
+  // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D
+  // The problem is in nodes on degenerated edges, we need to skip them
+  if ( theHelper.HasDegeneratedEdges() )
+  {
+    // here we decrease total nb of nodes by nb of nodes on degenerated edges
+    set<int> checkedSM;
+    for (TopExp_Explorer e(theMeshDS->ShapeToMesh(), TopAbs_EDGE ); e.More(); e.Next())
+    {
+      SMESH_subMesh* sm = theHelper.GetMesh()->GetSubMesh( e.Current() );
+      if ( checkedSM.insert( sm->GetId() ).second && theHelper.IsDegenShape(sm->GetId() )) {
+        if ( sm->GetSubMeshDS() )
+          nbNodes -= sm->GetSubMeshDS()->NbNodes();
+      }
+    }
+  }
+  const char* space    = "  ";
+  const int   dummyint = 0;  
+  
+  int aGhs3dID = 1;
+  SMDS_NodeIteratorPtr it = theMeshDS->nodesIterator();
+  const SMDS_MeshNode* node;
+    
+  
+  std::cout << std::endl;
+  std::cout << "The initial 2D mesh contains :" << std::endl;
+  std::cout << "    " << nbNodes << " nodes" << std::endl;
+  if (nbEnforcedVertices > 0)
+    std::cout << "    " << nbEnforcedVertices << " enforced vertices" << std::endl;
+  if (nbEnforcedNodes > 0)
+    std::cout << "    " << nbEnforcedNodes << " enforced nodes" << std::endl;
+//   std::cout << "Start writing vertices in 'mesh' file ..." << std::endl;
+  theFile << "Vertices" << std::endl;
+  theFile << nbNodes+nbEnforcedVertices+nbEnforcedNodes << std::endl;
+
+  // Loop from 1 to NB_NODES
+
+  while ( it->more() )
+  {
+    node = it->next();
+    if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_EDGE &&
+         theHelper.IsDegenShape( node->getshapeId() )) // Issue 020674
+      continue;
+
+    theSmdsToGhs3dIdMap.insert( make_pair( node->GetID(), aGhs3dID ));
+    theGhs3dIdToNodeMap.insert( make_pair( aGhs3dID, node ));
+    aGhs3dID++;
+
+    // X Y Z DUMMY_INT
+    theFile
+    << node->X() << space 
+    << node->Y() << space 
+    << node->Z() << space 
+    << dummyint << space ;
+    theFile << std::endl;
+  }
+  
+  // Iterate over the enforced vertices
+  GHS3DPlugin_Hypothesis::TEnforcedVertexValues::const_iterator vertexIt;
+  const TopoDS_Shape shapeToMesh = theMeshDS->ShapeToMesh();
+  std::map<int,double> enfVertexIndexSizeMap;
+  int i = 1;
+  for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
+    double x = vertexIt->first[0];
+    double y = vertexIt->first[1];
+    double z = vertexIt->first[2];
+    // Test if point is inside shape to mesh
+    gp_Pnt myPoint(x,y,z);
+    BRepClass3d_SolidClassifier scl(shapeToMesh);
+    scl.Perform(myPoint, 1e-7);
+    TopAbs_State result = scl.State();
+    if ( result == TopAbs_IN ) {
+//       MESSAGE("Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second);
+      // X Y Z PHY_SIZE DUMMY_INT
+      theFile
+      << x << space 
+      << y << space 
+      << z << space
+      << dummyint << space;
+      theFile << std::endl;
+      enfVertexIndexSizeMap[nbNodes + i] = vertexIt->second;
+      i++;
+    }
+//     else
+//         MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added ");
+  }
+  nbNodes = nbNodes + enfVertexIndexSizeMap.size()-1;
+  
+  // Iterate over the enforced nodes
+  TIDSortedNodeSet::const_iterator nodeIt;
+  int usedEnforcedNodes = 0;
+  for(nodeIt = theEnforcedNodes.begin() ; nodeIt != theEnforcedNodes.end() ; ++nodeIt) {
+    double x = (*nodeIt)->X();
+    double y = (*nodeIt)->Y();
+    double z = (*nodeIt)->Z();
+    // Test if point is inside shape to mesh
+    gp_Pnt myPoint(x,y,z);
+    BRepClass3d_SolidClassifier scl(shapeToMesh);
+    scl.Perform(myPoint, 1e-7);
+    TopAbs_State result = scl.State();
+    if ( result == TopAbs_IN ) {
+//       MESSAGE("Adding enforced node (" << x << "," << y <<"," << z << ")");
+      // X Y Z PHY_SIZE DUMMY_INT
+      theFile
+      << x << space 
+      << y << space 
+      << z << space
+      << dummyint << space;
+      theFile << std::endl;
+      enfVertexIndexSizeMap[nbNodes + i] = -1;
+      theNodeId2NodeIndexMap.insert( make_pair( (*nodeIt)->GetID(), nbNodes + i ));
+      i++;
+      usedEnforcedNodes++;
+    }
+//     else
+//         MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added ");
+  }
+  theFile << std::endl;
+//   std::cout << std::endl;
+//   std::cout << "End writing vertices in 'mesh' file." << std::endl;
+
+  if (!nbEnforcedVertices)
+    return true;
+  
+//   std::cout << "Start writing required vertices in 'mesh' file ..." << std::endl;
+  writeGMFHeader(theSolFile, 1);
+  theSolFile << "SolAtVertices" << std::endl;
+  theSolFile << enfVertexIndexSizeMap.size()-usedEnforcedNodes << std::endl;
+  theSolFile << "1 1" << std::endl;
+  theFile << std::endl;
+  theFile << "RequiredVertices" << std::endl;
+  theFile << enfVertexIndexSizeMap.size() << std::endl;
+  for (std::map<int,double>::const_iterator it = enfVertexIndexSizeMap.begin();it != enfVertexIndexSizeMap.end();++it) {
+    theFile << it->first << std::endl;
+    if (it->second != -1)
+      theSolFile << it->second << std::endl;
+  }
+  theFile << std::endl;
+  theSolFile << std::endl;
+  writeGMFEnd(theSolFile);
+//   std::cout << "End writing required vertices in 'mesh' file." << std::endl;
+
+  return true;
+}
+  
+static bool writeGMFFaces (ofstream &          theFile,
+                           const SMESH_ProxyMesh& theMesh,
+                           const TopoDS_Shape&    theShape,
+                           const map <int,int> &  theSmdsToGhs3dIdMap,
+                           TIDSortedElemSet & theEnforcedEdges,
+                           TIDSortedElemSet & theEnforcedTriangles,
+                           TIDSortedElemSet & theEnforcedQuadrangles,
+                           std::map <int,int>& theNodeId2NodeIndexMap)
+{
+  // record structure:
+  //
+  // NB_ELEMS DUMMY_INT
+  // Loop from 1 to NB_ELEMS
+  // NB_NODES NODE_NB_1 NODE_NB_2 ... DUMMY_INT
+
+  TopoDS_Shape aShape;
+  const SMESHDS_SubMesh* theSubMesh;
+  const SMDS_MeshElement* aFace;
+  const char* space    = "  ";
+  const int   dummyint = 0;
+  map<int,int>::const_iterator itOnMap;
+  SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace;
+  int aSmdsID, aNodeID;
+
+  TIDSortedElemSet::const_iterator elemIt;
+  int nbEnforcedEdges       = theEnforcedEdges.size();
+  int nbEnforcedTriangles   = theEnforcedTriangles.size();
+  int nbEnforcedQuadrangles = theEnforcedQuadrangles.size();
+  // count triangles bound to geometry
+  int nbTriangles = 0;
+  int nbQuadrangles = 0;
+  ostringstream aStream,aLocalStream;
+  aStream.clear();
+  aLocalStream.clear();
+
+  TopTools_IndexedMapOfShape facesMap, trianglesMap, quadranglesMap;
+  TopExp::MapShapes( theShape, TopAbs_FACE, facesMap );
+
+  for ( int i = 1; i <= facesMap.Extent(); ++i )
+    if (( theSubMesh  = theMesh.GetSubMesh( facesMap(i))))
+    {
+      SMDS_ElemIteratorPtr it = theSubMesh->GetElements();
+      while (it->more())
+      {
+        const SMDS_MeshElement *elem = it->next();
+        if (elem->NbNodes() == 3)
+        {
+          trianglesMap.Add(facesMap(i));
+          nbTriangles ++;
+        }
+        else if (elem->NbNodes() == 4)
+        {
+          quadranglesMap.Add(facesMap(i));
+          nbQuadrangles ++;
+        }
+      }
+    }
+
+  std::cout << "    " << facesMap.Extent() << " shapes of 2D dimension:" << std::endl;
+  std::cout << "      " << nbTriangles << " triangles" << std::endl;
+  std::cout << "      " << nbQuadrangles << " quadrangles" << std::endl;
+  if (nbEnforcedEdges) {
+    std::cout << "    " << nbEnforcedEdges+nbEnforcedTriangles+nbEnforcedQuadrangles 
+                        << " enforced shapes:" << std::endl;
+    std::cout << "      " << nbEnforcedEdges << " enforced edges" << std::endl;
+  }
+  if (nbEnforcedTriangles)
+    std::cout << "      " << nbEnforcedTriangles << " enforced triangles" << std::endl;
+  if (nbEnforcedQuadrangles)
+    std::cout << "      " << nbEnforcedQuadrangles << " enforced quadrangles" << std::endl;
+  std::cout << std::endl;
+  
+  //
+  //        EDGES : BEGIN
+  //
+  
+//   std::cout << "Start writing edges in 'mesh' file ..." << std::endl;
+  
+  // Iterate over the enforced edges
+  int usedEnforcedEdges = 0;
+  bool isOK;
+  for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
+    aFace = (*elemIt);
+    isOK = true;
+    itOnSubFace = aFace->nodesIterator();
+    aStream.clear();
+    while ( itOnSubFace->more() ) {
+      aNodeID = itOnSubFace->next()->GetID();
+      itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
+      if (itOnMap != theNodeId2NodeIndexMap.end())
+        aStream << (*itOnMap).second << space;
+      else {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      aLocalStream << aStream.str() << dummyint << std::endl;
+      usedEnforcedEdges++;
+    }
+  }
+  
+  if (usedEnforcedEdges) {
+    theFile << std::endl;
+    theFile << "Edges" << std::endl;
+    theFile << usedEnforcedEdges << std::endl;
+    theFile << aLocalStream.str();
+    aLocalStream.clear();
+    
+    theFile << std::endl;
+    theFile << "RequiredEdges" << std::endl;
+    theFile << usedEnforcedEdges << std::endl;
+    
+    // Iterate over the enforced edges
+    for (int i=0;i<usedEnforcedEdges;i++)
+      theFile << i+1 << std::endl;
+    
+    theFile << std::endl;
+  }
+
+  //
+  //        EDGES : END
+  //
+
+  //
+  //        TRIANGLES : BEGIN
+  //
+//   std::cout << "Start writing triangles in 'mesh' file ..." << std::endl;
+
+  for ( int i = 1; i <= trianglesMap.Extent(); i++ )
+  {
+    aShape = trianglesMap(i);
+    theSubMesh = theMesh.GetSubMesh(aShape);
+    if ( !theSubMesh ) continue;
+    itOnSubMesh = theSubMesh->GetElements();
+    while ( itOnSubMesh->more() )
+    {
+      aFace = itOnSubMesh->next();
+      if (aFace->NbNodes() != 3)
+        continue;
+
+      itOnSubFace = aFace->nodesIterator();
+      while ( itOnSubFace->more() ) {
+        // find GHS3D ID
+        aSmdsID = itOnSubFace->next()->GetID();
+        itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
+        // if ( itOnMap == theSmdsToGhs3dIdMap.end() ) {
+        //   cout << "not found node: " << aSmdsID << endl;
+        //   return false;
+        // }
+        ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
+
+        aLocalStream << (*itOnMap).second << space;
+      }
+      aLocalStream << dummyint << std::endl;
+    }
+  }
+  
+  // Iterate over the enforced triangles
+  int usedEnforcedTriangles = 0;
+  for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
+    aFace = (*elemIt);
+    isOK = true;
+    itOnSubFace = aFace->nodesIterator();
+    aStream.clear();
+    while ( itOnSubFace->more() ) {
+      aNodeID = itOnSubFace->next()->GetID();
+      itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
+      if (itOnMap != theNodeId2NodeIndexMap.end())
+        aStream << (*itOnMap).second << space;
+      else {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      aLocalStream << aStream.str() << dummyint << std::endl;
+      usedEnforcedTriangles++;
+    }
+  }
+  if (nbTriangles+usedEnforcedTriangles) {
+    theFile << std::endl;
+    theFile << "Triangles" << std::endl;
+    theFile << nbTriangles+usedEnforcedTriangles << std::endl;
+    theFile << aLocalStream.str();
+    aLocalStream.clear();
+    
+    theFile << std::endl;
+  }
+
+  //
+  //        TRIANGLES : END
+  //
+  
+  //
+  //        QUADRANGLES : BEGIN
+  //
+  
+//   std::cout << "Start writing quadrangles in 'mesh' file ..." << std::endl;
+
+  for ( int i = 1; i <= quadranglesMap.Extent(); i++ )
+  {
+    aShape = quadranglesMap(i);
+    theSubMesh = theMesh.GetSubMesh(aShape);
+    if ( !theSubMesh ) continue;
+    itOnSubMesh = theSubMesh->GetElements();
+    while ( itOnSubMesh->more() )
+    {
+      aFace = itOnSubMesh->next();
+      if (aFace->NbNodes() != 4)
+        continue;
+
+      itOnSubFace = aFace->nodesIterator();
+      while ( itOnSubFace->more() ) {
+        // find GHS3D ID
+        aSmdsID = itOnSubFace->next()->GetID();
+        itOnMap = theSmdsToGhs3dIdMap.find( aSmdsID );
+        // if ( itOnMap == theSmdsToGhs3dIdMap.end() ) {
+        //   cout << "not found node: " << aSmdsID << endl;
+        //   return false;
+        // }
+        ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
+
+        aLocalStream << (*itOnMap).second << space;
+      }
+      aLocalStream << dummyint << std::endl;
+    }
+  }
+  
+  // Iterate over the enforced quadrangles
+  int usedEnforcedQuadrangles = 0;
+  for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) {
+    aFace = (*elemIt);
+    isOK = true;
+    itOnSubFace = aFace->nodesIterator();
+    aStream.clear();
+    while ( itOnSubFace->more() ) {
+      aNodeID = itOnSubFace->next()->GetID();
+      itOnMap = theNodeId2NodeIndexMap.find(aNodeID);
+      if (itOnMap != theNodeId2NodeIndexMap.end())
+        aStream << (*itOnMap).second << space;
+      else {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      aLocalStream << aStream.str() << dummyint << std::endl;
+      usedEnforcedQuadrangles++;
+    }
+  }
+  if (nbQuadrangles+usedEnforcedQuadrangles) {
+    theFile << std::endl;
+    theFile << "Quadrilaterals" << std::endl;
+    theFile << nbQuadrangles+usedEnforcedQuadrangles << std::endl;
+    theFile << aLocalStream.str();
+    aLocalStream.clear();
+    
+    theFile << std::endl;
+  }
 
-//=======================================================================
-//function : countShape
-//purpose  :
-//=======================================================================
+  //
+  //        QUADRANGLES : END
+  //
 
-// template < class Mesh, class Shape >
-// static int countShape( Mesh* mesh, Shape shape ) {
-//   TopExp_Explorer expShape ( mesh->ShapeToMesh(), shape );
-//   int nbShape = 0;
-//   for ( ; expShape.More(); expShape.Next() ) {
-//       nbShape++;
-//   }
-//   return nbShape;
-// }
+  return true;
+}
+*/
 
 //=======================================================================
 //function : writeFaces
@@ -258,7 +1409,11 @@ static char* readMapIntLine(char* ptr, int tab[]) {
 static bool writeFaces (ofstream &             theFile,
                         const SMESH_ProxyMesh& theMesh,
                         const TopoDS_Shape&    theShape,
-                        const map <int,int> &  theSmdsToGhs3dIdMap)
+                        const map <int,int> &  theSmdsToGhs3dIdMap,
+                        const map <int,int> &  theEnforcedNodeIdToGhs3dIdMap,
+                        TIDSortedElemSet & theEnforcedEdges,
+                        TIDSortedElemSet & theEnforcedTriangles,
+                        TIDSortedElemSet & theEnforcedQuadrangles)
 {
   // record structure:
   //
@@ -275,21 +1430,39 @@ static bool writeFaces (ofstream &             theFile,
   SMDS_ElemIteratorPtr itOnSubMesh, itOnSubFace;
   int nbNodes, aSmdsID;
 
+  TIDSortedElemSet::const_iterator elemIt;
+  int nbEnforcedEdges       = theEnforcedEdges.size();
+  int nbEnforcedTriangles   = theEnforcedTriangles.size();
+  int nbEnforcedQuadrangles = theEnforcedQuadrangles.size();
   // count triangles bound to geometry
   int nbTriangles = 0;
 
-  TopTools_IndexedMapOfShape facesMap;
+  TopTools_IndexedMapOfShape facesMap, trianglesMap, quadranglesMap;
   TopExp::MapShapes( theShape, TopAbs_FACE, facesMap );
 
   for ( int i = 1; i <= facesMap.Extent(); ++i )
     if (( theSubMesh  = theMesh.GetSubMesh( facesMap(i))))
       nbTriangles += theSubMesh->NbElements();
 
-  std::cout << "    " << facesMap.Extent() << " shapes of 2D dimension" << std::endl;
+  std::cout << "    " << facesMap.Extent() << " shapes of 2D dimension and" << std::endl;
+  if (nbEnforcedEdges+nbEnforcedTriangles+nbEnforcedQuadrangles)
+    std::cout << "    " << nbEnforcedEdges+nbEnforcedTriangles+nbEnforcedQuadrangles 
+                        << " enforced shapes:" << std::endl;
+  if (nbEnforcedEdges)
+    std::cout << "      " << nbEnforcedEdges << " enforced edges" << std::endl;
+  if (nbEnforcedTriangles)
+    std::cout << "      " << nbEnforcedTriangles << " enforced triangles" << std::endl;
+  if (nbEnforcedQuadrangles)
+    std::cout << "      " << nbEnforcedQuadrangles << " enforced quadrangles" << std::endl;
   std::cout << std::endl;
 
-  theFile << space << nbTriangles << space << dummyint << std::endl;
+//   theFile << space << nbTriangles << space << dummyint << std::endl;
+  std::ostringstream globalStream, localStream, aStream;
 
+  //
+  //        FACES : BEGIN
+  //
+  
   for ( int i = 1; i <= facesMap.Extent(); i++ )
   {
     aShape = facesMap(i);
@@ -301,7 +1474,7 @@ static bool writeFaces (ofstream &             theFile,
       aFace = itOnSubMesh->next();
       nbNodes = aFace->NbNodes();
 
-      theFile << space << nbNodes;
+      localStream << nbNodes << space;
 
       itOnSubFace = aFace->nodesIterator();
       while ( itOnSubFace->more() ) {
@@ -314,16 +1487,145 @@ static bool writeFaces (ofstream &             theFile,
         // }
         ASSERT( itOnMap != theSmdsToGhs3dIdMap.end() );
 
-        theFile << space << (*itOnMap).second;
+        localStream << (*itOnMap).second << space ;
       }
 
       // (NB_NODES + 1) times: DUMMY_INT
       for ( int j=0; j<=nbNodes; j++)
-        theFile << space << dummyint;
+        localStream << dummyint << space ;
 
-      theFile << std::endl;
+      localStream << std::endl;
+    }
+  }
+  
+  globalStream << localStream.str();
+  localStream.str("");
+
+  //
+  //        FACES : END
+  //
+
+  //
+  //        ENFORCED EDGES : BEGIN
+  //
+  
+  // Iterate over the enforced edges
+  int usedEnforcedEdges = 0;
+  bool isOK;
+  for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
+    aFace = (*elemIt);
+    isOK = true;
+    itOnSubFace = aFace->nodesIterator();
+    aStream.str("");
+    aStream << "2" << space ;
+    while ( itOnSubFace->more() ) {
+      aSmdsID = itOnSubFace->next()->GetID();
+      itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID);
+      if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end())
+        aStream << (*itOnMap).second << space;
+      else {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      for ( int j=0; j<=2; j++)
+        aStream << dummyint << space ;
+//       aStream << dummyint << space << dummyint;
+      localStream << aStream.str() << std::endl;
+      usedEnforcedEdges++;
+    }
+  }
+  
+  if (usedEnforcedEdges) {
+    globalStream << localStream.str();
+    localStream.str("");
+  }
+
+  //
+  //        ENFORCED EDGES : END
+  //
+  //
+
+  //
+  //        ENFORCED TRIANGLES : BEGIN
+  //
+    // Iterate over the enforced triangles
+  int usedEnforcedTriangles = 0;
+  for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
+    aFace = (*elemIt);
+    isOK = true;
+    itOnSubFace = aFace->nodesIterator();
+    aStream.str("");
+    aStream << "3" << space ;
+    while ( itOnSubFace->more() ) {
+      aSmdsID = itOnSubFace->next()->GetID();
+      itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID);
+      if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end())
+        aStream << (*itOnMap).second << space;
+      else {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      for ( int j=0; j<=3; j++)
+        aStream << dummyint << space ;
+      localStream << aStream.str() << std::endl;
+      usedEnforcedTriangles++;
+    }
+  }
+  
+  if (usedEnforcedTriangles) {
+    globalStream << localStream.str();
+    localStream.str("");
+  }
+
+  //
+  //        ENFORCED TRIANGLES : END
+  //
+
+  //
+  //        ENFORCED QUADRANGLES : BEGIN
+  //
+    // Iterate over the enforced quadrangles
+  int usedEnforcedQuadrangles = 0;
+  for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) {
+    aFace = (*elemIt);
+    isOK = true;
+    itOnSubFace = aFace->nodesIterator();
+    aStream.str("");
+    aStream << "4" << space ;
+    while ( itOnSubFace->more() ) {
+      aSmdsID = itOnSubFace->next()->GetID();
+      itOnMap = theEnforcedNodeIdToGhs3dIdMap.find(aSmdsID);
+      if (itOnMap != theEnforcedNodeIdToGhs3dIdMap.end())
+        aStream << (*itOnMap).second << space;
+      else {
+        isOK = false;
+        break;
+      }
     }
+    if (isOK) {
+      for ( int j=0; j<=4; j++)
+        aStream << dummyint << space ;
+      localStream << aStream.str() << std::endl;
+      usedEnforcedQuadrangles++;
+    }
+  }
+  
+  if (usedEnforcedQuadrangles) {
+    globalStream << localStream.str();
+    localStream.str("");
   }
+  //
+  //        ENFORCED QUADRANGLES : END
+  //
+
+  theFile
+  << nbTriangles+usedEnforcedQuadrangles+usedEnforcedTriangles+usedEnforcedEdges
+  << " 0" << std::endl
+  << globalStream.str();
 
   return true;
 }
@@ -334,9 +1636,15 @@ static bool writeFaces (ofstream &             theFile,
 //=======================================================================
 
 static bool writeFaces (ofstream &                      theFile,
-                        const SMESH_ProxyMesh&          theMesh,
-                        vector <const SMDS_MeshNode*> & theNodeByGhs3dId)
+                        const SMESH_ProxyMesh&          theProxyMesh,
+                        SMESH_Mesh *                    theMesh,
+                        vector <const SMDS_MeshNode*> & theNodeByGhs3dId,
+                        vector <const SMDS_MeshNode*> & theEnforcedNodeByGhs3dId,
+                        TIDSortedElemSet &              theEnforcedEdges,
+                        TIDSortedElemSet &              theEnforcedTriangles,
+                        TIDSortedElemSet &              theEnforcedQuadrangles)
 {
+  MESSAGE("writeFaces");
   // record structure:
   //
   // NB_ELEMS DUMMY_INT
@@ -344,37 +1652,60 @@ static bool writeFaces (ofstream &                      theFile,
   //   NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
 
   int nbNodes, nbTriangles = 0;
-  map< const SMDS_MeshNode*,int >::iterator it;
   SMDS_ElemIteratorPtr nodeIt;
-  const SMDS_MeshElement* elem;
 
   const char* space    = "  ";
   const int   dummyint = 0;
 
+  int nbEnforcedEdges       = theEnforcedEdges.size();
+  int nbEnforcedTriangles   = theEnforcedTriangles.size();
+  int nbEnforcedQuadrangles = theEnforcedQuadrangles.size();
   // count faces
-  nbTriangles = theMesh.NbFaces();
+  nbTriangles = theProxyMesh.NbFaces();
 
   if ( nbTriangles == 0 )
     return false;
 
-  std::cout << "The initial 2D mesh contains " << nbTriangles << " faces and ";
+  std::cout << "Start writing in 'faces' file ..." << std::endl;
+  std::cout << std::endl;
+  std::cout << "The initial 2D mesh contains " << nbTriangles << " shapes of 2D dimension and " << std::endl;
+  if (nbEnforcedEdges+nbEnforcedTriangles+nbEnforcedQuadrangles)
+    std::cout << "    " << nbEnforcedEdges+nbEnforcedTriangles+nbEnforcedQuadrangles 
+                        << " enforced shapes:" << std::endl;
+  if (nbEnforcedEdges)
+    std::cout << "      " << nbEnforcedEdges << " enforced edges" << std::endl;
+  if (nbEnforcedTriangles)
+    std::cout << "      " << nbEnforcedTriangles << " enforced triangles" << std::endl;
+  if (nbEnforcedQuadrangles)
+    std::cout << "      " << nbEnforcedQuadrangles << " enforced quadrangles" << std::endl;
 
   // NB_ELEMS DUMMY_INT
-  theFile << space << nbTriangles << space << dummyint << std::endl;
+//   theFile << nbTriangles << space << dummyint << std::endl;
+
 
+  map<const SMDS_MeshNode*,int> aNodeToGhs3dIdMap, anEnforcedNodeToGhs3dIdMap;
+  map< const SMDS_MeshNode*,int >::iterator it;
+  TIDSortedElemSet anElemSet, anEnforcedElemSet;
+  TIDSortedElemSet::iterator elemIt;
+  const SMDS_MeshElement* elem;
+  auto_ptr< SMESH_ElementSearcher > pntCls ( SMESH_MeshEditor( theMesh ).GetElementSearcher());
+  bool isOK;
+  const SMDS_MeshNode* node;
+  int usedEnforcedEdges = 0;
+  int usedEnforcedTriangles = 0;
+  int usedEnforcedQuadrangles = 0;
 
-  map<const SMDS_MeshNode*,int> aNodeToGhs3dIdMap;
+  //
+  //        FACES : BEGIN
+  //
 
   // Loop from 1 to NB_ELEMS
 
-  SMDS_ElemIteratorPtr eIt = theMesh.GetFaces();
+  SMDS_ElemIteratorPtr eIt = theProxyMesh.GetFaces();
   while ( eIt->more() )
   {
     elem = eIt->next();
-    // NB_NODES PER FACE
-    nbNodes = elem->NbNodes();
-    theFile << space << nbNodes;
-
+    anElemSet.insert(elem);
     // NODE_NB_1 NODE_NB_2 ...
     nodeIt = elem->nodesIterator();
     while ( nodeIt->more() )
@@ -382,27 +1713,189 @@ static bool writeFaces (ofstream &                      theFile,
       // find GHS3D ID
       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
       int newId = aNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
-      it = aNodeToGhs3dIdMap.insert( make_pair( node, newId )).first;
-      theFile << space << it->second;
+      aNodeToGhs3dIdMap.insert( make_pair( node, newId ));
     }
+  }
 
-    // (NB_NODES + 1) times: DUMMY_INT
-    for ( int i=0; i<=nbNodes; i++)
-      theFile << space << dummyint;
-    theFile << std::endl;
+  //
+  //        FACES : END
+  //
+
+
+  //
+  //        ENFORCED EDGES : BEGIN
+  //
+  
+  // Iterate over the enforced edges
+  for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
+    elem = (*elemIt);
+    isOK = true;
+    nodeIt = elem->nodesIterator();
+    while ( nodeIt->more() ) {
+      // find GHS3D ID
+      node = castToNode( nodeIt->next() );
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(node->X(),node->Y(),node->Z());
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN ) {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      nodeIt = elem->nodesIterator();
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        int newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
+        anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
+      }
+      anEnforcedElemSet.insert(elem);
+      usedEnforcedEdges++;
+    }
+  }
+
+  //
+  //        ENFORCED EDGES : END
+  //
+  //
+
+
+  //
+  //        ENFORCED TRIANGLES : BEGIN
+  //
+  // Iterate over the enforced triangles
+  for(elemIt = theEnforcedTriangles.begin() ; elemIt != theEnforcedTriangles.end() ; ++elemIt) {
+    elem = (*elemIt);
+    isOK = true;
+    nodeIt = elem->nodesIterator();
+    while ( nodeIt->more() ) {
+      // find GHS3D ID
+      const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(node->X(),node->Y(),node->Z());
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN ) {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      nodeIt = elem->nodesIterator();
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        int newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
+        anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
+      }
+      anEnforcedElemSet.insert(elem);
+      usedEnforcedTriangles++;
+    }
+  }
+
+  //
+  //        ENFORCED TRIANGLES : END
+  //
+
+  //
+  //        ENFORCED QUADRANGLES : BEGIN
+  //
+    // Iterate over the enforced quadrangles
+  for(elemIt = theEnforcedQuadrangles.begin() ; elemIt != theEnforcedQuadrangles.end() ; ++elemIt) {
+    elem = (*elemIt);
+    isOK = true;
+    nodeIt = elem->nodesIterator();
+    while ( nodeIt->more() ) {
+      // find GHS3D ID
+      const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(node->X(),node->Y(),node->Z());
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN ) {
+        isOK = false;
+        break;
+      }
+    }
+    if (isOK) {
+      nodeIt = elem->nodesIterator();
+      while ( nodeIt->more() ) {
+        // find GHS3D ID
+        const SMDS_MeshNode* node = castToNode( nodeIt->next() );
+        int newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // ghs3d ids count from 1
+        anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
+      }
+      anEnforcedElemSet.insert(elem);
+      usedEnforcedQuadrangles++;
+    }
   }
 
+  //
+  //        ENFORCED QUADRANGLES : END
+  //
+
+
   // put nodes to theNodeByGhs3dId vector
+  std::cout << "aNodeToGhs3dIdMap.size(): "<<aNodeToGhs3dIdMap.size()<<std::endl;
   theNodeByGhs3dId.resize( aNodeToGhs3dIdMap.size() );
   map<const SMDS_MeshNode*,int>::const_iterator n2id = aNodeToGhs3dIdMap.begin();
   for ( ; n2id != aNodeToGhs3dIdMap.end(); ++ n2id)
   {
+//     std::cout << "n2id->first: "<<n2id->first<<std::endl;
     theNodeByGhs3dId[ n2id->second - 1 ] = n2id->first; // ghs3d ids count from 1
   }
 
+  // put nodes to theNodeByGhs3dId vector
+  std::cout << "anEnforcedNodeToGhs3dIdMap.size(): "<<anEnforcedNodeToGhs3dIdMap.size()<<std::endl;
+  theEnforcedNodeByGhs3dId.resize( anEnforcedNodeToGhs3dIdMap.size() );
+  n2id = anEnforcedNodeToGhs3dIdMap.begin();
+  for ( ; n2id != anEnforcedNodeToGhs3dIdMap.end(); ++ n2id)
+  {
+//     std::cout << "n2id->first: "<<n2id->first<<std::endl;
+    theEnforcedNodeByGhs3dId[ n2id->second - aNodeToGhs3dIdMap.size() - 1 ] = n2id->first; // ghs3d ids count from 1
+  }
+
+  std::cout << "anElemSet.size(): " << anElemSet.size() << std::endl;
+  std::cout << "anEnforcedElemSet.size(): " << anEnforcedElemSet.size() << std::endl;
+  theFile << anElemSet.size() + anEnforcedElemSet.size() << space << "0" << std::endl;
+  for(elemIt = anElemSet.begin() ; elemIt != anElemSet.end() ; ++elemIt) {
+    elem = (*elemIt);
+    theFile << elem->NbNodes() << space ;
+    nodeIt = elem->nodesIterator();
+    while ( nodeIt->more() ) {
+      // find GHS3D ID
+      node = castToNode( nodeIt->next() );
+      it = aNodeToGhs3dIdMap.find(node);
+      if (it == aNodeToGhs3dIdMap.end())
+        throw "Node not found";
+
+      theFile << it->second << space ;
+    }
+    for ( int j=0; j<=elem->NbNodes(); j++)
+      theFile << dummyint << space ;
+    theFile << std::endl;
+  }
+  for(elemIt = anEnforcedElemSet.begin() ; elemIt != anEnforcedElemSet.end() ; ++elemIt) {
+    elem = (*elemIt);
+    theFile << elem->NbNodes() << space ;
+    nodeIt = elem->nodesIterator();
+    while ( nodeIt->more() ) {
+      // find GHS3D ID
+      node = castToNode( nodeIt->next() );
+      it = anEnforcedNodeToGhs3dIdMap.find(node);
+      if (it == anEnforcedNodeToGhs3dIdMap.end())
+        throw "Node not found";
+
+      theFile << it->second << space ;
+    }
+    for ( int j=0; j<=elem->NbNodes(); j++)
+      theFile << dummyint << space ;
+    theFile << std::endl;
+  }
+
   return true;
 }
 
+
 //=======================================================================
 //function : writePoints
 //purpose  : 
@@ -411,8 +1904,11 @@ static bool writeFaces (ofstream &                      theFile,
 static bool writePoints (ofstream &                       theFile,
                          SMESH_MesherHelper&              theHelper,
                          map <int,int> &                  theSmdsToGhs3dIdMap,
+                         map <int,int> &                  theEnforcedNodeIdToGhs3dIdMap,
                          map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap,
-                         map<vector<double>,double> &     theEnforcedVertices)
+                         GHS3DPlugin_Hypothesis::TID2SizeMap & theNodeIDToSizeMap,
+                         GHS3DPlugin_Hypothesis::TEnforcedVertexValues & theEnforcedVertices,
+                         TIDSortedNodeSet & theEnforcedNodes)
 {
   // record structure:
   //
@@ -425,6 +1921,7 @@ static bool writePoints (ofstream &                       theFile,
   if ( nbNodes == 0 )
     return false;
   int nbEnforcedVertices = theEnforcedVertices.size();
+  int nbEnforcedNodes    = theEnforcedNodes.size();
 
   // Issue 020674: EDF 870 SMESH: Mesh generated by Netgen not usable by GHS3D
   // The problem is in nodes on degenerated edges, we need to skip them
@@ -452,12 +1949,14 @@ static bool writePoints (ofstream &                       theFile,
   std::cout << std::endl;
   std::cout << "The initial 2D mesh contains :" << std::endl;
   std::cout << "    " << nbNodes << " nodes" << std::endl;
-  if (nbEnforcedVertices > 0) {
+  if (nbEnforcedVertices > 0)
     std::cout << "    " << nbEnforcedVertices << " enforced vertices" << std::endl;
-  }
-  std::cout << std::endl;
-  std::cout << "Start writing in 'points' file ..." << std::endl;
-  theFile << space << nbNodes << std::endl;
+  if (nbEnforcedNodes > 0)
+    std::cout << "    " << nbEnforcedNodes << " enforced nodes" << std::endl;
+
+//   std::cout << std::endl;
+//   std::cout << "Start writing in 'points' file ..." << std::endl;
+  theFile << nbNodes << space << std::endl;
 
   // Loop from 1 to NB_NODES
 
@@ -474,46 +1973,91 @@ static bool writePoints (ofstream &                       theFile,
 
     // X Y Z DUMMY_INT
     theFile
-    << space << node->X()
-    << space << node->Y()
-    << space << node->Z()
-    << space << dummyint;
-
+    << node->X() << space 
+    << node->Y() << space 
+    << node->Z() << space 
+    << dummyint << space ;
     theFile << std::endl;
 
   }
   
-  // Iterate over the enforced vertices
-  GHS3DPlugin_Hypothesis::TEnforcedVertexValues::const_iterator vertexIt;
-  const TopoDS_Shape shapeToMesh = theMesh->ShapeToMesh();
-  for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
-    double x = vertexIt->first[0];
-    double y = vertexIt->first[1];
-    double z = vertexIt->first[2];
-    // Test if point is inside shape to mesh
-    gp_Pnt myPoint(x,y,z);
-    BRepClass3d_SolidClassifier scl(shapeToMesh);
-    scl.Perform(myPoint, 1e-7);
-    TopAbs_State result = scl.State();
-    if ( result == TopAbs_IN ) {
-        MESSAGE("Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second);
-        // X Y Z PHY_SIZE DUMMY_INT
-        theFile
-        << space << x
-        << space << y
-        << space << z
-        << space << vertexIt->second
-        << space << dummyint;
-    
-        theFile << std::endl;
+  // Iterate over the enforced nodes
+  TIDSortedNodeSet::const_iterator nodeIt;
+  std::map<int,double> enfVertexIndexSizeMap;
+  if (nbEnforcedNodes) {
+    for(nodeIt = theEnforcedNodes.begin() ; nodeIt != theEnforcedNodes.end() ; ++nodeIt) {
+      double x = (*nodeIt)->X();
+      double y = (*nodeIt)->Y();
+      double z = (*nodeIt)->Z();
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(x,y,z);
+      BRepClass3d_SolidClassifier scl(theMesh->ShapeToMesh());
+      scl.Perform(myPoint, 1e-7);
+      TopAbs_State result = scl.State();
+      if ( result != TopAbs_IN )
+        continue;
+      std::vector<double> coords;
+      coords.push_back(x);
+      coords.push_back(y);
+      coords.push_back(z);
+      if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
+        continue;
+        
+      double size = theNodeIDToSizeMap.find((*nodeIt)->GetID())->second;
+  //       theGhs3dIdToNodeMap.insert( make_pair( nbNodes + i, (*nodeIt) ));
+  //       MESSAGE("Adding enforced node (" << x << "," << y <<"," << z << ")");
+      // X Y Z PHY_SIZE DUMMY_INT
+      theFile
+      << x << space 
+      << y << space 
+      << z << space
+      << size << space
+      << dummyint << space;
+      theFile << std::endl;
+      theEnforcedNodeIdToGhs3dIdMap.insert( make_pair( (*nodeIt)->GetID(), aGhs3dID ));
+      enfVertexIndexSizeMap[aGhs3dID] = -1;
+      aGhs3dID++;
+  //     else
+  //         MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added ");
+    }
+  }
+  
+  if (nbEnforcedVertices) {
+    // Iterate over the enforced vertices
+    GHS3DPlugin_Hypothesis::TEnforcedVertexValues::const_iterator vertexIt;
+//     int i = 1;
+    for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
+      double x = vertexIt->first[0];
+      double y = vertexIt->first[1];
+      double z = vertexIt->first[2];
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(x,y,z);
+      BRepClass3d_SolidClassifier scl(theMesh->ShapeToMesh());
+      scl.Perform(myPoint, 1e-7);
+      TopAbs_State result = scl.State();
+      if ( result != TopAbs_IN )
+        continue;
+  //         MESSAGE("Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second);
+          // X Y Z PHY_SIZE DUMMY_INT
+      theFile
+      << x << space 
+      << y << space 
+      << z << space
+      << vertexIt->second << space 
+      << dummyint << space;
+      theFile << std::endl;
+      enfVertexIndexSizeMap[aGhs3dID] = vertexIt->second;
+      aGhs3dID++;
+      
+  //     else
+  //         MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added ");
     }
-    else
-        MESSAGE("Enforced vertex (" << x << "," << y <<"," << z << ") is not inside the geometry: it was not added ");
   }
+  theFile << std::endl;
   
   
-  std::cout << std::endl;
-  std::cout << "End writing in 'points' file." << std::endl;
+//   std::cout << std::endl;
+//   std::cout << "End writing in 'points' file." << std::endl;
 
   return true;
 }
@@ -526,7 +2070,10 @@ static bool writePoints (ofstream &                       theFile,
 static bool writePoints (ofstream &                            theFile,
                          SMESH_Mesh *                          theMesh,
                          const vector <const SMDS_MeshNode*> & theNodeByGhs3dId,
-                         map<vector<double>,double> &          theEnforcedVertices)
+                         const vector <const SMDS_MeshNode*> & theEnforcedNodeByGhs3dId,
+                         GHS3DPlugin_Hypothesis::TID2SizeMap & theNodeIDToSizeMap,
+                         GHS3DPlugin_Hypothesis::TEnforcedVertexValues & theEnforcedVertices,
+                         TIDSortedNodeSet & theEnforcedNodes)
 {
   // record structure:
   //
@@ -539,64 +2086,156 @@ static bool writePoints (ofstream &                            theFile,
     return false;
 
   int nbEnforcedVertices = theEnforcedVertices.size();
+  int nbEnforcedNodes    = theEnforcedNodes.size();
 
   const char* space    = "  ";
   const int   dummyint = 0;
 
   const SMDS_MeshNode* node;
+  std::set< std::vector<double> > nodesCoords;
 
   // NB_NODES
-  std::cout << std::endl;
-  std::cout << "The initial 2D mesh contains :" << std::endl;
+//   std::cout << std::endl;
+//   std::cout << "The initial 2D mesh contains :" << std::endl;
   std::cout << "    " << nbNodes << " nodes" << std::endl;
-  std::cout << "    " << nbEnforcedVertices << " enforced vertices" << std::endl;
+  if (nbEnforcedVertices > 0)
+    std::cout << "    " << nbEnforcedVertices << " enforced vertices" << std::endl;
+  if (nbEnforcedNodes > 0)
+    std::cout << "    " << nbEnforcedNodes << " enforced nodes" << std::endl;
   std::cout << std::endl;
   std::cout << "Start writing in 'points' file ..." << std::endl;
-  theFile << space << nbNodes << std::endl;
+  theFile << nbNodes << space << std::endl;
 
   // Loop from 1 to NB_NODES
 
   vector<const SMDS_MeshNode*>::const_iterator nodeIt = theNodeByGhs3dId.begin();
   vector<const SMDS_MeshNode*>::const_iterator after  = theNodeByGhs3dId.end();
+  
+  std::cout << theNodeByGhs3dId.size() << " nodes from mesh ..." << std::endl;
   for ( ; nodeIt != after; ++nodeIt )
   {
     node = *nodeIt;
 
     // X Y Z DUMMY_INT
     theFile
-    << space << node->X()
-    << space << node->Y()
-    << space << node->Z()
-    << space << dummyint;
+    << node->X() << space 
+    << node->Y() << space 
+    << node->Z() << space 
+    << dummyint << std::endl;
+    
+    std::vector<double> coords;
+    coords.push_back(node->X());
+    coords.push_back(node->Y());
+    coords.push_back(node->Z());
+    nodesCoords.insert(coords);
+  }
+  
+  if (nbEnforcedNodes) {
+    std::cout << theEnforcedNodes.size() << " nodes from enforced nodes ..." << std::endl;
+    // Iterate over the enforced nodes
+    TIDSortedNodeSet::const_iterator enfNodeIt;
+    auto_ptr< SMESH_ElementSearcher > pntCls ( SMESH_MeshEditor( theMesh ).GetElementSearcher());
+    for(enfNodeIt = theEnforcedNodes.begin() ; enfNodeIt != theEnforcedNodes.end() ; ++enfNodeIt)
+    {
+      node = *enfNodeIt;
+      
+      std::vector<double> coords;
+      coords.push_back(node->X());
+      coords.push_back(node->Y());
+      coords.push_back(node->Z());
+      
+      if (nodesCoords.find(coords) != nodesCoords.end()) {
+        std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z() << " found" << std::endl;
+        continue;
+      }
 
-    theFile << std::endl;
+      if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
+        continue;
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(node->X(),node->Y(),node->Z());
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN )
+        continue;
 
+      // X Y Z DUMMY_INT
+      theFile
+      << node->X() << space 
+      << node->Y() << space 
+      << node->Z() << space 
+      << theNodeIDToSizeMap.find(node->GetID())->second << space
+      << dummyint << std::endl;
+      
+      nodesCoords.insert(coords);
+    }
   }
   
-  // Iterate over the enforced vertices
-  GHS3DPlugin_Hypothesis::TEnforcedVertexValues::const_iterator vertexIt;
-  auto_ptr< SMESH_ElementSearcher > pntCls ( SMESH_MeshEditor( theMesh ).GetElementSearcher());
-  for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
-    double x = vertexIt->first[0];
-    double y = vertexIt->first[1];
-    double z = vertexIt->first[2];
-    // Test if point is inside shape to mesh
-    gp_Pnt myPoint(x,y,z);
-    TopAbs_State result = pntCls->GetPointState( myPoint );
-    if ( result == TopAbs_IN ) {
-        std::cout << "Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second << std::endl;
-
-        // X Y Z PHY_SIZE DUMMY_INT
-        theFile
-        << space << x
-        << space << y
-        << space << z
-        << space << vertexIt->second
-        << space << dummyint;
+  if (theEnforcedNodeByGhs3dId.size()) {
+    std::cout << theEnforcedNodeByGhs3dId.size() << " nodes from enforced elements ..." << std::endl;
+    // Iterate over the enforced nodes given by enforced elements
+    nodeIt = theEnforcedNodeByGhs3dId.begin();
+    after  = theEnforcedNodeByGhs3dId.end();
+    for ( ; nodeIt != after; ++nodeIt )
+    {
+      node = *nodeIt;
+      
+      std::vector<double> coords;
+      coords.push_back(node->X());
+      coords.push_back(node->Y());
+      coords.push_back(node->Z());
+      
+      if (nodesCoords.find(coords) != nodesCoords.end()) {
+        std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z() << " found" << std::endl;
+        continue;
+      }
+      
+      if (theEnforcedVertices.find(coords) != theEnforcedVertices.end())
+        continue;
+
+      // X Y Z DUMMY_INT
+      theFile
+      << node->X() << space 
+      << node->Y() << space 
+      << node->Z() << space 
+      << theNodeIDToSizeMap.find(node->GetID())->second << space
+      << dummyint << std::endl;
+      
+      nodesCoords.insert(coords);
+    }
+  }
+  
+  if (nbEnforcedVertices) {
+    std::cout << theEnforcedVertices.size() << " nodes from enforced vertices ..." << std::endl;
+    // Iterate over the enforced vertices
+    GHS3DPlugin_Hypothesis::TEnforcedVertexValues::const_iterator vertexIt;
+    auto_ptr< SMESH_ElementSearcher > pntCls ( SMESH_MeshEditor( theMesh ).GetElementSearcher());
+    for(vertexIt = theEnforcedVertices.begin() ; vertexIt != theEnforcedVertices.end() ; ++vertexIt) {
+      double x = vertexIt->first[0];
+      double y = vertexIt->first[1];
+      double z = vertexIt->first[2];
+      // Test if point is inside shape to mesh
+      gp_Pnt myPoint(x,y,z);
+      TopAbs_State result = pntCls->GetPointState( myPoint );
+      if ( result != TopAbs_IN )
+        continue;
+      std::cout << "Adding enforced vertex (" << x << "," << y <<"," << z << ") = " << vertexIt->second << std::endl;
+
+      // X Y Z PHY_SIZE DUMMY_INT
+      theFile
+      << x << space
+      << y << space
+      << z << space
+      << vertexIt->second << space
+      << dummyint << std::endl;
+      
+      std::vector<double> coords;
+      coords.push_back(x);
+      coords.push_back(y);
+      coords.push_back(z);
+      nodesCoords.insert(coords);
     
-        theFile << std::endl;
     }
   }
+  
   std::cout << std::endl;
   std::cout << "End writing in 'points' file." << std::endl;
 
@@ -809,7 +2448,11 @@ static bool readResultFile(const int                       fileOpen,
                            const int                       nbShape,
                            map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap,
                            bool                            toMeshHoles,
-                           int                             nbEnforcedVertices)
+                           int                             nbEnforcedVertices,
+                           int                             nbEnforcedNodes,
+                           TIDSortedElemSet &              theEnforcedEdges,
+                           TIDSortedElemSet &              theEnforcedTriangles,
+                           TIDSortedElemSet &              theEnforcedQuadrangles)
 {
   MESSAGE("GHS3DPlugin_GHS3D::readResultFile()");
   Kernel_Utils::Localizer loc;
@@ -881,14 +2524,12 @@ static bool readResultFile(const int                       fileOpen,
   for (int i=0; i < 4*nbElems; i++)
     nodeId = strtol(ptr, &ptr, 10);
 
-  MESSAGE("nbInputNodes: "<<nbInputNodes);
-  MESSAGE("nbEnforcedVertices: "<<nbEnforcedVertices);
   // Reading the nodeCoor and update the nodeMap
   for (int iNode=1; iNode <= nbNodes; iNode++) {
     for (int iCoor=0; iCoor < 3; iCoor++)
       coord[ iCoor ] = strtod(ptr, &ptr);
     nodeAssigne[ iNode ] = 1;
-    if ( iNode > (nbInputNodes-nbEnforcedVertices) ) {
+    if ( iNode > (nbInputNodes-(nbEnforcedVertices+nbEnforcedNodes)) ) {
       // Creating SMESH nodes
       // - for enforced vertices
       // - for vertices of forced edges
@@ -1068,7 +2709,12 @@ static bool readResultFile(const int                      fileOpen,
                            SMESH_Mesh&                    theMesh,
                            TopoDS_Shape                   aSolid,
                            vector <const SMDS_MeshNode*>& theNodeByGhs3dId,
-                           int                            nbEnforcedVertices)
+                           vector <const SMDS_MeshNode*>& theEnforcedNodeByGhs3dId,
+                           int                            nbEnforcedVertices,
+                           int                            nbEnforcedNodes,
+                           TIDSortedElemSet &             theEnforcedEdges,
+                           TIDSortedElemSet &             theEnforcedTriangles,
+                           TIDSortedElemSet &             theEnforcedQuadrangles)
 {
   SMESHDS_Mesh* theMeshDS = theMesh.GetMeshDS();
 
@@ -1139,7 +2785,7 @@ static bool readResultFile(const int                      fileOpen,
   for (int iNode=0; iNode < nbNodes; iNode++) {
     for (int iCoor=0; iCoor < 3; iCoor++)
       coord[ iCoor ] = strtod(ptr, &ptr);
-    if ((iNode+1) > (nbInputNodes-nbEnforcedVertices)) {
+    if ((iNode+1) > (nbInputNodes-(nbEnforcedVertices+nbEnforcedNodes+theEnforcedNodeByGhs3dId.size()))) {
       // Issue 0020682. Avoid creating nodes and tetras at place where
       // volumic elements already exist
       if ( elemSearcher &&
@@ -1254,6 +2900,16 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
 
   TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
   TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
+  TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName;
+#ifdef _DEBUG_
+  aGMFFileName    = aGenericName + ".mesh"; // GMF mesh file
+  aRequiredVerticesFileName    = aGenericName + "_required.mesh"; // GMF required vertices mesh file
+  aSolFileName    = aGenericName + "_required.sol"; // GMF solution file
+#else
+  aGMFFileName    = aGenericName + ".meshb"; // GMF mesh file
+  aRequiredVerticesFileName    = aGenericName + "_required.meshb"; // GMF required vertices mesh file
+  aSolFileName    = aGenericName + ".solb"; // GMF solution file
+#endif
   aFacesFileName  = aGenericName + ".faces";  // in faces
   aPointsFileName = aGenericName + ".points"; // in points
   aResultFileName = aGenericName + ".noboite";// out points and volumes
@@ -1265,25 +2921,30 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   // make input files
   // -----------------
 
+//   ofstream aGMFFile    ( aGMFFileName.ToCString()    , ios::out);
+//   ofstream aSolFile    ( aSolFileName.ToCString()    , ios::out);
   ofstream aFacesFile  ( aFacesFileName.ToCString()  , ios::out);
   ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
 
   Ok =
-    aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
+    aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open()
+                                  /*&& aGMFFile.rdbuf()->is_open()
+                                  && aSolFile.rdbuf()->is_open()*/;
   if (!Ok) {
     INFOS( "Can't write into " << aFacesFileName);
     return error(SMESH_Comment("Can't write into ") << aFacesFileName);
   }
-  map <int,int> aSmdsToGhs3dIdMap;
+  map <int,int> aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap;
   map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
-  map<vector<double>,double> enforcedVertices;
-  int nbEnforcedVertices = 0;
-  try {
-    enforcedVertices = GHS3DPlugin_Hypothesis::GetEnforcedVertices(_hyp);
-    nbEnforcedVertices = enforcedVertices.size();
-  }
-  catch(...) {
-  }
+  std::map <int, int> nodeID2nodeIndexMap;
+  GHS3DPlugin_Hypothesis::TEnforcedVertexValues enforcedVertices = GHS3DPlugin_Hypothesis::GetEnforcedVertices(_hyp);
+  TIDSortedNodeSet enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
+  TIDSortedElemSet enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
+  TIDSortedElemSet enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp);
+  TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp);
+  GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
+//   GHS3DPlugin_Hypothesis::TID2SizeMap elemIDToSizeMap = GHS3DPlugin_Hypothesis::GetElementIDToSizeMap(_hyp);
+  int nbEnforcedVertices = enforcedVertices.size();
 
   SMESH_MesherHelper helper( theMesh );
   helper.SetSubShape( theShape );
@@ -1316,11 +2977,38 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
       if ( !proxyMesh )
         return false;
     }
-
-    Ok = (writePoints( aPointsFile, helper, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap, enforcedVertices)
+// #if GHS3D_VERSION >= 42
+    Ok = writeGMFFile(aGMFFileName, aRequiredVerticesFileName, aSolFileName, helper, *proxyMesh, 
+                      aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap,
+                      enforcedNodes, enforcedEdges, enforcedTriangles, enforcedQuadrangles,
+                      enforcedVertices);
+/*
+    Ok = (writeGMFHeader( aGMFFile, 1) &&
+          writeGMFVertices( aGMFFile, aSolFile, helper, 
+                            aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap,
+                            enforcedVertices, enforcedNodes, nodeID2nodeIndexMap) &&
+          writeGMFFaces( aGMFFile, *proxyMesh, theShape, 
+                         aSmdsToGhs3dIdMap,
+                         enforcedEdges, enforcedTriangles, enforcedQuadrangles,
+                         nodeID2nodeIndexMap) &&
+          writeGMFEnd( aGMFFile ));
+*/
+// #else
+    Ok = (writePoints( aPointsFile, helper, 
+                       aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap, aGhs3dIdToNodeMap, 
+                       nodeIDToSizeMap,
+                       enforcedVertices, enforcedNodes)
           &&
-          writeFaces ( aFacesFile, *proxyMesh, theShape, aSmdsToGhs3dIdMap ));
+          writeFaces ( aFacesFile, *proxyMesh, theShape, 
+                       aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap,
+                       enforcedEdges, enforcedTriangles, enforcedQuadrangles));
+// #endif
   }
+  
+  int nbEnforcedNodes = enforcedNodes.size();
+  int nbEnforcedEdges = enforcedEdges.size();
+  int nbEnforcedTriangles = enforcedTriangles.size();
+  int nbEnforcedQuadrangles = enforcedQuadrangles.size();
 
   // Write aSmdsToGhs3dIdMap to temp file
   TCollection_AsciiString aSmdsToGhs3dIdMapFileName;
@@ -1338,6 +3026,8 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
     aIdsFile << myit->first << " " << myit->second << std::endl;
   }
 
+//   aGMFFile.close();
+//   aSolFile.close();
   aFacesFile.close();
   aPointsFile.close();
   aIdsFile.close();
@@ -1356,9 +3046,15 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   // run ghs3d mesher
   // -----------------
 
-  TCollection_AsciiString cmd( (char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp ).c_str() );
+  TCollection_AsciiString cmd = TCollection_AsciiString((char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp ).c_str() );
+#if GHS3D_VERSION >= 42
+  cmd += TCollection_AsciiString(" --in ") + aGenericName;
+  cmd += TCollection_AsciiString(" --required_vertices ") + aRequiredVerticesFileName;
+  cmd += TCollection_AsciiString(" --out ") + aGenericName;
+#else
   cmd += TCollection_AsciiString(" -f ") + aGenericName;  // file to read
-  cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
+#endif
+  cmd += TCollection_AsciiString(" -Om 1>" ) + aLogFileName;  // dump into file
 
   std::cout << std::endl;
   std::cout << "Ghs3d execution..." << std::endl;
@@ -1391,7 +3087,9 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
                          aResultFileName.ToCString(),
 #endif
                          theMesh, tabShape, tabBox, _nbShape, aGhs3dIdToNodeMap,
-                         toMeshHoles, nbEnforcedVertices );
+                         toMeshHoles, 
+                         nbEnforcedVertices, nbEnforcedNodes, 
+                         enforcedEdges, enforcedTriangles, enforcedQuadrangles );
   }
 
   // ---------------------
@@ -1458,6 +3156,16 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
 
   TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
   TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
+  TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName;
+#ifdef _DEBUG_
+  aGMFFileName    = aGenericName + ".mesh"; // GMF mesh file
+  aRequiredVerticesFileName    = aGenericName + "_required.mesh"; // GMF required vertices mesh file
+  aSolFileName    = aGenericName + "_required.sol"; // GMF solution file
+#else
+  aGMFFileName    = aGenericName + ".meshb"; // GMF mesh file
+  aRequiredVerticesFileName    = aGenericName + "_required.meshb"; // GMF required vertices mesh file
+  aSolFileName    = aGenericName + ".solb"; // GMF solution file
+#endif
   aFacesFileName  = aGenericName + ".faces";  // in faces
   aPointsFileName = aGenericName + ".points"; // in points
   aResultFileName = aGenericName + ".noboite";// out points and volumes
@@ -1469,24 +3177,31 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   // make input files
   // -----------------
 
+//   ofstream aGMFFile    ( aGMFFileName.ToCString()    , ios::out);
+//   ofstream aSolFile    ( aSolFileName.ToCString()    , ios::out);
   ofstream aFacesFile  ( aFacesFileName.ToCString()  , ios::out);
   ofstream aPointsFile  ( aPointsFileName.ToCString()  , ios::out);
   bool Ok =
-    aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
+    aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open()
+                                  /*&& aGMFFile.rdbuf()->is_open()
+                                  && aSolFile.rdbuf()->is_open()*/;
 
-  if (!Ok)
-    return error( SMESH_Comment("Can't write into ") << aPointsFileName);
-  
-  GHS3DPlugin_Hypothesis::TEnforcedVertexValues enforcedVertices;
-  int nbEnforcedVertices = 0;
-  try {
-    enforcedVertices = GHS3DPlugin_Hypothesis::GetEnforcedVertices(_hyp);
-    nbEnforcedVertices = enforcedVertices.size();
-  }
-  catch(...) {
+  if (!Ok) {
+    INFOS( "Can't write into " << aFacesFileName);
+    return error( SMESH_Comment("Can't write into ") << aFacesFileName);
   }
+  
+  std::map <int, int> nodeID2nodeIndexMap;
+  GHS3DPlugin_Hypothesis::TEnforcedVertexValues enforcedVertices = GHS3DPlugin_Hypothesis::GetEnforcedVertices(_hyp);
+  TIDSortedNodeSet enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
+  TIDSortedElemSet enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
+  TIDSortedElemSet enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp);
+  TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp);
+  GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
+  int nbEnforcedVertices = enforcedVertices.size();
 
-  vector <const SMDS_MeshNode*> aNodeByGhs3dId;
+
+  vector <const SMDS_MeshNode*> aNodeByGhs3dId, anEnforcedNodeByGhs3dId;
   {
     SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
     if ( theMesh.NbQuadrangles() > 0 )
@@ -1496,9 +3211,28 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
       proxyMesh.reset( aQuad2Trias );
     }
 
-    Ok = (writeFaces ( aFacesFile, *proxyMesh, aNodeByGhs3dId ) &&
-          writePoints( aPointsFile, &theMesh, aNodeByGhs3dId,enforcedVertices));
+// #if GHS3D_VERSION >= 42
+    Ok = writeGMFFile(aGMFFileName, aRequiredVerticesFileName, aSolFileName, *proxyMesh, &theMesh, 
+                      aNodeByGhs3dId, anEnforcedNodeByGhs3dId,
+                      enforcedNodes, enforcedEdges, enforcedTriangles, enforcedQuadrangles,
+                      enforcedVertices);
+
+// #else
+
+    Ok = (writeFaces ( aFacesFile, *proxyMesh, &theMesh, aNodeByGhs3dId, anEnforcedNodeByGhs3dId,
+                       enforcedEdges, enforcedTriangles, enforcedQuadrangles ) &&
+          writePoints( aPointsFile, &theMesh, aNodeByGhs3dId, anEnforcedNodeByGhs3dId,
+                       nodeIDToSizeMap, enforcedVertices, enforcedNodes));
+// #endif
   }  
+  
+  int nbEnforcedNodes = enforcedNodes.size();
+  int nbEnforcedEdges = enforcedEdges.size();
+  int nbEnforcedTriangles = enforcedTriangles.size();
+  int nbEnforcedQuadrangles = enforcedQuadrangles.size();
+  
+//   aGMFFile.close();
+//   aSolFile.close();
   aFacesFile.close();
   aPointsFile.close();
   
@@ -1515,13 +3249,25 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   // run ghs3d mesher
   // -----------------
 
-  TCollection_AsciiString cmd =
-    (char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str();
+  TCollection_AsciiString cmd = TCollection_AsciiString((char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str());
+#if GHS3D_VERSION >= 42
+  cmd += TCollection_AsciiString(" --in ") + aGenericName;
+  cmd += TCollection_AsciiString(" --required_vertices ") + aRequiredVerticesFileName;
+  cmd += TCollection_AsciiString(" --out ") + aGenericName;
+#else
   cmd += TCollection_AsciiString(" -f ") + aGenericName;  // file to read
-  cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
+#endif
+  cmd += TCollection_AsciiString(" -Om 1>" ) + aLogFileName;  // dump into file
+
+  std::cout << std::endl;
+  std::cout << "Ghs3d execution..." << std::endl;
+  std::cout << cmd << std::endl;
   
   system( cmd.ToCString() ); // run
 
+  std::cout << std::endl;
+  std::cout << "End of Ghs3d execution !" << std::endl;
+
   // --------------
   // read a result
   // --------------
@@ -1539,7 +3285,9 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
 #ifdef WNT
                          aResultFileName.ToCString(),
 #endif
-                         theMesh, theShape ,aNodeByGhs3dId, nbEnforcedVertices );
+                         theMesh, theShape ,aNodeByGhs3dId, anEnforcedNodeByGhs3dId,
+                         nbEnforcedVertices, nbEnforcedNodes, 
+                         enforcedEdges, enforcedTriangles, enforcedQuadrangles );
   }
   
   // ---------------------
index bdfa2b9fe502ad6fbd6b9436eabcc0c49d513f83..eec584152fa3f2a381c7ab6a21989f5aedd36808 100644 (file)
@@ -49,10 +49,19 @@ GHS3DPlugin_Hypothesis::GHS3DPlugin_Hypothesis(int hypId, int studyId, SMESH_Gen
   myToUseBoundaryRecoveryVersion(DefaultToUseBoundaryRecoveryVersion()),
   myToUseFemCorrection(DefaultToUseFEMCorrection()),
   myToRemoveCentralPoint(DefaultToRemoveCentralPoint()),
-  myEnforcedVertices(DefaultEnforcedVertices())
+  myEnforcedVertices(DefaultEnforcedVertices()),
+  _enfNodes(DefaultIDSortedNodeSet()),
+  _enfEdges(DefaultIDSortedElemSet()),
+  _enfTriangles(DefaultIDSortedElemSet()),
+  _enfQuadrangles(DefaultIDSortedElemSet())
 {
   _name = "GHS3D_Parameters";
   _param_algo_dim = 3;
+  _edgeID2nodeIDMap.clear();
+  _triID2nodeIDMap.clear();
+  _quadID2nodeIDMap.clear();
+  _nodeIDToSizeMap.clear();
+  _elementIDToSizeMap.clear();
 }
 
 //=======================================================================
@@ -328,6 +337,136 @@ void GHS3DPlugin_Hypothesis::SetEnforcedVertex(double x, double y, double z, dou
   NotifySubMeshesHypothesisModification();
 }
 
+//=======================================================================
+//function : SetEnforcedElements
+//=======================================================================
+void GHS3DPlugin_Hypothesis::SetEnforcedElements(TIDSortedElemSet theElemSet, SMESH::ElementType elementType, double size)
+{
+  MESSAGE("GHS3DPlugin_Hypothesis::SetEnforcedElements");
+  TIDSortedElemSet::const_iterator it = theElemSet.begin();
+  const SMDS_MeshElement* elem;
+  for (;it != theElemSet.end();++it)
+  {
+    elem = (*it);
+//     MESSAGE("Element ID: " << (*it)->GetID());
+    const SMDS_MeshNode* node = dynamic_cast<const SMDS_MeshNode*>(elem);
+    switch (elementType) {
+      case SMESH::NODE:
+        if (node) {
+//           MESSAGE("This is a node");
+          _enfNodes.insert(node);
+          _nodeIDToSizeMap.insert(make_pair(node->GetID(), size));
+        }
+        else {
+//           MESSAGE("This is an element");
+          _enfNodes.insert(elem->begin_nodes(),elem->end_nodes());
+          SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+          for (;nodeIt->more();)
+            _nodeIDToSizeMap.insert(make_pair(nodeIt->next()->GetID(), size));
+        }
+        NotifySubMeshesHypothesisModification();
+        break;
+      case SMESH::EDGE:
+        if (node) {
+//           MESSAGE("This is a node");
+        }
+        else {
+//           MESSAGE("This is an element");
+          if (elem->GetType() == SMDSAbs_Edge) {
+            _enfEdges.insert(elem);
+//             _enfNodes.insert(elem->begin_nodes(),elem->end_nodes());
+            _elementIDToSizeMap.insert(make_pair(elem->GetID(), size));
+            SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+            for (;nodeIt->more();) {
+              node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
+              _edgeID2nodeIDMap[elem->GetID()].push_back(node->GetID());
+              _nodeIDToSizeMap.insert(make_pair(node->GetID(), size));
+            }
+          }
+          else if (elem->GetType() > SMDSAbs_Edge) {
+            SMDS_ElemIteratorPtr it = elem->edgesIterator();
+            for (;it->more();) {
+              const SMDS_MeshElement* anEdge = it->next();
+              _enfEdges.insert(anEdge);
+//               _enfNodes.insert(anEdge->begin_nodes(),anEdge->end_nodes());
+              _elementIDToSizeMap.insert(make_pair(anEdge->GetID(), size));
+              SMDS_ElemIteratorPtr nodeIt = anEdge->nodesIterator();
+              for (;nodeIt->more();) {
+                node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
+                _edgeID2nodeIDMap[anEdge->GetID()].push_back(node->GetID());
+                _nodeIDToSizeMap.insert(make_pair(node->GetID(), size));
+              }
+            }
+          }
+        }
+        NotifySubMeshesHypothesisModification();
+        break;
+      case SMESH::FACE:
+        if (node) {
+//           MESSAGE("This is a node");
+        }
+        else {
+//           MESSAGE("This is an element");
+          if (elem->GetType() == SMDSAbs_Face)
+          {
+            if (elem->NbNodes() == 3) {
+              _enfTriangles.insert(elem);
+//               _enfNodes.insert(elem->begin_nodes(),elem->end_nodes());
+              _elementIDToSizeMap.insert(make_pair(elem->GetID(), size));
+              SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+              for (;nodeIt->more();) {
+                node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
+                _triID2nodeIDMap[elem->GetID()].push_back(node->GetID());
+                _nodeIDToSizeMap.insert(make_pair(node->GetID(), size));
+              }
+            }
+            else if (elem->NbNodes() == 4) {
+              _enfQuadrangles.insert(elem);
+//               _enfNodes.insert(elem->begin_nodes(),elem->end_nodes());
+              _elementIDToSizeMap.insert(make_pair(elem->GetID(), size));
+              SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
+              for (;nodeIt->more();) {
+                node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
+                _quadID2nodeIDMap[elem->GetID()].push_back(node->GetID());
+                _nodeIDToSizeMap.insert(make_pair(node->GetID(), size));
+              }
+            }
+          }
+          else if (elem->GetType() > SMDSAbs_Face) {
+            SMDS_ElemIteratorPtr it = elem->facesIterator();
+            for (;it->more();) {
+              const SMDS_MeshElement* aFace = it->next();
+              if (aFace->NbNodes() == 3) {
+                _enfTriangles.insert(aFace);
+//                 _enfNodes.insert(aFace->begin_nodes(),aFace->end_nodes());
+                _elementIDToSizeMap.insert(make_pair(aFace->GetID(), size));
+                SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
+                for (;nodeIt->more();) {
+                  node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
+                  _triID2nodeIDMap[aFace->GetID()].push_back(node->GetID());
+                  _nodeIDToSizeMap.insert(make_pair(node->GetID(), size));
+                }
+              }
+              else if (aFace->NbNodes() == 4) {
+                _enfQuadrangles.insert(aFace);
+//                 _enfNodes.insert(aFace->begin_nodes(),aFace->end_nodes());
+                _elementIDToSizeMap.insert(make_pair(aFace->GetID(), size));
+                SMDS_ElemIteratorPtr nodeIt = aFace->nodesIterator();
+                for (;nodeIt->more();) {
+                  node = dynamic_cast<const SMDS_MeshNode*>(nodeIt->next());
+                  _quadID2nodeIDMap[aFace->GetID()].push_back(node->GetID());
+                  _nodeIDToSizeMap.insert(make_pair(node->GetID(), size));
+                }
+              }
+            }
+          }
+        }
+        NotifySubMeshesHypothesisModification();
+        break;
+    };
+  }
+}
+
 //=======================================================================
 //function : GetEnforcedVertex
 //=======================================================================
@@ -377,6 +516,24 @@ void GHS3DPlugin_Hypothesis::ClearEnforcedVertices()
     NotifySubMeshesHypothesisModification();
 }
 
+//=======================================================================
+//function : ClearEnforcedMeshes
+//=======================================================================
+void GHS3DPlugin_Hypothesis::ClearEnforcedMeshes()
+{
+   _enfNodes.clear();
+   _enfEdges.clear();
+   _enfTriangles.clear();
+   _enfQuadrangles.clear();
+//    _edgeID2nodeIDMap.clear();
+//    _triID2nodeIDMap.clear();
+//    _quadID2nodeIDMap.clear();
+//    _nodeIDToSizeMap.clear();
+//    _elementIDToSizeMap.clear();
+   NotifySubMeshesHypothesisModification();
+}
+
+
 //=======================================================================
 //function : DefaultMeshHoles
 //=======================================================================
@@ -524,6 +681,15 @@ GHS3DPlugin_Hypothesis::TEnforcedVertexValues GHS3DPlugin_Hypothesis::DefaultEnf
   return GHS3DPlugin_Hypothesis::TEnforcedVertexValues();
 }
 
+TIDSortedNodeSet GHS3DPlugin_Hypothesis::DefaultIDSortedNodeSet()
+{
+  return TIDSortedNodeSet();
+}
+
+TIDSortedElemSet GHS3DPlugin_Hypothesis::DefaultIDSortedElemSet()
+{
+  return TIDSortedElemSet();
+}
 
 //=======================================================================
 //function : SaveTo
@@ -744,7 +910,7 @@ bool GHS3DPlugin_Hypothesis::SetParametersByDefaults(const TDefaults&  /*dflts*/
 std::string GHS3DPlugin_Hypothesis::CommandToRun(const GHS3DPlugin_Hypothesis* hyp,
                                             const bool                    hasShapeToMesh)
 {
-  TCollection_AsciiString cmd( "ghs3d" );
+  TCollection_AsciiString cmd( "ghs3d" ); // ghs3dV4.1_32bits (to permit the .mesh output)
   // check if any option is overridden by hyp->myTextOption
   bool m   = hyp ? ( hyp->myTextOption.find("-m")  == std::string::npos ) : true;
   bool M   = hyp ? ( hyp->myTextOption.find("-M")  == std::string::npos ) : true;
@@ -881,3 +1047,47 @@ GHS3DPlugin_Hypothesis::TEnforcedVertexValues GHS3DPlugin_Hypothesis::GetEnforce
     return hyp ? hyp->_GetEnforcedVertices():DefaultEnforcedVertices();
 }
 
+TIDSortedNodeSet GHS3DPlugin_Hypothesis::GetEnforcedNodes(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetEnforcedNodes():DefaultIDSortedNodeSet();
+}
+
+TIDSortedElemSet GHS3DPlugin_Hypothesis::GetEnforcedEdges(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetEnforcedEdges():DefaultIDSortedElemSet();
+}
+
+TIDSortedElemSet GHS3DPlugin_Hypothesis::GetEnforcedTriangles(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetEnforcedTriangles():DefaultIDSortedElemSet();
+}
+
+TIDSortedElemSet GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetEnforcedQuadrangles():DefaultIDSortedElemSet();
+}
+
+GHS3DPlugin_Hypothesis::TElemID2NodeIDMap GHS3DPlugin_Hypothesis::GetEdgeID2NodeIDMap(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetEdgeID2NodeIDMap(): GHS3DPlugin_Hypothesis::TElemID2NodeIDMap();
+}
+
+GHS3DPlugin_Hypothesis::TElemID2NodeIDMap GHS3DPlugin_Hypothesis::GetTri2NodeMap(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetTri2NodeMap(): GHS3DPlugin_Hypothesis::TElemID2NodeIDMap();
+}
+
+GHS3DPlugin_Hypothesis::TElemID2NodeIDMap GHS3DPlugin_Hypothesis::GetQuad2NodeMap(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetQuad2NodeMap(): GHS3DPlugin_Hypothesis::TElemID2NodeIDMap();
+}
+
+GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetNodeIDToSizeMap(): GHS3DPlugin_Hypothesis::TID2SizeMap();
+}
+
+GHS3DPlugin_Hypothesis::TID2SizeMap GHS3DPlugin_Hypothesis::GetElementIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp)
+{
+    return hyp ? hyp->_GetElementIDToSizeMap(): GHS3DPlugin_Hypothesis::TID2SizeMap();
+}
index 28fe2bb64b201c5d9c2c4e9a175bb3870b152353..fd51c7d1a3be467bd03f97cfa752f70df90270e5 100644 (file)
 
 #include "GHS3DPlugin_Defs.hxx"
 
-#include <SMESH_Hypothesis.hxx>
-#include <utilities.h>
+#include "SMESH_Hypothesis.hxx"
+#include "SMESH_Mesh_i.hxx"
+#include "SMESH_Gen_i.hxx"
+#include "SMESH_TypeDefs.hxx"
+#include "utilities.h"
 
 #include <stdexcept>
 #include <map>
@@ -117,6 +120,39 @@ public:
   /*!
    * To set an enforced vertex
    */
+//   struct TEnforcedNode {
+//     std::vector<double> coords;
+//     double size;
+//     std::string geomEntry;
+//     std::string groupName;
+//   };
+//   
+//   struct CompareEnfNodes {
+//     bool operator () (const TEnforcedNode* e1, const TEnforcedNode* e2) const {
+//       if (e1 && e2) {
+//         if (e1->coords.size() && e2->coords.size())
+//           return (e1->coords < e2->coords);
+//         else
+//           return (e1->geomEntry < e2->geomEntry);
+//       }
+//       return false;
+//     }
+//   };
+//   typedef std::set< TEnforcedNode*, CompareEnfNodes > TEnforcedNodeList;
+//   // Map Coords / Enforced node
+//   typedef std::map< std::vector<double>, TEnforcedNode* > TCoordsEnfNodeMap;
+//   // Map geom entry / Enforced ndoe
+//   typedef std::map< std::string, TEnforcedNode* > TGeomEntryEnfNodeMap;
+//   
+//   
+//   struct TEnforcedEdge {
+//     long ID;
+//     long node1;
+//     long node2;
+//     std::string groupName;
+//   };
+  
+  
   typedef std::map<std::vector<double>,double> TEnforcedVertexValues;
   void SetEnforcedVertex(double x, double y, double z, double size);
   double GetEnforcedVertex(double x, double y, double z) throw (std::invalid_argument);
@@ -124,6 +160,23 @@ public:
   const TEnforcedVertexValues _GetEnforcedVertices() const { return myEnforcedVertices; }
   void ClearEnforcedVertices();
 
+  /*!
+   * To set enforced elements
+   */
+  void SetEnforcedElements(TIDSortedElemSet theElemSet, SMESH::ElementType elementType, double size);
+  void ClearEnforcedMeshes();
+  const TIDSortedNodeSet _GetEnforcedNodes() const { return _enfNodes; }
+  const TIDSortedElemSet _GetEnforcedEdges() const { return _enfEdges; }
+  const TIDSortedElemSet _GetEnforcedTriangles() const { return _enfTriangles; }
+  const TIDSortedElemSet _GetEnforcedQuadrangles() const { return _enfQuadrangles; }
+  typedef std::map<int,std::vector<int> > TElemID2NodeIDMap;
+  const TElemID2NodeIDMap _GetEdgeID2NodeIDMap() const {return _edgeID2nodeIDMap; }
+  const TElemID2NodeIDMap _GetTri2NodeMap() const {return _triID2nodeIDMap; }
+  const TElemID2NodeIDMap _GetQuad2NodeMap() const {return _quadID2nodeIDMap; }
+  typedef std::map<int,double> TID2SizeMap;
+  const TID2SizeMap _GetNodeIDToSizeMap() const {return _nodeIDToSizeMap; }
+  const TID2SizeMap _GetElementIDToSizeMap() const {return _elementIDToSizeMap; }
+
   static bool   DefaultMeshHoles();
   static short  DefaultMaximumMemory();
   static short  DefaultInitialMemory();
@@ -136,6 +189,8 @@ public:
   static bool   DefaultToUseFEMCorrection();
   static bool   DefaultToRemoveCentralPoint();
   static TEnforcedVertexValues DefaultEnforcedVertices();
+  static TIDSortedNodeSet DefaultIDSortedNodeSet();
+  static TIDSortedElemSet DefaultIDSortedElemSet();
 
   /*!
    * \brief Return command to run ghs3d mesher excluding file prefix (-f)
@@ -150,7 +205,16 @@ public:
    * \brief Return the enforced vertices
    */
   static TEnforcedVertexValues GetEnforcedVertices(const GHS3DPlugin_Hypothesis* hyp);
-
+  static TIDSortedNodeSet GetEnforcedNodes(const GHS3DPlugin_Hypothesis* hyp);
+  static TIDSortedElemSet GetEnforcedEdges(const GHS3DPlugin_Hypothesis* hyp);
+  static TIDSortedElemSet GetEnforcedTriangles(const GHS3DPlugin_Hypothesis* hyp);
+  static TIDSortedElemSet GetEnforcedQuadrangles(const GHS3DPlugin_Hypothesis* hyp);
+  static TElemID2NodeIDMap GetEdgeID2NodeIDMap(const GHS3DPlugin_Hypothesis* hyp);
+  static TElemID2NodeIDMap GetTri2NodeMap(const GHS3DPlugin_Hypothesis* hyp);
+  static TElemID2NodeIDMap GetQuad2NodeMap(const GHS3DPlugin_Hypothesis* hyp);
+  static TID2SizeMap GetNodeIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp);
+  static TID2SizeMap GetElementIDToSizeMap(const GHS3DPlugin_Hypothesis* hyp);
+  
   // Persistence
   virtual std::ostream & SaveTo(std::ostream & save);
   virtual std::istream & LoadFrom(std::istream & load);
@@ -182,7 +246,15 @@ private:
   bool   myToRemoveCentralPoint;
   std::string myTextOption;
   TEnforcedVertexValues myEnforcedVertices;
-  
+  TIDSortedNodeSet _enfNodes;
+  TIDSortedElemSet _enfEdges;
+  TIDSortedElemSet _enfTriangles;
+  TIDSortedElemSet _enfQuadrangles;
+  TElemID2NodeIDMap _edgeID2nodeIDMap;
+  TElemID2NodeIDMap _triID2nodeIDMap;
+  TElemID2NodeIDMap _quadID2nodeIDMap;
+  TID2SizeMap _nodeIDToSizeMap;
+  TID2SizeMap _elementIDToSizeMap;
 };
 
 
index ff3953e3d1fda035db4dc22733064dde56c62a16..1ccb8e90457a0413de6ad93db2e1269b989d1e56 100644 (file)
 //
 #include "GHS3DPlugin_Hypothesis_i.hxx"
 
-#include <SMESH_Gen.hxx>
-#include <SMESH_PythonDump.hxx>
-
-#include <Utils_CorbaException.hxx>
-#include <utilities.h>
-#include <SMESH_Mesh_i.hxx>
-
+#include "SMESH_Gen.hxx"
+#include "SMESH_PythonDump.hxx"
+
+#include "Utils_CorbaException.hxx"
+#include "utilities.h"
+#include "SMESH_Mesh_i.hxx"
+#include "SMESH_Group_i.hxx"
+#include "SMESH_Gen_i.hxx"
+#include "SMESH_TypeDefs.hxx"
+
+#ifndef GHS3D_VERSION
+#define GHS3D_VERSION 41
+#endif
 //=======================================================================
 //function : GHS3DPlugin_Hypothesis_i
 //=======================================================================
@@ -418,7 +424,7 @@ void GHS3DPlugin_Hypothesis_i::RemoveEnforcedVertex(CORBA::Double x, CORBA::Doub
     ExDescription.text = ex.what();
     ExDescription.type = SALOME::BAD_PARAM;
     ExDescription.sourceFile = "GHS3DPlugin_Hypothesis::RemoveEnforcedVertex(x,y,z)";
-    ExDescription.lineNumber = 0;
+    ExDescription.lineNumber = 408;
     throw SALOME::SALOME_Exception(ExDescription);
   }
   catch (SALOME_Exception& ex) {
@@ -434,8 +440,179 @@ void GHS3DPlugin_Hypothesis_i::ClearEnforcedVertices()
 {
   ASSERT(myBaseImpl);
   this->GetImpl()->ClearEnforcedVertices();
+  SMESH::TPythonDump () << _this() << ".ClearEnforcedVertices() ";
+}
+
+//=======================================================================
+//function : ClearEnforcedMeshes
+//=======================================================================
+
+void GHS3DPlugin_Hypothesis_i::ClearEnforcedMeshes()
+{
+  ASSERT(myBaseImpl);
+  this->GetImpl()->ClearEnforcedMeshes();
+  SMESH::TPythonDump () << _this() << ".ClearEnforcedMeshes() ";
+}
+
+/*!
+ * \brief Adds enforced elements of type elementType using another mesh/sub-mesh/mesh group theSource.
+ */
+void GHS3DPlugin_Hypothesis_i::SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType)
+  throw (SALOME::SALOME_Exception)
+{
+#if GHS3D_VERSION >= 42
+  _SetEnforcedMesh(thesource, theType, -1.0);
+  SMESH_Mesh_i* theMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theSource);
+  SMESH_Group_i* theGroup_i = SMESH::DownCast<SMESH_Group_i*>( theSource);
+  if (theGroup_i)
+  {
+    SMESH::TPythonDump () << _this() << ".SetEnforcedMesh( " 
+                          << theSource << ", " << theType << ", " << theSize << " )";
+  }
+  else if (theMesh_i)
+  {
+    SMESH::TPythonDump () << _this() << ".SetEnforcedMesh( " 
+                          << theSource << ".GetMesh(), " << theType << ", " << theSize << " )";
+  }
+#else
+  SALOME::ExceptionStruct ExDescription;
+  ExDescription.text = "Bad version of GHS3D";
+  ExDescription.type = SALOME::BAD_PARAM;
+  ExDescription.sourceFile = "GHS3DPlugin_Hypothesis::SetEnforcedMesh(theSource, theType)";
+  ExDescription.lineNumber = 445;
+  throw SALOME::SALOME_Exception(ExDescription);
+#endif
+}
+
+/*!
+ * \brief Adds enforced elements of type elementType using another mesh/sub-mesh/mesh group theSource and a size.
+ */
+void GHS3DPlugin_Hypothesis_i::SetEnforcedMeshSize(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType, double theSize)
+  throw (SALOME::SALOME_Exception)
+{
+  if (theSize <= 0) {
+    SALOME::ExceptionStruct ExDescription;
+    ExDescription.text = "Size cannot be negative";
+    ExDescription.type = SALOME::BAD_PARAM;
+    ExDescription.sourceFile = "GHS3DPlugin_Hypothesis::SetEnforcedMeshSize(theSource, theType)";
+    ExDescription.lineNumber = 475;
+    throw SALOME::SALOME_Exception(ExDescription);
+  }
+  
+  _SetEnforcedMesh(theSource, theType, theSize);
+  SMESH_Mesh_i* theMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theSource);
+  SMESH_Group_i* theGroup_i = SMESH::DownCast<SMESH_Group_i*>( theSource);
+  if (theGroup_i)
+  {
+    SMESH::TPythonDump () << _this() << ".SetEnforcedMeshSize( " 
+                          << theSource << ", " << theType << ", " << theSize << " )";
+  }
+  else if (theMesh_i)
+  {
+    SMESH::TPythonDump () << _this() << ".SetEnforcedMeshSize( " 
+                          << theSource << ".GetMesh(), " << theType << ", " << theSize << " )";
+  }
 }
 
+void GHS3DPlugin_Hypothesis_i::_SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType theType, double theSize)
+  throw (SALOME::SALOME_Exception)
+{
+  ASSERT(myBaseImpl);
+  
+  if (CORBA::is_nil( theSource ))
+  {
+    SALOME::ExceptionStruct ExDescription;
+    ExDescription.text = "The source mesh CORBA object is NULL";
+    ExDescription.type = SALOME::BAD_PARAM;
+    ExDescription.sourceFile = "GHS3DPlugin_Hypothesis::_SetEnforcedMesh(theSource, theType, theSize)";
+    ExDescription.lineNumber = 502;
+    throw SALOME::SALOME_Exception(ExDescription);
+  }
+  
+  if ((theType != SMESH::NODE) && (theType != SMESH::EDGE) && (theType != SMESH::FACE))
+  {
+    SALOME::ExceptionStruct ExDescription;
+    ExDescription.text = "Bad elementType";
+    ExDescription.type = SALOME::BAD_PARAM;
+    ExDescription.sourceFile = "GHS3DPlugin_Hypothesis::_SetEnforcedMesh(theSource, theType, theSize)";
+    ExDescription.lineNumber = 502;
+    throw SALOME::SALOME_Exception(ExDescription);
+  }
+  
+  SMESH::array_of_ElementType_var types = theSource->GetTypes();
+//   MESSAGE("Required type is "<<theType);
+//   MESSAGE("Available types:");
+//   for (int i=0;i<types->length();i++){MESSAGE(types[i]);}
+  if ( types->length() >= 1 && types[types->length()-1] <  theType)
+  {
+    SALOME::ExceptionStruct ExDescription;
+    ExDescription.text = "The source mesh has bad type";
+    ExDescription.type = SALOME::BAD_PARAM;
+    ExDescription.sourceFile = "GHS3DPlugin_Hypothesis::_SetEnforcedMesh(theSource, theType, theSize)";
+    ExDescription.lineNumber = 502;
+    throw SALOME::SALOME_Exception(ExDescription);
+  }
+  
+  SMESHDS_Mesh* theMeshDS;
+  SMESH_Mesh_i* anImplPtr = SMESH::DownCast<SMESH_Mesh_i*>(theSource->GetMesh());
+  if (anImplPtr)
+    theMeshDS = anImplPtr->GetImpl().GetMeshDS();
+  else
+    return;
+  
+  SMESH_Mesh_i* theMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theSource);
+  SMESH_Group_i* theGroup_i = SMESH::DownCast<SMESH_Group_i*>( theSource);
+  TIDSortedElemSet theElemSet;
+
+  if (theMesh_i)
+  {
+    SMESH::long_array_var anIDs = theMesh_i->GetElementsByType(theType);
+    if ( anIDs->length() == 0 ){MESSAGE("The source mesh is empty");}
+    for (int i=0; i<anIDs->length(); i++) {
+      CORBA::Long ind = anIDs[i];
+      const SMDS_MeshElement * elem = theMeshDS->FindElement(ind);
+      if (elem)
+        theElemSet.insert( elem );
+    }
+    MESSAGE("Add "<<theElemSet.size()<<" types["<<theType<<"] from source mesh");
+  }
+  else if (theGroup_i && types->length() == 1 && types[0] == theType)
+  {
+    SMESH::long_array_var anIDs = theGroup_i->GetListOfID();
+    if ( anIDs->length() == 0 ){MESSAGE("The source group is empty");}
+    for (int i=0; i<anIDs->length(); i++) {
+      CORBA::Long ind = anIDs[i];
+      if (theType == SMESH::NODE)
+      {
+        const SMDS_MeshNode * node = theMeshDS->FindNode(ind);
+        if (node)
+          theElemSet.insert( node );
+      }
+      else
+      {
+        const SMDS_MeshElement * elem = theMeshDS->FindElement(ind);
+        if (elem)
+          theElemSet.insert( elem );
+      }
+    }
+    MESSAGE("Add "<<theElemSet.size()<<" types["<<theType<<"] from source group "<< theGroup_i->GetName());
+  }
+  
+  try {
+    this->GetImpl()->SetEnforcedElements(theElemSet, theType, theSize);
+  }
+  catch (const std::invalid_argument& ex) {
+    SALOME::ExceptionStruct ExDescription;
+    ExDescription.text = ex.what();
+    ExDescription.type = SALOME::BAD_PARAM;
+    ExDescription.sourceFile = "GHS3DPlugin_Hypothesis::_SetEnforcedMesh(theSource, theType, theSize)";
+    ExDescription.lineNumber = 502;
+    throw SALOME::SALOME_Exception(ExDescription);
+  }
+  catch (SALOME_Exception& ex) {
+    THROW_SALOME_CORBA_EXCEPTION( ex.what() ,SALOME::BAD_PARAM );
+  }
+}
 //=============================================================================
 /*!
  *  Get implementation
index 0cf9a26606649d196b30b49cc5c604008509775f..d9b59414e8b403b282902b4a87cefac188bcfda8 100644 (file)
@@ -31,6 +31,7 @@
 #include CORBA_SERVER_HEADER(GHS3DPlugin_Algorithm)
 
 #include "SMESH_Hypothesis_i.hxx"
+#include "SMESH_Mesh_i.hxx"
 #include "GHS3DPlugin_Hypothesis.hxx"
 
 class SMESH_Gen;
@@ -129,6 +130,13 @@ class GHS3DPLUGIN_EXPORT GHS3DPlugin_Hypothesis_i:
   void RemoveEnforcedVertex(CORBA::Double x, CORBA::Double y, CORBA::Double z) throw (SALOME::SALOME_Exception);
   GHS3DPlugin::GHS3DEnforcedVertexList* GetEnforcedVertices();
   void ClearEnforcedVertices();
+  /*!
+   * To set an enforced mesh
+   */
+  void SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType elementType) throw (SALOME::SALOME_Exception);
+  void SetEnforcedMeshSize(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType elementType, double size) throw (SALOME::SALOME_Exception);
+  void _SetEnforcedMesh(SMESH::SMESH_IDSource_ptr theSource, SMESH::ElementType elementType, double size) throw (SALOME::SALOME_Exception);
+  void ClearEnforcedMeshes();
 
   // Get implementation
   ::GHS3DPlugin_Hypothesis* GetImpl();
index 28751997741112da0836d41051ec9bceccee53e8..4e7dda2be4569a59a72da0550cfec0723859a897 100644 (file)
@@ -27,6 +27,7 @@ include $(top_srcdir)/adm_local/unix/make_common_starter.am
 
 # header files 
 salomeinclude_HEADERS = \
+       libmesh5.h \
        GHS3DPlugin_Defs.hxx \
        GHS3DPlugin_GHS3D.hxx \
        GHS3DPlugin_GHS3D_i.hxx \
@@ -37,6 +38,7 @@ salomeinclude_HEADERS = \
 lib_LTLIBRARIES = libGHS3DEngine.la
 
 dist_libGHS3DEngine_la_SOURCES = \
+  libmesh5.c \
   GHS3DPlugin_GHS3D.cxx \
   GHS3DPlugin_GHS3D_i.cxx \
   GHS3DPlugin_i.cxx \