Salome HOME
Revert "Merge branch 'yan/parallel_mesh2'"
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
index 8b0f40c3927e6ece2cb424873fdd14954b60acf3..2634540158055a32282a0217e706235199bd9e4a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #include <TopoDS_Wire.hxx>
 #include <gp_Pnt.hxx>
 
+// Have to be included before std headers
+#include <Python.h>
+#include <structmember.h>
+
 #ifdef WIN32
  #include <windows.h>
  #include <process.h>
 #include "SMESH_PreMeshInfo.hxx"
 #include "SMESH_PythonDump.hxx"
 #include "SMESH_ControlsDef.hxx"
+#include <SMESH_BoostTxtArchive.hxx>
 
 // to pass CORBA exception through SMESH_TRY
 #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
 #include <memory>
 
 #include <boost/archive/text_oarchive.hpp>
-#include <boost/archive/text_iarchive.hpp>
 #include <boost/serialization/list.hpp>
 #include <boost/serialization/string.hpp>
+#include <boost/filesystem.hpp>
+
+namespace fs = boost::filesystem;
 
 using namespace std;
 using SMESH::TPythonDump;
@@ -189,22 +196,22 @@ PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theOb
   }
   catch (PortableServer::POA::ObjectNotActive &ex)
   {
-    INFOS("GetServant: ObjectNotActive");
+    MESSAGE("GetServant: ObjectNotActive");
     return NULL;
   }
   catch (PortableServer::POA::WrongAdapter &ex)
   {
-    INFOS("GetServant: WrongAdapter: OK when several servants used to build several mesh in parallel...");
+    MESSAGE("GetServant: WrongAdapter: OK when several servants used to build several mesh in parallel...");
     return NULL;
   }
   catch (PortableServer::POA::WrongPolicy &ex)
   {
-    INFOS("GetServant: WrongPolicy");
+    MESSAGE("GetServant: WrongPolicy");
     return NULL;
   }
   catch (...)
   {
-    INFOS( "GetServant - Unknown exception was caught!!!" );
+    MESSAGE( "GetServant - Unknown exception was caught!!!" );
     return NULL;
   }
 }
@@ -460,18 +467,17 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
       // load plugin library
       if(MYDEBUG) MESSAGE("Loading server meshers plugin library ...");
 #ifdef WIN32
-#ifdef UNICODE
+#  ifdef UNICODE
       const wchar_t* path = Kernel_Utils::decode_s(aPlatformLibName);
-#else
+      SMESHUtils::ArrayDeleter<const wchar_t> deleter( path );
+#  else
       const char* path = aPlatformLibName.c_str();
-#endif
+#  endif
 #else
       const char* path = aPlatformLibName.c_str();
 #endif
       LibHandle libHandle = LoadLib( path );
-#if defined(WIN32) && defined(UNICODE)
-      delete path;
-#endif
+
       if (!libHandle)
       {
         // report any error, if occurred
@@ -1317,17 +1323,17 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName
  */
 //=============================================================================
 
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileName,
-                                                           SMESH::DriverMED_ReadStatus& theStatus,
-                                                           const char* theCommandNameForPython,
-                                                           const char* theFileNameForPython)
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char*                  theFileName,
+                                                     SMESH::DriverMED_ReadStatus& theStatus )
 {
+  checkFileReadable( theFileName );
+
 #ifdef WIN32
   char bname[ _MAX_FNAME ];
-  _splitpath( theFileNameForPython, NULL, NULL, bname, NULL );
+  _splitpath( theFileName, NULL, NULL, bname, NULL );
   string aFileName = bname;
 #else
-  string aFileName = basename( const_cast<char *>(theFileNameForPython) );
+  string aFileName = basename( const_cast<char *>( theFileName ));
 #endif
   // Retrieve mesh names from the file
   DriverMED_R_SMESHDS_Mesh myReader;
@@ -1340,59 +1346,57 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileNa
 
   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
 
-  // Python Dump
-  TPythonDump aPythonDump(this);
-  aPythonDump << "([";
+    // Python Dump
+    TPythonDump aPythonDump(this);
+    aPythonDump << "([";
 
-  if (theStatus == SMESH::DRS_OK) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder;
-    aStudyBuilder = getStudyServant()->NewBuilder();
-    aStudyBuilder->NewCommand();  // There is a transaction
+    if (theStatus == SMESH::DRS_OK)
+    {
+      SALOMEDS::StudyBuilder_var aStudyBuilder;
+      aStudyBuilder = getStudyServant()->NewBuilder();
+      aStudyBuilder->NewCommand();  // There is a transaction
 
-    aResult->length( aNames.size() );
-    int i = 0;
+      aResult->length( aNames.size() );
+      int i = 0;
 
-    // Iterate through all meshes and create mesh objects
-    for ( list<string>::iterator it = aNames.begin(); it != aNames.end(); it++ )
-    {
-      // Python Dump
-      if (i > 0) aPythonDump << ", ";
-
-      // create mesh
-      SMESH::SMESH_Mesh_var mesh = createMesh();
-
-      // publish mesh in the study
-      SALOMEDS::SObject_wrap aSO;
-      if ( CanPublishInStudy( mesh ) )
-        // little trick: for MED file theFileName and theFileNameForPython are the same, but they are different for SAUV
-        // - as names of meshes are stored in MED file, we use them for data publishing
-        // - as mesh name is not stored in UNV file, we use file name as name of mesh when publishing data
-        aSO = PublishMesh( mesh.in(), ( theFileName == theFileNameForPython ) ? (*it).c_str() : aFileName.c_str() );
-
-      // Python Dump
-      if ( !aSO->_is_nil() ) {
-        aPythonDump << aSO;
-      } else {
-        aPythonDump << "mesh_" << i;
-      }
+      // Iterate through all meshes and create mesh objects
+      for ( const std::string & meshName : aNames )
+      {
+        // Python Dump
+        if (i > 0) aPythonDump << ", ";
+
+        // create mesh
+        SMESH::SMESH_Mesh_var mesh = createMesh();
+
+        // publish mesh in the study
+        SALOMEDS::SObject_wrap aSO;
+        if ( CanPublishInStudy( mesh ) )
+          aSO = PublishMesh( mesh.in(), meshName.c_str() );
 
-      // Read mesh data (groups are published automatically by ImportMEDFile())
-      SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
-      ASSERT( meshServant );
-      SMESH::DriverMED_ReadStatus status1 =
-        meshServant->ImportMEDFile( theFileName, (*it).c_str() );
-      if (status1 > theStatus)
-        theStatus = status1;
+        // Python Dump
+        if ( !aSO->_is_nil() ) {
+          aPythonDump << aSO;
+        } else {
+          aPythonDump << "mesh_" << i;
+        }
+
+        // Read mesh data (groups are published automatically by ImportMEDFile())
+        SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
+        ASSERT( meshServant );
+        SMESH::DriverMED_ReadStatus status1 =
+          meshServant->ImportMEDFile( theFileName, meshName.c_str() );
+        if (status1 > theStatus)
+          theStatus = status1;
 
-      aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
-      meshServant->GetImpl().GetMeshDS()->Modified();
+        aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
+        meshServant->GetImpl().GetMeshDS()->Modified();
+      }
+      if ( !aStudyBuilder->_is_nil() )
+        aStudyBuilder->CommitCommand();
     }
-    if ( !aStudyBuilder->_is_nil() )
-      aStudyBuilder->CommitCommand();
-  }
 
-  // Update Python script
-  aPythonDump << "], status) = " << this << "." << theCommandNameForPython << "(r'" << theFileNameForPython << "')";
+    // Update Python script
+    aPythonDump << "], status) = " << this << ".CreateMeshesFromMED( r'" << theFileName << "' )";
   }
   // Dump creation of groups
   for ( CORBA::ULong  i = 0; i < aResult->length(); ++i )
@@ -1401,66 +1405,6 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileNa
   return aResult._retn();
 }
 
-//================================================================================
-/*!
- * \brief Create meshes by reading a MED file
- */
-//================================================================================
-
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char*                  theFileName,
-                                                     SMESH::DriverMED_ReadStatus& theStatus)
-{
-  Unexpect aCatch(SALOME_SalomeException);
-  checkFileReadable( theFileName );
-
-  SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(theFileName, theStatus,
-                                                        "CreateMeshesFromMED", theFileName);
-  return result;
-}
-
-//=============================================================================
-/*!
- *  SMESH_Gen_i::CreateMeshFromSAUV
- *
- *  Create mesh and import data from SAUV file
- */
-//=============================================================================
-
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromSAUV( const char*                  theFileName,
-                                                      SMESH::DriverMED_ReadStatus& theStatus)
-{
-  Unexpect aCatch(SALOME_SalomeException);
-  checkFileReadable( theFileName );
-
-  std::string sauvfilename(theFileName);
-  std::string medfilename(theFileName);
-  medfilename += ".med";
-  std::string cmd;
-#ifdef WIN32
-  cmd = "%PYTHONBIN% ";
-#else
-  cmd = "python3 ";
-#endif
-  cmd += "-c \"";
-  cmd += "from medutilities import convert ; convert(r'" + sauvfilename + "', 'GIBI', 'MED', 1, r'" + medfilename + "')";
-  cmd += "\"";
-  system(cmd.c_str());
-  SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(medfilename.c_str(),
-                                                        theStatus,
-                                                        "CreateMeshesFromSAUV",
-                                                        sauvfilename.c_str());
-#ifdef WIN32
-  cmd = "%PYTHONBIN% ";
-#else
-  cmd = "python3 ";
-#endif
-  cmd += "-c \"";
-  cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
-  cmd += "\"";
-  system(cmd.c_str());
-  return result;
-}
-
 //=============================================================================
 /*!
  *  SMESH_Gen_i::CreateMeshFromSTL
@@ -2676,28 +2620,31 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
 
     // copy elements
 
-    SMESH::array_of_ElementType_var srcElemTypes = theMeshesArray[i]->GetTypes();
-    if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
-      continue;
     std::vector< const SMDS_MeshElement* > newElems( initMeshDS->NbElements() + 1, 0 );
-    elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
-    while ( elemIt->more() )
+    SMESH::array_of_ElementType_var srcElemTypes = theMeshesArray[i]->GetTypes();
+    bool hasElems = (( srcElemTypes->length() > 1 ) ||
+                     ( srcElemTypes->length() == 1 && srcElemTypes[0] != SMESH::NODE ));
+    if ( hasElems )
     {
-      const SMDS_MeshElement* elem = elemIt->next();
-      elemType.myNodes.resize( elem->NbNodes() );
-
-      SMDS_NodeIteratorPtr itNodes = elem->nodeIterator();
-      for ( int k = 0; itNodes->more(); k++)
+      elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
+      while ( elemIt->more() )
       {
-        const SMDS_MeshNode* node = itNodes->next();
-        elemType.myNodes[ k ] = static_cast< const SMDS_MeshNode*> ( newNodes[ node->GetID() ]);
-      }
+        const SMDS_MeshElement* elem = elemIt->next();
+        elemType.myNodes.resize( elem->NbNodes() );
 
-      // creates a corresponding element on existent nodes in new mesh
-      newElems[ elem->GetID() ] =
-        newEditor.AddElement( elemType.myNodes, elemType.Init( elem, /*basicOnly=*/false ));
+        SMDS_NodeIteratorPtr itNodes = elem->nodeIterator();
+        for ( int k = 0; itNodes->more(); k++)
+        {
+          const SMDS_MeshNode* node = itNodes->next();
+          elemType.myNodes[ k ] = static_cast< const SMDS_MeshNode*> ( newNodes[ node->GetID() ]);
+        }
+
+        // creates a corresponding element on existent nodes in new mesh
+        newElems[ elem->GetID() ] =
+          newEditor.AddElement( elemType.myNodes, elemType.Init( elem, /*basicOnly=*/false ));
+      }
+      newEditor.ClearLastCreated(); // forget the history
     }
-    newEditor.ClearLastCreated(); // forget the history
 
 
     // create groups of just added elements
@@ -2862,6 +2809,133 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
   return newMesh._retn();
 }
 
+
+//================================================================================
+/*!
+ * \brief Create a mesh by copying a part of another mesh
+ *  \param mesh - TetraHedron mesh
+ *  \param meshName Name of the created mesh
+ *  \retval SMESH::SMESH_Mesh_ptr - the new mesh
+ */
+//================================================================================
+
+SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh,
+                                                  const char*               meshName,
+                                                  CORBA::Boolean            adapt_to_shape)
+{
+  Unexpect aCatch(SALOME_SalomeException);
+
+  TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh()
+  std::unique_ptr<TPythonDump> pyDumpDeleter( pyDump );
+
+  // 1. Get source mesh
+
+  if ( CORBA::is_nil( mesh ))
+    THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
+
+  SMESH::SMESH_Mesh_var srcMesh = mesh->GetMesh();
+  SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
+  if ( !srcMesh_i )
+    THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
+
+  CORBA::String_var mesh_var=GetORB()->object_to_string(mesh);
+  std::string mesh_ior = mesh_var.in();
+
+  //temporary folder for the generation of the med file
+  fs::path tmp_folder = fs::temp_directory_path() / fs::unique_path(fs::path("dual_mesh-%%%%"));
+  fs::create_directories(tmp_folder);
+  fs::path dual_mesh_file = tmp_folder / fs::path("tmp_dual_mesh.med");
+  std::string mesh_name(meshName);
+  MESSAGE("Working in folder" + tmp_folder.string());
+
+  // Running Python script
+  assert(Py_IsInitialized());
+  PyGILState_STATE gstate;
+  gstate = PyGILState_Ensure();
+
+
+  std::string ats;
+  if(adapt_to_shape)
+    ats = "True";
+  else
+    ats = "False";
+
+  std::string cmd="import salome.smesh.smesh_tools as smt\n";
+  cmd +="smt.smesh_create_dual_mesh(\"" + mesh_ior + "\", \"" +
+        dual_mesh_file.string() + "\", mesh_name=\"" + mesh_name + "\", adapt_to_shape=" + ats + ")";
+  MESSAGE(cmd);
+
+  PyObject *py_main = PyImport_AddModule("__main__");
+  PyObject *py_dict = PyModule_GetDict(py_main);
+
+  PyRun_String(cmd.c_str(), Py_file_input, py_dict, py_dict);
+
+  if (PyErr_Occurred()) {
+    // Restrieving python error
+    MESSAGE("Catching error")
+    PyObject *errtype, *errvalue, *traceback;
+    PyErr_Fetch(&errtype, &errvalue, &traceback);
+    if(errvalue != NULL) {
+      MESSAGE("Error has a value")
+      PyObject *s = PyObject_Str(errvalue);
+      Py_ssize_t size;
+      std::string msg = PyUnicode_AsUTF8AndSize(s, &size);
+      msg = "Issue with the execution of create_dual_mesh:\n"+msg;
+      MESSAGE("throwing exception")
+      // We need to deactivate the GIL before throwing the exception
+      PyGILState_Release(gstate);
+      THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::INTERNAL_ERROR );
+      Py_DECREF(s);
+    }
+    Py_XDECREF(errvalue);
+    Py_XDECREF(errtype);
+    Py_XDECREF(traceback);
+  }
+
+  PyGILState_Release(gstate);
+
+  MESSAGE("Mesh created in " + dual_mesh_file.string());
+
+  // Import created MED
+  SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
+  SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
+  if ( !newMesh_i )
+    THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
+  SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
+  if ( !meshSO->_is_nil() )
+  {
+    SetName( meshSO, meshName, meshName );
+    SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
+  }
+  int ret = newMesh_i->ImportMEDFile(dual_mesh_file.string().c_str(), meshName);
+  if(ret)
+    THROW_SALOME_CORBA_EXCEPTION( "Issue when importing mesh", SALOME::INTERNAL_ERROR );
+
+  /*
+  SMESH_Mesh& newMesh2 = newMesh_i->GetImpl();
+
+
+  MESSAGE("Loading file: " << dual_mesh_file.string() << " with mesh " << meshName);
+  int ret = newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName);
+    */
+
+  newMesh_i->GetImpl().GetMeshDS()->Modified();
+
+  *pyDump << newMesh << " = " << this
+          << ".CreateDualMesh("
+          << mesh << ", "
+          << "'" << mesh_name << "', "
+          << ats << ") ";
+
+  pyDumpDeleter.reset(); // allow dump in GetGroups()
+
+  if ( srcMesh_i->GetImpl().GetGroupIds().size() > 0 ) // dump created groups
+    MESSAGE("Dump of groups");
+    SMESH::ListOfGroups_var groups = newMesh->GetGroups();
+
+  return newMesh._retn();
+}
+
 //================================================================================
 /*!
  * \brief Create a mesh by copying a part of another mesh
@@ -4208,7 +4282,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
   // MED writer to be used by storage process
   DriverMED_W_SMESHDS_Mesh writer;
   writer.SetFile( meshfile.ToCString() );
-  writer.SetSaveNumbers( false ); // bos #24400
+  //writer.SetSaveNumbers( false ); // bos #24400 -- it leads to change of element IDs
 
   // IMP issue 20918
   // SetStoreName() to groups before storing hypotheses to let them refer to
@@ -5194,7 +5268,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
   TCollection_AsciiString aStudyName( "" );
   if ( isMultiFile ) {
     CORBA::WString_var url = aStudy->URL();
-    aStudyName = (char*)SALOMEDS_Tool::GetNameFromPath( Kernel_Utils::encode(url.in()) ).c_str();
+    SMESHUtils::ArrayDeleter<const char> urlMulibyte( Kernel_Utils::encode( url.in()) );
+    aStudyName = (char*)SALOMEDS_Tool::GetNameFromPath( urlMulibyte.get() ).c_str();
   }
   // Set names of temporary files
   TCollection_AsciiString filename = tmpDir + aStudyName + "_SMESH.hdf";
@@ -5916,7 +5991,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               if ( aNewGroup->_is_nil() )
                 continue;
 
-              string iorSubString = GetORB()->object_to_string( aNewGroup );
+              CORBA::String_var iorSubStringVar = GetORB()->object_to_string( aNewGroup );
+              string iorSubString(iorSubStringVar.in());
               int        newSubId = myStudyContext->findId( iorSubString );
               myStudyContext->mapOldToNew( subid, newSubId );
 
@@ -5995,13 +6071,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         aDataset->ReadFromDisk((char*) dataString.data() );
         aDataset->CloseOnDisk();
 
-        std::istringstream istream( dataString.data() );
-        boost::archive::text_iarchive archive( istream );
         std::list< std::list< std::string > > orderEntryLists;
-        try {
-          archive >> orderEntryLists;
-        }
-        catch (...) {}
+        SMESHUtils::BoostTxtArchive( dataString ) >> orderEntryLists;
 
         TListOfListOfInt anOrderIds;
         for ( const std::list< std::string >& entryList : orderEntryLists )
@@ -6244,8 +6315,9 @@ int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
 CORBA::Long  SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
 {
   if ( myStudyContext && !CORBA::is_nil( theObject )) {
-    string iorString = GetORB()->object_to_string( theObject );
-    return myStudyContext->findId( iorString );
+    CORBA::String_var iorString = GetORB()->object_to_string( theObject );
+    string iorStringCpp(iorString.in());
+    return myStudyContext->findId( iorStringCpp );
   }
   return 0;
 }
@@ -6319,46 +6391,6 @@ void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
       useCaseBuilder->AppendTo( where, sobj );        // append to the end of list
   }
 }
-//================================================================================
-/*!
- * \brief Returns true if algorithm can be used to mesh a given geometry
- *  \param [in] theAlgoType - the algorithm type
- *  \param [in] theLibName - a name of the Plug-in library implementing the algorithm
- *  \param [in] theGeomObject - the geometry to mesh
- *  \param [in] toCheckAll - if \c True, returns \c True if all shapes are meshable,
- *         else, returns \c True if at least one shape is meshable
- *  \return CORBA::Boolean - can or can't
- */
-//================================================================================
-
-CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
-                                           const char*           theLibName,
-                                           GEOM::GEOM_Object_ptr theGeomObject,
-                                           CORBA::Boolean        toCheckAll)
-{
-  SMESH_TRY;
-
-  std::string aPlatformLibName;
-  GenericHypothesisCreator_i* aCreator =
-    getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
-  if (aCreator)
-  {
-    TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
-    const SMESH_Algo::Features& feat = SMESH_Algo::GetFeatures( theAlgoType );
-    return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll, feat._dim );
-  }
-  else
-  {
-    return false;
-  }
-
-  SMESH_CATCH( SMESH::doNothing );
-
-#ifdef _DEBUG_
-  cout << "SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : "") << endl;
-#endif
-  return true;
-}
 
 //================================================================================
 /*!
@@ -6574,3 +6606,47 @@ std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
   }
   return res;
 }
+
+//================================================================================
+/*!
+ * \brief Returns true if algorithm can be used to mesh a given geometry
+ *  \param [in] theAlgoType - the algorithm type
+ *  \param [in] theLibName - a name of the Plug-in library implementing the algorithm
+ *  \param [in] theGeomObject - the geometry to mesh
+ *  \param [in] toCheckAll - if \c True, returns \c True if all shapes are meshable,
+ *         else, returns \c True if at least one shape is meshable
+ *  \return CORBA::Boolean - can or can't
+ */
+//================================================================================
+
+#undef SMY_OWN_CATCH
+#define SMY_OWN_CATCH // prevent re-throwing SALOME::SALOME_Exception in IsApplicable()
+
+CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
+                                           const char*           theLibName,
+                                           GEOM::GEOM_Object_ptr theGeomObject,
+                                           CORBA::Boolean        toCheckAll)
+{
+  SMESH_TRY;
+
+  std::string aPlatformLibName;
+  GenericHypothesisCreator_i* aCreator =
+    getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
+  if (aCreator)
+  {
+    TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
+    const SMESH_Algo::Features& feat = SMESH_Algo::GetFeatures( theAlgoType );
+    return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll, feat._dim );
+  }
+  else
+  {
+    return false;
+  }
+
+  SMESH_CATCH( SMESH::doNothing );
+
+#ifdef _DEBUG_
+  cout << "SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : "") << endl;
+#endif
+  return true;
+}