Salome HOME
bos #20282 EDF 22320 - general compute fails
[plugins/blsurfplugin.git] / src / BLSURFPlugin / BLSURFPlugin_BLSURF.cxx
index ea2ecf66757c0546f44a7b0149fcfa2ae380a16f..8222eafd243b208eb5b332b19903d3e0e0c91cfe 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2020  CEA/DEN, EDF R&D
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
@@ -37,7 +37,6 @@ extern "C"{
 
 
 #include <Basics_Utils.hxx>
-#include <Basics_OCCTVersion.hxx>
 
 #include <SMDS_EdgePosition.hxx>
 #include <SMESHDS_Group.hxx>
@@ -59,6 +58,7 @@ extern "C"{
 #include <cstdlib>
 
 // OPENCASCADE includes
+#include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
 #include <BRepBuilderAPI_MakePolygon.hxx>
 #include <BRepBuilderAPI_MakeWire.hxx>
@@ -146,8 +146,7 @@ namespace
   static PyTypeObject PyStdOut_Type = {
     /* The ob_type field must be initialized in the module init function
      * to be portable to Windows without using C++. */
-    PyObject_HEAD_INIT(NULL)
-    0,                            /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "PyOut",                      /*tp_name*/
     sizeof(PyStdOut),             /*tp_basicsize*/
     0,                            /*tp_itemsize*/
@@ -242,10 +241,9 @@ bool HasSizeMapOnVertex=false;
 //=============================================================================
 
 BLSURFPlugin_BLSURF::BLSURFPlugin_BLSURF(int        hypId,
-                                         int        studyId,
                                          SMESH_Gen* gen,
                                          bool       theHasGEOM)
-  : SMESH_2D_Algo(hypId, studyId, gen)
+  : SMESH_2D_Algo(hypId, gen)
 {
   _name = theHasGEOM ? "MG-CADSurf" : "MG-CADSurf_NOGEOM";//"BLSURF";
   _shapeType = (1 << TopAbs_FACE); // 1 bit /shape type
@@ -258,13 +256,6 @@ BLSURFPlugin_BLSURF::BLSURFPlugin_BLSURF(int        hypId,
   _supportSubmeshes = true;
   _requireShape = theHasGEOM;
 
-  smeshGen_i = SMESH_Gen_i::GetSMESHGen();
-  CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager");
-  SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
-
-  myStudy = NULL;
-  myStudy = aStudyMgr->GetStudyByID(_studyId);
-
   /* Initialize the Python interpreter */
   assert(Py_IsInitialized());
   PyGILState_STATE gstate;
@@ -503,19 +494,16 @@ projectionPoint getProjectionPoint(TopoDS_Face& theFace, const gp_Pnt& thePoint)
 /////////////////////////////////////////////////////////
 TopoDS_Shape BLSURFPlugin_BLSURF::entryToShape(std::string entry)
 {
-  TopoDS_Shape S;
-  if ( !entry.empty() )
-  {
-    GEOM::GEOM_Object_var aGeomObj;
-    SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() );
-    if (!aSObj->_is_nil()) {
-      CORBA::Object_var obj = aSObj->GetObject();
-      aGeomObj = GEOM::GEOM_Object::_narrow(obj);
-      aSObj->UnRegister();
-    }
-    if ( !aGeomObj->_is_nil() )
-      S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
-  }
+  GEOM::GEOM_Object_var aGeomObj;
+  TopoDS_Shape S = TopoDS_Shape();
+  SALOMEDS::SObject_var aSObj = SMESH_Gen_i::getStudyServant()->FindObjectID( entry.c_str() );
+  if (!aSObj->_is_nil()) {
+    CORBA::Object_var obj = aSObj->GetObject();
+    aGeomObj = GEOM::GEOM_Object::_narrow(obj);
+    aSObj->UnRegister();
+  }
+  if ( !aGeomObj->_is_nil() )
+    S = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( aGeomObj.in() );
   return S;
 }
 
@@ -892,6 +880,12 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
   bool   _quadraticMesh         = BLSURFPlugin_Hypothesis::GetDefaultQuadraticMesh();
   int    _verb                  = BLSURFPlugin_Hypothesis::GetDefaultVerbosity();
   //int    _topology              = BLSURFPlugin_Hypothesis::GetDefaultTopology();
+  bool   _useSurfaceProximity      = BLSURFPlugin_Hypothesis::GetDefaultUseSurfaceProximity     ();
+  int    _nbSurfaceProximityLayers = BLSURFPlugin_Hypothesis::GetDefaultNbSurfaceProximityLayers();
+  double _surfaceProximityRatio    = BLSURFPlugin_Hypothesis::GetDefaultSurfaceProximityRatio   ();
+  bool   _useVolumeProximity       = BLSURFPlugin_Hypothesis::GetDefaultUseVolumeProximity      ();
+  int    _nbVolumeProximityLayers  = BLSURFPlugin_Hypothesis::GetDefaultNbVolumeProximityLayers ();
+  double _volumeProximityRatio     = BLSURFPlugin_Hypothesis::GetDefaultVolumeProximityRatio    ();
 
   // PreCAD
   //int _precadMergeEdges         = BLSURFPlugin_Hypothesis::GetDefaultPreCADMergeEdges();
@@ -954,14 +948,21 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
     //_precadRemoveDuplicateCADFaces = hyp->GetPreCADRemoveDuplicateCADFaces();
     //_precadProcess3DTopology = hyp->GetPreCADProcess3DTopology();
     //_precadDiscardInput      = hyp->GetPreCADDiscardInput();
+    _useSurfaceProximity      = hyp->GetUseSurfaceProximity     ();
+    _nbSurfaceProximityLayers = hyp->GetNbSurfaceProximityLayers();
+    _surfaceProximityRatio    = hyp->GetSurfaceProximityRatio   ();
+    _useVolumeProximity       = hyp->GetUseVolumeProximity      ();
+    _nbVolumeProximityLayers  = hyp->GetNbVolumeProximityLayers ();
+    _volumeProximityRatio     = hyp->GetVolumeProximityRatio    ();
+
 
     const BLSURFPlugin_Hypothesis::TOptionValues& opts = hyp->GetOptionValues();
     BLSURFPlugin_Hypothesis::TOptionValues::const_iterator opIt;
     for ( opIt = opts.begin(); opIt != opts.end(); ++opIt ){
       MESSAGE("OptionValue: " << opIt->first.c_str() << ", value: " << opIt->second.c_str());
       if ( !opIt->second.empty() ) {
-               // With MeshGems 2.4-5, there are issues with periodicity and multithread
-               // => As a temporary workaround, we enforce to use only one thread if periodicity is used.
+        // With MeshGems 2.4-5, there are issues with periodicity and multithread
+        // => As a temporary workaround, we enforce to use only one thread if periodicity is used.
         if (opIt->first == "max_number_of_threads" && opIt->second != "1" && ! preCadFacesPeriodicityVector.empty()){
           std::cout << "INFO: Disabling multithread to avoid periodicity issues" << std::endl;
           set_param(css, opIt->first.c_str(), "1");
@@ -975,7 +976,7 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
     for ( opIt = custom_opts.begin(); opIt != custom_opts.end(); ++opIt )
       if ( !opIt->second.empty() ) {
         set_param(css, opIt->first.c_str(), opIt->second.c_str());
-     }
+      }
 
     const BLSURFPlugin_Hypothesis::TOptionValues& preCADopts = hyp->GetPreCADOptionValues();
     for ( opIt = preCADopts.begin(); opIt != preCADopts.end(); ++opIt )
@@ -1001,11 +1002,12 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
      case BLSURFPlugin_Hypothesis::PhysicalGlobalSize:
        set_param(css, "physical_size_mode", "global");
        set_param(css, "global_physical_size", _phySizeRel ? val_to_string_rel(_phySize).c_str() : val_to_string(_phySize).c_str());
+       //useGradation = true;
        break;
      case BLSURFPlugin_Hypothesis::PhysicalLocalSize:
        set_param(css, "physical_size_mode", "local");
        set_param(css, "global_physical_size", _phySizeRel ? val_to_string_rel(_phySize).c_str() : val_to_string(_phySize).c_str());
-       useGradation = true;
+       //useGradation = true;
        break;
      default:
        set_param(css, "physical_size_mode", "none");
@@ -1017,13 +1019,13 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
        set_param(css, "geometric_size_mode", "global");
        set_param(css, "geometric_approximation", val_to_string(_angleMesh).c_str());
        set_param(css, "chordal_error", val_to_string(_chordalError).c_str());
-       useGradation = true;
+       //useGradation = true;
        break;
      case BLSURFPlugin_Hypothesis::GeometricalLocalSize:
        set_param(css, "geometric_size_mode", "local");
        set_param(css, "geometric_approximation", val_to_string(_angleMesh).c_str());
        set_param(css, "chordal_error", val_to_string(_chordalError).c_str());
-       useGradation = true;
+       //useGradation = true;
        break;
      default:
        set_param(css, "geometric_size_mode", "none");
@@ -1054,6 +1056,7 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
      // - if maxsize is not explicitly specified, we pass default value computed automatically, in this case "relative" flag is ignored
      set_param(css, "max_size", _maxSizeRel ? val_to_string_rel(_maxSize).c_str() : val_to_string(_maxSize).c_str());
    }
+   useGradation = true; // bos #18758
    // anisotropic and quadrangle mesh requires disabling gradation
    if ( _anisotropic && _elementType != BLSURFPlugin_Hypothesis::Triangles )
      useGradation = false; // limitation of V1.3
@@ -1099,6 +1102,19 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
    set_param(css, "element_order",                     _quadraticMesh ? "quadratic" : "linear");
    set_param(css, "verbose",                           val_to_string(_verb).c_str());
 
+   set_param(css, "use_surface_proximity",             _useSurfaceProximity ? "yes" : "no" );
+   if ( _useSurfaceProximity )
+   {
+     set_param(css, "surface_proximity_layers",        SMESH_Comment( _nbSurfaceProximityLayers ));
+     set_param(css, "surface_proximity_ratio",         SMESH_Comment( _surfaceProximityRatio ));
+   }
+   set_param(css, "use_volume_proximity",             _useVolumeProximity ? "yes" : "no" );
+   if ( _useVolumeProximity )
+   {
+     set_param(css, "volume_proximity_layers",        SMESH_Comment( _nbVolumeProximityLayers ));
+     set_param(css, "volume_proximity_ratio",         SMESH_Comment( _volumeProximityRatio ));
+   }
+
    _smp_phy_size = _phySizeRel ? _phySize*diagonal : _phySize;
    if ( _verb > 0 )
      std::cout << "_smp_phy_size = " << _smp_phy_size << std::endl;
@@ -1485,12 +1501,8 @@ namespace
     bool operator()( const SMDS_MeshNode* n1, const SMDS_MeshNode* n2 ) const
     {
       // NEW ORDER: nodes earlier added to sub-mesh are considered "less"
-      return n1->getIdInShape() < n2->getIdInShape();
-      // SMDS_TypeOfPosition pos1 = n1->GetPosition()->GetTypeOfPosition();
-      // SMDS_TypeOfPosition pos2 = n2->GetPosition()->GetTypeOfPosition();
-      // if ( pos1 == pos2 ) return 0;
-      // if ( pos1 < pos2 || pos1 == SMDS_TOP_3DSPACE ) return 1;
-      // return -1;
+      //return n1->getIdInShape() < n2->getIdInShape();
+      return n1->GetID() < n2->GetID(); // earlier created nodes have less IDs
     }
     // sort sub-meshes in order: EDGE, VERTEX
     bool operator()( const SMESHDS_SubMesh* s1, const SMESHDS_SubMesh* s2 ) const
@@ -1526,11 +1538,10 @@ namespace
     }
     case TopAbs_EDGE: {
       std::multimap< double, const SMDS_MeshNode* > u2node;
-      const SMDS_EdgePosition* ePos;
       while ( nIt->more() )
       {
         const SMDS_MeshNode* n = nIt->next();
-        if (( ePos = dynamic_cast< const SMDS_EdgePosition* >( n->GetPosition() )))
+        if ( SMDS_EdgePositionPtr ePos = n->GetPosition() )
           u2node.insert( make_pair( ePos->GetUParameter(), n ));
       }
       if ( u2node.size() < 2 ) return;
@@ -1538,7 +1549,7 @@ namespace
       //double tol = (( u2node.rbegin()->first - u2node.begin()->first ) / 20.) / u2node.size();
       Standard_Real f,l;
       BRep_Tool::Range( TopoDS::Edge( shape ), f,l );
-      double tol = (( l - f ) / 20.) / u2node.size();
+      double tol = (( l - f ) / 10.) / u2node.size(); // 10. - adjusted for #17262
 
       std::multimap< double, const SMDS_MeshNode* >::iterator un2, un1;
       for ( un2 = u2node.begin(), un1 = un2++; un2 != u2node.end(); un1 = un2++ )
@@ -1777,7 +1788,7 @@ namespace
       const SMDS_MeshNode* nodes[27];
       const SMDS_MeshNode* nullNode = 0;
       double xyz[3];
-      SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator(/*idInceasingOrder=*/true);
+      SMDS_FaceIteratorPtr fIt = GetMeshDS()->facesIterator();
       while ( fIt->more() )
       {
         const SMDS_MeshElement* f = fIt->next();
@@ -1913,6 +1924,7 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
   typedef set< SMESHDS_SubMesh*, ShapeTypeCompare > TSubMeshSet;
   TSubMeshSet edgeSubmeshes;
   TSubMeshSet& mergeSubmeshes = edgeSubmeshes;
+  double existingPhySize = 0;
 
   TopTools_IndexedMapOfShape pmap, emap, fmap;
 
@@ -2019,11 +2031,7 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
      * (For this face, it will be called by cadsurf with your_face_object_ptr
      * as last parameter.
      */
-#if OCC_VERSION_MAJOR < 7
-    cad_face_t *fce = cad_face_new(c, iface, surf_fun, surfaces.back());
-#else
     cad_face_t *fce = cad_face_new(c, iface, surf_fun, surfaces.back().get());
-#endif
 
     /* by default a face has no tag (color).
        The following call sets it to the same value as the Geom module ID : */
@@ -2215,6 +2223,8 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
           // tmin and tmax can change in case of viscous layer on an adjacent edge
           tmin = nodeDataVec.front().param;
           tmax = nodeDataVec.back().param;
+
+          existingPhySize += nodeData->Length() / ( nodeDataVec.size() - 1 );
         }
         else
         {
@@ -2224,11 +2234,7 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
       }
 
       /* attach the edge to the current cadsurf face */
-#if OCC_VERSION_MAJOR < 7
-      cad_edge_t *edg = cad_edge_new(fce, ic, tmin, tmax, curv_fun, curves.back());
-#else
       cad_edge_t *edg = cad_edge_new(fce, ic, tmin, tmax, curv_fun, curves.back().get());
-#endif
 
       /* by default an edge has no tag (color).
          The following call sets it to the same value as the edge_id : */
@@ -2284,8 +2290,16 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
           //      << "\t uv = ( " << uv[0] << ","<< uv[1] << " ) "
           //      << "\t u = " << nData.param
           //      << "\t ID = " << nData.node->GetID() << endl;
-          dcad_edge_discretization_set_vertex_coordinates( dedge, iN+1, t, uv, nXYZ._xyz );
+          dcad_edge_discretization_set_vertex_coordinates( dedge, iN+1, t, uv, nXYZ.ChangeData() );
         }
+        TopoDS_Shape v = helper.GetSubShapeByNode( nodeDataVec[0].node, meshDS );
+        if ( !v.IsNull() && v.ShapeType() == TopAbs_VERTEX )
+          dcad_edge_discretization_set_vertex_tag( dedge, 1, pmap.Add( v ));
+
+        v = helper.GetSubShapeByNode( nodeDataVec.back().node, meshDS );
+        if ( !v.IsNull() && v.ShapeType() == TopAbs_VERTEX )
+          dcad_edge_discretization_set_vertex_tag( dedge, nbNodes, pmap.Add( v ));
+
         dcad_edge_discretization_set_property(dedge, DISTENE_DCAD_PROPERTY_REQUIRED);
       }
 
@@ -2360,44 +2374,6 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
     } // for edge
   } //for face
 
-  // Clear mesh from already meshed edges if possible else
-  // remember that merge is needed
-  TSubMeshSet::iterator smIt = edgeSubmeshes.begin();
-  for ( ; smIt != edgeSubmeshes.end(); ++smIt ) // loop on already meshed EDGEs
-  {
-    SMESHDS_SubMesh* smDS = *smIt;
-    if ( !smDS ) continue;
-    SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
-    if ( nIt->more() )
-    {
-      const SMDS_MeshNode* n = nIt->next();
-      if ( n->NbInverseElements( SMDSAbs_Face ) > 0 )
-      {
-        needMerge = true; // to correctly sew with viscous mesh
-        // add existing medium nodes to helper
-        if ( aMesh.NbEdges( ORDER_QUADRATIC ) > 0 )
-        {
-          SMDS_ElemIteratorPtr edgeIt = smDS->GetElements();
-          while ( edgeIt->more() )
-            helper.AddTLinks( static_cast<const SMDS_MeshEdge*>(edgeIt->next()));
-        }
-        continue;
-      }
-    }
-    if ( allowSubMeshClearing )
-    {
-      SMDS_ElemIteratorPtr eIt = smDS->GetElements();
-      while ( eIt->more() ) meshDS->RemoveFreeElement( eIt->next(), 0 );
-      SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
-      while ( nIt->more() ) meshDS->RemoveFreeNode( nIt->next(), 0 );
-      smDS->Clear();
-    }
-    else
-    {
-      needMerge = true;
-    }
-  }
-
   ///////////////////////
   // PERIODICITY       //
   ///////////////////////
@@ -2489,6 +2465,22 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
     }
   }
 
+  if ( !_hypothesis && !edgeSubmeshes.empty() && existingPhySize != 0 )
+  {
+    // prevent failure due to the default PhySize incompatible with size of existing 1D mesh
+    // and with face size
+    // double minFaceSize = existingPhySize / edgeSubmeshes.size();
+    // for ( int iF = 1; iF <= fmap.Extent(); ++iF )
+    // {
+    //   Bnd_Box box;
+    //   BRepBndLib::Add( fmap( iF ), box );
+    //   gp_XYZ delta = box.CornerMax().XYZ() - box.CornerMin().XYZ();
+    //   std::sort( delta.ChangeData(), delta.ChangeData() + 3 );
+    //   minFaceSize = Min( minFaceSize, delta.Coord(2) );
+    // }
+    // set_param(css, "global_physical_size", val_to_string( minFaceSize * 0.5 ).c_str());
+    // set_param(css, "max_size",             val_to_string( minFaceSize * 5 ).c_str());
+  }
   
   // TODO: be able to use a mesh in input.
   // See imsh usage in Products/templates/mg-cadsurf_template_common.cpp
@@ -2531,12 +2523,51 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
 
   mesh_t *msh = NULL;
   cadsurf_get_mesh(css, &msh);
-  if(!msh){
+  if ( !msh || STATUS_IS_ERROR( status ))
+  {
     /* release the mesh object */
     cadsurf_regain_mesh(css, msh);
     return error(_comment);
   }
 
+  // Clear mesh from already meshed edges if possible else
+  // remember that merge is needed
+  TSubMeshSet::iterator smIt = edgeSubmeshes.begin();
+  for ( ; smIt != edgeSubmeshes.end(); ++smIt ) // loop on already meshed EDGEs
+  {
+    SMESHDS_SubMesh* smDS = *smIt;
+    if ( !smDS ) continue;
+    SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+    if ( nIt->more() )
+    {
+      const SMDS_MeshNode* n = nIt->next();
+      if ( n->NbInverseElements( SMDSAbs_Face ) > 0 )
+      {
+        needMerge = true; // to correctly sew with viscous mesh
+        // add existing medium nodes to helper
+        if ( aMesh.NbEdges( ORDER_QUADRATIC ) > 0 )
+        {
+          SMDS_ElemIteratorPtr edgeIt = smDS->GetElements();
+          while ( edgeIt->more() )
+            helper.AddTLinks( static_cast<const SMDS_MeshEdge*>(edgeIt->next()));
+        }
+        continue;
+      }
+    }
+    if ( allowSubMeshClearing )
+    {
+      SMDS_ElemIteratorPtr eIt = smDS->GetElements();
+      while ( eIt->more() ) meshDS->RemoveFreeElement( eIt->next(), 0 );
+      SMDS_NodeIteratorPtr nIt = smDS->GetNodes();
+      while ( nIt->more() ) meshDS->RemoveFreeNode( nIt->next(), 0 );
+      smDS->Clear();
+    }
+    else
+    {
+      needMerge = true;
+    }
+  }
+
   std::string GMFFileName = BLSURFPlugin_Hypothesis::GetDefaultGMFFile();
   if (_hypothesis)
     GMFFileName = _hypothesis->GetGMFFile();
@@ -2574,9 +2605,9 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
     nodes[iv] = NULL;
     if ( tag > 0 && tag <= pmap.Extent() ) {
       TopoDS_Vertex v = TopoDS::Vertex(pmap(tag));
-      double tol = BRep_Tool::Tolerance( v );
-      gp_Pnt p = BRep_Tool::Pnt( v );
-      if ( p.IsEqual( gp_Pnt( xyz[0], xyz[1], xyz[2]), 2*tol))
+      double      tol = BRep_Tool::Tolerance( v );
+      gp_Pnt        p = BRep_Tool::Pnt( v );
+      if ( p.IsEqual( gp_Pnt( xyz[0], xyz[1], xyz[2]), 1e3*tol))
         xyz[0] = p.X(), xyz[1] = p.Y(), xyz[2] = p.Z();
       else
         tag = 0; // enforced or attracted vertex
@@ -2617,8 +2648,7 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
           }
           if (!groupDone)
           {
-            int groupId;
-            SMESH_Group* aGroup = aMesh.AddGroup(SMDSAbs_Node, currentEnfVertex->grpName.c_str(), groupId);
+            SMESH_Group* aGroup = aMesh.AddGroup( SMDSAbs_Node, currentEnfVertex->grpName.c_str() );
             aGroup->SetName( currentEnfVertex->grpName.c_str() );
             SMESHDS_Group* aGroupDS = static_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
             aGroupDS->SMDSGroup().Add(nodes[iv]);
@@ -2719,6 +2749,8 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
                             nodes[evtri[0]], nodes[evtri[1]], nodes[evtri[2]]);
     }
     else {
+      if ( helper.GetIsQuadratic() )
+        helper.SetSubShape( tag );
       tri = helper.AddFace(nodes[vtx[0]], nodes[vtx[1]], nodes[vtx[2]]);
     }
     meshDS->SetMeshElementOnShape(tri, tag);
@@ -2748,7 +2780,6 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
     };
     if (type == MESHGEMS_MESH_ELEMENT_TYPE_QUAD9) {
       // QUADRATIC QUADRANGLE
-      std::cout << "This is a quadratic quadrangle" << std::endl;
       if (tags[evquad[0]]) {
         meshDS->SetNodeOnFace(nodes[evquad[0]], tag);
         tags[evquad[0]] = false;
@@ -2946,15 +2977,15 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelpe
   // set node coordinates
   if ( meshDS->NbNodes() != meshDS->MaxNodeID() )
   {
-    meshDS->compactMesh();
+    meshDS->CompactMesh();
   }
-  SMESH_TNodeXYZ nXYZ;
+  SMESH_NodeXYZ nXYZ;
   nodeIt = meshDS->nodesIterator();
   meshgems_integer i;
   for ( i = 1; nodeIt->more(); ++i )
   {
     nXYZ.Set( nodeIt->next() );
-    meshgems_mesh_set_vertex_coordinates( msh, i, nXYZ._xyz );
+    meshgems_mesh_set_vertex_coordinates( msh, i, nXYZ.ChangeData() );
   }
 
   // set nodes of faces
@@ -3037,7 +3068,7 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelpe
   // add triangles
   meshgems_integer nbtri = 0;
   meshgems_mesh_get_triangle_count( omsh, &nbtri );
-  const SMDS_MeshNode* nodes[3];
+  const SMDS_MeshNode* nodes[4];
   for ( i = 1; i <= nbtri; ++i )
   {
     meshgems_mesh_get_triangle_vertices( omsh, i, nodeIDs );
@@ -3049,6 +3080,33 @@ bool BLSURFPlugin_BLSURF::Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelpe
     meshDS->AddFace( nodes[0], nodes[1], nodes[2] );
   }
 
+  // add quadrangles
+  meshgems_integer nbquad = 0;
+  meshgems_mesh_get_quadrangle_count( omsh, &nbquad );
+  for ( i = 1; i <= nbquad; ++i )
+  {
+    meshgems_mesh_get_quadrangle_vertices( omsh, i, nodeIDs );
+    for ( int j = 0; j < 4; ++j )
+    {
+      meshgems_mesh_get_vertex_tag( omsh, nodeIDs[j], &nodeID );
+      nodes[j] = meshDS->FindNode( nodeID );
+    }
+    meshDS->AddFace( nodes[0], nodes[1], nodes[2], nodes[3] );
+  }
+
+  if ( _hypothesis )
+  {
+    std::string GMFFileName = _hypothesis->GetGMFFile();
+    if ( !GMFFileName.empty() )
+    {
+      bool asciiFound  = (GMFFileName.find(".mesh", GMFFileName.size()-5) != std::string::npos);
+      bool binaryFound = (GMFFileName.find(".meshb",GMFFileName.size()-6) != std::string::npos);
+      if ( !asciiFound && !binaryFound )
+        GMFFileName.append(".mesh");
+      mesh_write_mesh(msh, GMFFileName.c_str());
+    }
+  }
+
   cadsurf_regain_mesh(css, omsh);
 
   // as we don't assign the new triangles to a shape (the pseudo-shape),
@@ -3207,7 +3265,7 @@ status_t surf_fun(real *uv, real *xyz, real*du, real *dv,
 status_t size_on_surface(integer face_id, real *uv, real *size, void *user_data)
 {
   TId2ClsAttractorVec::iterator f2attVec;
-  if (FaceId2PythonSmp.count(face_id) != 0){
+  if (FaceId2PythonSmp.count(face_id) != 0) {
     assert(Py_IsInitialized());
     PyGILState_STATE gstate;
     gstate = PyGILState_Ensure();