Salome HOME
bos #20282 EDF 22320 - general compute fails
[plugins/blsurfplugin.git] / src / BLSURFPlugin / BLSURFPlugin_BLSURF.cxx
index 2fbbd87ff114d96bf530d65a6a4f7fa9fcc4e17b..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
@@ -58,6 +58,7 @@ extern "C"{
 #include <cstdlib>
 
 // OPENCASCADE includes
+#include <BRepBndLib.hxx>
 #include <BRepBuilderAPI_MakeFace.hxx>
 #include <BRepBuilderAPI_MakePolygon.hxx>
 #include <BRepBuilderAPI_MakeWire.hxx>
@@ -145,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*/
@@ -241,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
@@ -257,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;
@@ -502,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;
 }
 
@@ -891,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();
@@ -953,6 +948,13 @@ 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;
@@ -1000,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");
@@ -1016,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");
@@ -1053,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
@@ -1098,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;
@@ -1532,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++ )
@@ -1907,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;
 
@@ -2205,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
         {
@@ -2354,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       //
   ///////////////////////
@@ -2483,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
@@ -2525,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();
@@ -2611,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]);
@@ -2713,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);
@@ -2742,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;
@@ -3031,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 );
@@ -3043,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),