Salome HOME
#18758 EDF 20879 - CADSurf gradation for submeshes
[plugins/blsurfplugin.git] / src / BLSURFPlugin / BLSURFPlugin_BLSURF.cxx
index 19e1c59a531ef7209e131e1f181503333d25cb8f..2fccd631396f90df50eea39e8f2343c21736e3b7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2019  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>
@@ -146,8 +145,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 +240,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 +255,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;
@@ -486,7 +476,7 @@ projectionPoint getProjectionPoint(TopoDS_Face& theFace, const gp_Pnt& thePoint)
       throw SMESH_ComputeError(COMPERR_BAD_PARMETERS,
                                "getProjectionPoint: can't project a vertex to a face");
 
-    Quantity_Parameter u,v;
+    Standard_Real u,v;
     projector.LowerDistanceParameters(u,v);
     myPoint.uv = gp_XY(u,v);
     gp_Pnt aPnt = projector.NearestPoint();
@@ -503,19 +493,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;
 }
 
@@ -875,7 +862,7 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
   double _gradation             = BLSURFPlugin_Hypothesis::GetDefaultGradation();
   double _use_volume_gradation  = BLSURFPlugin_Hypothesis::GetDefaultUseVolumeGradation();
   double _volume_gradation      = BLSURFPlugin_Hypothesis::GetDefaultVolumeGradation();
-  bool   _quadAllowed           = BLSURFPlugin_Hypothesis::GetDefaultQuadAllowed();
+  BLSURFPlugin_Hypothesis::ElementType _elementType = BLSURFPlugin_Hypothesis::GetDefaultElementType();
   double _angleMesh             = BLSURFPlugin_Hypothesis::GetDefaultAngleMesh();
   double _chordalError          = BLSURFPlugin_Hypothesis::GetDefaultChordalError(diagonal);
   bool   _anisotropic           = BLSURFPlugin_Hypothesis::GetDefaultAnisotropic();
@@ -892,6 +879,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();
@@ -899,6 +892,7 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
   //int _precadProcess3DTopology  = BLSURFPlugin_Hypothesis::GetDefaultPreCADProcess3DTopology();
   //int _precadDiscardInput       = BLSURFPlugin_Hypothesis::GetDefaultPreCADDiscardInput();
 
+  const BLSURFPlugin_Hypothesis::TPreCadPeriodicityVector preCadFacesPeriodicityVector = BLSURFPlugin_Hypothesis::GetPreCadFacesPeriodicityVector(hyp);
 
   if (hyp) {
     _physicalMesh  = (int) hyp->GetPhysicalMesh();
@@ -924,7 +918,7 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
     _use_volume_gradation    = hyp->GetUseVolumeGradation();
     if (hyp->GetVolumeGradation() > 0 && _use_volume_gradation )
       _volume_gradation      = hyp->GetVolumeGradation();
-    _quadAllowed     = hyp->GetQuadAllowed();
+    _elementType     = hyp->GetElementType();
     if (hyp->GetAngleMesh() > 0)
       _angleMesh     = hyp->GetAngleMesh();
     if (hyp->GetChordalError() > 0)
@@ -953,19 +947,35 @@ 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 )
+    for ( opIt = opts.begin(); opIt != opts.end(); ++opIt ){
+      MESSAGE("OptionValue: " << opIt->first.c_str() << ", value: " << opIt->second.c_str());
       if ( !opIt->second.empty() ) {
-        set_param(css, opIt->first.c_str(), opIt->second.c_str());
+        // 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");
+        }
+        else
+          set_param(css, opIt->first.c_str(), opIt->second.c_str());
       }
+    }
 
     const BLSURFPlugin_Hypothesis::TOptionValues& custom_opts = hyp->GetCustomOptionValues();
     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 )
@@ -991,11 +1001,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");
@@ -1007,13 +1018,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");
@@ -1045,13 +1056,30 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
      set_param(css, "max_size", _maxSizeRel ? val_to_string_rel(_maxSize).c_str() : val_to_string(_maxSize).c_str());
    }
    // anisotropic and quadrangle mesh requires disabling gradation
-   if ( _anisotropic && _quadAllowed )
-     useGradation = false; // limitation of V1.3
+   // if ( _anisotropic && _elementType != BLSURFPlugin_Hypothesis::Triangles )
+   //   useGradation = false; // limitation of V1.3
+   useGradation = true; // bos #18758
    if ( useGradation && _use_gradation )
      set_param(css, "gradation",                       val_to_string(_gradation).c_str());
    if ( useGradation && _use_volume_gradation )
      set_param(css, "volume_gradation",                val_to_string(_volume_gradation).c_str());
-   set_param(css, "element_generation",                _quadAllowed ? "quad_dominant" : "triangle");
+
+   // New since MeshGems 2.5: add full_quad
+   const char * element_generation = "";
+   switch ( _elementType )
+   {
+     case BLSURFPlugin_Hypothesis::Triangles:
+       element_generation = "triangle";
+       break;
+     case BLSURFPlugin_Hypothesis::QuadrangleDominant:
+       element_generation = "quad_dominant";
+       break;
+     case BLSURFPlugin_Hypothesis::Quadrangles:
+       element_generation = "full_quad";
+       break;
+     default: ;
+   }
+   set_param(css, "element_generation",                element_generation);
 
 
    set_param(css, "metric",                            _anisotropic ? "anisotropic" : "isotropic");
@@ -1073,6 +1101,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;
@@ -1341,8 +1382,6 @@ void BLSURFPlugin_BLSURF::SetParameters(const BLSURFPlugin_Hypothesis* hyp,
    _preCadFacesIDsPeriodicityVector.clear();
    _preCadEdgesIDsPeriodicityVector.clear();
 
-  const BLSURFPlugin_Hypothesis::TPreCadPeriodicityVector preCadFacesPeriodicityVector = BLSURFPlugin_Hypothesis::GetPreCadFacesPeriodicityVector(hyp);
-
   for (std::size_t i = 0; i<preCadFacesPeriodicityVector.size(); i++){
     createPreCadFacesPeriodicity(theGeomShape, preCadFacesPeriodicityVector[i]);
   }
@@ -1461,12 +1500,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
@@ -1502,11 +1537,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;
@@ -1514,7 +1548,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++ )
@@ -1579,19 +1613,20 @@ namespace
     const TopoDS_Face& makeProxyFace( SMESH_ProxyMesh::Ptr& viscousMesh,
                                       const TopoDS_Face&    origFace)
     {
-      // get data of nodes on inner boundary of viscous layers
       SMESH_Mesh* origMesh = viscousMesh->GetMesh();
+
+      SMESH_MesherHelper helper( *origMesh );
+      helper.SetSubShape( origFace );
+      const bool hasSeam = helper.HasRealSeam();
+
+      // get data of nodes on inner boundary of viscous layers
       TError err;
       TSideVector wireVec = StdMeshers_FaceSide::GetFaceWires(origFace, *origMesh,
                                                               /*skipMediumNodes = */true,
-                                                              err, viscousMesh );
+                                                              err, &helper, viscousMesh );
       if ( err && err->IsKO() )
         throw *err.get(); // it should be caught at SMESH_subMesh
 
-      SMESH_MesherHelper helper( *origMesh );
-      helper.SetSubShape( origFace );
-      const bool hasSeam = helper.HasRealSeam();
-
       // proxy nodes and corresponding tmp VERTEXes
       std::vector<const SMDS_MeshNode*> origNodes;
       std::vector<TopoDS_Vertex>        tmpVertex;
@@ -1752,7 +1787,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();
@@ -1994,11 +2029,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 : */
@@ -2199,22 +2230,20 @@ 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 : */
       // IMP23368. Do not set tag to an EDGE shared by FACEs of a hyper-patch
       bool isInHyperPatch = false;
       {
-        std::set< int > faceTags;
+        std::set< int > faceTags, faceIDs;
         TopTools_ListIteratorOfListOfShape fIt( e2ffmap.FindFromKey( e ));
         for ( ; fIt.More(); fIt.Next() )
         {
           int faceTag = meshDS->ShapeToIndex( fIt.Value() );
+          if ( !faceIDs.insert( faceTag ).second )
+            continue; // a face encounters twice for a seam edge
           int hpTag   = BLSURFPlugin_Hypothesis::GetHyperPatchTag( faceTag, _hypothesis );
           if ( !faceTags.insert( hpTag ).second )
           {
@@ -2257,8 +2286,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);
       }
 
@@ -2394,7 +2431,7 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
       //   cout << o.str() << endl;
       if (_preCadFacesIDsPeriodicityVector[i].theSourceVerticesCoords.empty())
       {
-        // If no source points, call peridoicity without transformation function
+        // If no source points, call periodicity without transformation function
         meshgems_cad_periodicity_transformation_t periodicity_transformation = NULL;
         status = cad_add_face_multiple_periodicity_with_transformation_function(c, theFace1_ids_c, theFace1_ids.size(),
                                                                                 theFace2_ids_c, theFace2_ids.size(), periodicity_transformation, NULL);
@@ -2422,7 +2459,7 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
     for (std::size_t i=0; i < _preCadEdgesIDsPeriodicityVector.size(); i++){
       std::vector<int> theEdge1_ids = _preCadEdgesIDsPeriodicityVector[i].shape1IDs;
       std::vector<int> theEdge2_ids = _preCadEdgesIDsPeriodicityVector[i].shape2IDs;
-      // Use the address of the first element of the vector to initialise the array
+      // Use the address of the first element of the vector to initialize the array
       int* theEdge1_ids_c = &theEdge1_ids[0];
       int* theEdge2_ids_c = &theEdge2_ids[0];
 
@@ -2439,7 +2476,7 @@ bool BLSURFPlugin_BLSURF::compute(SMESH_Mesh&         aMesh,
 
       if (_preCadEdgesIDsPeriodicityVector[i].theSourceVerticesCoords.empty())
       {
-        // If no source points, call peridoicity without transformation function
+        // If no source points, call periodicity without transformation function
         meshgems_cad_periodicity_transformation_t periodicity_transformation = NULL;
         status = cad_add_edge_multiple_periodicity_with_transformation_function(c, theEdge1_ids_c, theEdge1_ids.size(),
                                                                                 theEdge2_ids_c, theEdge2_ids.size(), periodicity_transformation, NULL);
@@ -2547,9 +2584,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
@@ -2590,8 +2627,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]);
@@ -2692,6 +2728,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);
@@ -2721,7 +2759,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;
@@ -2919,15 +2956,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
@@ -3010,7 +3047,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 );
@@ -3022,6 +3059,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),
@@ -3180,7 +3244,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();
@@ -3367,7 +3431,7 @@ bool BLSURFPlugin_BLSURF::Evaluate(SMESH_Mesh&         aMesh,
   bool   _phySizeRel    = BLSURFPlugin_Hypothesis::GetDefaultPhySizeRel();
   //int    _geometricMesh = BLSURFPlugin_Hypothesis::GetDefaultGeometricMesh();
   double _angleMesh     = BLSURFPlugin_Hypothesis::GetDefaultAngleMesh();
-  bool   _quadAllowed   = BLSURFPlugin_Hypothesis::GetDefaultQuadAllowed();
+  BLSURFPlugin_Hypothesis::ElementType   _elementType   = BLSURFPlugin_Hypothesis::GetDefaultElementType();
   if(_hypothesis) {
     _physicalMesh  = (int) _hypothesis->GetPhysicalMesh();
     _phySizeRel         = _hypothesis->IsPhySizeRel();
@@ -3376,7 +3440,7 @@ bool BLSURFPlugin_BLSURF::Evaluate(SMESH_Mesh&         aMesh,
     //_geometricMesh = (int) hyp->GetGeometricMesh();
     if (_hypothesis->GetAngleMesh() > 0)
       _angleMesh        = _hypothesis->GetAngleMesh();
-    _quadAllowed        = _hypothesis->GetQuadAllowed();
+    _elementType        = _hypothesis->GetElementType();
   } else {
     //0020968: EDF1545 SMESH: Problem in the creation of a mesh group on geometry
     // GetDefaultPhySize() sometimes leads to computation failure
@@ -3456,7 +3520,7 @@ bool BLSURFPlugin_BLSURF::Evaluate(SMESH_Mesh&         aMesh,
     int nbQuad = 0;
     int nbTria = (int) ( anArea/( ELen*ELen*sqrt(3.) / 4 ) );
     int nbNodes = (int) ( ( nbTria*3 - (nb1d-1)*2 ) / 6 + 1 );
-    if ( _quadAllowed )
+    if ( _elementType != BLSURFPlugin_Hypothesis::Quadrangles )
     {
       if ( nb1dVec.size() == 4 ) // quadrangle geom face
       {