X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH_I%2FSMESH_Gen_i.cxx;h=204466afefea833d8bb90b3bfd220ad675a54b84;hp=79f87e11617f8195f42c6ef7d54559e7c9c859b9;hb=6472eab132825fec572beda8276947593f85ffa1;hpb=d0f366c4a3a66a71b0be94f7a6e2d146f80a94c4 diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 79f87e116..ac0b69600 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -1,117 +1,172 @@ -// SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses +// Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE // -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. // +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File : SMESH_Gen_i.cxx // Author : Paul RASCLE, EDF // Module : SMESH -// $Header$ +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include +#include #include -#include -#include #include -#include -#include -#include -#include +#include #include -#include +#include +#include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include -#include -#include "Utils_CorbaException.hxx" -#include "utilities.h" -#include -#include -#include +#ifdef WIN32 + #include + #include +#else + #include + #include // for basename function +#endif -#include +#ifdef WIN32 + #define LibHandle HMODULE + #define LoadLib( name ) LoadLibrary( name ) + #define GetProc GetProcAddress + #define UnLoadLib( handle ) FreeLibrary( handle ); +#else // WIN32 + #define LibHandle void* + #ifdef DYNLOAD_LOCAL + #define LoadLib( name ) dlopen( name, RTLD_LAZY | RTLD_LOCAL ) + #else // DYNLOAD_LOCAL + #define LoadLib( name ) dlopen( name, RTLD_LAZY | RTLD_GLOBAL ) + #endif // DYNLOAD_LOCAL + #define GetProc dlsym + #define UnLoadLib( handle ) dlclose( handle ); +#endif // WIN32 #include "SMESH_Gen_i.hxx" -#include "SMESH_Mesh_i.hxx" -#include "SMESH_Hypothesis_i.hxx" -#include "SMESH_Algo_i.hxx" -#include "SMESH_Group_i.hxx" -#include "SMESH_PythonDump.hxx" +#include "SMESH_version.h" +#include "DriverMED_W_SMESHDS_Mesh.h" +#include "DriverMED_R_SMESHDS_Mesh.h" +#ifdef WITH_CGNS +#include "DriverCGNS_Read.hxx" +#endif +#include "MED_Factory.hxx" +#include "SMDS_EdgePosition.hxx" +#include "SMDS_FacePosition.hxx" +#include "SMDS_SetIterator.hxx" +#include "SMDS_SpacePosition.hxx" +#include "SMDS_VertexPosition.hxx" #include "SMESHDS_Document.hxx" #include "SMESHDS_Group.hxx" #include "SMESHDS_GroupOnGeom.hxx" -#include "SMESH_Mesh.hxx" -#include "SMESH_Hypothesis.hxx" +#include "SMESH_Algo_i.hxx" +#include "SMESH_File.hxx" #include "SMESH_Group.hxx" +#include "SMESH_Group_i.hxx" +#include "SMESH_Hypothesis.hxx" +#include "SMESH_Hypothesis_i.hxx" +#include "SMESH_Mesh.hxx" #include "SMESH_MeshEditor.hxx" +#include "SMESH_Mesh_i.hxx" +#include "SMESH_PreMeshInfo.hxx" +#include "SMESH_PythonDump.hxx" +#include "SMESH_ControlsDef.hxx" -#include "SMDS_EdgePosition.hxx" -#include "SMDS_FacePosition.hxx" +// to pass CORBA exception through SMESH_TRY +#define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; } +#include "SMESH_TryCatch.hxx" // to include after OCC headers! #include CORBA_SERVER_HEADER(SMESH_Group) #include CORBA_SERVER_HEADER(SMESH_Filter) +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) -#include "DriverMED_W_SMESHDS_Mesh.h" -#include "DriverMED_R_SMESHDS_Mesh.h" -#include "SALOMEDS_Tool.hxx" -#include "SALOME_NamingService.hxx" -#include "SALOME_LifeCycleCORBA.hxx" -#include "Utils_SINGLETON.hxx" -#include "OpUtil.hxx" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog) +#include CORBA_CLIENT_HEADER(SALOME_Session) -#include "GEOM_Client.hxx" -#include "Utils_ExceptHandlers.hxx" +// helpers about SALOME::GenericObj +#include +#include +#include #include -#include +#include +#include +#include +#include +#include using namespace std; using SMESH::TPythonDump; +using SMESH::TVar; #define NUM_TMP_FILES 2 #ifdef _DEBUG_ -static int MYDEBUG = 1; +static int MYDEBUG = 0; #else static int MYDEBUG = 0; #endif // Static variables definition +GEOM::GEOM_Gen_var SMESH_Gen_i::myGeomGen; CORBA::ORB_var SMESH_Gen_i::myOrb; PortableServer::POA_var SMESH_Gen_i::myPoa; SALOME_NamingService* SMESH_Gen_i::myNS = NULL; SALOME_LifeCycleCORBA* SMESH_Gen_i::myLCC = NULL; SMESH_Gen_i* SMESH_Gen_i::mySMESHGen = NULL; + +const int nbElemPerDiagonal = 10; + //============================================================================= /*! * GetServant [ static ] @@ -127,9 +182,25 @@ PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theOb try { PortableServer::Servant aServant = GetPOA()->reference_to_servant( theObject ); return aServant; - } - catch (...) { - INFOS( "GetServant - Unknown exception was caught!!!" ); + } + catch (PortableServer::POA::ObjectNotActive &ex) + { + INFOS("GetServant: ObjectNotActive"); + return NULL; + } + catch (PortableServer::POA::WrongAdapter &ex) + { + INFOS("GetServant: WrongAdapter: OK when several servants used to build several mesh in parallel..."); + return NULL; + } + catch (PortableServer::POA::WrongPolicy &ex) + { + INFOS("GetServant: WrongPolicy"); + return NULL; + } + catch (...) + { + INFOS( "GetServant - Unknown exception was caught!!!" ); return NULL; } } @@ -144,16 +215,16 @@ PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theOb CORBA::Object_var SMESH_Gen_i::SObjectToObject( SALOMEDS::SObject_ptr theSObject ) { - SALOMEDS::GenericAttribute_var anAttr; + SALOMEDS::GenericAttribute_wrap anAttr; CORBA::Object_var anObj; if ( !theSObject->_is_nil() ) { try { - if( theSObject->FindAttribute( anAttr, "AttributeIOR" ) ) { - SALOMEDS::AttributeIOR_var anIOR = SALOMEDS::AttributeIOR::_narrow( anAttr ); - CORBA::String_var aValue = anIOR->Value(); - if( strcmp( aValue, "" ) != 0 ) - anObj = GetORB()->string_to_object( aValue ); - } + if( theSObject->FindAttribute( anAttr.inout(), "AttributeIOR" ) ) { + SALOMEDS::AttributeIOR_wrap anIOR = anAttr; + CORBA::String_var aValue = anIOR->Value(); + if( strcmp( aValue, "" ) != 0 ) + anObj = GetORB()->string_to_object( aValue ); + } } catch( ... ) { INFOS( "SObjectToObject - Unknown exception was caught!!!" ); @@ -166,7 +237,7 @@ CORBA::Object_var SMESH_Gen_i::SObjectToObject( SALOMEDS::SObject_ptr theSObject /*! * GetNS [ static ] * - * Get SALOME_NamingService object + * Get SALOME_NamingService object */ //============================================================================= @@ -186,14 +257,33 @@ SALOME_NamingService* SMESH_Gen_i::GetNS() * * Get SALOME_LifeCycleCORBA object */ -//============================================================================= -SALOME_LifeCycleCORBA* SMESH_Gen_i::GetLCC() { +//============================================================================= + +SALOME_LifeCycleCORBA* SMESH_Gen_i::GetLCC() +{ if ( myLCC == NULL ) { myLCC = new SALOME_LifeCycleCORBA( GetNS() ); } return myLCC; } +//============================================================================= +/*! + * GetGeomEngine [ static ] + * + * Get GEOM::GEOM_Gen reference + */ +//============================================================================= + +GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine( bool isShaper ) +{ + Engines::EngineComponent_ptr temp = + GetLCC()->FindOrLoad_Component( isShaper ? "FactoryServer" : "FactoryServer", + isShaper ? "SHAPERSTUDY" : "GEOM" ); + myGeomGen = GEOM::GEOM_Gen::_narrow( temp ); + + return myGeomGen; +} //============================================================================= /*! @@ -201,11 +291,14 @@ SALOME_LifeCycleCORBA* SMESH_Gen_i::GetLCC() { * * Get GEOM::GEOM_Gen reference */ -//============================================================================= -GEOM::GEOM_Gen_ptr SMESH_Gen_i::GetGeomEngine() { - GEOM::GEOM_Gen_var aGeomEngine = - GEOM::GEOM_Gen::_narrow( GetLCC()->FindOrLoad_Component("FactoryServer","GEOM") ); - return aGeomEngine._retn(); +//============================================================================= + +GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine( GEOM::GEOM_Object_ptr go ) +{ + GEOM::GEOM_Gen_ptr gen; + if ( !CORBA::is_nil( go )) + gen = go->GetGen(); + return gen; } //============================================================================= @@ -218,34 +311,63 @@ GEOM::GEOM_Gen_ptr SMESH_Gen_i::GetGeomEngine() { SMESH_Gen_i::SMESH_Gen_i() { - INFOS( "SMESH_Gen_i::SMESH_Gen_i : default constructor" ); } //============================================================================= /*! - * SMESH_Gen_i::SMESH_Gen_i + * SMESH_Gen_i::SMESH_Gen_i * * Standard constructor, used with Container */ //============================================================================= SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr orb, - PortableServer::POA_ptr poa, - PortableServer::ObjectId* contId, - const char* instanceName, + PortableServer::POA_ptr poa, + PortableServer::ObjectId* contId, + const char* instanceName, const char* interfaceName ) - : Engines_Component_i( orb, poa, contId, instanceName, interfaceName ) + : Engines_Component_i( orb, poa, contId, instanceName, interfaceName ) { - INFOS( "SMESH_Gen_i::SMESH_Gen_i : standard constructor" ); myOrb = CORBA::ORB::_duplicate(orb); myPoa = PortableServer::POA::_duplicate(poa); - + _thisObj = this ; _id = myPoa->activate_object( _thisObj ); - + + myStudyContext = new StudyContext; + + myIsEmbeddedMode = false; + myIsEnablePublish = true; myShapeReader = NULL; // shape reader mySMESHGen = this; + myIsHistoricalPythonDump = true; + myToForgetMeshDataOnHypModif = false; + + // set it in standalone mode only + //OSD::SetSignal( true ); + + // 0020605: EDF 1190 SMESH: Display performance. 80 seconds for 52000 cells. + // find out mode (embedded or standalone) here else + // meshes created before calling SMESH_Client::GetSMESHGen(), which calls + // SMESH_Gen_i::SetEmbeddedMode(), have wrong IsEmbeddedMode flag + if ( SALOME_NamingService* ns = GetNS() ) + { + CORBA::Object_var obj = ns->Resolve( "/Kernel/Session" ); + SALOME::Session_var session = SALOME::Session::_narrow( obj ) ; + if ( !session->_is_nil() ) + { + CORBA::String_var str_host = session->getHostname(); + CORBA::Long s_pid = session->getPID(); + string my_host = Kernel_Utils::GetHostname(); +#ifdef WIN32 + long my_pid = (long)_getpid(); +#else + long my_pid = (long) getpid(); +#endif + SetEmbeddedMode( s_pid == my_pid && my_host == str_host.in() ); + } + } } //============================================================================= @@ -258,45 +380,79 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr orb, SMESH_Gen_i::~SMESH_Gen_i() { - INFOS( "SMESH_Gen_i::~SMESH_Gen_i" ); - // delete hypothesis creators - map::iterator itHyp; + map::iterator itHyp, itHyp2; for (itHyp = myHypCreatorMap.begin(); itHyp != myHypCreatorMap.end(); itHyp++) { - delete (*itHyp).second; + // same creator can be mapped under different names + GenericHypothesisCreator_i* creator = (*itHyp).second; + if ( !creator ) + continue; + delete creator; + for (itHyp2 = itHyp; itHyp2 != myHypCreatorMap.end(); itHyp2++) + if ( creator == (*itHyp2).second ) + (*itHyp2).second = 0; } myHypCreatorMap.clear(); // Clear study contexts data - map::iterator it; - for ( it = myStudyContextMap.begin(); it != myStudyContextMap.end(); ++it ) { - delete it->second; - } - myStudyContextMap.clear(); + delete myStudyContext; + // delete shape reader - if ( !myShapeReader ) + if ( myShapeReader ) delete myShapeReader; } - //============================================================================= /*! - * SMESH_Gen_i::createHypothesis + * SMESH_Gen_i::getHypothesisCreator * - * Create hypothesis of given type + * Get hypothesis creator */ //============================================================================= -SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName, - const char* theLibName) - throw (SALOME::SALOME_Exception) +GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHypName, + const char* theLibName, + std::string& thePlatformLibName) + throw (SALOME::SALOME_Exception) { - Unexpect aCatch(SALOME_SalomeException); - if(MYDEBUG) MESSAGE( "Create Hypothesis <" << theHypName << "> from " << theLibName); + std::string aPlatformLibName; + /* It's Need to translate lib name for WIN32 or X platform */ + if ( theLibName && theLibName[0] != '\0' ) + { + int libNameLen = strlen(theLibName); + //check for old format "libXXXXXXX.so" + if (libNameLen > 7 && + !strncmp( theLibName, "lib", 3 ) && + !strcmp( theLibName+libNameLen-3, ".so" )) + { + //the old format +#if defined(WIN32) + aPlatformLibName = std::string( theLibName+3, libNameLen-6 ) + ".dll"; +#elif defined(__APPLE__) + aPlatformLibName = std::string( theLibName, libNameLen-3 ) + ".dylib"; +#else + aPlatformLibName = theLibName; +#endif + } + else + { + //try to use new format +#if defined(WIN32) + aPlatformLibName = theLibName; + aPlatformLibName += ".dll"; +#elif defined(__APPLE__) + aPlatformLibName = std::string( "lib" ) + std::string( theLibName ) + ".dylib"; +#else + aPlatformLibName = std::string( "lib" ) + std::string( theLibName ) + ".so"; +#endif + } + } + thePlatformLibName = aPlatformLibName; - // create a new hypothesis object servant - SMESH_Hypothesis_i* myHypothesis_i = 0; - SMESH::SMESH_Hypothesis_var hypothesis_i; + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "Create Hypothesis <" << theHypName << "> from " << aPlatformLibName); + typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char* ); + GenericHypothesisCreator_i* aCreator; try { // check, if creator for this hypothesis type already exists @@ -304,61 +460,99 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName { // load plugin library if(MYDEBUG) MESSAGE("Loading server meshers plugin library ..."); - void* libHandle = dlopen (theLibName, RTLD_LAZY); +#ifdef WIN32 +#ifdef UNICODE + const wchar_t* path = Kernel_Utils::decode_s(aPlatformLibName); +#else + const char* path = aPlatformLibName.c_str(); +#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 occured + // report any error, if occurred +#ifndef WIN32 const char* anError = dlerror(); - throw(SALOME_Exception(anError)); + throw(SALOME_Exception( anError )); +#else + throw(SALOME_Exception ( SMESH_Comment("Can't load meshers plugin library " ) + << aPlatformLibName)); +#endif } // get method, returning hypothesis creator if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ..."); - typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char* theHypName); GetHypothesisCreator procHandle = - (GetHypothesisCreator)dlsym( libHandle, "GetHypothesisCreator" ); + (GetHypothesisCreator)GetProc( libHandle, "GetHypothesisCreator" ); if (!procHandle) { - throw(SALOME_Exception(LOCALIZED("bad hypothesis plugin library"))); - dlclose(libHandle); + throw(SALOME_Exception(SMESH_Comment("bad hypothesis plugin library") + << aPlatformLibName )); + UnLoadLib(libHandle); } // get hypothesis creator if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << theHypName); - GenericHypothesisCreator_i* aCreator = procHandle(theHypName); + aCreator = procHandle(theHypName); if (!aCreator) { - throw(SALOME_Exception(LOCALIZED("no such a hypothesis in this plugin"))); + throw(SALOME_Exception( SMESH_Comment( theHypName ) << " is missing from " + << aPlatformLibName)); } - // map hypothesis creator to a hypothesis name myHypCreatorMap[string(theHypName)] = aCreator; + return aCreator; + } + else + { + return myHypCreatorMap[string(theHypName)]; } - - // create a new hypothesis object, store its ref. in studyContext - if(MYDEBUG) MESSAGE("Create Hypothesis " << theHypName); - myHypothesis_i = - myHypCreatorMap[string(theHypName)]->Create (myPoa, GetCurrentStudyID(), &myGen); - // _CS_gbo Explicit activation (no longer made in the constructor). - myHypothesis_i->Activate(); - myHypothesis_i->SetLibName(theLibName); // for persistency assurance } catch (SALOME_Exception& S_ex) { THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM); } + return aCreator; +} - if (!myHypothesis_i) - return hypothesis_i._retn(); - - // activate the CORBA servant of hypothesis - hypothesis_i = SMESH::SMESH_Hypothesis::_narrow( myHypothesis_i->_this() ); - int nextId = RegisterObject( hypothesis_i ); - if(MYDEBUG) MESSAGE( "Add hypo to map with id = "<< nextId ); +//============================================================================= +/*! + * SMESH_Gen_i::createHypothesis + * + * Create hypothesis of given type + */ +//============================================================================= +SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName, + const char* theLibName) +{ + SMESH_Hypothesis_i* myHypothesis_i = 0; + SMESH::SMESH_Hypothesis_var hypothesis_i; + std::string aPlatformLibName; + GenericHypothesisCreator_i* aCreator = + getHypothesisCreator(theHypName, theLibName, aPlatformLibName); + // create a new hypothesis object, store its ref. in studyContext + myHypothesis_i = aCreator->Create(myPoa, &myGen); + if (myHypothesis_i) + { + myHypothesis_i->SetLibName( aPlatformLibName.c_str() ); // for persistency assurance + CORBA::String_var hypName = myHypothesis_i->GetName(); + myHypCreatorMap[ hypName.in() ] = aCreator; + + // activate the CORBA servant of hypothesis + hypothesis_i = myHypothesis_i->_this(); + int nextId = RegisterObject( hypothesis_i ); + if(MYDEBUG) { MESSAGE( "Add hypo to map with id = "<< nextId ); } + else { nextId = 0; } // avoid "unused variable" warning in release mode + } return hypothesis_i._retn(); } - + //============================================================================= /*! * SMESH_Gen_i::createMesh @@ -367,7 +561,7 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName */ //============================================================================= SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh() - throw ( SALOME::SALOME_Exception ) + throw ( SALOME::SALOME_Exception ) { Unexpect aCatch(SALOME_SalomeException); if(MYDEBUG) MESSAGE( "SMESH_Gen_i::createMesh" ); @@ -375,14 +569,16 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh() // Get or create the GEOM_Client instance try { // create a new mesh object servant, store it in a map in study context - SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this, GetCurrentStudyID() ); + SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this ); // create a new mesh object - meshServant->SetImpl( myGen.CreateMesh( GetCurrentStudyID() )); + if(MYDEBUG) MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode); + meshServant->SetImpl( myGen.CreateMesh( myIsEmbeddedMode )); // activate the CORBA servant of Mesh SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( meshServant->_this() ); int nextId = RegisterObject( mesh ); - if(MYDEBUG) MESSAGE( "Add mesh to map with id = "<< nextId); + if(MYDEBUG) { MESSAGE( "Add mesh to map with id = "<< nextId); } + else { nextId = 0; } // avoid "unused variable" warning in release mode return mesh._retn(); } catch (SALOME_Exception& S_ex) { @@ -401,7 +597,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh() GEOM_Client* SMESH_Gen_i::GetShapeReader() { // create shape reader if necessary - if ( !myShapeReader ) + if ( !myShapeReader ) myShapeReader = new GEOM_Client(GetContainerRef()); ASSERT( myShapeReader ); return myShapeReader; @@ -409,74 +605,212 @@ GEOM_Client* SMESH_Gen_i::GetShapeReader() //============================================================================= /*! - * SMESH_Gen_i::SetCurrentStudy + * SMESH_Gen_i::SetGeomEngine + * + * Set GEOM::GEOM_Gen reference + */ +//============================================================================= +//GEOM::GEOM_Gen_ptr SMESH_Gen_i::SetGeomEngine( const char* containerLoc ) +void SMESH_Gen_i::SetGeomEngine( GEOM::GEOM_Gen_ptr geomcompo ) +{ + //Engines::Component_ptr temp=GetLCC()->FindOrLoad_Component(containerLoc,"GEOM"); + //myGeomGen=GEOM::GEOM_Gen::_narrow(temp); + myGeomGen=GEOM::GEOM_Gen::_duplicate(geomcompo); + //return myGeomGen; +} + +//============================================================================= +/*! + * SMESH_Gen_i::SetEmbeddedMode * - * Set current study + * Set current mode */ //============================================================================= -void SMESH_Gen_i::SetCurrentStudy( SALOMEDS::Study_ptr theStudy ) +void SMESH_Gen_i::SetEmbeddedMode( CORBA::Boolean theMode ) { - //if(MYDEBUG) - //MESSAGE( "SMESH_Gen_i::SetCurrentStudy" ); - myCurrentStudy = SALOMEDS::Study::_duplicate( theStudy ); - // create study context, if it doesn't exist and set current study - int studyId = GetCurrentStudyID(); - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SetCurrentStudy: study Id = " << studyId ); - if ( myStudyContextMap.find( studyId ) == myStudyContextMap.end() ) { - myStudyContextMap[ studyId ] = new StudyContext; + myIsEmbeddedMode = theMode; + + if ( !myIsEmbeddedMode ) { + //PAL10867: disable signals catching with "noexcepthandler" option + char* envNoCatchSignals = getenv("NOT_INTERCEPT_SIGNALS"); + if (!envNoCatchSignals || !atoi(envNoCatchSignals)) + { + bool raiseFPE; +#ifdef _DEBUG_ + raiseFPE = true; + char* envDisableFPE = getenv("DISABLE_FPE"); + if (envDisableFPE && atoi(envDisableFPE)) + raiseFPE = false; +#else + raiseFPE = false; +#endif + OSD::SetSignal( raiseFPE ); + } + // else OSD::SetSignal() is called in GUI } +} - SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder(); - if( !myCurrentStudy->FindComponent( "GEOM" )->_is_nil() ) - aStudyBuilder->LoadWith( myCurrentStudy->FindComponent( "GEOM" ), GetGeomEngine() ); +//============================================================================= +/*! + * SMESH_Gen_i::IsEmbeddedMode + * + * Get current mode + */ +//============================================================================= + +CORBA::Boolean SMESH_Gen_i::IsEmbeddedMode() +{ + return myIsEmbeddedMode; +} - // set current study for geom engine - //if ( !CORBA::is_nil( GetGeomEngine() ) ) - // GetGeomEngine()->GetCurrentStudy( myCurrentStudy->StudyId() ); +//============================================================================= +/*! + * SMESH_Gen_i::SetEnablePublish + * + * Set enable publishing in the study + */ +//============================================================================= +void SMESH_Gen_i::SetEnablePublish( CORBA::Boolean theIsEnablePublish ) +{ + myIsEnablePublish = theIsEnablePublish; } //============================================================================= /*! - * SMESH_Gen_i::GetCurrentStudy + * SMESH_Gen_i::IsEnablePublish * - * Get current study + * Check enable publishing */ //============================================================================= -SALOMEDS::Study_ptr SMESH_Gen_i::GetCurrentStudy() +CORBA::Boolean SMESH_Gen_i::IsEnablePublish() { - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetCurrentStudy: study Id = " << GetCurrentStudyID() ); - return SALOMEDS::Study::_duplicate( myCurrentStudy ); + return myIsEnablePublish; } //============================================================================= /*! - * SMESH_Gen_i::GetCurrentStudyContext + * SMESH_Gen_i::UpdateStudy * - * Get current study context + * Update study (needed at switching GEOM->SMESH) */ //============================================================================= -StudyContext* SMESH_Gen_i::GetCurrentStudyContext() + +void SMESH_Gen_i::UpdateStudy() { - if ( !CORBA::is_nil( myCurrentStudy ) && - myStudyContextMap.find( GetCurrentStudyID() ) != myStudyContextMap.end() ) - return myStudyContextMap[ myCurrentStudy->StudyId() ]; - else - return 0; + if ( !myStudyContext ) + myStudyContext = new StudyContext; + + SALOMEDS::Study_var aStudy = getStudyServant(); + if ( !CORBA::is_nil( aStudy ) ) + { + SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder(); + + SALOMEDS::SComponent_wrap GEOM_var = aStudy->FindComponent( "GEOM" ); + if( !GEOM_var->_is_nil() ) + aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine( /*isShaper=*/false ) ); + + GEOM_var = aStudy->FindComponent( "SHAPERSTUDY" ); + if( !GEOM_var->_is_nil() ) + aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine( /*isShaper=*/true ) ); + + // NPAL16168, issue 0020210 + // Let meshes update their data depending on GEOM groups that could change + CORBA::String_var compDataType = ComponentDataType(); + SALOMEDS::SComponent_wrap me = aStudy->FindComponent( compDataType.in() ); + if ( !me->_is_nil() ) { + SALOMEDS::ChildIterator_wrap anIter = aStudy->NewChildIterator( me ); + for ( ; anIter->More(); anIter->Next() ) { + SALOMEDS::SObject_wrap so = anIter->Value(); + CORBA::Object_var ior = SObjectToObject( so ); + if ( SMESH_Mesh_i* mesh = SMESH::DownCast( ior )) + mesh->CheckGeomModif(); + } + } + } +} + +//================================================================================ +/*! + * \brief Return true if mesh has ICON_SMESH_TREE_GEOM_MODIF icon + */ +//================================================================================ + +bool SMESH_Gen_i::isGeomModifIcon( SMESH::SMESH_Mesh_ptr mesh ) +{ + SALOMEDS::SObject_wrap so = ObjectToSObject( mesh ); + SALOMEDS::GenericAttribute_wrap attr; + if ( ! so->_is_nil() && so->FindAttribute( attr.inout(), "AttributePixMap" )) + { + SALOMEDS::AttributePixMap_wrap pm = attr; + CORBA::String_var ico = pm->GetPixMap(); + return ( strcmp( ico.in(), "ICON_SMESH_TREE_GEOM_MODIF" ) == 0 ); + } + return false; +} + +//================================================================================= +// function : hasObjectInfo() +// purpose : shows if module provides information for its objects +//================================================================================= + +bool SMESH_Gen_i::hasObjectInfo() +{ + return true; +} + +//================================================================================= +// function : getObjectInfo() +// purpose : returns an information for a given object by its entry +//================================================================================= + +char* SMESH_Gen_i::getObjectInfo( const char* entry ) +{ + // for a mesh with icon == ICON_SMESH_TREE_GEOM_MODIF show a warning; + // for the rest, "module 'SMESH', ID=0:1:2:*" + + SMESH_Comment txt; + + SALOMEDS::SObject_wrap so = getStudyServant()->FindObjectID( entry ); + CORBA::Object_var obj = SObjectToObject( so ); + SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( obj ); + if ( isGeomModifIcon( mesh )) + { + txt << "The geometry was changed and the mesh needs to be recomputed"; + } + + if ( txt.empty() ) + { + CORBA::String_var compType = ComponentDataType(); + txt << "module '" << compType << "', ID=" << entry; + } + return CORBA::string_dup( txt ); +} + +//============================================================================= +/*! + * SMESH_Gen_i::GetStudyContext + * + * Get study context + */ +//============================================================================= +StudyContext* SMESH_Gen_i::GetStudyContext() +{ + return myStudyContext; } //============================================================================= /*! - * SMESH_Gen_i::CreateHypothesis + * SMESH_Gen_i::CreateHypothesis * - * Create hypothesis/algorothm of given type and publish it in the study + * Create hypothesis/algorithm of given type and publish it in the study */ //============================================================================= SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypName, const char* theLibName ) - throw ( SALOME::SALOME_Exception ) + throw ( SALOME::SALOME_Exception ) { Unexpect aCatch(SALOME_SalomeException); // Create hypothesis/algorithm @@ -484,7 +818,7 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam // Publish hypothesis/algorithm in the study if ( CanPublishInStudy( hyp ) ) { - SALOMEDS::SObject_var aSO = PublishHypothesis( myCurrentStudy, hyp ); + SALOMEDS::SObject_wrap aSO = PublishHypothesis( hyp ); if ( !aSO->_is_nil() ) { // Update Python script TPythonDump() << aSO << " = " << this << ".CreateHypothesis('" @@ -497,29 +831,70 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam //================================================================================ /*! - * \brief Return hypothesis of given type holding parameter values of the existing mesh - * \param theHypType - hypothesis type name - * \param theLibName - plugin library name - * \param theMesh - The mesh of interest - * \param theGeom - The shape to get parameter values from - * \retval SMESH::SMESH_Hypothesis_ptr - The returned hypothesis may be the one existing - * in a study and used to compute the mesh, or a temporary one created just to pass - * parameter values + * \brief Return a hypothesis initialized by given average length. + * \param theHypType - hypothesis type name + * \param theLibName - plugin library name + * \param theAverageLength - average length + * \param theQuadDominated - is quad-dominated flag + * \retval SMESH::SMESH_Hypothesis_ptr - the new hypothesis */ //================================================================================ SMESH::SMESH_Hypothesis_ptr -SMESH_Gen_i::GetHypothesisParameterValues (const char* theHypType, - const char* theLibName, - SMESH::SMESH_Mesh_ptr theMesh, - GEOM::GEOM_Object_ptr theGeom) - throw ( SALOME::SALOME_Exception ) +SMESH_Gen_i::CreateHypothesisByAverageLength( const char* theHypType, + const char* theLibName, + CORBA::Double theAverageLength, + CORBA::Boolean theQuadDominated) + throw ( SALOME::SALOME_Exception ) +{ + SMESH::HypInitParams initParams = { ::SMESH_Hypothesis::BY_AVERAGE_LENGTH, + theAverageLength, theQuadDominated }; + + SMESH::SMESH_Hypothesis_var hyp = + GetHypothesisParameterValues( theHypType, theLibName, + SMESH::SMESH_Mesh::_nil(), + GEOM::GEOM_Object::_nil(), + initParams ); + SALOMEDS::SObject_wrap so = PublishHypothesis( hyp ); + + TPythonDump() << hyp << " = " << this << ".CreateHypothesisByAverageLength( '" + << theHypType << "', '" + << theLibName << "', " + << theAverageLength << ", " + << theQuadDominated << " )"; + + return hyp._retn(); +} + +//================================================================================ +/*! + * \brief Return a hypothesis holding parameter values corresponding either to the mesh + * existing on the given geometry or to size of the geometry. + * \param theHypType - hypothesis type name + * \param theLibName - plugin library name + * \param theMesh - The mesh of interest + * \param theGeom - The shape to get parameter values from + * \retval SMESH::SMESH_Hypothesis_ptr - The returned hypothesis may be the one existing + * in a study and used to compute the mesh, or a temporary one created just to pass + * parameter values + */ +//================================================================================ + +SMESH::SMESH_Hypothesis_ptr +SMESH_Gen_i::GetHypothesisParameterValues( const char* theHypType, + const char* theLibName, + SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theGeom, + const SMESH::HypInitParams& theParams) + throw ( SALOME::SALOME_Exception ) { Unexpect aCatch(SALOME_SalomeException); - if ( CORBA::is_nil( theMesh ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM ); - if ( CORBA::is_nil( theGeom ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM ); + + const bool byMesh = ( theParams.way == ::SMESH_Hypothesis::BY_MESH ); + if ( byMesh && CORBA::is_nil( theMesh ) ) + return SMESH::SMESH_Hypothesis::_nil(); + if ( byMesh && CORBA::is_nil( theGeom ) ) + return SMESH::SMESH_Hypothesis::_nil(); // ----------------------------------------------- // find hypothesis used to mesh theGeom @@ -528,54 +903,292 @@ SMESH_Gen_i::GetHypothesisParameterValues (const char* theHypType, // get mesh and shape SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh ); TopoDS_Shape shape = GeomObjectToShape( theGeom ); - if ( !meshServant || shape.IsNull() ) - return SMESH::SMESH_Hypothesis::_nil(); - ::SMESH_Mesh& mesh = meshServant->GetImpl(); - - if ( mesh.NbNodes() == 0 ) // empty mesh + if ( byMesh && ( !meshServant || meshServant->NbNodes()==0 || shape.IsNull() )) return SMESH::SMESH_Hypothesis::_nil(); + ::SMESH_Mesh* mesh = meshServant ? &meshServant->GetImpl() : (::SMESH_Mesh*)0; - // create a temporary hypothesis to know its dimention + // create a temporary hypothesis to know its dimension SMESH::SMESH_Hypothesis_var tmpHyp = this->createHypothesis( theHypType, theLibName ); SMESH_Hypothesis_i* hypServant = SMESH::DownCast( tmpHyp ); if ( !hypServant ) return SMESH::SMESH_Hypothesis::_nil(); ::SMESH_Hypothesis* hyp = hypServant->GetImpl(); - // look for a hypothesis of theHypType used to mesh the shape - if ( myGen.GetShapeDim( shape ) == hyp->GetDim() ) - { - // check local shape - SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( theGeom ); - int nbLocalHyps = aHypList->length(); - for ( int i = 0; i < nbLocalHyps; i++ ) - if ( strcmp( theHypType, aHypList[i]->GetName() ) == 0 ) // FOUND local! - return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] ); - // check super shapes - TopTools_ListIteratorOfListOfShape itShape( mesh.GetAncestors( shape )); - while ( nbLocalHyps == 0 && itShape.More() ) { - GEOM::GEOM_Object_ptr geomObj = ShapeToGeomObject( itShape.Value() ); - if ( ! CORBA::is_nil( geomObj )) { - SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( geomObj ); - nbLocalHyps = aHypList->length(); - for ( int i = 0; i < nbLocalHyps; i++ ) - if ( strcmp( theHypType, aHypList[i]->GetName() ) == 0 ) // FOUND global! - return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] ); - } - itShape.Next(); - } - } - - // let the temporary hypothesis find out some how parameter values - if ( hyp->SetParametersByMesh( &mesh, shape )) - return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp ); - - return SMESH::SMESH_Hypothesis::_nil(); -} - -//============================================================================= -/*! - * SMESH_Gen_i::CreateMesh + if ( byMesh ) { + // look for a hypothesis of theHypType used to mesh the shape + if ( myGen.GetShapeDim( shape ) == hyp->GetDim() ) + { + // check local shape + SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( theGeom ); + int nbLocalHyps = aHypList->length(); + for ( int i = 0; i < nbLocalHyps; i++ ) { + CORBA::String_var hypName = aHypList[i]->GetName(); + if ( strcmp( theHypType, hypName.in() ) == 0 ) // FOUND local! + return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] ); + } + // check super shapes + TopTools_ListIteratorOfListOfShape itShape( mesh->GetAncestors( shape )); + while ( nbLocalHyps == 0 && itShape.More() ) { + GEOM::GEOM_Object_ptr geomObj = ShapeToGeomObject( itShape.Value() ); + if ( ! CORBA::is_nil( geomObj )) { + SMESH::ListOfHypothesis_var aHypList = theMesh->GetHypothesisList( geomObj ); + nbLocalHyps = aHypList->length(); + for ( int i = 0; i < nbLocalHyps; i++ ) + if ( strcmp( theHypType, aHypList[i]->GetName() ) == 0 ) // FOUND global! + return SMESH::SMESH_Hypothesis::_duplicate( aHypList[i] ); + } + itShape.Next(); + } + } + + // let the temporary hypothesis find out somehow parameter values by mesh + if ( hyp->SetParametersByMesh( mesh, shape )) + return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp ); + } + else + { + ::SMESH_Hypothesis::TDefaults dflts; + dflts._way = ( ::SMESH_Hypothesis::InitWay) theParams.way; + dflts._nbSegments = myGen.GetDefaultNbSegments(); + dflts._elemLength = theParams.averageLength; + dflts._quadDominated = theParams.quadDominated; + if ( theParams.way == ::SMESH_Hypothesis::BY_GEOM ) + { + if ( mesh ) + dflts._diagonal = mesh->GetShapeDiagonalSize(); + else + dflts._diagonal = ::SMESH_Mesh::GetShapeDiagonalSize( shape ); + dflts._elemLength = dflts._diagonal / myGen.GetBoundaryBoxSegmentation(); + dflts._shape = &shape; + } + + // let the hypothesis initialize it's values + if ( hyp->SetParametersByDefaults( dflts, mesh )) + return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp ); + } + + return SMESH::SMESH_Hypothesis::_nil(); +} + +//============================================================================= +/*! + * Returns \c True if a hypothesis is assigned to a sole sub-mesh in a current Study + * \param [in] theHyp - the hypothesis of interest + * \param [out] theMesh - the sole mesh using \a theHyp + * \param [out] theShape - the sole geometry \a theHyp is assigned to + * \return boolean - \c True if \a theMesh and \a theShape are sole using \a theHyp + * + * If two meshes on same shape have theHyp assigned to the same sub-shape, they are + * considered as SAME sub-mesh => result is \c true. + * This method ids used to initialize SMESHGUI_GenericHypothesisCreator with + * a shape to which an hyp being edited is assigned. + */ +//============================================================================= + +CORBA::Boolean SMESH_Gen_i::GetSoleSubMeshUsingHyp( SMESH::SMESH_Hypothesis_ptr theHyp, + SMESH::SMESH_Mesh_out theMesh, + GEOM::GEOM_Object_out theShape) +{ + if ( CORBA::is_nil( theHyp )) + return false; + + // get Mesh component SO + CORBA::String_var compDataType = ComponentDataType(); + SALOMEDS::SComponent_wrap comp = getStudyServant()->FindComponent( compDataType.in() ); + if ( CORBA::is_nil( comp )) + return false; + + // look for child SO of meshes + SMESH::SMESH_Mesh_var foundMesh; + TopoDS_Shape foundShape; + bool isSole = true; + SALOMEDS::ChildIterator_wrap meshIter = getStudyServant()->NewChildIterator( comp ); + for ( ; meshIter->More() && isSole; meshIter->Next() ) + { + SALOMEDS::SObject_wrap curSO = meshIter->Value(); + CORBA::Object_var obj = SObjectToObject( curSO ); + SMESH_Mesh_i* mesh_i = SMESH::DownCast< SMESH_Mesh_i* >( obj ); + if ( ! mesh_i ) + continue; + + // look for a sole shape where theHyp is assigned + bool isHypFound = false; + const ShapeToHypothesis & s2hyps = mesh_i->GetImpl().GetMeshDS()->GetHypotheses(); + ShapeToHypothesis::Iterator s2hypsIt( s2hyps ); + for ( ; s2hypsIt.More() && isSole; s2hypsIt.Next() ) + { + const THypList& hyps = s2hypsIt.Value(); + THypList::const_iterator h = hyps.begin(); + for ( ; h != hyps.end(); ++h ) + if ( (*h)->GetID() == theHyp->GetId() ) + break; + if ( h != hyps.end()) // theHyp found + { + isHypFound = true; + if ( ! foundShape.IsNull() && + ! foundShape.IsSame( s2hypsIt.Key() )) // not a sole sub-shape + { + foundShape.Nullify(); + isSole = false; + break; + } + foundShape = s2hypsIt.Key(); + } + } // loop on assigned hyps + + if ( isHypFound && !foundShape.IsNull() ) // a mesh using theHyp is found + { + if ( !foundMesh->_is_nil() ) // not a sole mesh + { + if ( !foundMesh->HasShapeToMesh() || + !mesh_i ->HasShapeToMesh() ) + { + isSole = ( foundMesh->HasShapeToMesh() == mesh_i->HasShapeToMesh() ); + } + else + { + GEOM::GEOM_Object_var s1 = mesh_i ->GetShapeToMesh(); + GEOM::GEOM_Object_var s2 = foundMesh->GetShapeToMesh(); + isSole = s1->IsSame( s2 ); + } + } + foundMesh = SMESH::SMESH_Mesh::_narrow( obj ); + } + + } // loop on meshes + + if ( isSole && + ! foundMesh->_is_nil() && + ! foundShape.IsNull() ) + { + theMesh = foundMesh._retn(); + theShape = ShapeToGeomObject( foundShape ); + return ( !theMesh->_is_nil() && !theShape->_is_nil() ); + } + return false; +} + +//============================================================================= +/*! + * Sets number of segments per diagonal of boundary box of geometry by which + * default segment length of appropriate 1D hypotheses is defined + */ +//============================================================================= + +void SMESH_Gen_i::SetBoundaryBoxSegmentation( CORBA::Long theNbSegments ) + throw ( SALOME::SALOME_Exception ) +{ + if ( theNbSegments > 0 ) + myGen.SetBoundaryBoxSegmentation( int( theNbSegments )); + else + THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM ); +} +//============================================================================= + /*! + * \brief Sets default number of segments per edge + */ +//============================================================================= +void SMESH_Gen_i::SetDefaultNbSegments(CORBA::Long theNbSegments) + throw ( SALOME::SALOME_Exception ) +{ + if ( theNbSegments > 0 ) + myGen.SetDefaultNbSegments( int(theNbSegments) ); + else + THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM ); +} + +//============================================================================= +/*! + Set an option value +*/ +//============================================================================= + +void SMESH_Gen_i::SetOption(const char* name, const char* value) +{ + if ( name && value && strlen( value ) > 0 ) + { + string msgToGUI; + if ( strcmp(name, "historical_python_dump") == 0 ) + { + myIsHistoricalPythonDump = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true + msgToGUI = "preferences/SMESH/historical_python_dump/"; + msgToGUI += myIsHistoricalPythonDump ? "true" : "false"; + } + else if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 ) + { + myToForgetMeshDataOnHypModif = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true + msgToGUI = "preferences/SMESH/forget_mesh_on_hyp_modif/"; + msgToGUI += myToForgetMeshDataOnHypModif ? "true" : "false"; + } + else if ( strcmp(name, "default_grp_color") == 0 ) + { + vector color; + string str = value; + // color must be presented as a string of following form: + if ( str.at(0) == '#' && str.length() == 7 ) { // hexadecimal color ("#ffaa00", for example) + str = str.substr(1); + for ( size_t i = 0; i < str.length()/2; i++ ) + if ( str.at(i*2) >= '0' && str.at(i*2) <= 'f' && str.at(i*2+1) >= '0' && str.at(i*2+1) <= 'f' ) + color.push_back( strtol( str.substr( i*2, 2 ).c_str(), NULL, 16 ) ); + } + else if ( value ) { // rgb color ("255,170,0", for example) + string tempValue( value ); + char* colorValue = strtok( &tempValue[0], "," ); + while ( colorValue != NULL ) { + int c_value = atoi( colorValue ); + if ( c_value >= 0 && c_value <= 255 ) + color.push_back( c_value ); + colorValue = strtok( NULL, "," ); + } + } + if ( color.size() == 3 ) { // color must have three valid component + SMESHDS_GroupBase::SetDefaultColor( Quantity_Color( color[0]/255., color[1]/255., color[2]/255., Quantity_TOC_RGB ) ); + myDefaultGroupColor = value; + msgToGUI = "preferences/SMESH/default_grp_color/"; + msgToGUI += value; + } + } + + // update preferences in case if SetOption() is invoked from python console + if ( !msgToGUI.empty() ) + { + CORBA::Object_var obj = SMESH_Gen_i::GetNS()->Resolve( "/Kernel/Session" ); + SALOME::Session_var session = SALOME::Session::_narrow( obj ); + if ( !CORBA::is_nil( session ) ) + session->emitMessageOneWay(msgToGUI.c_str()); + } + } +} + +//============================================================================= +/*! + Return an option value +*/ +//============================================================================= + +char* SMESH_Gen_i::GetOption(const char* name) +{ + if ( name ) + { + if ( strcmp(name, "historical_python_dump") == 0 ) + { + return CORBA::string_dup( myIsHistoricalPythonDump ? "true" : "false" ); + } + if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 ) + { + return CORBA::string_dup( myToForgetMeshDataOnHypModif ? "true" : "false" ); + } + if ( strcmp(name, "default_grp_color") == 0 ) + { + return CORBA::string_dup( myDefaultGroupColor.c_str() ); + } + } + return CORBA::string_dup( "" ); +} + +//============================================================================= +/*! + * SMESH_Gen_i::CreateMesh * * Create empty mesh on a shape and publish it in the study */ @@ -595,9 +1208,9 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObj // publish mesh in the study if ( CanPublishInStudy( mesh ) ) { - SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder(); + SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder(); aStudyBuilder->NewCommand(); // There is a transaction - SALOMEDS::SObject_var aSO = PublishMesh( myCurrentStudy, mesh.in() ); + SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() ); aStudyBuilder->CommitCommand(); if ( !aSO->_is_nil() ) { // Update Python script @@ -608,6 +1221,60 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObj return mesh._retn(); } +//============================================================================= +/*! + * SMESH_Gen_i::CreateEmptyMesh + * + * Create empty mesh + */ +//============================================================================= + +SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateEmptyMesh() + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" ); + // create mesh + SMESH::SMESH_Mesh_var mesh = this->createMesh(); + + // publish mesh in the study + if ( CanPublishInStudy( mesh ) ) { + SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder(); + aStudyBuilder->NewCommand(); // There is a transaction + SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() ); + aStudyBuilder->CommitCommand(); + if ( !aSO->_is_nil() ) { + // Update Python script + TPythonDump() << aSO << " = " << this << ".CreateEmptyMesh()"; + } + } + + return mesh._retn(); +} + +namespace +{ + //================================================================================ + /*! + * \brief Throws an exception in case if the file can't be read + */ + //================================================================================ + + void checkFileReadable( const char* theFileName ) throw ( SALOME::SALOME_Exception ) + { + SMESH_File f ( theFileName ); + if ( !f ) + { + if ( !f.error().empty() ) + THROW_SALOME_CORBA_EXCEPTION( f.error().c_str(), SALOME::BAD_PARAM); + + THROW_SALOME_CORBA_EXCEPTION + (( SMESH_Comment("Can't open for reading the file ") << theFileName ).c_str(), + SALOME::BAD_PARAM ); + } + } +} + //============================================================================= /*! * SMESH_Gen_i::CreateMeshFromUNV @@ -620,25 +1287,31 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName throw ( SALOME::SALOME_Exception ) { Unexpect aCatch(SALOME_SalomeException); - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshesFromUNV" ); + + checkFileReadable( theFileName ); SMESH::SMESH_Mesh_var aMesh = createMesh(); - string aFileName; // = boost::filesystem::path(theFileName).leaf(); + string aFileName; // publish mesh in the study if ( CanPublishInStudy( aMesh ) ) { - SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder(); + SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder(); aStudyBuilder->NewCommand(); // There is a transaction - SALOMEDS::SObject_var aSO = PublishMesh( myCurrentStudy, aMesh.in(), aFileName.c_str() ); + SALOMEDS::SObject_wrap aSO = PublishMesh( aMesh.in(), aFileName.c_str() ); aStudyBuilder->CommitCommand(); if ( !aSO->_is_nil() ) { // Update Python script - TPythonDump() << aSO << " = smeshgen.CreateMeshesFromUNV('" << theFileName << "')"; + TPythonDump() << aSO << " = " << this << ".CreateMeshesFromUNV(r'" << theFileName << "')"; } } SMESH_Mesh_i* aServant = dynamic_cast( GetServant( aMesh ).in() ); ASSERT( aServant ); aServant->ImportUNVFile( theFileName ); + + // Dump creation of groups + SMESH::ListOfGroups_var groups = aServant->GetGroups(); + + aServant->GetImpl().GetMeshDS()->Modified(); return aMesh._retn(); } @@ -650,18 +1323,18 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName */ //============================================================================= -SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName, - SMESH::DriverMED_ReadStatus& theStatus) - throw ( SALOME::SALOME_Exception ) +SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileName, + SMESH::DriverMED_ReadStatus& theStatus, + const char* theCommandNameForPython, + const char* theFileNameForPython) { - Unexpect aCatch(SALOME_SalomeException); - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshFromMED" ); - - // Python Dump - TPythonDump aPythonDump; - aPythonDump << "(["; - //TCollection_AsciiString aStr ("(["); - +#ifdef WIN32 + char bname[ _MAX_FNAME ]; + _splitpath( theFileNameForPython, NULL, NULL, bname, NULL ); + string aFileName = bname; +#else + string aFileName = basename( const_cast(theFileNameForPython) ); +#endif // Retrieve mesh names from the file DriverMED_R_SMESHDS_Mesh myReader; myReader.SetFile( theFileName ); @@ -670,55 +1343,122 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName, list aNames = myReader.GetMeshNames(aStatus); SMESH::mesh_array_var aResult = new SMESH::mesh_array(); theStatus = (SMESH::DriverMED_ReadStatus)aStatus; + + { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups() + + // Python Dump + TPythonDump aPythonDump; + aPythonDump << "(["; + if (theStatus == SMESH::DRS_OK) { - SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder(); + SALOMEDS::StudyBuilder_var aStudyBuilder; + aStudyBuilder = getStudyServant()->NewBuilder(); aStudyBuilder->NewCommand(); // There is a transaction + aResult->length( aNames.size() ); int i = 0; - + // Iterate through all meshes and create mesh objects - for ( list::iterator it = aNames.begin(); it != aNames.end(); it++ ) { + for ( list::iterator it = aNames.begin(); it != aNames.end(); it++ ) + { // Python Dump - //if (i > 0) aStr += ", "; if (i > 0) aPythonDump << ", "; // create mesh SMESH::SMESH_Mesh_var mesh = createMesh(); - + // publish mesh in the study - SALOMEDS::SObject_var aSO; + SALOMEDS::SObject_wrap aSO; if ( CanPublishInStudy( mesh ) ) - aSO = PublishMesh( myCurrentStudy, mesh.in(), (*it).c_str() ); + // 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() ) { - // Python Dump aPythonDump << aSO; - //aStr += aSO->GetID(); } else { - // Python Dump aPythonDump << "mesh_" << i; -// aStr += "mesh_"; -// aStr += TCollection_AsciiString(i); } // Read mesh data (groups are published automatically by ImportMEDFile()) SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( mesh ).in() ); ASSERT( meshServant ); SMESH::DriverMED_ReadStatus status1 = - meshServant->ImportMEDFile( theFileName, (*it).c_str() ); + meshServant->ImportMEDFile( theFileName, (*it).c_str() ); if (status1 > theStatus) - theStatus = status1; + theStatus = status1; aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh ); + meshServant->GetImpl().GetMeshDS()->Modified(); } - aStudyBuilder->CommitCommand(); + if ( !aStudyBuilder->_is_nil() ) + aStudyBuilder->CommitCommand(); } // Update Python script - aPythonDump << "], status) = " << this << ".CreateMeshesFromMED('" << theFileName << "')"; + aPythonDump << "], status) = " << this << "." << theCommandNameForPython << "(r'" << theFileNameForPython << "')"; + } + // Dump creation of groups + for ( CORBA::ULong i = 0; i < aResult->length(); ++i ) + SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups(); return aResult._retn(); } +SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName, + SMESH::DriverMED_ReadStatus& theStatus) + throw ( SALOME::SALOME_Exception ) +{ + 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) + throw ( SALOME::SALOME_Exception ) +{ + 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 @@ -731,98 +1471,473 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName throw ( SALOME::SALOME_Exception ) { Unexpect aCatch(SALOME_SalomeException); - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshesFromSTL" ); + checkFileReadable( theFileName ); SMESH::SMESH_Mesh_var aMesh = createMesh(); - string aFileName; // = boost::filesystem::path(theFileName).leaf(); + //string aFileName; +#ifdef WIN32 + char bname[ _MAX_FNAME ]; + _splitpath( theFileName, NULL, NULL, bname, NULL ); + string aFileName = bname; +#else + string aFileName = basename( const_cast(theFileName) ); +#endif // publish mesh in the study if ( CanPublishInStudy( aMesh ) ) { - SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder(); + SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder(); aStudyBuilder->NewCommand(); // There is a transaction - SALOMEDS::SObject_var aSO = PublishInStudy - ( myCurrentStudy, SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() ); + SALOMEDS::SObject_wrap aSO = PublishInStudy( SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() ); aStudyBuilder->CommitCommand(); if ( !aSO->_is_nil() ) { // Update Python script - TPythonDump() << aSO << " = " << this << ".CreateMeshesFromSTL('" << theFileName << "')"; + TPythonDump() << aSO << " = " << this << ".CreateMeshesFromSTL(r'" << theFileName << "')"; } } SMESH_Mesh_i* aServant = dynamic_cast( GetServant( aMesh ).in() ); ASSERT( aServant ); aServant->ImportSTLFile( theFileName ); + aServant->GetImpl().GetMeshDS()->Modified(); return aMesh._retn(); } -//============================================================================= +//================================================================================ /*! - * SMESH_Gen_i::IsReadyToCompute - * - * Returns true if mesh contains enough data to be computed + * \brief Create meshes and import data from the CGSN file */ -//============================================================================= +//================================================================================ -CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh, - GEOM::GEOM_Object_ptr theShapeObject ) +SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char* theFileName, + SMESH::DriverMED_ReadStatus& theStatus) throw ( SALOME::SALOME_Exception ) { Unexpect aCatch(SALOME_SalomeException); - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IsReadyToCompute" ); + checkFileReadable( theFileName ); - if ( CORBA::is_nil( theShapeObject ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", - SALOME::BAD_PARAM ); + SMESH::mesh_array_var aResult = new SMESH::mesh_array(); - if ( CORBA::is_nil( theMesh ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", - SALOME::BAD_PARAM ); +#ifdef WITH_CGNS + // Retrieve nb meshes from the file + DriverCGNS_Read myReader; + myReader.SetFile( theFileName ); + Driver_Mesh::Status aStatus; + int nbMeshes = myReader.GetNbMeshes(aStatus); + theStatus = (SMESH::DriverMED_ReadStatus)aStatus; - try { - // get mesh servant - SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() ); - ASSERT( meshServant ); - if ( meshServant ) { - // get local TopoDS_Shape - TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject ); - // call implementation - ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); - return myGen.CheckAlgoState( myLocMesh, myLocShape ); + aResult->length( nbMeshes ); + + { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups() + + // Python Dump + TPythonDump aPythonDump; + aPythonDump << "(["; + + if (theStatus == SMESH::DRS_OK) + { + SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder(); + aStudyBuilder->NewCommand(); // There is a transaction + + int i = 0; + + // Iterate through all meshes and create mesh objects + for ( ; i < nbMeshes; ++i ) + { + // Python Dump + if (i > 0) aPythonDump << ", "; + + // create mesh + SMESH::SMESH_Mesh_var mesh = createMesh(); + aResult[i] = SMESH::SMESH_Mesh::_duplicate( mesh ); + + // Read mesh data (groups are published automatically by ImportMEDFile()) + SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( mesh ).in() ); + ASSERT( meshServant ); + string meshName; + SMESH::DriverMED_ReadStatus status1 = + meshServant->ImportCGNSFile( theFileName, i, meshName ); + if (status1 > theStatus) + theStatus = status1; + + meshServant->GetImpl().GetMeshDS()->Modified(); + // publish mesh in the study + SALOMEDS::SObject_wrap aSO; + if ( CanPublishInStudy( mesh ) ) + aSO = PublishMesh( mesh.in(), meshName.c_str() ); + + // Python Dump + if ( !aSO->_is_nil() ) { + aPythonDump << aSO; + } + else { + aPythonDump << "mesh_" << i; + } + } + aStudyBuilder->CommitCommand(); } + + aPythonDump << "], status) = " << this << ".CreateMeshesFromCGNS(r'" << theFileName << "')"; } - catch ( SALOME_Exception& S_ex ) { - INFOS( "catch exception "<< S_ex.what() ); - } - return false; + // Dump creation of groups + for ( CORBA::ULong i = 0; i < aResult->length(); ++i ) + SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups(); +#else + THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR); +#endif + + return aResult._retn(); } //================================================================================ /*! - * \brief Returns errors of hypotheses definintion - * \param theMesh - the mesh - * \param theSubObject - the main or sub- shape - * \retval SMESH::algo_error_array* - sequence of errors + * \brief Create a mesh and import data from a GMF file */ //================================================================================ -SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMesh, - GEOM::GEOM_Object_ptr theSubObject ) - throw ( SALOME::SALOME_Exception ) +SMESH::SMESH_Mesh_ptr +SMESH_Gen_i::CreateMeshesFromGMF( const char* theFileName, + CORBA::Boolean theMakeRequiredGroups, + SMESH::ComputeError_out theError) + throw ( SALOME::SALOME_Exception ) { Unexpect aCatch(SALOME_SalomeException); - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetAlgoState()" ); - - if ( CORBA::is_nil( theSubObject ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM ); - - if ( CORBA::is_nil( theMesh ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM ); + checkFileReadable( theFileName ); - SMESH::algo_error_array_var error_array = new SMESH::algo_error_array; - try { + SMESH::SMESH_Mesh_var aMesh = createMesh(); +#ifdef WIN32 + char bname[ _MAX_FNAME ]; + _splitpath( theFileName, NULL, NULL, bname, NULL ); + string aFileName = bname; +#else + string aFileName = basename( const_cast(theFileName) ); +#endif + // publish mesh in the study + if ( CanPublishInStudy( aMesh ) ) { + SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder(); + aStudyBuilder->NewCommand(); // There is a transaction + SALOMEDS::SObject_wrap aSO = PublishInStudy( SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() ); + aStudyBuilder->CommitCommand(); + if ( !aSO->_is_nil() ) { + // Update Python script + TPythonDump() << "("<< aSO << ", error) = " << this << ".CreateMeshesFromGMF(r'" + << theFileName << "', " + << theMakeRequiredGroups << " )"; + } + } + SMESH_Mesh_i* aServant = dynamic_cast( GetServant( aMesh ).in() ); + ASSERT( aServant ); + theError = aServant->ImportGMFFile( theFileName, theMakeRequiredGroups ); + aServant->GetImpl().GetMeshDS()->Modified(); + return aMesh._retn(); +} + + +//============================================================================= +/*! + * SMESH_Gen_i::IsReadyToCompute + * + * Returns true if mesh contains enough data to be computed + */ +//============================================================================= + +CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theShapeObject ) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IsReadyToCompute" ); + + if ( CORBA::is_nil( theShapeObject ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", + SALOME::BAD_PARAM ); + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", + SALOME::BAD_PARAM ); + + try { + // get mesh servant + SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() ); + ASSERT( meshServant ); + if ( meshServant ) { + // get local TopoDS_Shape + TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject ); + // call implementation + ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); + return myGen.CheckAlgoState( myLocMesh, myLocShape ); + } + } + catch ( SALOME_Exception& S_ex ) { + INFOS( "catch exception "<< S_ex.what() ); + } + return false; +} + +//================================================================================ +/*! + * \brief Find SObject for an algo + */ +//================================================================================ + +SALOMEDS::SObject_ptr SMESH_Gen_i::GetAlgoSO(const ::SMESH_Algo* algo) +{ + if ( algo ) { + SALOMEDS::Study_var aStudy = getStudyServant(); + if ( !aStudy->_is_nil() ) { + // find algo in the study + CORBA::String_var compDataType = ComponentDataType(); + SALOMEDS::SComponent_wrap father = aStudy->FindComponent( compDataType.in() ); + if ( !father->_is_nil() ) { + SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( father ); + for ( ; itBig->More(); itBig->Next() ) { + SALOMEDS::SObject_wrap gotBranch = itBig->Value(); + if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) { + SALOMEDS::ChildIterator_wrap algoIt = aStudy->NewChildIterator( gotBranch ); + for ( ; algoIt->More(); algoIt->Next() ) { + SALOMEDS::SObject_wrap algoSO = algoIt->Value(); + CORBA::Object_var algoIOR = SObjectToObject( algoSO ); + if ( !CORBA::is_nil( algoIOR )) { + SMESH_Hypothesis_i* impl = SMESH::DownCast( algoIOR ); + if ( impl && impl->GetImpl() == algo ) + return algoSO._retn(); + } + } // loop on algo SO's + break; + } // if algo tag + } // SMESH component iterator + } + } + } + return SALOMEDS::SObject::_nil(); +} + +//================================================================================ +/*! + * \brief Return errors of mesh computation + */ +//================================================================================ + +SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theSubObject ) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetComputeErrors()" ); + + if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh()) + THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM ); + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM ); + + SMESH::compute_error_array_var error_array = new SMESH::compute_error_array; + try { + if ( SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh )) + { + TopoDS_Shape shape; + if(theMesh->HasShapeToMesh()) + shape = GeomObjectToShape( theSubObject ); + else + shape = SMESH_Mesh::PseudoShape(); + + ::SMESH_Mesh& mesh = meshServant->GetImpl(); + + error_array->length( mesh.GetMeshDS()->MaxShapeIndex() ); + int nbErr = 0; + + SMESH_subMesh *sm = mesh.GetSubMesh(shape); + const bool includeSelf = true, complexShapeFirst = true; + SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(includeSelf, + complexShapeFirst); + while ( smIt->more() ) + { + sm = smIt->next(); + // if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX ) + // break; + SMESH_ComputeErrorPtr error = sm->GetComputeError(); + if ( error && !error->IsOK() ) + { + if ( !( error->myAlgo ) && + !( error->myAlgo = sm->GetAlgo() )) + continue; + SMESH::ComputeError & errStruct = error_array[ nbErr++ ]; + errStruct.code = -( error->myName < 0 ? error->myName + 1: error->myName ); // -1 -> 0 + errStruct.comment = error->myComment.c_str(); + errStruct.subShapeID = sm->GetId(); + SALOMEDS::SObject_wrap algoSO = GetAlgoSO( error->myAlgo ); + if ( !algoSO->_is_nil() ) { + CORBA::String_var algoName = algoSO->GetName(); + errStruct.algoName = algoName; + } + else { + errStruct.algoName = error->myAlgo->GetName(); + } + errStruct.hasBadMesh = error->HasBadElems(); + } + } + error_array->length( nbErr ); + } + } + catch ( SALOME_Exception& S_ex ) { + INFOS( "catch exception "<< S_ex.what() ); + } + + return error_array._retn(); +} + +//================================================================================ +/*! + * \brief Return mesh elements preventing computation of a subshape + */ +//================================================================================ + +SMESH::MeshPreviewStruct* +SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh, + CORBA::Short theSubShapeID ) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetBadInputElements()" ); + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM ); + + SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct; + try { + // mesh servant + if ( SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh )) + { + // mesh implementation + ::SMESH_Mesh& mesh = meshServant->GetImpl(); + // submesh by subshape id + if ( SMESH_subMesh * sm = mesh.GetSubMeshContaining( theSubShapeID )) + { + // compute error + SMESH_ComputeErrorPtr error = sm->GetComputeError(); + if ( error && error->HasBadElems() ) + { + typedef map TNode2LocalIDMap; + typedef TNode2LocalIDMap::iterator TNodeLocalID; + + // get nodes of elements and count elements + TNode2LocalIDMap mapNode2LocalID; + list< TNodeLocalID > connectivity; + int i, nbElements = 0, nbConnNodes = 0; + + const list& badElems = + static_cast( error.get() )->myBadElements; + list::const_iterator elemIt = badElems.begin(); + list::const_iterator elemEnd = badElems.end(); + for ( ; elemIt != elemEnd; ++elemIt, ++nbElements ) + { + SMDS_ElemIteratorPtr nIt = (*elemIt)->nodesIterator(); + while ( nIt->more() ) + connectivity.push_back + ( mapNode2LocalID.insert( make_pair( nIt->next(), ++nbConnNodes)).first ); + } + // fill node coords and assign local ids to the nodes + int nbNodes = mapNode2LocalID.size(); + result->nodesXYZ.length( nbNodes ); + TNodeLocalID node2ID = mapNode2LocalID.begin(); + for ( i = 0; i < nbNodes; ++i, ++node2ID ) { + node2ID->second = i; + const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first; + result->nodesXYZ[i].x = node->X(); + result->nodesXYZ[i].y = node->Y(); + result->nodesXYZ[i].z = node->Z(); + } + // fill connectivity + result->elementConnectivities.length( nbConnNodes ); + list< TNodeLocalID >::iterator connIt = connectivity.begin(); + for ( i = 0; i < nbConnNodes; ++i, ++connIt ) { + result->elementConnectivities[i] = (*connIt)->second; + } + // fill element types + result->elementTypes.length( nbElements ); + for ( i = 0, elemIt = badElems.begin(); i elementTypes[i].SMDS_ElementType = (SMESH::ElementType) elem->GetType(); + result->elementTypes[i].isPoly = elem->IsPoly(); + result->elementTypes[i].nbNodesInElement = elem->NbNodes(); + } + } + } + } + } + catch ( SALOME_Exception& S_ex ) { + INFOS( "catch exception "<< S_ex.what() ); + } + + return result._retn(); +} + +//================================================================================ +/*! + * \brief Create a group of elements preventing computation of a sub-shape + */ +//================================================================================ + +SMESH::ListOfGroups* +SMESH_Gen_i::MakeGroupsOfBadInputElements( SMESH::SMESH_Mesh_ptr theMesh, + CORBA::Short theSubShapeID, + const char* theGroupName ) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + + SMESH::ListOfGroups_var groups; + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM ); + + try { + if ( SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh )) + { + groups = meshServant->MakeGroupsOfBadInputElements( theSubShapeID, theGroupName ); + TPythonDump() << groups << " = " << this + << ".MakeGroupsOfBadInputElements( " + << theMesh << ", " << theSubShapeID << ", '" << theGroupName << "' )"; + } + } + catch ( SALOME_Exception& S_ex ) { + INFOS( "catch exception "<< S_ex.what() ); + } + return groups._retn(); +} + +//================================================================================ +/*! + * \brief Returns errors of hypotheses definition + * \param theMesh - the mesh + * \param theSubObject - the main or sub- shape + * \retval SMESH::algo_error_array* - sequence of errors + */ +//================================================================================ + +SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theSubObject ) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetAlgoState()" ); + + if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh()) + THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM ); + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM ); + + SMESH::algo_error_array_var error_array = new SMESH::algo_error_array; + try { SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh ); ASSERT( meshServant ); if ( meshServant ) { - TopoDS_Shape myLocShape = GeomObjectToShape( theSubObject ); + TopoDS_Shape myLocShape; + if(theMesh->HasShapeToMesh()) + myLocShape = GeomObjectToShape( theSubObject ); + else + myLocShape = SMESH_Mesh::PseudoShape(); + ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); list< ::SMESH_Gen::TAlgoStateError > error_list; list< ::SMESH_Gen::TAlgoStateError >::iterator error; @@ -832,242 +1947,2209 @@ SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMes int i = 0; for ( error = error_list.begin(); error != error_list.end(); ++error ) { - // error name - SMESH::AlgoStateErrorName errName; - switch ( error->_name ) { - case ::SMESH_Gen::MISSING_ALGO: errName = SMESH::MISSING_ALGO; break; - case ::SMESH_Gen::MISSING_HYPO: errName = SMESH::MISSING_HYPO; break; - case ::SMESH_Gen::NOT_CONFORM_MESH: errName = SMESH::NOT_CONFORM_MESH; break; - default: - THROW_SALOME_CORBA_EXCEPTION( "bad error name",SALOME::BAD_PARAM ); - } - // algo name - CORBA::String_var algoName; - if ( error->_algo ) { - if ( !myCurrentStudy->_is_nil() ) { - // find algo in the study - SALOMEDS::SComponent_var father = SALOMEDS::SComponent::_narrow - ( myCurrentStudy->FindComponent( ComponentDataType() ) ); - if ( !father->_is_nil() ) { - SALOMEDS::ChildIterator_var itBig = myCurrentStudy->NewChildIterator( father ); - for ( ; itBig->More(); itBig->Next() ) { - SALOMEDS::SObject_var gotBranch = itBig->Value(); - if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) { - SALOMEDS::ChildIterator_var algoIt = myCurrentStudy->NewChildIterator( gotBranch ); - for ( ; algoIt->More(); algoIt->Next() ) { - SALOMEDS::SObject_var algoSO = algoIt->Value(); - CORBA::Object_var algoIOR = SObjectToObject( algoSO ); - if ( !CORBA::is_nil( algoIOR )) { - SMESH_Hypothesis_i* myImpl = SMESH::DownCast( algoIOR ); - if ( myImpl && myImpl->GetImpl() == error->_algo ) { - algoName = algoSO->GetName(); - break; - } - } - } // loop on algo SO's - break; - } // if algo tag - } // SMESH component iterator - } + // fill AlgoStateError structure + SMESH::AlgoStateError & errStruct = error_array[ i++ ]; + errStruct.state = SMESH_Mesh_i::ConvertHypothesisStatus( error->_name ); + errStruct.algoDim = error->_algoDim; + errStruct.isGlobalAlgo = error->_isGlobalAlgo; + errStruct.algoName = ""; + SALOMEDS::SObject_wrap algoSO = GetAlgoSO( error->_algo ); + if ( !algoSO->_is_nil() ) { + CORBA::String_var algoName = algoSO->GetName(); + errStruct.algoName = algoName.in(); + } + } + } + } + catch ( SALOME_Exception& S_ex ) { + INFOS( "catch exception "<< S_ex.what() ); + } + return error_array._retn(); +} + +//============================================================================= +/*! + * SMESH_Gen_i::GetSubShapesId + * + * Get sub-shapes unique ID's list + */ +//============================================================================= + +SMESH::long_array* +SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr theMainShapeObject, + const SMESH::object_array& theListOfSubShapeObject ) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetSubShapesId" ); + + SMESH::long_array_var shapesId = new SMESH::long_array; + set setId; + + if ( CORBA::is_nil( theMainShapeObject ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM ); + + try + { + TopoDS_Shape myMainShape = GeomObjectToShape(theMainShapeObject); + TopTools_IndexedMapOfShape myIndexToShape; + TopExp::MapShapes(myMainShape,myIndexToShape); + + for ( CORBA::ULong i = 0; i < theListOfSubShapeObject.length(); i++ ) + { + GEOM::GEOM_Object_var aShapeObject + = GEOM::GEOM_Object::_narrow(theListOfSubShapeObject[i]); + if ( CORBA::is_nil( aShapeObject ) ) + THROW_SALOME_CORBA_EXCEPTION ("bad shape object reference", \ + SALOME::BAD_PARAM ); + + TopoDS_Shape locShape = GeomObjectToShape(aShapeObject); + for (TopExp_Explorer exp(locShape,TopAbs_FACE); exp.More(); exp.Next()) + { + const TopoDS_Face& F = TopoDS::Face(exp.Current()); + setId.insert(myIndexToShape.FindIndex(F)); + if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(F)); + } + for (TopExp_Explorer exp(locShape,TopAbs_EDGE); exp.More(); exp.Next()) + { + const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); + setId.insert(myIndexToShape.FindIndex(E)); + if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(E)); + } + for (TopExp_Explorer exp(locShape,TopAbs_VERTEX); exp.More(); exp.Next()) + { + const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current()); + setId.insert(myIndexToShape.FindIndex(V)); + if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(V)); + } + } + shapesId->length(setId.size()); + set::iterator iind; + int i=0; + for (iind = setId.begin(); iind != setId.end(); iind++) + { + if(MYDEBUG) SCRUTE((*iind)); + shapesId[i] = (*iind); + if(MYDEBUG) SCRUTE(shapesId[i]); + i++; + } + } + catch (SALOME_Exception& S_ex) + { + THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM); + } + + return shapesId._retn(); +} + +//============================================================================= +/*! + * SMESH_Gen_i::Compute + * + * Compute mesh on a shape + */ +//============================================================================= + +CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theShapeObject ) + throw ( SALOME::SALOME_Exception ) +{ + //MEMOSTAT; + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Compute" ); + + if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh()) + THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", + SALOME::BAD_PARAM ); + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", + SALOME::BAD_PARAM ); + + // Update Python script + TPythonDump() << "isDone = " << this << ".Compute( " + << theMesh << ", " << theShapeObject << ")"; + + try { + // get mesh servant + SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh ); + ASSERT( meshServant ); + if ( meshServant ) { + if ( isGeomModifIcon( theMesh )) + meshServant->Clear(); + else + meshServant->Load(); + // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation" + meshServant->CheckGeomModif(); + // get local TopoDS_Shape + TopoDS_Shape myLocShape; + if(theMesh->HasShapeToMesh()) + myLocShape = GeomObjectToShape( theShapeObject ); + else + myLocShape = SMESH_Mesh::PseudoShape(); + // call implementation compute + ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); + myGen.PrepareCompute( myLocMesh, myLocShape ); + int how = ::SMESH_Gen::COMPACT_MESH; + if ( myLocShape != myLocMesh.GetShapeToMesh() ) // compute a sub-mesh + how |= ::SMESH_Gen::SHAPE_ONLY; + bool ok = myGen.Compute( myLocMesh, myLocShape, how ); + meshServant->CreateGroupServants(); // algos can create groups (issue 0020918) + myLocMesh.GetMeshDS()->Modified(); + UpdateIcons( theMesh ); + if ( ok ) + HighLightInvalid( theMesh, /*isInvalid=*/false ); + return ok; + } + } + catch ( std::bad_alloc ) { + INFOS( "Compute(): lack of memory" ); + } + catch ( SALOME_Exception& S_ex ) { + INFOS( "Compute(): catch exception "<< S_ex.what() ); + } + catch ( ... ) { + INFOS( "Compute(): unknown exception " ); + } + return false; +} + +//============================================================================= +/*! + * SMESH_Gen_i::CancelCompute + * + * Cancel Compute mesh on a shape + */ +//============================================================================= + +void SMESH_Gen_i::CancelCompute( SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theShapeObject ) +{ + if ( SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() )) + { + ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); + TopoDS_Shape myLocShape; + if(theMesh->HasShapeToMesh()) + myLocShape = GeomObjectToShape( theShapeObject ); + else + myLocShape = SMESH_Mesh::PseudoShape(); + myGen.CancelCompute( myLocMesh, myLocShape); + } +} + +//============================================================================= +/*! + * SMESH_Gen_i::Precompute + * + * Compute mesh as preview till indicated dimension on shape + */ +//============================================================================= + +SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theShapeObject, + SMESH::Dimension theDimension, + SMESH::long_array& theShapesId) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Precompute" ); + + if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh()) + THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", + SALOME::BAD_PARAM ); + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", + SALOME::BAD_PARAM ); + + SMESH::MeshPreviewStruct_var result = new SMESH::MeshPreviewStruct; + try { + // get mesh servant + SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() ); + meshServant->Load(); + ASSERT( meshServant ); + if ( meshServant ) { + // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation" + meshServant->CheckGeomModif(); + // get local TopoDS_Shape + TopoDS_Shape myLocShape; + if(theMesh->HasShapeToMesh()) + myLocShape = GeomObjectToShape( theShapeObject ); + else + return result._retn();; + + // call implementation compute + ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); + TSetOfInt shapeIds; + ::MeshDimension aDim = (MeshDimension)theDimension; + if ( myGen.Compute( myLocMesh, myLocShape, ::SMESH_Gen::COMPACT_MESH, aDim, &shapeIds ) ) + { + int nbShapeId = shapeIds.size(); + theShapesId.length( nbShapeId ); + // iterates on shapes and collect mesh entities into mesh preview + TSetOfInt::const_iterator idIt = shapeIds.begin(); + TSetOfInt::const_iterator idEnd = shapeIds.end(); + std::map< int, int > mapOfShIdNb; + std::set< SMESH_TLink > setOfEdge; + std::list< SMDSAbs_ElementType > listOfElemType; + typedef map TNode2LocalIDMap; + typedef TNode2LocalIDMap::iterator TNodeLocalID; + TNode2LocalIDMap mapNode2LocalID; + list< TNodeLocalID > connectivity; + int i, nbConnNodes = 0; + std::set< const SMESH_subMesh* > setOfVSubMesh; + // iterates on shapes + for ( ; idIt != idEnd; idIt++ ) + { + if ( mapOfShIdNb.find( *idIt ) != mapOfShIdNb.end() ) + continue; + SMESH_subMesh* sm = myLocMesh.GetSubMeshContaining(*idIt); + if ( !sm || !sm->IsMeshComputed() ) + continue; + + const TopoDS_Shape& aSh = sm->GetSubShape(); + const int shDim = myGen.GetShapeDim( aSh ); + if ( shDim < 1 || shDim > theDimension ) + continue; + + mapOfShIdNb[ *idIt ] = 0; + theShapesId[ mapOfShIdNb.size() - 1 ] = *idIt; + + SMESHDS_SubMesh* smDS = sm->GetSubMeshDS(); + if ( !smDS ) continue; + + if ( theDimension == SMESH::DIM_2D ) + { + SMDS_ElemIteratorPtr faceIt = smDS->GetElements(); + while ( faceIt->more() ) + { + const SMDS_MeshElement* face = faceIt->next(); + int aNbNode = face->NbNodes(); + if ( aNbNode > 4 ) + aNbNode /= 2; // do not take into account additional middle nodes + + SMDS_MeshNode* node1 = (SMDS_MeshNode*)face->GetNode( 0 ); + for ( int nIndx = 0; nIndx < aNbNode; nIndx++ ) + { + SMDS_MeshNode* node2 = (SMDS_MeshNode*)face->GetNode( nIndx+1 < aNbNode ? nIndx+1 : 0 ); + if ( setOfEdge.insert( SMESH_TLink ( node1, node2 ) ).second ) + { + listOfElemType.push_back( SMDSAbs_Edge ); + connectivity.push_back + ( mapNode2LocalID.insert( make_pair( node1, ++nbConnNodes)).first ); + connectivity.push_back + ( mapNode2LocalID.insert( make_pair( node2, ++nbConnNodes)).first ); + } + node1 = node2; + } + } + } + else if ( theDimension == SMESH::DIM_1D ) + { + SMDS_NodeIteratorPtr nodeIt = smDS->GetNodes(); + while ( nodeIt->more() ) + { + listOfElemType.push_back( SMDSAbs_Node ); + connectivity.push_back + ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first ); + } + // add corner nodes by first vertex from edge + SMESH_subMeshIteratorPtr edgeSmIt = + sm->getDependsOnIterator(/*includeSelf*/false, + /*complexShapeFirst*/false); + while ( edgeSmIt->more() ) + { + SMESH_subMesh* vertexSM = edgeSmIt->next(); + // check that vertex is not already treated + if ( !setOfVSubMesh.insert( vertexSM ).second ) + continue; + if ( vertexSM->GetSubShape().ShapeType() != TopAbs_VERTEX ) + continue; + + const SMESHDS_SubMesh* vertexSmDS = vertexSM->GetSubMeshDS(); + SMDS_NodeIteratorPtr nodeIt = vertexSmDS->GetNodes(); + while ( nodeIt->more() ) + { + listOfElemType.push_back( SMDSAbs_Node ); + connectivity.push_back + ( mapNode2LocalID.insert( make_pair( nodeIt->next(), ++nbConnNodes)).first ); + } + } + } + } + + // fill node coords and assign local ids to the nodes + int nbNodes = mapNode2LocalID.size(); + result->nodesXYZ.length( nbNodes ); + TNodeLocalID node2ID = mapNode2LocalID.begin(); + for ( i = 0; i < nbNodes; ++i, ++node2ID ) { + node2ID->second = i; + const SMDS_MeshNode* node = (const SMDS_MeshNode*) node2ID->first; + result->nodesXYZ[i].x = node->X(); + result->nodesXYZ[i].y = node->Y(); + result->nodesXYZ[i].z = node->Z(); + } + // fill connectivity + result->elementConnectivities.length( nbConnNodes ); + list< TNodeLocalID >::iterator connIt = connectivity.begin(); + for ( i = 0; i < nbConnNodes; ++i, ++connIt ) { + result->elementConnectivities[i] = (*connIt)->second; + } + + // fill element types + result->elementTypes.length( listOfElemType.size() ); + std::list< SMDSAbs_ElementType >::const_iterator typeIt = listOfElemType.begin(); + std::list< SMDSAbs_ElementType >::const_iterator typeEnd = listOfElemType.end(); + for ( i = 0; typeIt != typeEnd; ++i, ++typeIt ) + { + SMDSAbs_ElementType elemType = *typeIt; + result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType)elemType; + result->elementTypes[i].isPoly = false; + result->elementTypes[i].nbNodesInElement = elemType == SMDSAbs_Edge ? 2 : 1; + } + + // correct number of shapes + theShapesId.length( mapOfShIdNb.size() ); + } + } + } + catch ( std::bad_alloc ) { + INFOS( "Precompute(): lack of memory" ); + } + catch ( SALOME_Exception& S_ex ) { + INFOS( "Precompute(): catch exception "<< S_ex.what() ); + } + catch ( ... ) { + INFOS( "Precompute(): unknown exception " ); + } + return result._retn(); +} + + +//============================================================================= +/*! + * SMESH_Gen_i::Evaluate + * + * Evaluate mesh on a shape + */ +//============================================================================= + +SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theShapeObject) +// SMESH::long_array& theNbElems) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Evaluate" ); + + if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh()) + THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", + SALOME::BAD_PARAM ); + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", + SALOME::BAD_PARAM ); + + SMESH::long_array_var nbels = new SMESH::long_array; + nbels->length(SMESH::Entity_Last); + int i = SMESH::Entity_Node; + for (; i < SMESH::Entity_Last; i++) + nbels[i] = 0; + + // Update Python script + TPythonDump() << "theNbElems = " << this << ".Evaluate( " + << theMesh << ", " << theShapeObject << ")"; + + try { + // get mesh servant + SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() ); + ASSERT( meshServant ); + if ( meshServant ) { + meshServant->Load(); + // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation" + meshServant->CheckGeomModif(); + // get local TopoDS_Shape + TopoDS_Shape myLocShape; + if(theMesh->HasShapeToMesh()) + myLocShape = GeomObjectToShape( theShapeObject ); + else + myLocShape = SMESH_Mesh::PseudoShape(); + // call implementation compute + ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); + MapShapeNbElems aResMap; + /*CORBA::Boolean ret =*/ myGen.Evaluate( myLocMesh, myLocShape, aResMap); + MapShapeNbElemsItr anIt = aResMap.begin(); + for(; anIt!=aResMap.end(); anIt++) { + const vector& aVec = (*anIt).second; + for ( i = SMESH::Entity_Node; i < (int)aVec.size(); i++ ) { + int nbElem = aVec[i]; + if ( nbElem < 0 ) // algo failed, check that it has reported a message + { + SMESH_subMesh* sm = anIt->first; + SMESH_ComputeErrorPtr& error = sm->GetComputeError(); + const SMESH_Algo* algo = sm->GetAlgo(); + if ( (algo && !error.get()) || error->IsOK() ) + error.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED,"Failed to evaluate",algo)); + } + else + { + nbels[i] += aVec[i]; + } + } + } + return nbels._retn(); + } + } + catch ( std::bad_alloc ) { + INFOS( "Evaluate(): lack of memory" ); + } + catch ( SALOME_Exception& S_ex ) { + INFOS( "Evaluate(): catch exception "<< S_ex.what() ); + } + catch ( ... ) { + INFOS( "Evaluate(): unknown exception " ); + } + + return nbels._retn(); +} + +//================================================================================ +/*! + * \brief Return geometrical object the given element is built on + * \param theMesh - the mesh the element is in + * \param theElementID - the element ID + * \param theGeomName - the name of the result geom object if it is not yet published + * \retval GEOM::GEOM_Object_ptr - the found or just published geom object (no need to UnRegister()) + */ +//================================================================================ + +GEOM::GEOM_Object_ptr +SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr theMesh, + CORBA::Long theElementID, + const char* theGeomName) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + + GEOM::GEOM_Object_wrap geom = FindGeometryByMeshElement(theMesh, theElementID); + if ( !geom->_is_nil() ) { + GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh(); + GEOM::GEOM_Gen_var geomGen = GetGeomEngine( geom ); + + // try to find the corresponding SObject + SALOMEDS::SObject_wrap SObj = ObjectToSObject( geom.in() ); + if ( SObj->_is_nil() ) // submesh can be not found even if published + { + // try to find published submesh + GEOM::ListOfLong_var list = geom->GetSubShapeIndices(); + if ( !geom->IsMainShape() && list->length() == 1 ) { + SALOMEDS::SObject_wrap mainSO = ObjectToSObject( mainShape ); + SALOMEDS::ChildIterator_wrap it; + if ( !mainSO->_is_nil() ) { + it = getStudyServant()->NewChildIterator( mainSO ); + } + if ( !it->_is_nil() ) { + for ( it->InitEx(true); it->More(); it->Next() ) { + SALOMEDS::SObject_wrap so = it->Value(); + CORBA::Object_var obj = SObjectToObject( so ); + GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj ); + if ( !subGeom->_is_nil() ) { + GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices(); + if ( subList->length() == 1 && list[0] == subList[0] ) { + SObj = so; + geom = subGeom; + break; + } + } + } + } + } + } + if ( SObj->_is_nil() && !geomGen->_is_nil() ) // publish a new subshape + SObj = geomGen->AddInStudy( geom, theGeomName, mainShape ); + + // return only published geometry + if ( !SObj->_is_nil() ) { + //return geom._retn(); -- servant of geom must be UnRegister()ed; + CORBA::Object_var obj = SObjectToObject( SObj ); + GEOM::GEOM_Object_var go = GEOM::GEOM_Object::_narrow( obj ); + return go._retn(); + } + } + return GEOM::GEOM_Object::_nil(); +} + +//================================================================================ +/*! + * \brief Return geometrical object the given element is built on. + * \param theMesh - the mesh the element is in + * \param theElementID - the element ID + * \retval GEOM::GEOM_Object_ptr - the found or created (UnRegister()!) geom object + */ +//================================================================================ + +GEOM::GEOM_Object_ptr +SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr theMesh, + CORBA::Long theElementID) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM ); + + GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh(); + GEOM::GEOM_Gen_var geomGen = GetGeomEngine( mainShape ); + + // get a core mesh DS + SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh ); + if ( meshServant && !geomGen->_is_nil() && !mainShape->_is_nil() ) + { + ::SMESH_Mesh & mesh = meshServant->GetImpl(); + SMESHDS_Mesh* meshDS = mesh.GetMeshDS(); + // find the element in mesh + if ( const SMDS_MeshElement * elem = meshDS->FindElement( theElementID ) ) { + // find a shape id by the element + if ( int shapeID = ::SMESH_MeshEditor( &mesh ).FindShape( elem )) { + // get a geom object by the shape id + GEOM::GEOM_Object_var geom = ShapeToGeomObject( meshDS->IndexToShape( shapeID )); + if ( geom->_is_nil() ) { + // try to find a published sub-shape + SALOMEDS::SObject_wrap mainSO = ObjectToSObject( mainShape ); + SALOMEDS::ChildIterator_wrap it; + if ( !mainSO->_is_nil() ) { + it = getStudyServant()->NewChildIterator( mainSO ); + } + if ( !it->_is_nil() ) { + for ( it->InitEx(true); it->More(); it->Next() ) { + SALOMEDS::SObject_wrap so = it->Value(); + CORBA::Object_var obj = SObjectToObject( so ); + GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj ); + if ( !subGeom->_is_nil() ) { + GEOM::ListOfLong_var subList = subGeom->GetSubShapeIndices(); + if ( subList->length() == 1 && shapeID == subList[0] ) { + geom = subGeom; + break; + } + } + } + } + } + if ( geom->_is_nil() ) { + // explode + GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations(); + if ( !op->_is_nil() ) + geom = op->GetSubShape( mainShape, shapeID ); + } + else { + geom->Register(); + } + if ( !geom->_is_nil() ) { + GeomObjectToShape( geom ); // let geom client remember the found shape + return geom._retn(); + } + } + } + } + return GEOM::GEOM_Object::_nil(); +} + +//================================================================================ +/*! + * SMESH_Gen_i::Concatenate + * + * Concatenate the given meshes into one mesh + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr +SMESH_Gen_i::Concatenate(const SMESH::ListOfIDSources& theMeshesArray, + CORBA::Boolean theUniteIdenticalGroups, + CORBA::Boolean theMergeNodesAndElements, + CORBA::Double theMergeTolerance, + SMESH::SMESH_Mesh_ptr theMeshToAppendTo) + throw ( SALOME::SALOME_Exception ) +{ + return ConcatenateCommon(theMeshesArray, + theUniteIdenticalGroups, + theMergeNodesAndElements, + theMergeTolerance, + false, + theMeshToAppendTo); +} + +//================================================================================ +/*! + * SMESH_Gen_i::ConcatenateWithGroups + * + * Concatenate the given meshes into one mesh + * Create the groups of all elements from initial meshes + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr +SMESH_Gen_i::ConcatenateWithGroups(const SMESH::ListOfIDSources& theMeshesArray, + CORBA::Boolean theUniteIdenticalGroups, + CORBA::Boolean theMergeNodesAndElements, + CORBA::Double theMergeTolerance, + SMESH::SMESH_Mesh_ptr theMeshToAppendTo) + throw ( SALOME::SALOME_Exception ) +{ + return ConcatenateCommon(theMeshesArray, + theUniteIdenticalGroups, + theMergeNodesAndElements, + theMergeTolerance, + true, + theMeshToAppendTo); +} + +//================================================================================ +/*! + * SMESH_Gen_i::ConcatenateCommon + * + * Concatenate the given meshes into one mesh + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr +SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray, + CORBA::Boolean theUniteIdenticalGroups, + CORBA::Boolean theMergeNodesAndElements, + CORBA::Double theMergeTolerance, + CORBA::Boolean theCommonGroups, + SMESH::SMESH_Mesh_ptr theMeshToAppendTo) + throw ( SALOME::SALOME_Exception ) +{ + std::unique_ptr< TPythonDump > pPythonDump( new TPythonDump ); + TPythonDump& pythonDump = *pPythonDump; // prevent dump of called methods + + // create mesh if theMeshToAppendTo not provided + SMESH::SMESH_Mesh_var newMesh; + if ( CORBA::is_nil( theMeshToAppendTo )) + newMesh = CreateEmptyMesh(); + else + newMesh = SMESH::SMESH_Mesh::_duplicate( theMeshToAppendTo ); + SMESH_Mesh_i* newImpl = SMESH::DownCast( newMesh ); + if ( !newImpl ) return newMesh._retn(); + newImpl->Load(); + + ::SMESH_Mesh& locMesh = newImpl->GetImpl(); + SMESHDS_Mesh* newMeshDS = locMesh.GetMeshDS(); + + typedef std::list TListOfNewGroups; + typedef std::pair TNameAndType; + typedef std::map< TNameAndType, TListOfNewGroups > TGroupsMap; + TGroupsMap groupsMap; + TListOfNewGroups listOfNewGroups; + + if ( !CORBA::is_nil( theMeshToAppendTo )) + { + // fill groupsMap with existing groups + SMESH::ListOfGroups_var groups = theMeshToAppendTo->GetGroups(); + for ( CORBA::ULong i = 0; i < groups->length(); ++i ) + { + SMESH::SMESH_Group_var group = SMESH::SMESH_Group::_narrow( groups[ i ]); + if ( !group->_is_nil() ) + { + CORBA::String_var name = group->GetName(); + SMESH::ElementType type = group->GetType(); + groupsMap[ TNameAndType( name.in(), type ) ].push_back( group ); + } + } + } + + ::SMESH_MeshEditor newEditor( &locMesh ); + ::SMESH_MeshEditor::ElemFeatures elemType; + + // loop on sub-meshes + for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++ ) + { + if ( CORBA::is_nil( theMeshesArray[i] )) continue; + SMESH::SMESH_Mesh_var initMesh = theMeshesArray[i]->GetMesh(); + SMESH_Mesh_i* initImpl = SMESH::DownCast( initMesh ); + if ( !initImpl ) continue; + if ( initMesh->_is_equivalent( theMeshToAppendTo )) + continue; + initImpl->Load(); + + // assure that IDs increment by one during iteration + ::SMESH_Mesh& initLocMesh = initImpl->GetImpl(); + SMESHDS_Mesh* initMeshDS = initLocMesh.GetMeshDS(); + if ( initMeshDS->MaxNodeID() > initMeshDS->NbNodes() || + initMeshDS->MaxElementID() > initMeshDS->NbElements() ) + { + initMeshDS->Modified(); + initMeshDS->CompactMesh(); + } + + // remember nb of elements before filling in + SMESH::long_array_var prevState = newMesh->GetNbElementsByType(); + + // copy nodes + + std::vector< const SMDS_MeshElement* > newNodes( initMeshDS->NbNodes() + 1, 0 ); + SMDS_ElemIteratorPtr elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::NODE ); + while ( elemIt->more() ) + { + SMESH_NodeXYZ node = elemIt->next(); + newNodes[ node->GetID() ] = newMeshDS->AddNode( node.X(), node.Y(), node.Z() ); + } + + // 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() ) + { + const SMDS_MeshElement* elem = elemIt->next(); + elemType.myNodes.resize( elem->NbNodes() ); + + 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 + + + // create groups of just added elements + SMESH::SMESH_Group_var newGroup; + SMESH::ElementType groupType; + if ( theCommonGroups ) + { + // type names + const char* typeNames[] = { "All","Nodes","Edges","Faces","Volumes","0DElems","Balls" }; + { // check of typeNames: compilation failure mains that NB_ELEMENT_TYPES changed: + const int nbNames = sizeof(typeNames) / sizeof(const char*); + int _assert[( nbNames == SMESH::NB_ELEMENT_TYPES ) ? 2 : -1 ]; _assert[0]=_assert[1]=0; + } + + SMESH::long_array_var curState = newMesh->GetNbElementsByType(); + + for( groupType = SMESH::NODE; + groupType < SMESH::NB_ELEMENT_TYPES; + groupType = (SMESH::ElementType)( groupType + 1 )) + { + if ( curState[ groupType ] <= prevState[ groupType ]) + continue; // no elements of groupType added from the i-th mesh + + // make a group name + std::string groupName = "Gr"; + SALOMEDS::SObject_wrap meshSO = ObjectToSObject( theMeshesArray[i] ); + if ( meshSO ) { + CORBA::String_var name = meshSO->GetName(); + groupName += name; + } + groupName += "_"; + groupName += typeNames[ groupType ]; + + // make and fill a group + newGroup = newImpl->CreateGroup( groupType, groupName.c_str() ); + std::vector< const SMDS_MeshElement* > & elemVec = + ( groupType == SMESH::NODE ) ? newNodes : newElems; + if ( SMESH_Group_i* grp_i = SMESH::DownCast( newGroup )) + { + if ( SMESHDS_Group* grpDS = dynamic_cast( grp_i->GetGroupDS() )) + { + for ( size_t j = 0; j < elemVec.size(); ++j ) + { + if ( elemVec[j] && elemVec[j]->GetType() == grpDS->GetType() ) + grpDS->Add( elemVec[j] ); + } + } + } + listOfNewGroups.clear(); + listOfNewGroups.push_back( newGroup ); + groupsMap.insert( std::make_pair( TNameAndType( groupName, groupType ), + listOfNewGroups )); + } + } + + if ( SMESH_Mesh_i* initImpl = SMESH::DownCast( theMeshesArray[i] )) + { + // copy groups + + SMESH::SMESH_GroupBase_ptr group; + CORBA::String_var groupName; + SMESH::long_array_var newIDs = new SMESH::long_array(); + + // loop on groups of a source mesh + SMESH::ListOfGroups_var listOfGroups = initImpl->GetGroups(); + for ( CORBA::ULong iG = 0; iG < listOfGroups->length(); iG++ ) + { + group = listOfGroups[iG]; + groupType = group->GetType(); + groupName = group->GetName(); + std::string name = groupName.in(); + + // convert a list of IDs + newIDs->length( group->Size() ); + std::vector< const SMDS_MeshElement* > & elemVec = + ( groupType == SMESH::NODE ) ? newNodes : newElems; + SMDS_ElemIteratorPtr itGrElems = initImpl->GetElements( group, SMESH::ALL ); + int nbElems = 0; + while ( itGrElems->more() ) + { + const SMDS_MeshElement* elem = itGrElems->next(); + const SMDS_MeshElement* newElem = elemVec[ elem->GetID() ]; + if ( newElem ) + newIDs[ nbElems++ ] = newElem->GetID(); + } + newIDs->length( nbElems ); + + // check that a current group name and type don't have identical ones in final mesh + listOfNewGroups.clear(); + TNameAndType nameAndType( name, groupType ); + TGroupsMap::iterator anIter = groupsMap.find( nameAndType ); + if ( anIter == groupsMap.end() ) + { + // add a new group in the mesh + newGroup = newImpl->CreateGroup( groupType, groupName.in() ); + newGroup->Add( newIDs ); + + listOfNewGroups.push_back( newGroup ); + groupsMap.insert( std::make_pair( nameAndType, listOfNewGroups )); + } + else if ( theUniteIdenticalGroups ) + { + // unite identical groups + TListOfNewGroups& aNewGroups = anIter->second; + aNewGroups.front()->Add( newIDs ); + } + else + { + // rename identical groups + newGroup = newImpl->CreateGroup( groupType, groupName ); + newGroup->Add( newIDs ); + + TListOfNewGroups& newGroups = anIter->second; + std::string newGroupName; + if ( newGroups.size() == 1 ) + { + newGroupName = name + "_1"; + newGroups.front()->SetName( newGroupName.c_str() ); + } + newGroupName = name + "_" + SMESH_Comment( newGroups.size() + 1 ); + newGroup->SetName( newGroupName.c_str() ); + newGroups.push_back( newGroup ); + } + } // loop on groups + } // if an IDSource is a mesh + } //meshes loop + + if ( theMergeNodesAndElements ) // merge nodes + { + TIDSortedNodeSet meshNodes; // no input nodes == treat all + SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes; + newEditor.FindCoincidentNodes( meshNodes, theMergeTolerance, groupsOfNodes, + /*SeparateCornersAndMedium=*/ false ); + newEditor.MergeNodes( groupsOfNodes ); + // merge elements + newEditor.MergeEqualElements(); + } + + // Update Python script + pythonDump << newMesh << " = " << this + << "." << ( theCommonGroups ? "ConcatenateWithGroups" : "Concatenate" ) << "( " + << theMeshesArray << ", " + << theUniteIdenticalGroups << ", " + << theMergeNodesAndElements << ", " + << TVar( theMergeTolerance ) << ", " + << theMeshToAppendTo << " )"; + + pPythonDump.reset(); // enable python dump from GetGroups() + + // 0020577: EDF 1164 SMESH: Bad dump of concatenate with create common groups + if ( !newMesh->_is_nil() ) + { + SMESH::ListOfGroups_var groups = newMesh->GetGroups(); + } + + // IPAL21468 Change icon of compound because it need not be computed. + SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh ); + SetPixMap( meshSO, "ICON_SMESH_TREE_MESH" ); + + newMeshDS->Modified(); + + return newMesh._retn(); +} + +//================================================================================ +/*! + * \brief Create a mesh by copying a part of another mesh + * \param meshPart - a part of mesh to copy + * \param toCopyGroups - to create in the new mesh groups + * the copied elements belongs to + * \param toKeepIDs - to preserve IDs of the copied elements or not + * \retval SMESH::SMESH_Mesh_ptr - the new mesh + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, + const char* meshName, + CORBA::Boolean toCopyGroups, + CORBA::Boolean toKeepIDs) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + + TPythonDump* pyDump = new TPythonDump; // prevent dump from CreateMesh() + std::unique_ptr pyDumpDeleter( pyDump ); + + // 1. Get source mesh + + if ( CORBA::is_nil( meshPart )) + THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM ); + + SMESH::SMESH_Mesh_var srcMesh = meshPart->GetMesh(); + SMESH_Mesh_i* srcMesh_i = SMESH::DownCast( srcMesh ); + if ( !srcMesh_i ) + THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM ); + + SMESHDS_Mesh* srcMeshDS = srcMesh_i->GetImpl().GetMeshDS(); + + // 2. Make a new mesh + + SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil()); + SMESH_Mesh_i* newMesh_i = SMESH::DownCast( 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, "Mesh" ); + SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); + } + SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); + ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() ); + ::SMESH_MeshEditor::ElemFeatures elemType; + + // 3. Get elements to copy + + SMDS_ElemIteratorPtr srcElemIt; SMDS_NodeIteratorPtr srcNodeIt; + TIDSortedElemSet srcElems; + SMESH::array_of_ElementType_var srcElemTypes = meshPart->GetTypes(); + if ( SMESH::DownCast( meshPart )) + { + srcMesh_i->Load(); + srcElemIt = srcMeshDS->elementsIterator(); + srcNodeIt = srcMeshDS->nodesIterator(); + } + else + { + SMESH::long_array_var ids = meshPart->GetIDs(); + if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes + { + for ( CORBA::ULong i=0; i < ids->length(); i++ ) + if ( const SMDS_MeshElement * elem = srcMeshDS->FindNode( ids[i] )) + srcElems.insert( elem ); + } + else + { + for ( CORBA::ULong i = 0; i < ids->length(); i++ ) + if ( const SMDS_MeshElement * elem = srcMeshDS->FindElement( ids[i] )) + srcElems.insert( elem ); + } + if ( srcElems.empty() ) + return newMesh._retn(); + + typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator > ElIter; + srcElemIt = SMDS_ElemIteratorPtr( new ElIter( srcElems.begin(), srcElems.end() )); + } + + // 4. Copy elements + + typedef map TE2EMap; + TE2EMap e2eMapByType[ SMDSAbs_NbElementTypes ]; + TE2EMap& n2nMap = e2eMapByType[ SMDSAbs_Node ]; + int iN; + const SMDS_MeshNode *nSrc, *nTgt; + vector< const SMDS_MeshNode* > nodes; + while ( srcElemIt->more() ) + { + const SMDS_MeshElement * elem = srcElemIt->next(); + // find / add nodes + nodes.resize( elem->NbNodes()); + SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); + if ( toKeepIDs ) { + for ( iN = 0; nIt->more(); ++iN ) + { + nSrc = static_cast( nIt->next() ); + nTgt = newMeshDS->FindNode( nSrc->GetID()); + if ( !nTgt ) + nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID()); + nodes[ iN ] = nTgt; + } + } + else { + for ( iN = 0; nIt->more(); ++iN ) + { + nSrc = static_cast( nIt->next() ); + TE2EMap::iterator n2n = n2nMap.insert( make_pair( nSrc, SMDS_pNode(0) )).first; + if ( !n2n->second ) + n2n->second = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() ); + nodes[ iN ] = (const SMDS_MeshNode*) n2n->second; + } + } + // add elements + if ( elem->GetType() != SMDSAbs_Node ) + { + elemType.Init( elem, /*basicOnly=*/false ); + if ( toKeepIDs ) elemType.SetID( elem->GetID() ); + + const SMDS_MeshElement * newElem = editor.AddElement( nodes, elemType ); + if ( toCopyGroups && !toKeepIDs ) + e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem )); + } + } // while ( srcElemIt->more() ) + + // 4(b). Copy free nodes + + if ( srcNodeIt && srcMeshDS->NbNodes() != newMeshDS->NbNodes() ) + { + while ( srcNodeIt->more() ) + { + nSrc = srcNodeIt->next(); + if ( nSrc->NbInverseElements() == 0 ) + { + if ( toKeepIDs ) + nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID()); + else + n2nMap[ nSrc ] = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() ); + } + } + } + + // 5. Copy groups + + int nbNewGroups = 0; + if ( toCopyGroups ) + { + SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups(); + while ( gIt->more() ) + { + SMESH_Group* group = gIt->next(); + const SMESHDS_GroupBase* groupDS = group->GetGroupDS(); + + // Check group type. We copy nodal groups containing nodes of copied element + SMDSAbs_ElementType groupType = groupDS->GetType(); + if ( groupType != SMDSAbs_Node && + newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 ) + continue; // group type differs from types of meshPart + + // Find copied elements in the group + vector< const SMDS_MeshElement* > groupElems; + SMDS_ElemIteratorPtr eIt = groupDS->GetElements(); + if ( toKeepIDs ) + { + const SMDS_MeshElement* foundElem; + if ( groupType == SMDSAbs_Node ) + { + while ( eIt->more() ) + if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() ))) + groupElems.push_back( foundElem ); + } + else + { + while ( eIt->more() ) + if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() ))) + groupElems.push_back( foundElem ); + } + } + else + { + TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ]; + if ( e2eMap.empty() ) continue; + int minID = e2eMap.begin()->first->GetID(); + int maxID = e2eMap.rbegin()->first->GetID(); + TE2EMap::iterator e2e; + while ( eIt->more() && groupElems.size() < e2eMap.size()) + { + const SMDS_MeshElement* e = eIt->next(); + if ( e->GetID() < minID || e->GetID() > maxID ) continue; + if ((e2e = e2eMap.find( e )) != e2eMap.end()) + groupElems.push_back( e2e->second ); + } + } + // Make a new group + if ( !groupElems.empty() ) + { + SMESH::SMESH_Group_var newGroupObj = + newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() ); + if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast( newGroupObj)) + { + SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS(); + SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup(); + for ( unsigned i = 0; i < groupElems.size(); ++i ) + smdsGroup.Add( groupElems[i] ); + + nbNewGroups++; + } + } + } + } + + newMeshDS->Modified(); + + *pyDump << newMesh << " = " << this + << ".CopyMesh( " << meshPart << ", " + << "'" << meshName << "', " + << toCopyGroups << ", " + << toKeepIDs << ")"; + + pyDumpDeleter.reset(); // allow dump in GetGroups() + + if ( nbNewGroups > 0 ) // dump created groups + SMESH::ListOfGroups_var groups = newMesh->GetGroups(); + + return newMesh._retn(); +} + + +namespace // utils for CopyMeshWithGeom() +{ + typedef std::map< std::string, std::string > TStr2StrMap; + typedef std::map< std::string, std::set< std::string > > TStr2StrSetMap; + typedef std::map< std::set, int > TIdSet2IndexMap; + typedef std::map< std::string, int > TName2IndexMap; + + //================================================================================ + /*! + * \brief Return a new sub-shape corresponding to an old one + */ + //================================================================================ + + struct ShapeMapper + { + SMESH_Mesh_i* mySrcMesh_i; + SMESH_Mesh_i* myNewMesh_i; + SMESH_Gen_i* myGen_i; + bool myToPublish; + bool myIsSameGeom; + + TStr2StrMap myOld2NewEntryMap; // map of study entries + + GEOM::ListOfGO_var mySubshapes; // sub-shapes existing in the new geometry + TIdSet2IndexMap myIds2SubshapeIndex; // to find an existing sub-shape + TName2IndexMap myName2SubshapeIndex; // to find an existing sub-shape by name + + bool myGIPMapDone; + GEOM::ListOfListOfLong_var myGIPMap; // filled by GetInPlaceMap() + + // not directly relating to shape search + TStr2StrSetMap myInvalidMap; // blame shape -> invalid objects + + //================================================================================ + /*! + * \brief Constructor + */ + ShapeMapper( SMESH_Mesh_i* srcMesh_i, + SMESH_Mesh_i* newMesh_i, + SMESH_Gen_i* smeshGen_i ) + : mySrcMesh_i( srcMesh_i ), + myNewMesh_i( newMesh_i ), + myGen_i ( smeshGen_i ), + myToPublish( smeshGen_i->IsEnablePublish() ), + myGIPMapDone( false ) + { + // retrieve from the study shape mapping made thanks to + // "Set presentation parameters and sub-shapes from arguments" option + + GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh(); + GEOM::GEOM_Object_var mainShapeOld = mySrcMesh_i->GetShapeToMesh(); + SALOMEDS::SObject_wrap oldSO = myGen_i->ObjectToSObject( mainShapeOld ); + SALOMEDS::SObject_wrap newSO = myGen_i->ObjectToSObject( mainShapeNew ); + if ( newSO->_is_nil() ) + { + myToPublish = false; + return; + } + if (( myIsSameGeom = mainShapeNew->_is_equivalent( mainShapeOld ))) + return; + CORBA::String_var oldEntry = oldSO->GetID(); + CORBA::String_var newEntry = newSO->GetID(); + myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ), + std::string( newEntry.in() ))); + std::string newMainEntry = newEntry.in(); + + SALOMEDS::Study_var study = myGen_i->getStudyServant(); + GEOM::GEOM_Gen_var geomGen = myGen_i->GetGeomEngine( mainShapeNew ); + GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations(); + mySubshapes = op->GetExistingSubObjects( mainShapeNew, + /*groupsOnly=*/false ); + for ( CORBA::ULong i = 0; i < mySubshapes->length(); ++i ) + { + newSO = myGen_i->ObjectToSObject( mySubshapes[ i ]); + SALOMEDS::ChildIterator_wrap anIter = study->NewChildIterator( newSO ); + bool refFound = false; + for ( ; anIter->More(); anIter->Next() ) + { + SALOMEDS::SObject_wrap so = anIter->Value(); + if ( so->ReferencedObject( oldSO.inout() )) + { + oldEntry = oldSO->GetID(); + newEntry = newSO->GetID(); + if (( refFound = ( newMainEntry != oldEntry.in() ))) + myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ), + std::string( newEntry.in() ))); + } + } + if ( !refFound ) + { + GEOM::GEOM_Object_var father = mySubshapes[ i ]->GetMainShape(); + if ( father->_is_equivalent( mainShapeNew )) + { + GEOM::ListOfLong_var ids = mySubshapes[ i ]->GetSubShapeIndices(); + std::set< int > idSet( &ids[0] , &ids[0] + ids->length() ); + myIds2SubshapeIndex.insert( std::make_pair( idSet, i )); + CORBA::String_var name = newSO->GetName(); + if ( name.in()[0] ) + myName2SubshapeIndex.insert( std::make_pair( name.in(), i )); + } + } + } + } + + //================================================================================ + /*! + * \brief Find a new sub-shape corresponding to an old one + */ + GEOM::GEOM_Object_ptr FindNew( GEOM::GEOM_Object_ptr oldShape ) + { + if ( myIsSameGeom ) + return GEOM::GEOM_Object::_duplicate( oldShape ); + + GEOM::GEOM_Object_var newShape; + + if ( CORBA::is_nil( oldShape )) + return newShape._retn(); + + if ( !isChildOfOld( oldShape )) + return GEOM::GEOM_Object::_duplicate( oldShape ); // shape independent of the old shape + + GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh(); + GEOM::GEOM_Gen_var geomGen = myGen_i->GetGeomEngine( mainShapeNew ); + + // try to find by entry or name + if ( myToPublish ) + { + CORBA::String_var oldEntry = oldShape->GetStudyEntry(); + TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry.in() ); + if ( o2nID != myOld2NewEntryMap.end() ) + { + newShape = getShapeByEntry( o2nID->second ); + } + if ( newShape->_is_nil() ) + { + CORBA::String_var name = oldShape->GetName(); + TName2IndexMap::iterator n2ind = myName2SubshapeIndex.find( name.in() ); + if ( n2ind != myName2SubshapeIndex.end() ) + { + newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ n2ind->second ]); + GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices(); + GEOM::ListOfLong_var newIndices = newShape->GetSubShapeIndices(); + if ( oldIndices->length() == 0 || + newIndices->length() == 0 || + getShapeType( myNewMesh_i, newIndices[0] ) != + getShapeType( mySrcMesh_i, oldIndices[0] )) + newShape = GEOM::GEOM_Object::_nil(); + } + } + } + + if ( newShape->_is_nil() ) + { + // try to construct a new sub-shape using myGIPMap + buildGIPMap(); + std::vector< int > newIndices; + GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices(); + for ( CORBA::ULong i = 0; i < oldIndices->length(); ++i ) + { + findNewIDs( oldIndices[i], newIndices ); + } + if ( newIndices.size() < oldIndices->length() ) // issue #17096 + { + newIndices.clear(); + newShape = getInPlace( oldShape ); + } + if ( !newIndices.empty() && newShape->_is_nil() ) + { + // search for a sub-shape with same ids + std::set< int > idSet( newIndices.begin(), newIndices.end() ); + TIdSet2IndexMap::iterator ids2ind = myIds2SubshapeIndex.find( idSet ); + if ( ids2ind != myIds2SubshapeIndex.end() ) { + newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ ids2ind->second ]); + } + if ( newShape->_is_nil() ) + try + { + // create a new shape + if ( newIndices.size() > 1 || oldShape->GetType() == GEOM_GROUP ) + { + int groupType = getShapeType( myNewMesh_i, newIndices[0] ); + + GEOM::GEOM_IGroupOperations_ptr grOp = geomGen->GetIGroupOperations(); + newShape = grOp->CreateGroup( mainShapeNew, groupType ); + + GEOM::ListOfLong_var newIndicesList = new GEOM::ListOfLong(); + newIndicesList->length( newIndices.size() ); + for ( size_t i = 0; i < newIndices.size(); ++i ) + newIndicesList[ i ] = newIndices[ i ]; + grOp->UnionIDs( newShape, newIndicesList ); + } + else + { + GEOM::GEOM_IShapesOperations_wrap shOp = geomGen->GetIShapesOperations(); + newShape = shOp->GetSubShape( mainShapeNew, newIndices[0] ); + } + } + catch (...) + { + } + } + } + + if ( !newShape->_is_nil() && myToPublish ) + { + CORBA::String_var oldEntry, newEntry = newShape->GetStudyEntry(); + if ( !newEntry.in() || !newEntry.in()[0] ) + { + CORBA::String_var name = oldShape->GetName(); + SALOMEDS::SObject_wrap so = geomGen->AddInStudy( newShape, name, mainShapeNew ); + newEntry = newShape->GetStudyEntry(); + oldEntry = oldShape->GetStudyEntry(); + myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ), + std::string( newEntry.in() ))); + } + } + + return newShape._retn(); + } + + //================================================================================ + /*! + * \brief Return a study entry of a new shape by study entry of the old one + */ + std::string FindNew( const std::string & oldEntry ) + { + if ( myIsSameGeom ) + return oldEntry; + + TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry ); + if ( o2nID != myOld2NewEntryMap.end() ) + return o2nID->second; + + GEOM::GEOM_Object_var oldShape = getShapeByEntry( oldEntry ); + if ( oldShape->_is_nil() || !isChildOfOld( oldShape )) + return oldEntry; + + GEOM::GEOM_Object_ptr newShape = FindNew( oldShape ); + if ( newShape->_is_nil() ) + return std::string(); + + CORBA::String_var newEntry = newShape->GetStudyEntry(); + return newEntry.in(); + } + + //================================================================================ + /*! + * \brief Return a sub-shape ID of a new shape by a sub-shape ID of the old one. + * Return zero if not found or there are more than one new ID + */ + int FindNew( int oldID ) + { + if ( myIsSameGeom ) + return oldID; + + buildGIPMap(); + + int newID = 0; + + if ( 0 < oldID && oldID < (int)myGIPMap->length() ) + { + if ( myGIPMap[ oldID ].length() == 1 ) + { + newID = myGIPMap[ oldID ][ 0 ]; + } + else if ( myGIPMap[ oldID ].length() > 1 && + getShapeType( mySrcMesh_i, oldID ) == TopAbs_VERTEX ) + { + // select a meshed VERTEX + SMESH_subMesh* newSM; + for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length() && !newID; ++i ) + if (( newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( myGIPMap[ oldID ][ i ] )) && + ( !newSM->IsEmpty() )) + newID = myGIPMap[ oldID ][ i ]; + } + } + return newID; + } + + //================================================================================ + /*! + * \brief Return a sub-shape ID of a new shape by an old sub-mesh. + * Return zero if the old shape is not kept as is in the new shape. + */ + int FindNewNotChanged( SMESH_subMesh* oldSM ) + { + if ( myIsSameGeom ) + return oldSM->GetId(); + + int newID = FindNew( oldSM->GetId() ); + if ( !newID ) + return 0; + + SMESH_subMesh* newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( newID ); + if ( !newSM ) + return 0; + + // consider a sub-shape as not changed if all its sub-shapes are mapped into + // one new sub-shape of the same type. + + if ( oldSM->DependsOn().size() != + newSM->DependsOn().size() ) + return 0; + + SMESH_subMeshIteratorPtr srcSMIt = oldSM->getDependsOnIterator( /*includeSelf=*/true ); + while ( srcSMIt->more() ) + { + oldSM = srcSMIt->next(); + int newSubID = FindNew( oldSM->GetId() ); + if ( getShapeType( myNewMesh_i, newSubID ) != + getShapeType( mySrcMesh_i, oldSM->GetId() )) + return 0; + } + return newID; + } + + //================================================================================ + /*! + * \brief Return shape by study entry + */ + GEOM::GEOM_Object_ptr getShapeByEntry( const std::string & entry ) + { + GEOM::GEOM_Object_var shape; + SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry.c_str() ); + if ( !so->_is_nil() ) + { + CORBA::Object_var obj = so->GetObject(); + shape = GEOM::GEOM_Object::_narrow( obj ); + } + return shape._retn(); + } + + //================================================================================ + /*! + * \brief Fill myGIPMap by calling GetInPlaceMap() + */ + void buildGIPMap() + { + if ( !myGIPMapDone ) + { + myGIPMapDone = true; + + GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh(); + GEOM::GEOM_Object_var mainShapeOld = mySrcMesh_i->GetShapeToMesh(); + GEOM::GEOM_Gen_var geomGen = myGen_i->GetGeomEngine( mainShapeNew ); + GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations(); + try + { + myGIPMap = op->GetInPlaceMap( mainShapeNew, mainShapeOld ); + } + catch( ... ) + { + myGIPMap = new GEOM::ListOfListOfLong(); + } + } + } + + //================================================================================ + /*! + * \brief Get new sub-shape by calling GetInPlace() + */ + GEOM::GEOM_Object_ptr getInPlace( GEOM::GEOM_Object_ptr oldShape ) + { + GEOM::GEOM_Object_var newShape; + + GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh(); + GEOM::GEOM_Gen_var geomGen = myGen_i->GetGeomEngine( mainShapeNew ); + GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations(); + try + { + newShape = op->GetInPlace( mainShapeNew, oldShape ); + } + catch( ... ) + { + } + return newShape._retn(); + } + + //================================================================================ + /*! + * \brief Find a new sub-shape indices by an old one in myGIPMap. Return + * number of found IDs + */ + int findNewIDs( int oldID, std::vector< int >& newIDs ) + { + size_t prevNbIDs = newIDs.size(); + + if ( 0 < oldID && oldID < (int) myGIPMap->length() ) + { + for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length(); ++i ) + newIDs.push_back( myGIPMap[ oldID ][ i ]); + } + return newIDs.size() - prevNbIDs; + } + + //================================================================================ + /*! + * \brief Check if an object relates to the old shape + */ + bool isChildOfOld( GEOM::GEOM_Object_ptr oldShape ) + { + if ( CORBA::is_nil( oldShape )) + return false; + GEOM::GEOM_Object_var mainShapeOld1 = mySrcMesh_i->GetShapeToMesh(); + GEOM::GEOM_Object_var mainShapeOld2 = oldShape->GetMainShape(); + return ( mainShapeOld1->_is_equivalent( mainShapeOld2 ) || + mainShapeOld1->_is_equivalent( oldShape )); + } + + //================================================================================ + /*! + * \brief Return shape type by shape ID + */ + TopAbs_ShapeEnum getShapeType( SMESH_Mesh_i* mesh_i, int shapeID ) + { + SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS(); + const TopoDS_Shape& shape = meshDS->IndexToShape( shapeID ); + return shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType(); + } + + //================================================================================ + /*! + * \brief Store a source sub-shape for which a counterpart not found and + * a smesh object invalid due to that + */ + void AddInvalid( GEOM::GEOM_Object_var srcShape, + SALOMEDS::SObject_wrap smeshSO ) + { + CORBA::String_var geomEntry = srcShape->GetStudyEntry(); + if ( geomEntry.in()[0] && !smeshSO->_is_nil() ) + { + CORBA::String_var smeshEntry = smeshSO->GetID(); + myInvalidMap[ geomEntry.in() ].insert( smeshEntry.in() ); + } + } + + //================================================================================ + /*! + * \brief Store a source sub-shape for which a counterpart not found and + * a smesh object invalid due to that + */ + void AddInvalid( std::string geomEntry, + SALOMEDS::SObject_wrap smeshSO ) + { + if ( !geomEntry.empty() ) + { + CORBA::String_var smeshEntry = smeshSO->GetID(); + myInvalidMap[ geomEntry ].insert( smeshEntry.in() ); + } + } + + //================================================================================ + /*! + * \brief Store a source sub-shape for which a counterpart not found and + * a smesh object invalid due to that + */ + void AddInvalid( int oldGeomID, + SALOMEDS::SObject_wrap smeshSO ) + { + int shapeType = getShapeType( mySrcMesh_i, oldGeomID ); + if ( shapeType < 0 || shapeType > TopAbs_SHAPE ) + return; + + const char* typeName[] = { "COMPOUND","COMPSOLID","SOLID","SHELL", + "FACE","WIRE","EDGE","VERTEX","SHAPE" }; + + SMESH_Comment geomName( typeName[ shapeType ]); + geomName << " #" << oldGeomID; + + CORBA::String_var smeshEntry = smeshSO->GetID(); + myInvalidMap[ geomName ].insert( smeshEntry.in() ); + } + + //================================================================================ + /*! + * \brief Return entries of a source sub-shape for which a counterpart not found and + * of smesh objects invalid due to that + */ + void GetInvalid( SMESH::string_array_out & theInvalidEntries, + std::vector< SALOMEDS::SObject_wrap > & theInvalidMeshSObjects) + { + int nbSO = 0; + TStr2StrSetMap::iterator entry2entrySet = myInvalidMap.begin(); + for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet ) + { + nbSO += 1 + entry2entrySet->second.size(); + } + int iSO = theInvalidMeshSObjects.size(), iEntry = 0; + theInvalidEntries->length ( nbSO ); + theInvalidMeshSObjects.resize( theInvalidMeshSObjects.size() + nbSO - myInvalidMap.size() ); + + entry2entrySet = myInvalidMap.begin(); + for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet ) + { + theInvalidEntries[ iEntry++ ] = entry2entrySet->first.c_str(); + + std::set< std::string > & entrySet = entry2entrySet->second; + std::set< std::string >::iterator entry = entrySet.begin(); + for ( ; entry != entrySet.end(); ++entry ) + { + theInvalidEntries[ iEntry++ ] = entry->c_str(); + + SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry->c_str() ); + if ( !so->_is_nil() ) + theInvalidMeshSObjects[ iSO++ ] = so; + } + } + } + + }; // struct ShapeMapper + + //================================================================================ + /*! + * \brief Append an item to a CORBA sequence + */ + template < class CORBA_seq, class ITEM > + void append( CORBA_seq& seq, ITEM item ) + { + if ( !CORBA::is_nil( item )) + { + seq->length( 1 + seq->length() ); + seq[ seq->length() - 1 ] = item; + } + } +} // namespace // utils for CopyMeshWithGeom() + +//================================================================================ +/*! + * \brief Create a mesh by copying definitions of another mesh to a given geometry + * \param [in] sourceMesh - a mesh to copy + * \param [in] newGeometry - a new geometry + * \param [in] toCopyGroups - to create groups in the new mesh + * \param [in] toReuseHypotheses - if True, existing hypothesis will be used by the new mesh, + * otherwise new hypotheses with the same parameters will be created for the new mesh. + * \param [in] toCopyElements - to copy mesh elements of same sub-shapes of the two geometries + * \param [out] newMesh - return a new mesh + * \param [out] newGroups - return new groups + * \param [out] newSubmeshes - return new sub-meshes + * \param [out] newHypotheses - return new algorithms and hypotheses + * \param [out] invalidEntries - return study entries of objects whose + * counterparts are not found in the newGeometry, followed by entries + * of mesh sub-objects that are invalid because they depend on a not found + * preceding sub-shape + * \return CORBA::Boolean - is a success + */ +//================================================================================ + +CORBA::Boolean SMESH_Gen_i::CopyMeshWithGeom( SMESH::SMESH_Mesh_ptr theSourceMesh, + GEOM::GEOM_Object_ptr theNewGeometry, + const char* theMeshName, + CORBA::Boolean theToCopyGroups, + CORBA::Boolean theToReuseHypotheses, + CORBA::Boolean theToCopyElements, + SMESH::SMESH_Mesh_out theNewMesh, + SMESH::ListOfGroups_out theNewGroups, + SMESH::submesh_array_out theNewSubmeshes, + SMESH::ListOfHypothesis_out theNewHypotheses, + SMESH::string_array_out theInvalidEntries) +throw ( SALOME::SALOME_Exception ) +{ + if ( CORBA::is_nil( theSourceMesh ) || + CORBA::is_nil( theNewGeometry )) + THROW_SALOME_CORBA_EXCEPTION( "NULL arguments", SALOME::BAD_PARAM ); + + if ( !theSourceMesh->HasShapeToMesh() ) + THROW_SALOME_CORBA_EXCEPTION( "Source mesh not on geometry", SALOME::BAD_PARAM ); + + bool ok = true; + SMESH_TRY; + + TPythonDump pyDump; // prevent dump from CreateMesh() + + theNewMesh = CreateMesh( theNewGeometry ); + theNewGroups = new SMESH::ListOfGroups(); + theNewSubmeshes = new SMESH::submesh_array(); + theNewHypotheses = new SMESH::ListOfHypothesis(); + theInvalidEntries = new SMESH::string_array(); + + std::vector< SALOMEDS::SObject_wrap > invalidSObjects; + + GEOM::GEOM_Object_var srcGeom = theSourceMesh->GetShapeToMesh(); + GEOM::GEOM_Object_var geom, newGeom; + SALOMEDS::SObject_wrap so; + + SMESH_Mesh_i* srcMesh_i = SMESH::DownCast( theSourceMesh ); + SMESH_Mesh_i* newMesh_i = SMESH::DownCast( theNewMesh ); + srcMesh_i->Load(); + + ShapeMapper shapeMapper( srcMesh_i, newMesh_i, this ); + + // treat hypotheses of mesh and sub-meshes + SMESH::submesh_array_var smList = theSourceMesh->GetSubMeshes(); + for ( CORBA::ULong iSM = 0; iSM <= smList->length(); ++iSM ) + { + bool isSubMesh = ( iSM < smList->length() ); + if ( isSubMesh ) + { + // create a new sub-mesh + SMESH::SMESH_subMesh_var newSM; + geom = smList[iSM]->GetSubShape(); + so = ObjectToSObject( smList[iSM] ); + CORBA::String_var name; + if ( !so->_is_nil() ) + name = so->GetName(); + newGeom = shapeMapper.FindNew( geom ); + if ( newGeom->_is_nil() ) + { + newSM = createInvalidSubMesh( theNewMesh, geom, name.in() ); + shapeMapper.AddInvalid( geom, ObjectToSObject( newSM )); + ok = false; + } + else + { + newSM = theNewMesh->GetSubMesh( newGeom, name.in() ); + } + append( theNewSubmeshes, newSM ); + + if ( newGeom->_is_nil() ) + continue; // don't assign hypotheses + } + else + { + newGeom = GEOM::GEOM_Object::_duplicate( theNewGeometry ); + geom = srcGeom; + so = ObjectToSObject( theNewMesh ); + SetName( so, theMeshName, "Mesh" ); + } + + // assign hypotheses + SMESH::ListOfHypothesis_var hypList = theSourceMesh->GetHypothesisList( geom ); + for ( CORBA::ULong iHyp = 0; iHyp < hypList->length(); ++iHyp ) + { + SMESH::SMESH_Hypothesis_var hyp = hypList[ iHyp ]; + SMESH_Hypothesis_i* hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp ); + + // get geometry hyp depends on + std::vector< std::string > entryArray; + std::vector< int > subIDArray; + bool dependsOnGeom = hyp_i->getObjectsDependOn( entryArray, subIDArray ); + + if ( !theToReuseHypotheses || dependsOnGeom ) + { + // create a new hypothesis + CORBA::String_var type = hyp->GetName(); + CORBA::String_var lib = hyp->GetLibName(); + CORBA::String_var data = hyp_i->SaveTo(); + if ( data.in()[0] ) + { + hyp = CreateHypothesis( type, lib ); + hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp ); + hyp_i->LoadFrom( data.in() ); + append( theNewHypotheses, hyp ); + } + } + + // update geometry hyp depends on + if ( dependsOnGeom ) + { + for ( size_t iGeo = 0; iGeo < entryArray.size(); ++iGeo ) + { + if ( !entryArray[ iGeo ].empty() ) + { + std::string newEntry = shapeMapper.FindNew( entryArray[ iGeo ]); + if ( newEntry.empty() ) + { + ok = false; + shapeMapper.AddInvalid( entryArray[ iGeo ], ObjectToSObject( hyp )); + shapeMapper.AddInvalid( entryArray[ iGeo ], so ); // sub-mesh + } + entryArray[ iGeo ] = newEntry; + } + } + for ( size_t iGeo = 0; iGeo < subIDArray.size(); ++iGeo ) + { + if ( subIDArray[ iGeo ] > 0 ) + { + int newID = shapeMapper.FindNew( subIDArray[ iGeo ]); + if ( newID < 1 ) + { + ok = false; + shapeMapper.AddInvalid( subIDArray[ iGeo ], ObjectToSObject( hyp )); + shapeMapper.AddInvalid( subIDArray[ iGeo ], so ); // sub-mesh + } + subIDArray[ iGeo ] = newID; + } + } + if ( !hyp_i->setObjectsDependOn( entryArray, subIDArray )) + ok = false; + } + + CORBA::String_var errorText; + theNewMesh->AddHypothesis( newGeom, hyp, errorText.out() ); + if ( errorText.in()[0] ) + ok = false; + + } // loop on hypotheses + } // loop on sub-meshes and mesh + + + // copy mesh elements, keeping IDs + SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); + if ( theToCopyElements && theSourceMesh->NbNodes() > 0 ) + { + ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() ); + ::SMESH_MeshEditor::ElemFeatures elemData; + + SMESH_subMesh* srcMainSM = srcMesh_i->GetImpl().GetSubMeshContaining( 1 ); + SMESH_subMeshIteratorPtr srcSMIt = srcMainSM->getDependsOnIterator( /*includeSelf=*/true, + /*vertexLast=*/false); + while ( srcSMIt->more() ) + { + SMESH_subMesh* srcSM = srcSMIt->next(); + if ( srcSM->IsEmpty() ) + continue; // not yet computed + int newID = shapeMapper.FindNewNotChanged( srcSM ); + if ( newID < 1 ) + continue; + + SMESHDS_SubMesh* srcSMDS = srcSM->GetSubMeshDS(); + SMDS_NodeIteratorPtr nIt = srcSMDS->GetNodes(); + while ( nIt->more() ) + { + SMESH_NodeXYZ node( nIt->next() ); + const SMDS_MeshNode* newNode = newMeshDS->AddNodeWithID( node.X(), node.Y(), node.Z(), + node->GetID() ); + const SMDS_PositionPtr pos = node->GetPosition(); + const double* uv = pos->GetParameters(); + switch ( pos->GetTypeOfPosition() ) + { + case SMDS_TOP_3DSPACE: newMeshDS->SetNodeInVolume( newNode, newID ); break; + case SMDS_TOP_FACE: newMeshDS->SetNodeOnFace ( newNode, newID, uv[0], uv[1] ); break; + case SMDS_TOP_EDGE: newMeshDS->SetNodeOnEdge ( newNode, newID, uv[0] ); break; + case SMDS_TOP_VERTEX: newMeshDS->SetNodeOnVertex( newNode, newID ); break; + default: ; + } + } + SMDS_ElemIteratorPtr eIt = srcSMDS->GetElements(); + while( eIt->more() ) + { + const SMDS_MeshElement* e = eIt->next(); + elemData.Init( e, /*basicOnly=*/false ); + elemData.SetID( e->GetID() ); + elemData.myNodes.resize( e->NbNodes() ); + SMDS_NodeIteratorPtr nnIt = e->nodeIterator(); + size_t iN; + for ( iN = 0; nnIt->more(); ++iN ) + { + const SMDS_MeshNode* srcNode = nnIt->next(); + elemData.myNodes[ iN ] = newMeshDS->FindNode( srcNode->GetID() ); + if ( !elemData.myNodes[ iN ]) + break; + } + if ( iN == elemData.myNodes.size() ) + if ( const SMDS_MeshElement * newElem = editor.AddElement( elemData.myNodes, elemData )) + newMeshDS->SetMeshElementOnShape( newElem, newID ); + } + if ( SMESH_subMesh* newSM = newMesh_i->GetImpl().GetSubMeshContaining( newID )) + newSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + } + + newMeshDS->Modified(); + } + + + // treat groups + + TStr2StrMap old2newGroupMap; + + SALOME::GenericObj_wrap< SMESH::FilterManager > filterMgr = CreateFilterManager(); + + SMESH::ListOfGroups_var groups = theSourceMesh->GetGroups(); + CORBA::ULong nbGroups = theToCopyGroups ? groups->length() : 0, nbAddedGroups = 0; + for ( CORBA::ULong i = 0; i < nbGroups + nbAddedGroups; ++i ) + { + SMESH::SMESH_Group_var stdlGroup = SMESH::SMESH_Group::_narrow ( groups[ i ]); + SMESH::SMESH_GroupOnGeom_var geomGroup = SMESH::SMESH_GroupOnGeom::_narrow ( groups[ i ]); + SMESH::SMESH_GroupOnFilter_var fltrGroup = SMESH::SMESH_GroupOnFilter::_narrow( groups[ i ]); + + CORBA::String_var name = groups[ i ]->GetName(); + SMESH::ElementType elemType = groups[ i ]->GetType(); + + SMESH::SMESH_GroupBase_var newGroup; + + if ( !stdlGroup->_is_nil() ) + { + if ( newMeshDS->GetMeshInfo().NbElements( SMDSAbs_ElementType( elemType )) > 0 ) + { + SMESH::long_array_var elemIDs = stdlGroup->GetIDs(); + const bool isElem = ( elemType != SMESH::NODE ); + CORBA::ULong iE = 0; + for ( ; iE < elemIDs->length(); ++iE ) // check if any element has been copied + if ( newMeshDS->GetElementType( elemIDs[ iE ], isElem ) != SMDSAbs_All ) + break; + if ( iE < elemIDs->length() ) + { + stdlGroup = theNewMesh->CreateGroup( elemType, name ); + stdlGroup->Add( elemIDs ); + newGroup = SMESH::SMESH_GroupBase::_narrow( stdlGroup ); + } + } + } + else if ( !geomGroup->_is_nil() ) + { + GEOM::GEOM_Object_var geom = geomGroup->GetShape(); + GEOM::GEOM_Object_var newGeom = shapeMapper.FindNew( geom ); + if ( newGeom->_is_nil() ) + { + newGroup = theNewMesh->CreateGroup( elemType, name ); // just to notify the user + shapeMapper.AddInvalid( geom, ObjectToSObject( newGroup )); + ok = false; + } + else + { + newGroup = theNewMesh->CreateGroupFromGEOM( elemType, name, newGeom ); + } + } + else if ( !fltrGroup->_is_nil() ) + { + // replace geometry in a filter + SMESH::Filter_var filter = fltrGroup->GetFilter(); + SMESH::Filter::Criteria_var criteria; + filter->GetCriteria( criteria.out() ); + + bool isMissingGroup = false; + std::vector< std::string > badEntries; + + for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr ) + { + const char* thresholdID = criteria[ iCr ].ThresholdID.in(); + switch ( criteria[ iCr ].Type ) + { + case SMESH::FT_BelongToMeshGroup: + { + SALOME::GenericObj_wrap< SMESH::BelongToMeshGroup > btgg = filterMgr->CreateBelongToMeshGroup(); + btgg->SetGroupID( thresholdID ); + SMESH::SMESH_GroupBase_ptr refGroup = btgg->GetGroup(); + SALOMEDS::SObject_wrap refGroupSO = ObjectToSObject( refGroup ); + if ( refGroupSO->_is_nil() ) + break; + CORBA::String_var refID = refGroupSO->GetID(); + TStr2StrMap::iterator o2nID = old2newGroupMap.find( refID.in() ); + if ( o2nID == old2newGroupMap.end() ) + { + isMissingGroup = true; // corresponding new group not yet created + break; + } + criteria[ iCr ].ThresholdID = o2nID->second.c_str(); + + if ( o2nID->second.empty() ) // new referred group is invalid + badEntries.push_back( refID.in() ); + break; + } + case SMESH::FT_BelongToGeom: + case SMESH::FT_BelongToPlane: + case SMESH::FT_BelongToCylinder: + case SMESH::FT_BelongToGenSurface: + case SMESH::FT_LyingOnGeom: + { + std::string newID = shapeMapper.FindNew( thresholdID ); + criteria[ iCr ].ThresholdID = newID.c_str(); + if ( newID.empty() ) + badEntries.push_back( thresholdID ); + break; + } + case SMESH::FT_ConnectedElements: + { + if ( thresholdID && thresholdID[0] ) + { + std::string newID = shapeMapper.FindNew( thresholdID ); + criteria[ iCr ].ThresholdID = newID.c_str(); + if ( newID.empty() ) + badEntries.push_back( thresholdID ); } - if ( algoName.in() == 0 ) - // use algo type name - algoName = CORBA::string_dup( error->_algo->GetName() ); + break; } - // fill AlgoStateError structure - SMESH::AlgoStateError & errStruct = error_array[ i++ ]; - errStruct.name = errName; - errStruct.algoName = algoName; - errStruct.algoDim = error->_algoDim; - errStruct.isGlobalAlgo = error->_isGlobalAlgo; + default:; + } + } // loop on criteria + + if ( isMissingGroup && i < nbGroups ) + { + // to treat the group again + append( groups, SMESH::SMESH_GroupBase::_duplicate( groups[ i ])); + ++nbAddedGroups; + continue; } - } - } - catch ( SALOME_Exception& S_ex ) { - INFOS( "catch exception "<< S_ex.what() ); - } - return error_array._retn(); -} + SMESH::Filter_var newFilter = filterMgr->CreateFilter(); + newFilter->SetCriteria( criteria ); -//============================================================================= -/*! - * SMESH_Gen_i::GetSubShapesId - * - * Get sub-shapes unique ID's list - */ -//============================================================================= + newGroup = theNewMesh->CreateGroupFromFilter( elemType, name, newFilter ); + newFilter->UnRegister(); -SMESH::long_array* SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr theMainShapeObject, - const SMESH::object_array& theListOfSubShapeObject ) - throw ( SALOME::SALOME_Exception ) -{ - Unexpect aCatch(SALOME_SalomeException); - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetSubShapesId" ); + SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup ); + for ( size_t iEnt = 0; iEnt < badEntries.size(); ++iEnt ) + shapeMapper.AddInvalid( badEntries[ iEnt ], newSO ); - SMESH::long_array_var shapesId = new SMESH::long_array; - set setId; + if ( isMissingGroup ) // all groups treated but a referred groups still not found + { + invalidSObjects.push_back( ObjectToSObject( newGroup )); + ok = false; + } + if ( !badEntries.empty() ) + ok = false; - if ( CORBA::is_nil( theMainShapeObject ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", - SALOME::BAD_PARAM ); + } // treat a group on filter - try - { - TopoDS_Shape myMainShape = GeomObjectToShape(theMainShapeObject); - TopTools_IndexedMapOfShape myIndexToShape; - TopExp::MapShapes(myMainShape,myIndexToShape); - - for ( int i = 0; i < theListOfSubShapeObject.length(); i++ ) - { - GEOM::GEOM_Object_var aShapeObject - = GEOM::GEOM_Object::_narrow(theListOfSubShapeObject[i]); - if ( CORBA::is_nil( aShapeObject ) ) - THROW_SALOME_CORBA_EXCEPTION ("bad shape object reference", \ - SALOME::BAD_PARAM ); - - TopoDS_Shape locShape = GeomObjectToShape(aShapeObject); - for (TopExp_Explorer exp(locShape,TopAbs_FACE); exp.More(); exp.Next()) - { - const TopoDS_Face& F = TopoDS::Face(exp.Current()); - setId.insert(myIndexToShape.FindIndex(F)); - if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(F)); - } - for (TopExp_Explorer exp(locShape,TopAbs_EDGE); exp.More(); exp.Next()) - { - const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); - setId.insert(myIndexToShape.FindIndex(E)); - if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(E)); - } - for (TopExp_Explorer exp(locShape,TopAbs_VERTEX); exp.More(); exp.Next()) - { - const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current()); - setId.insert(myIndexToShape.FindIndex(V)); - if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(V)); - } - } - shapesId->length(setId.size()); - set::iterator iind; - int i=0; - for (iind = setId.begin(); iind != setId.end(); iind++) - { - if(MYDEBUG) SCRUTE((*iind)); - shapesId[i] = (*iind); - if(MYDEBUG) SCRUTE(shapesId[i]); - i++; - } - } - catch (SALOME_Exception& S_ex) + append( theNewGroups, newGroup ); + + // fill old2newGroupMap + SALOMEDS::SObject_wrap srcSO = ObjectToSObject( groups[i] ); + SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup ); + if ( !srcSO->_is_nil() ) { - THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM); + CORBA::String_var srcID, newID(""); + srcID = srcSO->GetID(); + if ( !newSO->_is_nil() ) + newID = newSO->GetID(); + old2newGroupMap.insert( std::make_pair( std::string( srcID.in() ), + std::string( newID.in() ))); } - return shapesId._retn(); + if ( newGroup->_is_nil() ) + ok = false; + + } // loop on groups + + newMeshDS->CompactMesh(); + + // set mesh name + if ( !theMeshName || !theMeshName[0] ) + { + SALOMEDS::SObject_wrap soNew = ObjectToSObject( theNewMesh ); + SALOMEDS::SObject_wrap soOld = ObjectToSObject( theSourceMesh ); + CORBA::String_var oldName = soOld->GetName(); + SetName( soNew, oldName.in(), "Mesh" ); + } + // mark invalid objects + shapeMapper.GetInvalid( theInvalidEntries, invalidSObjects ); + + for ( size_t i = 0; i < invalidSObjects.size(); ++i ) + highLightInvalid( invalidSObjects[i].in(), true ); + + pyDump << "ok, " + << theNewMesh << ", " + << theNewGroups << ", " + << *theNewSubmeshes.ptr() << ", " + << *theNewHypotheses.ptr() << ", " + << "invalidEntries = " << this << ".CopyMeshWithGeom( " + << theSourceMesh << ", " + << theNewGeometry << ", " + << "'" << theMeshName << "', " + << theToCopyGroups << ", " + << theToReuseHypotheses << ", " + << theToCopyElements << " )"; + + SMESH_CATCH( SMESH::throwCorbaException ); + + return ok; } -//============================================================================= +//================================================================================ /*! - * SMESH_Gen_i::Compute - * - * Compute mesh on a shape + * \brief Get version of MED format being used. */ -//============================================================================= +//================================================================================ -CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh, - GEOM::GEOM_Object_ptr theShapeObject ) - throw ( SALOME::SALOME_Exception ) +char* SMESH_Gen_i::GetMEDFileVersion() { - Unexpect aCatch(SALOME_SalomeException); - if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Compute" ); - - if ( CORBA::is_nil( theShapeObject ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", - SALOME::BAD_PARAM ); - - if ( CORBA::is_nil( theMesh ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", - SALOME::BAD_PARAM ); - - // Update Python script - TPythonDump() << "isDone = " << this << ".Compute( " - << theMesh << ", " << theShapeObject << ")"; - TPythonDump() << "if not isDone: print 'Mesh " << theMesh << " : computation failed'"; - - try { - // get mesh servant - SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() ); - ASSERT( meshServant ); - if ( meshServant ) { - // get local TopoDS_Shape - TopoDS_Shape myLocShape = GeomObjectToShape( theShapeObject ); - // call implementation compute - ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); - return myGen.Compute( myLocMesh, myLocShape); - } - } - catch ( SALOME_Exception& S_ex ) { - INFOS( "Compute(): catch exception "<< S_ex.what() ); - } - catch ( ... ) { - INFOS( "Compute(): unknown exception " ); - } - return false; + MED::TInt majeur, mineur, release; + majeur = mineur = release = 0; + MED::GetVersionRelease(majeur, mineur, release); + std::ostringstream version; + version << majeur << "." << mineur << "." << release; + return CORBA::string_dup( version.str().c_str() ); } //================================================================================ /*! - * \brief Return geometrical object the given element is built on - * \param theMesh - the mesh the element is in - * \param theElementID - the element ID - * \param theGeomName - the name of the result geom object if it is not yet published - * \retval GEOM::GEOM_Object_ptr - the found or just published geom object + * SMESH_Gen_i::GetMEDVersion + * + * Get MED version of the file by its name */ //================================================================================ +char* SMESH_Gen_i::GetMEDVersion(const char* theFileName) +{ + std::string version = MED::GetMEDVersion( theFileName ); + return CORBA::string_dup( version.c_str() ); +} -GEOM::GEOM_Object_ptr -SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr theMesh, - CORBA::Long theElementID, - const char* theGeomName) - throw ( SALOME::SALOME_Exception ) +//================================================================================ +/*! + * SMESH_Gen_i::CheckCompatibility + * + * Check compatibility of file with MED format being used, read only. + */ +//================================================================================ +CORBA::Boolean SMESH_Gen_i::CheckCompatibility(const char* theFileName) { - Unexpect aCatch(SALOME_SalomeException); - if ( CORBA::is_nil( theMesh ) ) - THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM ); + return MED::CheckCompatibility( theFileName ); +} - GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh(); - GEOM::GEOM_Gen_var geomGen = GetGeomEngine(); +//================================================================================ +/*! + * SMESH_Gen_i::CheckWriteCompatibility + * + * Check compatibility of file with MED format being used, for append on write. + */ +//================================================================================ +CORBA::Boolean SMESH_Gen_i::CheckWriteCompatibility(const char* theFileName) +{ + return MED::CheckCompatibility( theFileName, true ); +} - // get a core mesh DS - SMESH_Mesh_i* meshServant = SMESH::DownCast( theMesh ); - if ( meshServant && !geomGen->_is_nil() && !mainShape->_is_nil() ) - { - ::SMESH_Mesh & mesh = meshServant->GetImpl(); - SMESHDS_Mesh* meshDS = mesh.GetMeshDS(); - // find the element in mesh - if ( const SMDS_MeshElement * elem = meshDS->FindElement( theElementID ) ) - // find a shape id by the element - if ( int shapeID = ::SMESH_MeshEditor( &mesh ).FindShape( elem )) { - // get a geom object by the shape id - GEOM::GEOM_Object_var geom = ShapeToGeomObject( meshDS->IndexToShape( shapeID )); - if ( geom->_is_nil() ) { - GEOM::GEOM_IShapesOperations_var op = - geomGen->GetIShapesOperations( GetCurrentStudyID() ); - if ( !op->_is_nil() ) - geom = op->GetSubShape( mainShape, shapeID ); - } - if ( !geom->_is_nil() ) { - // try to find the corresponding SObject - GeomObjectToShape( geom ); // geom client remembers the found shape - SALOMEDS::SObject_var SObj = ObjectToSObject( myCurrentStudy, geom.in() ); - if ( SObj->_is_nil() ) - // publish a new subshape - SObj = geomGen->AddInStudy( myCurrentStudy, geom, theGeomName, mainShape ); - // return only published geometry - if ( !SObj->_is_nil() ) - return geom._retn(); - } - } +//================================================================================ +/*! + * SMESH_Gen_i::GetMeshNames + * + * Get names of meshes defined in file with the specified name + */ +//================================================================================ +SMESH::string_array* SMESH_Gen_i::GetMeshNames(const char* theFileName) +{ + //MESSAGE("GetMeshNames " << theFileName); + SMESH::string_array_var aResult = new SMESH::string_array(); + MED::PWrapper aMed = MED::CrWrapperR( theFileName ); + MED::TErr anErr; + MED::TInt aNbMeshes = aMed->GetNbMeshes( &anErr ); + //MESSAGE("---" << aNbMeshes); + if( anErr >= 0 ) { + aResult->length( aNbMeshes ); + for( MED::TInt i = 0; i < aNbMeshes; i++ ) { + MED::PMeshInfo aMeshInfo = aMed->GetPMeshInfo( i+1 ); + aResult[i] = CORBA::string_dup( aMeshInfo->GetName().c_str() ); + } } - return GEOM::GEOM_Object::_nil(); + return aResult._retn(); } //============================================================================= @@ -1081,42 +4163,39 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, const char* theURL, bool isMultiFile ) { - INFOS( "SMESH_Gen_i::Save" ); + // localizing + Kernel_Utils::Localizer loc; -// ASSERT( theComponent->GetStudy()->StudyId() == myCurrentStudy->StudyId() ) - // san -- in case differs from theComponent's study, - // use that of the component - if ( myCurrentStudy->_is_nil() || - theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId() ) - SetCurrentStudy( theComponent->GetStudy() ); + if (!myStudyContext) + UpdateStudy(); // Store study contents as a set of python commands - SavePython(myCurrentStudy); + SavePython(); + + SALOMEDS::Study_var aStudy = getStudyServant(); - StudyContext* myStudyContext = GetCurrentStudyContext(); - // Declare a byte stream SALOMEDS::TMPFile_var aStreamFile; - + // Obtain a temporary dir TCollection_AsciiString tmpDir = ( isMultiFile ) ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str(); // Create a sequence of files processed - SALOMEDS::ListOfFileNames_var aFileSeq = new SALOMEDS::ListOfFileNames; - aFileSeq->length( NUM_TMP_FILES ); + SALOMEDS_Tool::ListOfFiles aFileSeq; + aFileSeq.reserve( NUM_TMP_FILES ); TCollection_AsciiString aStudyName( "" ); - if ( isMultiFile ) - aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() ); + if ( isMultiFile ) + aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( Kernel_Utils::encode(aStudy->URL()) ).c_str() ); // Set names of temporary files TCollection_AsciiString filename = aStudyName + TCollection_AsciiString( "_SMESH.hdf" ); // for SMESH data itself TCollection_AsciiString meshfile = aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" ); // for mesh data to be stored in MED file - aFileSeq[ 0 ] = CORBA::string_dup( filename.ToCString() ); - aFileSeq[ 1 ] = CORBA::string_dup( meshfile.ToCString() ); + aFileSeq.push_back(CORBA::string_dup( filename.ToCString() )); + aFileSeq.push_back(CORBA::string_dup( meshfile.ToCString() )); filename = tmpDir + filename; meshfile = tmpDir + meshfile; @@ -1130,26 +4209,68 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, //Remove the files if they exist: BugID: 11225 +#ifndef WIN32 /* unix functionality */ TCollection_AsciiString cmd("rm -f \""); +#else /* windows */ + TCollection_AsciiString cmd("del /F \""); +#endif + cmd+=filename; cmd+="\" \""; cmd+=meshfile; cmd+="\""; +#ifdef WIN32 + cmd+=" 2>NUL"; +#endif system(cmd.ToCString()); // MED writer to be used by storage process DriverMED_W_SMESHDS_Mesh myWriter; myWriter.SetFile( meshfile.ToCString() ); + // IMP issue 20918 + // SetStoreName() to groups before storing hypotheses to let them refer to + // groups using "store name", which is "Group " + { + SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( theComponent ); + for ( ; itBig->More(); itBig->Next() ) { + SALOMEDS::SObject_wrap gotBranch = itBig->Value(); + if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) { + CORBA::Object_var anObject = SObjectToObject( gotBranch ); + if ( !CORBA::is_nil( anObject ) ) { + SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ; + if ( !myMesh->_is_nil() ) { + myMesh->Load(); // load from study file if not yet done + TPythonDump pd; // not to dump GetGroups() + SMESH::ListOfGroups_var groups = myMesh->GetGroups(); + for ( CORBA::ULong i = 0; i < groups->length(); ++i ) + { + SMESH_GroupBase_i* grImpl = SMESH::DownCast( groups[i]); + if ( grImpl ) + { + CORBA::String_var objStr = GetORB()->object_to_string( grImpl->_this() ); + int anId = myStudyContext->findId( string( objStr.in() ) ); + char grpName[ 30 ]; + sprintf( grpName, "Group %d %d", anId, grImpl->GetLocalID() ); + SMESHDS_GroupBase* aGrpBaseDS = grImpl->GetGroupDS(); + aGrpBaseDS->SetStoreName( grpName ); + } + } + } + } + } + } + } + // Write data // ---> create HDF file - aFile = new HDFfile( filename.ToCString() ); + aFile = new HDFfile( (char*) filename.ToCString() ); aFile->CreateOnDisk(); // --> iterator for top-level objects - SALOMEDS::ChildIterator_var itBig = myCurrentStudy->NewChildIterator( theComponent ); + SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( theComponent ); for ( ; itBig->More(); itBig->Next() ) { - SALOMEDS::SObject_var gotBranch = itBig->Value(); + SALOMEDS::SObject_wrap gotBranch = itBig->Value(); // --> hypotheses root branch (only one for the study) if ( gotBranch->Tag() == GetHypothesisRootTag() ) { @@ -1158,48 +4279,65 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, aTopGroup->CreateOnDisk(); // iterator for all hypotheses - SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( gotBranch ); + SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( gotBranch ); for ( ; it->More(); it->Next() ) { - SALOMEDS::SObject_var mySObject = it->Value(); - CORBA::Object_var anObject = SObjectToObject( mySObject ); - if ( !CORBA::is_nil( anObject ) ) { + SALOMEDS::SObject_wrap mySObject = it->Value(); + CORBA::Object_var anObject = SObjectToObject( mySObject ); + if ( !CORBA::is_nil( anObject ) ) { SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject ); if ( !myHyp->_is_nil() ) { - SMESH_Hypothesis_i* myImpl = dynamic_cast( GetServant( myHyp ).in() ); - if ( myImpl ) { - string hypname = string( myHyp->GetName() ); - string libname = string( myHyp->GetLibName() ); - int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) ); - string hypdata = string( myImpl->SaveTo() ); - - // for each hypothesis create HDF group basing on its id - char hypGrpName[30]; - sprintf( hypGrpName, "Hypothesis %d", id ); - aGroup = new HDFgroup( hypGrpName, aTopGroup ); - aGroup->CreateOnDisk(); - // --> type name of hypothesis - aSize[ 0 ] = hypname.length() + 1; - aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) ); - aDataset->CloseOnDisk(); - // --> server plugin library name of hypothesis - aSize[ 0 ] = libname.length() + 1; - aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( libname.c_str() ) ); - aDataset->CloseOnDisk(); - // --> persistent data of hypothesis - aSize[ 0 ] = hypdata.length() + 1; - aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) ); - aDataset->CloseOnDisk(); - // close hypothesis HDF group - aGroup->CloseOnDisk(); - } - } - } + SMESH_Hypothesis_i* myImpl = dynamic_cast( GetServant( myHyp ).in() ); + if ( myImpl ) { + CORBA::String_var hn = myHyp->GetName(), ln = myHyp->GetLibName(); + std::string hypname = hn.in(); + std::string libname = ln.in(); + // BUG SWP13062 + // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for + // WIN32 and ".so" for X-system) must be deleted + int libname_len = libname.length(); +#ifdef WIN32 + if( libname_len > 4 ) + libname.resize( libname_len - 4 ); +#else + // PAL17753 (Regression: missing hypothesis in restored study) + // "lib" also should be removed from the beginning + //if( libname_len > 3 ) + //libname.resize( libname_len - 3 ); + if( libname_len > 6 ) + libname = libname.substr( 3, libname_len - 3 - 3 ); +#endif + CORBA::String_var objStr = GetORB()->object_to_string( anObject ); + CORBA::String_var hypdata = myImpl->SaveTo(); + int id = myStudyContext->findId( string( objStr.in() )); + + // for each hypothesis create HDF group basing on its id + char hypGrpName[30]; + sprintf( hypGrpName, "Hypothesis %d", id ); + aGroup = new HDFgroup( hypGrpName, aTopGroup ); + aGroup->CreateOnDisk(); + // --> type name of hypothesis + aSize[ 0 ] = hypname.length() + 1; + aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) ); + aDataset->CloseOnDisk(); + // --> server plugin library name of hypothesis + aSize[ 0 ] = libname.length() + 1; + aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( libname.c_str() ) ); + aDataset->CloseOnDisk(); + // --> persistent data of hypothesis + aSize[ 0 ] = strlen( hypdata.in() ) + 1; + aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( hypdata.in() ) ); + aDataset->CloseOnDisk(); + // close hypothesis HDF group + aGroup->CloseOnDisk(); + } + } + } } // close hypotheses root HDF group aTopGroup->CloseOnDisk(); @@ -1211,48 +4349,65 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, aTopGroup->CreateOnDisk(); // iterator for all algorithms - SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( gotBranch ); + SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( gotBranch ); for ( ; it->More(); it->Next() ) { - SALOMEDS::SObject_var mySObject = it->Value(); - CORBA::Object_var anObject = SObjectToObject( mySObject ); - if ( !CORBA::is_nil( anObject ) ) { + SALOMEDS::SObject_wrap mySObject = it->Value(); + CORBA::Object_var anObject = SObjectToObject( mySObject ); + if ( !CORBA::is_nil( anObject ) ) { SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow( anObject ); if ( !myHyp->_is_nil() ) { - SMESH_Hypothesis_i* myImpl = dynamic_cast( GetServant( myHyp ).in() ); - if ( myImpl ) { - string hypname = string( myHyp->GetName() ); - string libname = string( myHyp->GetLibName() ); - int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) ); - string hypdata = string( myImpl->SaveTo() ); - - // for each algorithm create HDF group basing on its id - char hypGrpName[30]; - sprintf( hypGrpName, "Algorithm %d", id ); - aGroup = new HDFgroup( hypGrpName, aTopGroup ); - aGroup->CreateOnDisk(); - // --> type name of algorithm - aSize[0] = hypname.length() + 1; - aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) ); - aDataset->CloseOnDisk(); - // --> server plugin library name of hypothesis - aSize[0] = libname.length() + 1; - aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( libname.c_str() ) ); - aDataset->CloseOnDisk(); - // --> persistent data of algorithm - aSize[0] = hypdata.length() + 1; - aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) ); - aDataset->CloseOnDisk(); - // close algorithm HDF group - aGroup->CloseOnDisk(); - } - } - } + SMESH_Hypothesis_i* myImpl = dynamic_cast( GetServant( myHyp ).in() ); + if ( myImpl ) { + CORBA::String_var hn = myHyp->GetName(), ln = myHyp->GetLibName(); + std::string hypname = hn.in(); + std::string libname = ln.in(); + // BUG SWP13062 + // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for + // WIN32 and ".so" for X-system) must be deleted + int libname_len = libname.length(); +#ifdef WIN32 + if( libname_len > 4 ) + libname.resize( libname_len - 4 ); +#else + // PAL17753 (Regression: missing hypothesis in restored study) + // "lib" also should be removed from the beginning + //if( libname_len > 3 ) + //libname.resize( libname_len - 3 ); + if( libname_len > 6 ) + libname = libname.substr( 3, libname_len - 3 - 3 ); +#endif + CORBA::String_var objStr = GetORB()->object_to_string( anObject ); + CORBA::String_var hypdata = myImpl->SaveTo(); + int id = myStudyContext->findId( string( objStr.in() ) ); + + // for each algorithm create HDF group basing on its id + char hypGrpName[30]; + sprintf( hypGrpName, "Algorithm %d", id ); + aGroup = new HDFgroup( hypGrpName, aTopGroup ); + aGroup->CreateOnDisk(); + // --> type name of algorithm + aSize[0] = hypname.length() + 1; + aDataset = new HDFdataset( "Name", aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( hypname.c_str() ) ); + aDataset->CloseOnDisk(); + // --> server plugin library name of hypothesis + aSize[0] = libname.length() + 1; + aDataset = new HDFdataset( "LibName", aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( libname.c_str() ) ); + aDataset->CloseOnDisk(); + // --> persistent data of algorithm + aSize[0] = strlen( hypdata.in() ) + 1; + aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( hypdata.in() )); + aDataset->CloseOnDisk(); + // close algorithm HDF group + aGroup->CloseOnDisk(); + } + } + } } // close algorithms root HDF group aTopGroup->CloseOnDisk(); @@ -1261,154 +4416,207 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, else if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) { CORBA::Object_var anObject = SObjectToObject( gotBranch ); if ( !CORBA::is_nil( anObject ) ) { - SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ; + SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ; if ( !myMesh->_is_nil() ) { - SMESH_Mesh_i* myImpl = dynamic_cast( GetServant( myMesh ).in() ); - if ( myImpl ) { - int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) ); - ::SMESH_Mesh& myLocMesh = myImpl->GetImpl(); - SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS(); - - // for each mesh open the HDF group basing on its id - char meshGrpName[ 30 ]; - sprintf( meshGrpName, "Mesh %d", id ); - aTopGroup = new HDFgroup( meshGrpName, aFile ); - aTopGroup->CreateOnDisk(); - - // --> put dataset to hdf file which is a flag that mesh has data - string strHasData = "0"; - // check if the mesh is not empty - if ( mySMESHDSMesh->NbNodes() > 0 ) { - // write mesh data to med file - myWriter.SetMesh( mySMESHDSMesh ); - myWriter.SetMeshId( id ); - strHasData = "1"; - } - aSize[ 0 ] = strHasData.length() + 1; - aDataset = new HDFdataset( "Has data", aTopGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( strHasData.c_str() ) ); - aDataset->CloseOnDisk(); - - // write reference on a shape if exists - SALOMEDS::SObject_var myRef; + SMESH_Mesh_i* myImpl = dynamic_cast( GetServant( myMesh ).in() ); + if ( myImpl ) { + CORBA::String_var objStr = GetORB()->object_to_string( anObject ); + int id = myStudyContext->findId( string( objStr.in() ) ); + ::SMESH_Mesh& myLocMesh = myImpl->GetImpl(); + SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS(); + bool hasShape = myLocMesh.HasShapeToMesh(); + + // for each mesh open the HDF group basing on its id + char meshGrpName[ 30 ]; + sprintf( meshGrpName, "Mesh %d", id ); + aTopGroup = new HDFgroup( meshGrpName, aFile ); + aTopGroup->CreateOnDisk(); + + // --> put dataset to hdf file which is a flag that mesh has data + string strHasData = "0"; + // check if the mesh is not empty + if ( mySMESHDSMesh->NbNodes() > 0 ) { + // write mesh data to med file + myWriter.SetMesh( mySMESHDSMesh ); + myWriter.SetMeshId( id ); + strHasData = "1"; + } + aSize[ 0 ] = strHasData.length() + 1; + aDataset = new HDFdataset( "Has data", aTopGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( strHasData.c_str() ) ); + aDataset->CloseOnDisk(); + + // ouv : NPAL12872 + // for each mesh open the HDF group basing on its auto color parameter + char meshAutoColorName[ 30 ]; + sprintf( meshAutoColorName, "AutoColorMesh %d", id ); + int anAutoColor[1]; + anAutoColor[0] = myImpl->GetAutoColor(); + aSize[ 0 ] = 1; + aDataset = new HDFdataset( meshAutoColorName, aTopGroup, HDF_INT32, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( anAutoColor ); + aDataset->CloseOnDisk(); + + // issue 0020693. Store _isModified flag + int isModified = myLocMesh.GetIsModified(); + aSize[ 0 ] = 1; + aDataset = new HDFdataset( "_isModified", aTopGroup, HDF_INT32, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( &isModified ); + aDataset->CloseOnDisk(); + + // issue 20918. Store Persistent Id of SMESHDS_Mesh + int meshPersistentId = mySMESHDSMesh->GetPersistentId(); + aSize[ 0 ] = 1; + aDataset = new HDFdataset( "meshPersistentId", aTopGroup, HDF_INT32, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( &meshPersistentId ); + aDataset->CloseOnDisk(); + + // Store SMESH_Mesh_i::_mainShapeTick + int shapeTick = myImpl->MainShapeTick(); + aSize[ 0 ] = 1; + aDataset = new HDFdataset( "shapeTick", aTopGroup, HDF_INT32, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( &shapeTick ); + aDataset->CloseOnDisk(); + + // write reference on a shape if exists + SALOMEDS::SObject_wrap myRef; bool shapeRefFound = false; - bool found = gotBranch->FindSubObject( GetRefOnShapeTag(), myRef ); - if ( found ) { - SALOMEDS::SObject_var myShape; - bool ok = myRef->ReferencedObject( myShape ); - if ( ok ) { - shapeRefFound = (! CORBA::is_nil( myShape->GetObject() )); - string myRefOnObject = myShape->GetID(); - if ( shapeRefFound && myRefOnObject.length() > 0 ) { - aSize[ 0 ] = myRefOnObject.length() + 1; - aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); - aDataset->CloseOnDisk(); - } - } - } - - // write applied hypotheses if exist - SALOMEDS::SObject_var myHypBranch; - found = gotBranch->FindSubObject( GetRefOnAppliedHypothesisTag(), myHypBranch ); - if ( found && !shapeRefFound ) { // remove applied hyps - myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch ); + bool found = gotBranch->FindSubObject( GetRefOnShapeTag(), myRef.inout() ); + if ( found ) { + SALOMEDS::SObject_wrap myShape; + bool ok = myRef->ReferencedObject( myShape.inout() ); + if ( ok ) { + CORBA::Object_var shapeObj = myShape->GetObject(); + shapeRefFound = (! CORBA::is_nil( shapeObj )); + CORBA::String_var myRefOnObject = myShape->GetID(); + if ( shapeRefFound && myRefOnObject.in()[0] ) { + aSize[ 0 ] = strlen( myRefOnObject.in() ) + 1; + aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( myRefOnObject.in() ) ); + aDataset->CloseOnDisk(); + } + } + } + + // Store file info + std::string info = myImpl->FileInfoToString(); + if ( !info.empty() ) + { + aSize[ 0 ] = info.size(); + aDataset = new HDFdataset( "file info", aTopGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( (char*) info.data() ); + aDataset->CloseOnDisk(); + } + + // write applied hypotheses if exist + SALOMEDS::SObject_wrap myHypBranch; + found = gotBranch->FindSubObject( GetRefOnAppliedHypothesisTag(), myHypBranch.inout() ); + if ( found && !shapeRefFound && hasShape ) { // remove applied hyps + aStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch ); } - if ( found && shapeRefFound ) { - aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup ); - aGroup->CreateOnDisk(); - - SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myHypBranch ); - int hypNb = 0; - for ( ; it->More(); it->Next() ) { - SALOMEDS::SObject_var mySObject = it->Value(); - SALOMEDS::SObject_var myRefOnHyp; - bool ok = mySObject->ReferencedObject( myRefOnHyp ); - if ( ok ) { - // san - it is impossible to recover applied hypotheses + if ( found && (shapeRefFound || !hasShape) ) { + aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup ); + aGroup->CreateOnDisk(); + + SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myHypBranch ); + int hypNb = 0; + for ( ; it->More(); it->Next() ) { + SALOMEDS::SObject_wrap mySObject = it->Value(); + SALOMEDS::SObject_wrap myRefOnHyp; + bool ok = mySObject->ReferencedObject( myRefOnHyp.inout() ); + if ( ok ) { + // san - it is impossible to recover applied hypotheses // using their entries within Load() method, - // for there are no AttributeIORs in the study when Load() is working. - // Hence, it is better to store persistent IDs of hypotheses as references to them - - //string myRefOnObject = myRefOnHyp->GetID(); - CORBA::Object_var anObject = SObjectToObject( myRefOnHyp ); - int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) ); - //if ( myRefOnObject.length() > 0 ) { - //aSize[ 0 ] = myRefOnObject.length() + 1; - char hypName[ 30 ], hypId[ 30 ]; - sprintf( hypName, "Hyp %d", ++hypNb ); - sprintf( hypId, "%d", id ); - aSize[ 0 ] = strlen( hypId ) + 1; - aDataset = new HDFdataset( hypName, aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); - aDataset->WriteOnDisk( hypId ); - aDataset->CloseOnDisk(); - //} - } - } - aGroup->CloseOnDisk(); - } - - // write applied algorithms if exist - SALOMEDS::SObject_var myAlgoBranch; - found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(), myAlgoBranch ); - if ( found && !shapeRefFound ) { // remove applied algos - myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch ); + // for there are no AttributeIORs in the study when Load() is working. + // Hence, it is better to store persistent IDs of hypotheses as references to them + + //string myRefOnObject = myRefOnHyp->GetID(); + CORBA::Object_var anObject = SObjectToObject( myRefOnHyp ); + CORBA::String_var objStr = GetORB()->object_to_string( anObject ); + int id = myStudyContext->findId( string( objStr.in() ) ); + //if ( myRefOnObject.length() > 0 ) { + //aSize[ 0 ] = myRefOnObject.length() + 1; + char hypName[ 30 ], hypId[ 30 ]; + sprintf( hypName, "Hyp %d", ++hypNb ); + sprintf( hypId, "%d", id ); + aSize[ 0 ] = strlen( hypId ) + 1; + aDataset = new HDFdataset( hypName, aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); + aDataset->WriteOnDisk( hypId ); + aDataset->CloseOnDisk(); + //} + } + } + aGroup->CloseOnDisk(); } - if ( found && shapeRefFound ) { - aGroup = new HDFgroup( "Applied Algorithms", aTopGroup ); - aGroup->CreateOnDisk(); - - SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myAlgoBranch ); - int algoNb = 0; - for ( ; it->More(); it->Next() ) { - SALOMEDS::SObject_var mySObject = it->Value(); - SALOMEDS::SObject_var myRefOnAlgo; - bool ok = mySObject->ReferencedObject( myRefOnAlgo ); - if ( ok ) { - // san - it is impossible to recover applied algorithms + + // write applied algorithms if exist + SALOMEDS::SObject_wrap myAlgoBranch; + found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(), + myAlgoBranch.inout() ); + if ( found && !shapeRefFound && hasShape) { // remove applied algos + aStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch ); + } + if ( found && (shapeRefFound || !hasShape)) { + aGroup = new HDFgroup( "Applied Algorithms", aTopGroup ); + aGroup->CreateOnDisk(); + + SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myAlgoBranch ); + int algoNb = 0; + for ( ; it->More(); it->Next() ) { + SALOMEDS::SObject_wrap mySObject = it->Value(); + SALOMEDS::SObject_wrap myRefOnAlgo; + bool ok = mySObject->ReferencedObject( myRefOnAlgo.inout() ); + if ( ok ) { + // san - it is impossible to recover applied algorithms // using their entries within Load() method, - // for there are no AttributeIORs in the study when Load() is working. - // Hence, it is better to store persistent IDs of algorithms as references to them - - //string myRefOnObject = myRefOnAlgo->GetID(); - CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo ); - int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) ); - //if ( myRefOnObject.length() > 0 ) { - //aSize[ 0 ] = myRefOnObject.length() + 1; - char algoName[ 30 ], algoId[ 30 ]; - sprintf( algoName, "Algo %d", ++algoNb ); - sprintf( algoId, "%d", id ); - aSize[ 0 ] = strlen( algoId ) + 1; - aDataset = new HDFdataset( algoName, aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); - aDataset->WriteOnDisk( algoId ); - aDataset->CloseOnDisk(); - //} - } - } - aGroup->CloseOnDisk(); - } - - // --> submesh objects sub-branches - - for ( int i = GetSubMeshOnVertexTag(); i <= GetSubMeshOnCompoundTag(); i++ ) { - SALOMEDS::SObject_var mySubmeshBranch; - found = gotBranch->FindSubObject( i, mySubmeshBranch ); + // for there are no AttributeIORs in the study when Load() is working. + // Hence, it is better to store persistent IDs of algorithms as references to them + + //string myRefOnObject = myRefOnAlgo->GetID(); + CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo ); + CORBA::String_var objStr = GetORB()->object_to_string( anObject ); + int id = myStudyContext->findId( string( objStr.in() ) ); + //if ( myRefOnObject.length() > 0 ) { + //aSize[ 0 ] = myRefOnObject.length() + 1; + char algoName[ 30 ], algoId[ 30 ]; + sprintf( algoName, "Algo %d", ++algoNb ); + sprintf( algoId, "%d", id ); + aSize[ 0 ] = strlen( algoId ) + 1; + aDataset = new HDFdataset( algoName, aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); + aDataset->WriteOnDisk( algoId ); + aDataset->CloseOnDisk(); + //} + } + } + aGroup->CloseOnDisk(); + } + + // --> submesh objects sub-branches + + for ( int i = GetSubMeshOnVertexTag(); i <= GetSubMeshOnCompoundTag(); i++ ) { + SALOMEDS::SObject_wrap mySubmeshBranch; + found = gotBranch->FindSubObject( i, mySubmeshBranch.inout() ); if ( found ) // check if there is shape reference in submeshes { bool hasShapeRef = false; - SALOMEDS::ChildIterator_var itSM = - myCurrentStudy->NewChildIterator( mySubmeshBranch ); - for ( ; itSM->More(); itSM->Next() ) { - SALOMEDS::SObject_var mySubRef, myShape, mySObject = itSM->Value(); - if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef )) - mySubRef->ReferencedObject( myShape ); + SALOMEDS::ChildIterator_wrap itSM = + aStudy->NewChildIterator( mySubmeshBranch ); + for ( ; itSM->More(); itSM->Next() ) { + SALOMEDS::SObject_wrap mySubRef, myShape, mySObject = itSM->Value(); + if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() )) + mySubRef->ReferencedObject( myShape.inout() ); if ( !CORBA::is_nil( myShape ) && !CORBA::is_nil( myShape->GetObject() )) hasShapeRef = true; else @@ -1429,55 +4637,56 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, } } } - myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySObject ); + aStudy->NewBuilder()->RemoveObjectWithChildren( mySObject ); } } // loop on submeshes of a type if ( !shapeRefFound || !hasShapeRef ) { // remove the whole submeshes branch - myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch ); + aStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch ); found = false; } } // end check if there is shape reference in submeshes - if ( found ) { - char name_meshgroup[ 30 ]; - if ( i == GetSubMeshOnVertexTag() ) - strcpy( name_meshgroup, "SubMeshes On Vertex" ); - else if ( i == GetSubMeshOnEdgeTag() ) - strcpy( name_meshgroup, "SubMeshes On Edge" ); - else if ( i == GetSubMeshOnWireTag() ) - strcpy( name_meshgroup, "SubMeshes On Wire" ); - else if ( i == GetSubMeshOnFaceTag() ) - strcpy( name_meshgroup, "SubMeshes On Face" ); - else if ( i == GetSubMeshOnShellTag() ) - strcpy( name_meshgroup, "SubMeshes On Shell" ); - else if ( i == GetSubMeshOnSolidTag() ) - strcpy( name_meshgroup, "SubMeshes On Solid" ); - else if ( i == GetSubMeshOnCompoundTag() ) - strcpy( name_meshgroup, "SubMeshes On Compound" ); - - // for each type of submeshes create container HDF group - aGroup = new HDFgroup( name_meshgroup, aTopGroup ); - aGroup->CreateOnDisk(); - - // iterator for all submeshes of given type - SALOMEDS::ChildIterator_var itSM = myCurrentStudy->NewChildIterator( mySubmeshBranch ); - for ( ; itSM->More(); itSM->Next() ) { - SALOMEDS::SObject_var mySObject = itSM->Value(); - CORBA::Object_var anSubObject = SObjectToObject( mySObject ); - if ( !CORBA::is_nil( anSubObject )) + if ( found ) { + char name_meshgroup[ 30 ]; + if ( i == GetSubMeshOnVertexTag() ) + strcpy( name_meshgroup, "SubMeshes On Vertex" ); + else if ( i == GetSubMeshOnEdgeTag() ) + strcpy( name_meshgroup, "SubMeshes On Edge" ); + else if ( i == GetSubMeshOnWireTag() ) + strcpy( name_meshgroup, "SubMeshes On Wire" ); + else if ( i == GetSubMeshOnFaceTag() ) + strcpy( name_meshgroup, "SubMeshes On Face" ); + else if ( i == GetSubMeshOnShellTag() ) + strcpy( name_meshgroup, "SubMeshes On Shell" ); + else if ( i == GetSubMeshOnSolidTag() ) + strcpy( name_meshgroup, "SubMeshes On Solid" ); + else if ( i == GetSubMeshOnCompoundTag() ) + strcpy( name_meshgroup, "SubMeshes On Compound" ); + + // for each type of submeshes create container HDF group + aGroup = new HDFgroup( name_meshgroup, aTopGroup ); + aGroup->CreateOnDisk(); + + // iterator for all submeshes of given type + SALOMEDS::ChildIterator_wrap itSM = aStudy->NewChildIterator( mySubmeshBranch ); + for ( ; itSM->More(); itSM->Next() ) { + SALOMEDS::SObject_wrap mySObject = itSM->Value(); + CORBA::Object_var anSubObject = SObjectToObject( mySObject ); + if ( !CORBA::is_nil( anSubObject )) { - SMESH::SMESH_subMesh_var mySubMesh = SMESH::SMESH_subMesh::_narrow( anSubObject ) ; - int subid = myStudyContext->findId( string( GetORB()->object_to_string( anSubObject ) ) ); - - // for each mesh open the HDF group basing on its id - char submeshGrpName[ 30 ]; - sprintf( submeshGrpName, "SubMesh %d", subid ); - aSubGroup = new HDFgroup( submeshGrpName, aGroup ); - aSubGroup->CreateOnDisk(); - - // write reference on a shape, already checked if it exists - SALOMEDS::SObject_var mySubRef, myShape; - if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef )) - mySubRef->ReferencedObject( myShape ); + SMESH::SMESH_subMesh_var mySubMesh = SMESH::SMESH_subMesh::_narrow( anSubObject ) ; + CORBA::String_var objStr = GetORB()->object_to_string( anSubObject ); + int subid = myStudyContext->findId( string( objStr.in() ) ); + + // for each mesh open the HDF group basing on its id + char submeshGrpName[ 30 ]; + sprintf( submeshGrpName, "SubMesh %d", subid ); + aSubGroup = new HDFgroup( submeshGrpName, aGroup ); + aSubGroup->CreateOnDisk(); + + // write reference on a shape, already checked if it exists + SALOMEDS::SObject_wrap mySubRef, myShape; + if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() )) + mySubRef->ReferencedObject( myShape.inout() ); string myRefOnObject = myShape->GetID(); if ( myRefOnObject.length() > 0 ) { aSize[ 0 ] = myRefOnObject.length() + 1; @@ -1487,189 +4696,289 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, aDataset->CloseOnDisk(); } - // write applied hypotheses if exist - SALOMEDS::SObject_var mySubHypBranch; - found = mySObject->FindSubObject( GetRefOnAppliedHypothesisTag(), mySubHypBranch ); - if ( found ) { - aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup ); - aSubSubGroup->CreateOnDisk(); - - SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( mySubHypBranch ); - int hypNb = 0; - for ( ; it->More(); it->Next() ) { - SALOMEDS::SObject_var mySubSObject = it->Value(); - SALOMEDS::SObject_var myRefOnHyp; - bool ok = mySubSObject->ReferencedObject( myRefOnHyp ); - if ( ok ) { - //string myRefOnObject = myRefOnHyp->GetID(); - CORBA::Object_var anObject = SObjectToObject( myRefOnHyp ); - int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) ); - //if ( myRefOnObject.length() > 0 ) { - //aSize[ 0 ] = myRefOnObject.length() + 1; - char hypName[ 30 ], hypId[ 30 ]; - sprintf( hypName, "Hyp %d", ++hypNb ); - sprintf( hypId, "%d", id ); - aSize[ 0 ] = strlen( hypId ) + 1; - aDataset = new HDFdataset( hypName, aSubSubGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); - aDataset->WriteOnDisk( hypId ); - aDataset->CloseOnDisk(); - //} - } - } - aSubSubGroup->CloseOnDisk(); - } - - // write applied algorithms if exist - SALOMEDS::SObject_var mySubAlgoBranch; - found = mySObject->FindSubObject( GetRefOnAppliedAlgorithmsTag(), mySubAlgoBranch ); - if ( found ) { - aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup ); - aSubSubGroup->CreateOnDisk(); - - SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( mySubAlgoBranch ); - int algoNb = 0; - for ( ; it->More(); it->Next() ) { - SALOMEDS::SObject_var mySubSObject = it->Value(); - SALOMEDS::SObject_var myRefOnAlgo; - bool ok = mySubSObject->ReferencedObject( myRefOnAlgo ); - if ( ok ) { - //string myRefOnObject = myRefOnAlgo->GetID(); - CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo ); - int id = myStudyContext->findId( string( GetORB()->object_to_string( anObject ) ) ); - //if ( myRefOnObject.length() > 0 ) { - //aSize[ 0 ] = myRefOnObject.length() + 1; - char algoName[ 30 ], algoId[ 30 ]; - sprintf( algoName, "Algo %d", ++algoNb ); - sprintf( algoId, "%d", id ); - aSize[ 0 ] = strlen( algoId ) + 1; - aDataset = new HDFdataset( algoName, aSubSubGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); - aDataset->WriteOnDisk( algoId ); - aDataset->CloseOnDisk(); - //} - } - } - aSubSubGroup->CloseOnDisk(); - } - // close submesh HDF group - aSubGroup->CloseOnDisk(); - } - } - // close container of submeshes by type HDF group - aGroup->CloseOnDisk(); - } - } + // write applied hypotheses if exist + SALOMEDS::SObject_wrap mySubHypBranch; + found = mySObject->FindSubObject( GetRefOnAppliedHypothesisTag(), + mySubHypBranch.inout() ); + if ( found ) { + aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup ); + aSubSubGroup->CreateOnDisk(); + + SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( mySubHypBranch ); + int hypNb = 0; + for ( ; it->More(); it->Next() ) { + SALOMEDS::SObject_wrap mySubSObject = it->Value(); + SALOMEDS::SObject_wrap myRefOnHyp; + bool ok = mySubSObject->ReferencedObject( myRefOnHyp.inout() ); + if ( ok ) { + //string myRefOnObject = myRefOnHyp->GetID(); + CORBA::Object_var anObject = SObjectToObject( myRefOnHyp ); + CORBA::String_var objStr = GetORB()->object_to_string( anObject ); + int id = myStudyContext->findId( string( objStr.in() ) ); + //if ( myRefOnObject.length() > 0 ) { + //aSize[ 0 ] = myRefOnObject.length() + 1; + char hypName[ 30 ], hypId[ 30 ]; + sprintf( hypName, "Hyp %d", ++hypNb ); + sprintf( hypId, "%d", id ); + aSize[ 0 ] = strlen( hypId ) + 1; + aDataset = new HDFdataset( hypName, aSubSubGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); + aDataset->WriteOnDisk( hypId ); + aDataset->CloseOnDisk(); + //} + } + } + aSubSubGroup->CloseOnDisk(); + } + + // write applied algorithms if exist + SALOMEDS::SObject_wrap mySubAlgoBranch; + found = mySObject->FindSubObject( GetRefOnAppliedAlgorithmsTag(), + mySubAlgoBranch.inout() ); + if ( found ) { + aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup ); + aSubSubGroup->CreateOnDisk(); + + SALOMEDS::ChildIterator_wrap it = + aStudy->NewChildIterator( mySubAlgoBranch ); + int algoNb = 0; + for ( ; it->More(); it->Next() ) { + SALOMEDS::SObject_wrap mySubSObject = it->Value(); + SALOMEDS::SObject_wrap myRefOnAlgo; + bool ok = mySubSObject->ReferencedObject( myRefOnAlgo.inout() ); + if ( ok ) { + //string myRefOnObject = myRefOnAlgo->GetID(); + CORBA::Object_var anObject = SObjectToObject( myRefOnAlgo ); + CORBA::String_var objStr = GetORB()->object_to_string( anObject ); + int id = myStudyContext->findId( string( objStr.in() ) ); + //if ( myRefOnObject.length() > 0 ) { + //aSize[ 0 ] = myRefOnObject.length() + 1; + char algoName[ 30 ], algoId[ 30 ]; + sprintf( algoName, "Algo %d", ++algoNb ); + sprintf( algoId, "%d", id ); + aSize[ 0 ] = strlen( algoId ) + 1; + aDataset = new HDFdataset( algoName, aSubSubGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + //aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); + aDataset->WriteOnDisk( algoId ); + aDataset->CloseOnDisk(); + //} + } + } + aSubSubGroup->CloseOnDisk(); + } + // close submesh HDF group + aSubGroup->CloseOnDisk(); + } + } + // close container of submeshes by type HDF group + aGroup->CloseOnDisk(); + } + } // All sub-meshes will be stored in MED file - if ( shapeRefFound ) - myWriter.AddAllSubMeshes(); - - // groups root sub-branch - SALOMEDS::SObject_var myGroupsBranch; - for ( int i = GetNodeGroupsTag(); i <= GetVolumeGroupsTag(); i++ ) { - found = gotBranch->FindSubObject( i, myGroupsBranch ); - if ( found ) { - char name_group[ 30 ]; - if ( i == GetNodeGroupsTag() ) - strcpy( name_group, "Groups of Nodes" ); - else if ( i == GetEdgeGroupsTag() ) - strcpy( name_group, "Groups of Edges" ); - else if ( i == GetFaceGroupsTag() ) - strcpy( name_group, "Groups of Faces" ); - else if ( i == GetVolumeGroupsTag() ) - strcpy( name_group, "Groups of Volumes" ); - - aGroup = new HDFgroup( name_group, aTopGroup ); - aGroup->CreateOnDisk(); - - SALOMEDS::ChildIterator_var it = myCurrentStudy->NewChildIterator( myGroupsBranch ); - for ( ; it->More(); it->Next() ) { - SALOMEDS::SObject_var mySObject = it->Value(); - CORBA::Object_var aSubObject = SObjectToObject( mySObject ); - if ( !CORBA::is_nil( aSubObject ) ) { - SMESH_GroupBase_i* myGroupImpl = + // .. will NOT (PAL 12992) + //if ( shapeRefFound ) + //myWriter.AddAllSubMeshes(); + + // store submesh order if any + const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder(); + if ( theOrderIds.size() ) { + char order_list[ 30 ]; + strcpy( order_list, "Mesh Order" ); + // count number of submesh ids + int nbIDs = 0; + TListOfListOfInt::const_iterator idIt = theOrderIds.begin(); + for ( ; idIt != theOrderIds.end(); idIt++ ) + nbIDs += (*idIt).size(); + // number of values = number of IDs + + // number of lists (for separators) - 1 + int* smIDs = new int [ nbIDs + theOrderIds.size() - 1 ]; + idIt = theOrderIds.begin(); + for ( int i = 0; idIt != theOrderIds.end(); idIt++ ) { + const TListOfInt& idList = *idIt; + if (idIt != theOrderIds.begin()) // not first list + smIDs[ i++ ] = -1/* *idList.size()*/; // separator between lists + // dump submesh ids from current list + TListOfInt::const_iterator id_smId = idList.begin(); + for( ; id_smId != idList.end(); id_smId++ ) + smIDs[ i++ ] = *id_smId; + } + // write HDF group + aSize[ 0 ] = nbIDs + theOrderIds.size() - 1; + + aDataset = new HDFdataset( order_list, aTopGroup, HDF_INT32, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( smIDs ); + aDataset->CloseOnDisk(); + // + delete[] smIDs; + } + + // groups root sub-branch + SALOMEDS::SObject_wrap myGroupsBranch; + for ( int i = GetNodeGroupsTag(); i <= GetBallElementsGroupsTag(); i++ ) { + found = gotBranch->FindSubObject( i, myGroupsBranch.inout() ); + if ( found ) { + char name_group[ 30 ]; + if ( i == GetNodeGroupsTag() ) + strcpy( name_group, "Groups of Nodes" ); + else if ( i == GetEdgeGroupsTag() ) + strcpy( name_group, "Groups of Edges" ); + else if ( i == GetFaceGroupsTag() ) + strcpy( name_group, "Groups of Faces" ); + else if ( i == GetVolumeGroupsTag() ) + strcpy( name_group, "Groups of Volumes" ); + else if ( i == Get0DElementsGroupsTag() ) + strcpy( name_group, "Groups of 0D Elements" ); + else if ( i == GetBallElementsGroupsTag() ) + strcpy( name_group, "Groups of Balls" ); + + aGroup = new HDFgroup( name_group, aTopGroup ); + aGroup->CreateOnDisk(); + + SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myGroupsBranch ); + for ( ; it->More(); it->Next() ) { + SALOMEDS::SObject_wrap mySObject = it->Value(); + CORBA::Object_var aSubObject = SObjectToObject( mySObject ); + if ( !CORBA::is_nil( aSubObject ) ) { + SMESH_GroupBase_i* myGroupImpl = dynamic_cast( GetServant( aSubObject ).in() ); - if ( !myGroupImpl ) - continue; + if ( !myGroupImpl ) + continue; + SMESHDS_GroupBase* aGrpBaseDS = myGroupImpl->GetGroupDS(); + if ( !aGrpBaseDS ) + continue; - int anId = myStudyContext->findId( string( GetORB()->object_to_string( aSubObject ) ) ); - - // For each group, create a dataset named "Group " + CORBA::String_var objStr = GetORB()->object_to_string( aSubObject ); + int anId = myStudyContext->findId( string( objStr.in() ) ); + + // For each group, create a dataset named "Group " // and store the group's user name into it - char grpName[ 30 ]; - sprintf( grpName, "Group %d", anId ); - char* aUserName = myGroupImpl->GetName(); - aSize[ 0 ] = strlen( aUserName ) + 1; - - aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 ); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( aUserName ); - aDataset->CloseOnDisk(); - - // Store the group contents into MED file - if ( myLocMesh.GetGroup( myGroupImpl->GetLocalID() ) ) { - - if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen_i::Save(): saving group with StoreName = " - << grpName << " to MED file" ); - SMESHDS_GroupBase* aGrpBaseDS = - myLocMesh.GetGroup( myGroupImpl->GetLocalID() )->GetGroupDS(); - aGrpBaseDS->SetStoreName( grpName ); - - // Pass SMESHDS_Group to MED writer - SMESHDS_Group* aGrpDS = dynamic_cast( aGrpBaseDS ); - if ( aGrpDS ) - myWriter.AddGroup( aGrpDS ); - - // write reference on a shape if exists - SMESHDS_GroupOnGeom* aGeomGrp = - dynamic_cast( aGrpBaseDS ); - if ( aGeomGrp ) { - SALOMEDS::SObject_var mySubRef, myShape; - if (mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef ) && - mySubRef->ReferencedObject( myShape ) && - !CORBA::is_nil( myShape->GetObject() )) - { - string myRefOnObject = myShape->GetID(); - if ( myRefOnObject.length() > 0 ) { - char aRefName[ 30 ]; - sprintf( aRefName, "Ref on shape %d", anId); - aSize[ 0 ] = myRefOnObject.length() + 1; - aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1); - aDataset->CreateOnDisk(); - aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) ); - aDataset->CloseOnDisk(); - } - } - else // shape ref is invalid: - { - // save a group on geometry as ordinary group - myWriter.AddGroup( aGeomGrp ); + const char* grpName = aGrpBaseDS->GetStoreName(); + CORBA::String_var aUserName = myGroupImpl->GetName(); + aSize[ 0 ] = strlen( aUserName ) + 1; + + aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( aUserName ); + aDataset->CloseOnDisk(); + + // ouv : NPAL12872 + // For each group, create a dataset named "Group Color" + // and store the group's color into it + char grpColorName[ 30 ]; + sprintf( grpColorName, "ColorGroup %d", anId ); + SALOMEDS::Color aColor = myGroupImpl->GetColor(); + double anRGB[3]; + anRGB[ 0 ] = aColor.R; + anRGB[ 1 ] = aColor.G; + anRGB[ 2 ] = aColor.B; + aSize[ 0 ] = 3; + aDataset = new HDFdataset( grpColorName, aGroup, HDF_FLOAT64, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( anRGB ); + aDataset->CloseOnDisk(); + + // Pass SMESHDS_Group to MED writer + SMESHDS_Group* aGrpDS = dynamic_cast( aGrpBaseDS ); + if ( aGrpDS ) + myWriter.AddGroup( aGrpDS ); + + // write reference on a shape if exists + SMESHDS_GroupOnGeom* aGeomGrp = + dynamic_cast( aGrpBaseDS ); + if ( aGeomGrp ) { + SALOMEDS::SObject_wrap mySubRef, myShape; + if (mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ) && + mySubRef->ReferencedObject( myShape.inout() ) && + !CORBA::is_nil( myShape->GetObject() )) + { + CORBA::String_var myRefOnObject = myShape->GetID(); + if ( myRefOnObject.in()[0] ) { + char aRefName[ 30 ]; + sprintf( aRefName, "Ref on shape %d", anId); + aSize[ 0 ] = strlen( myRefOnObject.in() ) + 1; + aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( myRefOnObject.in() )); + aDataset->CloseOnDisk(); } } - } - } - } - aGroup->CloseOnDisk(); - } - } // loop on groups - - if ( strcmp( strHasData.c_str(), "1" ) == 0 ) + else // shape ref is invalid: + { + // save a group on geometry as ordinary group + myWriter.AddGroup( aGeomGrp ); + } + } + else if ( SMESH_GroupOnFilter_i* aFilterGrp_i = + dynamic_cast( myGroupImpl )) + { + std::string str = aFilterGrp_i->FilterToString(); + std::string hdfGrpName = "Filter " + SMESH_Comment(anId); + aSize[ 0 ] = str.length() + 1; + aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup, HDF_STRING, aSize, 1); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( ( char* )( str.c_str() ) ); + aDataset->CloseOnDisk(); + } + } + } + aGroup->CloseOnDisk(); + } + } // loop on groups + + if ( strcmp( strHasData.c_str(), "1" ) == 0 ) { // Flush current mesh information into MED file - myWriter.Perform(); + myWriter.Perform(); + + // save info on nb of elements + SMESH_PreMeshInfo::SaveToFile( myImpl, id, aFile ); // maybe a shape was deleted in the study - if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() ) { + if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() && hasShape) { TopoDS_Shape nullShape; myLocMesh.ShapeToMesh( nullShape ); // remove shape referring data } - // Store node positions on sub-shapes (SMDS_Position): - - if ( !mySMESHDSMesh->SubMeshes().empty() ) + SMESHDS_SubMeshIteratorPtr smIt = mySMESHDSMesh->SubMeshes(); + if ( smIt->more() ) { + // Store submeshes + // ---------------- + aGroup = new HDFgroup( "Submeshes", aTopGroup ); + aGroup->CreateOnDisk(); + + // each element belongs to one or none submesh, + // so for each node/element, we store a submesh ID + + // Store submesh IDs + for ( int isNode = 0; isNode < 2; ++isNode ) + { + SMDS_ElemIteratorPtr eIt = + mySMESHDSMesh->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All ); + int nbElems = isNode ? mySMESHDSMesh->NbNodes() : mySMESHDSMesh->GetMeshInfo().NbElements(); + if ( nbElems < 1 ) + continue; + std::vector smIDs; smIDs.reserve( nbElems ); + while ( eIt->more() ) + if ( const SMDS_MeshElement* e = eIt->next()) + smIDs.push_back( e->getshapeId() ); + // write HDF group + aSize[ 0 ] = nbElems; + string aDSName( isNode ? "Node Submeshes" : "Element Submeshes"); + aDataset = new HDFdataset( (char*)aDSName.c_str(), aGroup, HDF_INT32, aSize, 1 ); + aDataset->CreateOnDisk(); + aDataset->WriteOnDisk( & smIDs[0] ); + aDataset->CloseOnDisk(); + } + + aGroup->CloseOnDisk(); + + // Store node positions on sub-shapes (SMDS_Position): + // ---------------------------------------------------- + aGroup = new HDFgroup( "Node Positions", aTopGroup ); aGroup->CreateOnDisk(); @@ -1681,21 +4990,21 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, // "Face V positions" - V parameter of node on face // Find out nb of nodes on edges and faces - // Collect corresponing sub-meshes + // Collect corresponding sub-meshes int nbEdgeNodes = 0, nbFaceNodes = 0; list aEdgeSM, aFaceSM; // loop on SMESHDS_SubMesh'es - const map& aSubMeshes = mySMESHDSMesh->SubMeshes(); - map::const_iterator itSubM ( aSubMeshes.begin() ); - for ( ; itSubM != aSubMeshes.end() ; itSubM++ ) + while ( smIt->more() ) { - SMESHDS_SubMesh* aSubMesh = (*itSubM).second; + SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( smIt->next() ); if ( aSubMesh->IsComplexSubmesh() ) continue; // submesh containing other submeshs int nbNodes = aSubMesh->NbNodes(); if ( nbNodes == 0 ) continue; - int aShapeID = (*itSubM).first; + int aShapeID = aSubMesh->GetID(); + if ( aShapeID < 1 || aShapeID > mySMESHDSMesh->MaxShapeIndex() ) + continue; int aShapeType = mySMESHDSMesh->IndexToShape( aShapeID ).ShapeType(); // write only SMDS_FacePosition and SMDS_EdgePosition switch ( aShapeType ) { @@ -1728,8 +5037,6 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, for ( ; itSM != pListSM->end(); itSM++ ) { SMESHDS_SubMesh* aSubMesh = (*itSM); - if ( aSubMesh->IsComplexSubmesh() ) - continue; // submesh containing other submeshs SMDS_NodeIteratorPtr itNode = aSubMesh->GetNodes(); // loop on nodes in aSubMesh @@ -1742,8 +5049,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, // Position const SMDS_PositionPtr pos = node->GetPosition(); if ( onFace ) { // on FACE - const SMDS_FacePosition* fPos = - dynamic_cast( pos.get() ); + SMDS_FacePositionPtr fPos = pos; if ( fPos ) { aUPos[ iNode ] = fPos->GetUParameter(); aVPos[ iNode ] = fPos->GetVParameter(); @@ -1753,8 +5059,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, nbNodes--; } else { // on EDGE - const SMDS_EdgePosition* ePos = - dynamic_cast( pos.get() ); + SMDS_EdgePositionPtr ePos = pos; if ( ePos ) { aUPos[ iNode ] = ePos->GetUParameter(); iNode++; @@ -1797,15 +5102,15 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, } // treat positions on edges or faces // close "Node Positions" group - aGroup->CloseOnDisk(); + aGroup->CloseOnDisk(); } // if ( there are submeshes in SMESHDS_Mesh ) } // if ( hasData ) - // close mesh HDF group - aTopGroup->CloseOnDisk(); - } - } + // close mesh HDF group + aTopGroup->CloseOnDisk(); + } + } } } } @@ -1815,13 +5120,12 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, delete aFile; // Convert temporary files to stream - aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq.in(), isMultiFile ); + aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq, isMultiFile ); // Remove temporary files and directory - if ( !isMultiFile ) - SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true ); + if ( !isMultiFile ) + SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq, true ); - INFOS( "SMESH_Gen_i::Save() completed" ); return aStreamFile._retn(); } @@ -1829,37 +5133,29 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent, /*! * SMESH_Gen_i::SaveASCII * - * Save SMESH module's data in ASCII format (not implemented yet) + * Save SMESH module's data in ASCII format */ //============================================================================= SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent, - const char* theURL, - bool isMultiFile ) { + const char* theURL, + bool isMultiFile ) { if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SaveASCII" ); SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile ); return aStreamFile._retn(); -} -//============================================================================= -/*! - * SMESH_Gen_i::loadGeomData - * - * Load GEOM module data - */ -//============================================================================= + //after usual saving needs to encipher binary to text string + //Any binary symbol will be represent as "|xx" () hexadecimal format number + int size = aStreamFile.in().length(); + _CORBA_Octet* buffer = new _CORBA_Octet[size*3+1]; + for ( int i = 0; i < size; i++ ) + sprintf( (char*)&(buffer[i*3]), "|%02x", aStreamFile[i] ); -void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot ) -{ - if ( theCompRoot->_is_nil() ) - return; + buffer[size * 3] = '\0'; - SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theCompRoot->GetStudy() ); - if ( aStudy->_is_nil() ) - return; + SALOMEDS::TMPFile_var anAsciiStreamFile = new SALOMEDS::TMPFile(size*3, size*3, buffer, 1); - SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder(); - aStudyBuilder->LoadWith( theCompRoot, GetGeomEngine() ); + return anAsciiStreamFile._retn(); } //============================================================================= @@ -1871,40 +5167,31 @@ void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot ) //============================================================================= bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, - const SALOMEDS::TMPFile& theStream, - const char* theURL, - bool isMultiFile ) + const SALOMEDS::TMPFile& theStream, + const char* theURL, + bool isMultiFile ) { - INFOS( "SMESH_Gen_i::Load" ); + UpdateStudy(); // load geom data + Kernel_Utils::Localizer loc; - if ( myCurrentStudy->_is_nil() || - theComponent->GetStudy()->StudyId() != myCurrentStudy->StudyId() ) - SetCurrentStudy( theComponent->GetStudy() ); - -/* if( !theComponent->_is_nil() ) - { - //SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theComponent->GetStudy() ); - if( !myCurrentStudy->FindComponent( "GEOM" )->_is_nil() ) - loadGeomData( myCurrentStudy->FindComponent( "GEOM" ) ); - }*/ + SALOMEDS::Study_var aStudy = getStudyServant(); - StudyContext* myStudyContext = GetCurrentStudyContext(); - // Get temporary files location TCollection_AsciiString tmpDir = - isMultiFile ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str(); + ( char* )( isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir().c_str() ); // Convert the stream into sequence of files to process - SALOMEDS::ListOfFileNames_var aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream, - tmpDir.ToCString(), - isMultiFile ); + SALOMEDS_Tool::ListOfFiles aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream, + tmpDir.ToCString(), + isMultiFile ); TCollection_AsciiString aStudyName( "" ); - if ( isMultiFile ) - aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() ); - + if ( isMultiFile ) { + CORBA::WString_var url = aStudy->URL(); + aStudyName = (char*)SALOMEDS_Tool::GetNameFromPath( Kernel_Utils::encode(url.in()) ).c_str(); + } // Set names of temporary files - TCollection_AsciiString filename = tmpDir + aStudyName + TCollection_AsciiString( "_SMESH.hdf" ); - TCollection_AsciiString meshfile = tmpDir + aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" ); + TCollection_AsciiString filename = tmpDir + aStudyName + "_SMESH.hdf"; + TCollection_AsciiString meshfile = tmpDir + aStudyName + "_SMESH_Mesh.med"; int size; HDFfile* aFile; @@ -1916,7 +5203,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, // Read data // ---> open HDF file - aFile = new HDFfile( filename.ToCString() ); + aFile = new HDFfile( (char*) filename.ToCString() ); try { aFile->OpenOnDisk( HDF_RDONLY ); } @@ -1925,205 +5212,229 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, return false; } - DriverMED_R_SMESHDS_Mesh myReader; - myReader.SetFile( meshfile.ToCString() ); + TPythonDump pd; // prevent dump during loading + + // DriverMED_R_SMESHDS_Mesh myReader; + // myReader.SetFile( meshfile.ToCString() ); + + // For PAL13473 ("Repetitive mesh") implementation. + // New dependencies between SMESH objects are established: + // now hypotheses can refer to meshes, shapes and other hypotheses. + // To keep data consistent, the following order of data restoration + // imposed: + // 1. Create hypotheses + // 2. Create all meshes + // 3. Load hypotheses' data + // 4. All the rest + + list< pair< SMESH_Hypothesis_i*, string > > hypDataList; + list< pair< SMESH_Mesh_i*, HDFgroup* > > meshGroupList; + list< SMESH::Filter_var > filters; // get total number of top-level groups - int aNbGroups = aFile->nInternalObjects(); + int aNbGroups = aFile->nInternalObjects(); if ( aNbGroups > 0 ) { // --> in first turn we should read&create hypotheses if ( aFile->ExistInternalObject( "Hypotheses" ) ) { // open hypotheses root HDF group - aTopGroup = new HDFgroup( "Hypotheses", aFile ); + aTopGroup = new HDFgroup( "Hypotheses", aFile ); aTopGroup->OpenOnDisk(); // get number of hypotheses - int aNbObjects = aTopGroup->nInternalObjects(); + int aNbObjects = aTopGroup->nInternalObjects(); for ( int j = 0; j < aNbObjects; j++ ) { - // try to identify hypothesis - char hypGrpName[ HDF_NAME_MAX_LEN+1 ]; + // try to identify hypothesis + char hypGrpName[ HDF_NAME_MAX_LEN+1 ]; aTopGroup->InternalObjectIndentify( j, hypGrpName ); - if ( string( hypGrpName ).substr( 0, 10 ) == string( "Hypothesis" ) ) { - // open hypothesis group - aGroup = new HDFgroup( hypGrpName, aTopGroup ); - aGroup->OpenOnDisk(); - - // --> get hypothesis id - int id = atoi( string( hypGrpName ).substr( 10 ).c_str() ); - string hypname; - string libname; - string hypdata; - - // get number of datasets - int aNbSubObjects = aGroup->nInternalObjects(); - for ( int k = 0; k < aNbSubObjects; k++ ) { - // identify dataset - char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ]; - aGroup->InternalObjectIndentify( k, name_of_subgroup ); - // --> get hypothesis name - if ( strcmp( name_of_subgroup, "Name" ) == 0 ) { - aDataset = new HDFdataset( name_of_subgroup, aGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* hypname_str = new char[ size ]; - aDataset->ReadFromDisk( hypname_str ); - hypname = string( hypname_str ); - delete [] hypname_str; - aDataset->CloseOnDisk(); - } - // --> get hypothesis plugin library name - if ( strcmp( name_of_subgroup, "LibName" ) == 0 ) { - aDataset = new HDFdataset( name_of_subgroup, aGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* libname_str = new char[ size ]; - aDataset->ReadFromDisk( libname_str ); - if(MYDEBUG) SCRUTE( libname_str ); - libname = string( libname_str ); - delete [] libname_str; - aDataset->CloseOnDisk(); - } - // --> get hypothesis data - if ( strcmp( name_of_subgroup, "Data" ) == 0 ) { - aDataset = new HDFdataset( name_of_subgroup, aGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* hypdata_str = new char[ size ]; - aDataset->ReadFromDisk( hypdata_str ); - hypdata = string( hypdata_str ); - delete [] hypdata_str; - aDataset->CloseOnDisk(); - } - } - // close hypothesis HDF group - aGroup->CloseOnDisk(); - - // --> restore hypothesis from data - if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty - if(MYDEBUG) MESSAGE("VSR - load hypothesis : id = " << id << - ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str()); + if ( string( hypGrpName ).substr( 0, 10 ) == string( "Hypothesis" ) ) { + // open hypothesis group + aGroup = new HDFgroup( hypGrpName, aTopGroup ); + aGroup->OpenOnDisk(); + + // --> get hypothesis id + int id = atoi( string( hypGrpName ).substr( 10 ).c_str() ); + string hypname; + string libname; + string hypdata; + + // get number of datasets + int aNbSubObjects = aGroup->nInternalObjects(); + for ( int k = 0; k < aNbSubObjects; k++ ) { + // identify dataset + char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ]; + aGroup->InternalObjectIndentify( k, name_of_subgroup ); + // --> get hypothesis name + if ( strcmp( name_of_subgroup, "Name" ) == 0 ) { + aDataset = new HDFdataset( name_of_subgroup, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* hypname_str = new char[ size ]; + aDataset->ReadFromDisk( hypname_str ); + hypname = string( hypname_str ); + delete [] hypname_str; + aDataset->CloseOnDisk(); + } + // --> get hypothesis plugin library name + if ( strcmp( name_of_subgroup, "LibName" ) == 0 ) { + aDataset = new HDFdataset( name_of_subgroup, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* libname_str = new char[ size ]; + aDataset->ReadFromDisk( libname_str ); + if(MYDEBUG) SCRUTE( libname_str ); + libname = string( libname_str ); + delete [] libname_str; + aDataset->CloseOnDisk(); + } + // --> get hypothesis data + if ( strcmp( name_of_subgroup, "Data" ) == 0 ) { + aDataset = new HDFdataset( name_of_subgroup, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* hypdata_str = new char[ size ]; + aDataset->ReadFromDisk( hypdata_str ); + hypdata = string( hypdata_str ); + delete [] hypdata_str; + aDataset->CloseOnDisk(); + } + } + // close hypothesis HDF group + aGroup->CloseOnDisk(); + + // --> restore hypothesis from data + if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty + if(MYDEBUG) MESSAGE("VSR - load hypothesis : id = " << id << + ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str()); SMESH::SMESH_Hypothesis_var myHyp; - - try { // protect persistence mechanism against exceptions - myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() ); - } - catch (...) { - INFOS( "Exception during hypothesis creation" ); - } - - SMESH_Hypothesis_i* myImpl = dynamic_cast( GetServant( myHyp ).in() ); - if ( myImpl ) { - myImpl->LoadFrom( hypdata.c_str() ); - string iorString = GetORB()->object_to_string( myHyp ); - int newId = myStudyContext->findId( iorString ); - myStudyContext->mapOldToNew( id, newId ); - } - else - if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" ); + + try { // protect persistence mechanism against exceptions + myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() ); + } + catch (...) { + INFOS( "Exception during hypothesis creation" ); + } + + SMESH_Hypothesis_i* myImpl = dynamic_cast( GetServant( myHyp ).in() ); + if ( myImpl ) { + // myImpl->LoadFrom( hypdata.c_str() ); + hypDataList.push_back( make_pair( myImpl, hypdata )); + CORBA::String_var iorString = GetORB()->object_to_string( myHyp ); + int newId = myStudyContext->findId( iorString.in() ); + myStudyContext->mapOldToNew( id, newId ); + } + else + if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" ); } } } // close hypotheses root HDF group aTopGroup->CloseOnDisk(); + aTopGroup = 0; } // --> then we should read&create algorithms if ( aFile->ExistInternalObject( "Algorithms" ) ) { // open algorithms root HDF group - aTopGroup = new HDFgroup( "Algorithms", aFile ); + aTopGroup = new HDFgroup( "Algorithms", aFile ); aTopGroup->OpenOnDisk(); // get number of algorithms - int aNbObjects = aTopGroup->nInternalObjects(); + int aNbObjects = aTopGroup->nInternalObjects(); for ( int j = 0; j < aNbObjects; j++ ) { - // try to identify algorithm - char hypGrpName[ HDF_NAME_MAX_LEN+1 ]; + // try to identify algorithm + char hypGrpName[ HDF_NAME_MAX_LEN+1 ]; aTopGroup->InternalObjectIndentify( j, hypGrpName ); - if ( string( hypGrpName ).substr( 0, 9 ) == string( "Algorithm" ) ) { - // open algorithm group - aGroup = new HDFgroup( hypGrpName, aTopGroup ); - aGroup->OpenOnDisk(); - - // --> get algorithm id - int id = atoi( string( hypGrpName ).substr( 9 ).c_str() ); - string hypname; - string libname; - string hypdata; - - // get number of datasets - int aNbSubObjects = aGroup->nInternalObjects(); - for ( int k = 0; k < aNbSubObjects; k++ ) { - // identify dataset - char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ]; - aGroup->InternalObjectIndentify( k, name_of_subgroup ); - // --> get algorithm name - if ( strcmp( name_of_subgroup, "Name" ) == 0 ) { - aDataset = new HDFdataset( name_of_subgroup, aGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* hypname_str = new char[ size ]; - aDataset->ReadFromDisk( hypname_str ); - hypname = string( hypname_str ); - delete [] hypname_str; - aDataset->CloseOnDisk(); - } - // --> get algorithm plugin library name - if ( strcmp( name_of_subgroup, "LibName" ) == 0 ) { - aDataset = new HDFdataset( name_of_subgroup, aGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* libname_str = new char[ size ]; - aDataset->ReadFromDisk( libname_str ); - if(MYDEBUG) SCRUTE( libname_str ); - libname = string( libname_str ); - delete [] libname_str; - aDataset->CloseOnDisk(); - } - // --> get algorithm data - if ( strcmp( name_of_subgroup, "Data" ) == 0 ) { - aDataset = new HDFdataset( name_of_subgroup, aGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* hypdata_str = new char[ size ]; - aDataset->ReadFromDisk( hypdata_str ); - if(MYDEBUG) SCRUTE( hypdata_str ); - hypdata = string( hypdata_str ); - delete [] hypdata_str; - aDataset->CloseOnDisk(); - } - } - // close algorithm HDF group - aGroup->CloseOnDisk(); - - // --> restore algorithm from data - if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty - if(MYDEBUG) MESSAGE("VSR - load algo : id = " << id << - ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str()); + if ( string( hypGrpName ).substr( 0, 9 ) == string( "Algorithm" ) ) { + // open algorithm group + aGroup = new HDFgroup( hypGrpName, aTopGroup ); + aGroup->OpenOnDisk(); + + // --> get algorithm id + int id = atoi( string( hypGrpName ).substr( 9 ).c_str() ); + string hypname; + string libname; + string hypdata; + + // get number of datasets + int aNbSubObjects = aGroup->nInternalObjects(); + for ( int k = 0; k < aNbSubObjects; k++ ) { + // identify dataset + char name_of_subgroup[ HDF_NAME_MAX_LEN+1 ]; + aGroup->InternalObjectIndentify( k, name_of_subgroup ); + // --> get algorithm name + if ( strcmp( name_of_subgroup, "Name" ) == 0 ) { + aDataset = new HDFdataset( name_of_subgroup, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* hypname_str = new char[ size ]; + aDataset->ReadFromDisk( hypname_str ); + hypname = string( hypname_str ); + delete [] hypname_str; + aDataset->CloseOnDisk(); + } + // --> get algorithm plugin library name + if ( strcmp( name_of_subgroup, "LibName" ) == 0 ) { + aDataset = new HDFdataset( name_of_subgroup, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* libname_str = new char[ size ]; + aDataset->ReadFromDisk( libname_str ); + if(MYDEBUG) SCRUTE( libname_str ); + libname = string( libname_str ); + delete [] libname_str; + aDataset->CloseOnDisk(); + } + // --> get algorithm data + if ( strcmp( name_of_subgroup, "Data" ) == 0 ) { + aDataset = new HDFdataset( name_of_subgroup, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* hypdata_str = new char[ size ]; + aDataset->ReadFromDisk( hypdata_str ); + if(MYDEBUG) SCRUTE( hypdata_str ); + hypdata = string( hypdata_str ); + delete [] hypdata_str; + aDataset->CloseOnDisk(); + } + } + // close algorithm HDF group + aGroup->CloseOnDisk(); + + // --> restore algorithm from data + if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty + if(MYDEBUG) MESSAGE("VSR - load algo : id = " << id << + ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str()); SMESH::SMESH_Hypothesis_var myHyp; - - try { // protect persistence mechanism against exceptions - myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() ); - } - catch (...) { - INFOS( "Exception during hypothesis creation" ); - } - - SMESH_Hypothesis_i* myImpl = dynamic_cast( GetServant( myHyp ).in() ); - if ( myImpl ) { - myImpl->LoadFrom( hypdata.c_str() ); - string iorString = GetORB()->object_to_string( myHyp ); - int newId = myStudyContext->findId( iorString ); - myStudyContext->mapOldToNew( id, newId ); - } - else - if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" ); + + try { // protect persistence mechanism against exceptions + myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() ); + } + catch( SALOME::SALOME_Exception& ex ) + { + INFOS( "Exception during hypothesis creation: " << ex.details.text ); + } + catch (...) { + INFOS( "Exception during hypothesis creation" ); + } + + SMESH_Hypothesis_i* myImpl = dynamic_cast( GetServant( myHyp ).in() ); + if ( myImpl ) { + //myImpl->LoadFrom( hypdata.c_str() ); + hypDataList.push_back( make_pair( myImpl, hypdata )); + CORBA::String_var iorString = GetORB()->object_to_string( myHyp ); + int newId = myStudyContext->findId( iorString.in() ); + myStudyContext->mapOldToNew( id, newId ); + } + else + if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" ); } } } // close algorithms root HDF group aTopGroup->CloseOnDisk(); + aTopGroup = 0; } // --> the rest groups should be meshes @@ -2133,550 +5444,623 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, aFile->InternalObjectIndentify( i, meshName ); if ( string( meshName ).substr( 0, 4 ) == string( "Mesh" ) ) { - // --> get mesh id - int id = atoi( string( meshName ).substr( 4 ).c_str() ); - if ( id <= 0 ) - continue; - - bool hasData = false; - - // open mesh HDF group - aTopGroup = new HDFgroup( meshName, aFile ); - aTopGroup->OpenOnDisk(); - - // get number of child HDF objects - int aNbObjects = aTopGroup->nInternalObjects(); - if ( aNbObjects > 0 ) { - // create mesh - if(MYDEBUG) MESSAGE( "VSR - load mesh : id = " << id ); - SMESH::SMESH_Mesh_var myNewMesh = this->createMesh(); - SMESH_Mesh_i* myNewMeshImpl = dynamic_cast( GetServant( myNewMesh ).in() ); + // --> get mesh id + int id = atoi( string( meshName ).substr( 4 ).c_str() ); + if ( id <= 0 ) + continue; + + // open mesh HDF group + aTopGroup = new HDFgroup( meshName, aFile ); + aTopGroup->OpenOnDisk(); + + // get number of child HDF objects + int aNbObjects = aTopGroup->nInternalObjects(); + if ( aNbObjects > 0 ) { + // create mesh + if(MYDEBUG) MESSAGE( "VSR - load mesh : id = " << id ); + SMESH::SMESH_Mesh_var myNewMesh = this->createMesh(); + SMESH_Mesh_i* myNewMeshImpl = dynamic_cast( GetServant( myNewMesh ).in() ); if ( !myNewMeshImpl ) - continue; - string iorString = GetORB()->object_to_string( myNewMesh ); - int newId = myStudyContext->findId( iorString ); - myStudyContext->mapOldToNew( id, newId ); - - ::SMESH_Mesh& myLocMesh = myNewMeshImpl->GetImpl(); - SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS(); - - // try to find mesh data dataset - if ( aTopGroup->ExistInternalObject( "Has data" ) ) { - // load mesh "has data" flag - aDataset = new HDFdataset( "Has data", aTopGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* strHasData = new char[ size ]; - aDataset->ReadFromDisk( strHasData ); - aDataset->CloseOnDisk(); - if ( strcmp( strHasData, "1") == 0 ) { - // read mesh data from MED file - myReader.SetMesh( mySMESHDSMesh ); - myReader.SetMeshId( id ); - myReader.Perform(); - hasData = true; - } - } - - // try to read and set reference to shape - GEOM::GEOM_Object_var aShapeObject; - if ( aTopGroup->ExistInternalObject( "Ref on shape" ) ) { - // load mesh "Ref on shape" - it's an entry to SObject - aDataset = new HDFdataset( "Ref on shape", aTopGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* refFromFile = new char[ size ]; - aDataset->ReadFromDisk( refFromFile ); - aDataset->CloseOnDisk(); - if ( strlen( refFromFile ) > 0 ) { - SALOMEDS::SObject_var shapeSO = myCurrentStudy->FindObjectID( refFromFile ); - - // Make sure GEOM data are loaded first - //loadGeomData( shapeSO->GetFatherComponent() ); - - CORBA::Object_var shapeObject = SObjectToObject( shapeSO ); - if ( !CORBA::is_nil( shapeObject ) ) { - aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject ); - if ( !aShapeObject->_is_nil() ) - myNewMeshImpl->SetShape( aShapeObject ); - } - } - } - - // try to get applied algorithms - if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) { - aGroup = new HDFgroup( "Applied Algorithms", aTopGroup ); - aGroup->OpenOnDisk(); - // get number of applied algorithms - int aNbSubObjects = aGroup->nInternalObjects(); - if(MYDEBUG) MESSAGE( "VSR - number of applied algos " << aNbSubObjects ); - for ( int j = 0; j < aNbSubObjects; j++ ) { - char name_dataset[ HDF_NAME_MAX_LEN+1 ]; - aGroup->InternalObjectIndentify( j, name_dataset ); - // check if it is an algorithm - if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) { - aDataset = new HDFdataset( name_dataset, aGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* refFromFile = new char[ size ]; - aDataset->ReadFromDisk( refFromFile ); - aDataset->CloseOnDisk(); - - // san - it is impossible to recover applied algorithms using their entries within Load() method - - //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile ); - //CORBA::Object_var hypObject = SObjectToObject( hypSO ); - int id = atoi( refFromFile ); - string anIOR = myStudyContext->getIORbyOldId( id ); - if ( !anIOR.empty() ) { - CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() ); - if ( !CORBA::is_nil( hypObject ) ) { - SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject ); - if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() ) - myNewMeshImpl->addHypothesis( aShapeObject, anHyp ); - } - } - } - } - aGroup->CloseOnDisk(); - } - - // try to get applied hypotheses - if ( aTopGroup->ExistInternalObject( "Applied Hypotheses" ) ) { - aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup ); - aGroup->OpenOnDisk(); - // get number of applied hypotheses - int aNbSubObjects = aGroup->nInternalObjects(); - for ( int j = 0; j < aNbSubObjects; j++ ) { - char name_dataset[ HDF_NAME_MAX_LEN+1 ]; - aGroup->InternalObjectIndentify( j, name_dataset ); - // check if it is a hypothesis - if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) { - aDataset = new HDFdataset( name_dataset, aGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* refFromFile = new char[ size ]; - aDataset->ReadFromDisk( refFromFile ); - aDataset->CloseOnDisk(); - - // san - it is impossible to recover applied hypotheses using their entries within Load() method - - //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile ); - //CORBA::Object_var hypObject = SObjectToObject( hypSO ); - int id = atoi( refFromFile ); - string anIOR = myStudyContext->getIORbyOldId( id ); - if ( !anIOR.empty() ) { - CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() ); - if ( !CORBA::is_nil( hypObject ) ) { - SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject ); - if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() ) - myNewMeshImpl->addHypothesis( aShapeObject, anHyp ); - } - } - } - } - aGroup->CloseOnDisk(); - } - - // --> try to find submeshes containers for each type of submesh - for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) { - char name_meshgroup[ 30 ]; - if ( j == GetSubMeshOnVertexTag() ) - strcpy( name_meshgroup, "SubMeshes On Vertex" ); - else if ( j == GetSubMeshOnEdgeTag() ) - strcpy( name_meshgroup, "SubMeshes On Edge" ); - else if ( j == GetSubMeshOnWireTag() ) - strcpy( name_meshgroup, "SubMeshes On Wire" ); - else if ( j == GetSubMeshOnFaceTag() ) - strcpy( name_meshgroup, "SubMeshes On Face" ); - else if ( j == GetSubMeshOnShellTag() ) - strcpy( name_meshgroup, "SubMeshes On Shell" ); - else if ( j == GetSubMeshOnSolidTag() ) - strcpy( name_meshgroup, "SubMeshes On Solid" ); - else if ( j == GetSubMeshOnCompoundTag() ) - strcpy( name_meshgroup, "SubMeshes On Compound" ); - - // try to get submeshes container HDF group - if ( aTopGroup->ExistInternalObject( name_meshgroup ) ) { - // open submeshes containers HDF group - aGroup = new HDFgroup( name_meshgroup, aTopGroup ); - aGroup->OpenOnDisk(); - - // get number of submeshes - int aNbSubMeshes = aGroup->nInternalObjects(); - for ( int k = 0; k < aNbSubMeshes; k++ ) { - // identify submesh - char name_submeshgroup[ HDF_NAME_MAX_LEN+1 ]; - aGroup->InternalObjectIndentify( k, name_submeshgroup ); - if ( string( name_submeshgroup ).substr( 0, 7 ) == string( "SubMesh" ) ) { - // --> get submesh id - int subid = atoi( string( name_submeshgroup ).substr( 7 ).c_str() ); - if ( subid <= 0 ) - continue; - // open submesh HDF group - aSubGroup = new HDFgroup( name_submeshgroup, aGroup ); - aSubGroup->OpenOnDisk(); - - // try to read and set reference to subshape - GEOM::GEOM_Object_var aSubShapeObject; - SMESH::SMESH_subMesh_var aSubMesh; - - if ( aSubGroup->ExistInternalObject( "Ref on shape" ) ) { - // load submesh "Ref on shape" - it's an entry to SObject - aDataset = new HDFdataset( "Ref on shape", aSubGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* refFromFile = new char[ size ]; - aDataset->ReadFromDisk( refFromFile ); - aDataset->CloseOnDisk(); - if ( strlen( refFromFile ) > 0 ) { - SALOMEDS::SObject_var subShapeSO = myCurrentStudy->FindObjectID( refFromFile ); - CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO ); - if ( !CORBA::is_nil( subShapeObject ) ) { - aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject ); - if ( !aSubShapeObject->_is_nil() ) - aSubMesh = SMESH::SMESH_subMesh::_duplicate - ( myNewMeshImpl->createSubMesh( aSubShapeObject ) ); - if ( aSubMesh->_is_nil() ) - continue; - string iorSubString = GetORB()->object_to_string( aSubMesh ); - int newSubId = myStudyContext->findId( iorSubString ); - myStudyContext->mapOldToNew( subid, newSubId ); - } - } - } - - if ( aSubMesh->_is_nil() ) - continue; - - // VSR: Get submesh data from MED convertor -// int anInternalSubmeshId = aSubMesh->GetId(); // this is not a persistent ID, it's an internal one computed from sub-shape -// if (myNewMeshImpl->_mapSubMesh.find(anInternalSubmeshId) != myNewMeshImpl->_mapSubMesh.end()) { -// if(MYDEBUG) MESSAGE("VSR - SMESH_Gen_i::Load(): loading from MED file submesh with ID = " << -// subid << " for subshape # " << anInternalSubmeshId); -// SMESHDS_SubMesh* aSubMeshDS = -// myNewMeshImpl->_mapSubMesh[anInternalSubmeshId]->CreateSubMeshDS(); -// if ( !aSubMeshDS ) { -// if(MYDEBUG) MESSAGE("VSR - SMESH_Gen_i::Load(): FAILED to create a submesh for subshape # " << -// anInternalSubmeshId << " in current mesh!"); -// } -// else -// myReader.GetSubMesh( aSubMeshDS, subid ); -// } - - // try to get applied algorithms - if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) { - // open "applied algorithms" HDF group - aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup ); - aSubSubGroup->OpenOnDisk(); - // get number of applied algorithms - int aNbSubObjects = aSubSubGroup->nInternalObjects(); - for ( int l = 0; l < aNbSubObjects; l++ ) { - char name_dataset[ HDF_NAME_MAX_LEN+1 ]; - aSubSubGroup->InternalObjectIndentify( l, name_dataset ); - // check if it is an algorithm - if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) { - aDataset = new HDFdataset( name_dataset, aSubSubGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* refFromFile = new char[ size ]; - aDataset->ReadFromDisk( refFromFile ); - aDataset->CloseOnDisk(); - - //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile ); - //CORBA::Object_var hypObject = SObjectToObject( hypSO ); - int id = atoi( refFromFile ); - string anIOR = myStudyContext->getIORbyOldId( id ); - if ( !anIOR.empty() ) { - CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() ); - if ( !CORBA::is_nil( hypObject ) ) { - SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject ); - if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() ) - myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp ); - } - } - } - } - // close "applied algorithms" HDF group - aSubSubGroup->CloseOnDisk(); - } - - // try to get applied hypotheses - if ( aSubGroup->ExistInternalObject( "Applied Hypotheses" ) ) { - // open "applied hypotheses" HDF group - aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup ); - aSubSubGroup->OpenOnDisk(); - // get number of applied hypotheses - int aNbSubObjects = aSubSubGroup->nInternalObjects(); - for ( int l = 0; l < aNbSubObjects; l++ ) { - char name_dataset[ HDF_NAME_MAX_LEN+1 ]; - aSubSubGroup->InternalObjectIndentify( l, name_dataset ); - // check if it is a hypothesis - if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) { - aDataset = new HDFdataset( name_dataset, aSubSubGroup ); - aDataset->OpenOnDisk(); - size = aDataset->GetSize(); - char* refFromFile = new char[ size ]; - aDataset->ReadFromDisk( refFromFile ); - aDataset->CloseOnDisk(); - - //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile ); - //CORBA::Object_var hypObject = SObjectToObject( hypSO ); - int id = atoi( refFromFile ); - string anIOR = myStudyContext->getIORbyOldId( id ); - if ( !anIOR.empty() ) { - CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() ); - if ( !CORBA::is_nil( hypObject ) ) { - SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject ); - if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() ) - myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp ); - } - } - } - } - // close "applied hypotheses" HDF group - aSubSubGroup->CloseOnDisk(); - } - - // close submesh HDF group - aSubGroup->CloseOnDisk(); - } - } - // close submeshes containers HDF group - aGroup->CloseOnDisk(); - } - } - - if(hasData) { - // Read sub-meshes from MED - if(MYDEBUG) MESSAGE("Create all sub-meshes"); - myReader.CreateAllSubMeshes(); - - - // Read node positions on sub-shapes (SMDS_Position) - - if ( aTopGroup->ExistInternalObject( "Node Positions" )) - { - // There are 5 datasets to read: - // "Nodes on Edges" - ID of node on edge - // "Edge positions" - U parameter on node on edge - // "Nodes on Faces" - ID of node on face - // "Face U positions" - U parameter of node on face - // "Face V positions" - V parameter of node on face - char* aEid_DSName = "Nodes on Edges"; - char* aEu_DSName = "Edge positions"; - char* aFu_DSName = "Face U positions"; - //char* aFid_DSName = "Nodes on Faces"; - //char* aFv_DSName = "Face V positions"; - - // data to retrieve - int nbEids = 0, nbFids = 0; - int *aEids = 0, *aFids = 0; - double *aEpos = 0, *aFupos = 0, *aFvpos = 0; - - // open a group - aGroup = new HDFgroup( "Node Positions", aTopGroup ); - aGroup->OpenOnDisk(); - - // loop on 5 data sets - int aNbObjects = aGroup->nInternalObjects(); - for ( int i = 0; i < aNbObjects; i++ ) - { - // identify dataset - char aDSName[ HDF_NAME_MAX_LEN+1 ]; - aGroup->InternalObjectIndentify( i, aDSName ); - // read data - aDataset = new HDFdataset( aDSName, aGroup ); + continue; + meshGroupList.push_back( make_pair( myNewMeshImpl, aTopGroup )); + + CORBA::String_var iorString = GetORB()->object_to_string( myNewMesh ); + int newId = myStudyContext->findId( iorString.in() ); + myStudyContext->mapOldToNew( id, newId ); + + // ouv : NPAL12872 + // try to read and set auto color flag + char aMeshAutoColorName[ 30 ]; + sprintf( aMeshAutoColorName, "AutoColorMesh %d", id); + if( aTopGroup->ExistInternalObject( aMeshAutoColorName ) ) + { + aDataset = new HDFdataset( aMeshAutoColorName, aTopGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + int* anAutoColor = new int[ size ]; + aDataset->ReadFromDisk( anAutoColor ); + aDataset->CloseOnDisk(); + myNewMeshImpl->GetImpl().SetAutoColor( (bool)anAutoColor[0] ); + delete [] anAutoColor; + } + + // try to read and set reference to shape + GEOM::GEOM_Object_var aShapeObject; + if ( aTopGroup->ExistInternalObject( "Ref on shape" ) ) { + // load mesh "Ref on shape" - it's an entry to SObject + aDataset = new HDFdataset( "Ref on shape", aTopGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* refFromFile = new char[ size ]; + aDataset->ReadFromDisk( refFromFile ); + aDataset->CloseOnDisk(); + if ( strlen( refFromFile ) > 0 ) { + SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile ); + CORBA::Object_var shapeObject = SObjectToObject( shapeSO ); + if ( !CORBA::is_nil( shapeObject ) ) { + aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject ); + if ( !aShapeObject->_is_nil() ) + myNewMeshImpl->SetShape( aShapeObject ); + } + } + delete [] refFromFile; + } + + // issue 20918. Restore Persistent Id of SMESHDS_Mesh + if ( aTopGroup->ExistInternalObject( "meshPersistentId" ) ) + { + aDataset = new HDFdataset( "meshPersistentId", aTopGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + int* meshPersistentId = new int[ size ]; + aDataset->ReadFromDisk( meshPersistentId ); + aDataset->CloseOnDisk(); + myNewMeshImpl->GetImpl().GetMeshDS()->SetPersistentId( *meshPersistentId ); + delete [] meshPersistentId; + } + + // Restore SMESH_Mesh_i::_mainShapeTick + if ( aTopGroup->ExistInternalObject( "shapeTick" )) + { + aDataset = new HDFdataset( "shapeTick", aTopGroup ); + aDataset->OpenOnDisk(); + int* shapeTick = & myNewMeshImpl->MainShapeTick(); + aDataset->ReadFromDisk( shapeTick ); + aDataset->CloseOnDisk(); + } + + // Restore file info + if ( aTopGroup->ExistInternalObject( "file info" )) + { + aDataset = new HDFdataset( "file info", aTopGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + std::string info( size, ' '); + aDataset->ReadFromDisk( (char*) info.data() ); + aDataset->CloseOnDisk(); + myNewMeshImpl->FileInfoFromString( info ); + } + } + } + } // reading MESHes + + // As all object that can be referred by hypothesis are created, + // we can restore hypothesis data + + list< pair< SMESH_Hypothesis_i*, string > >::iterator hyp_data; + for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data ) + { + SMESH_Hypothesis_i* hyp = hyp_data->first; + string & data = hyp_data->second; + hyp->LoadFrom( data.c_str() ); + } + + // Restore the rest mesh data + + list< pair< SMESH_Mesh_i*, HDFgroup* > >::iterator meshi_group; + for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group ) + { + aTopGroup = meshi_group->second; + SMESH_Mesh_i* myNewMeshImpl = meshi_group->first; + //::SMESH_Mesh& myLocMesh = myNewMeshImpl->GetImpl(); + //SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS(); + + GEOM::GEOM_Object_var aShapeObject = myNewMeshImpl->GetShapeToMesh(); + bool hasData = false; + + // get mesh old id + CORBA::String_var iorString = GetORB()->object_to_string( myNewMeshImpl->_this() ); + int newId = myStudyContext->findId( iorString.in() ); + int meshOldId = myStudyContext->getOldId( newId ); + + // try to find mesh data dataset + if ( aTopGroup->ExistInternalObject( "Has data" ) ) { + // load mesh "has data" flag + aDataset = new HDFdataset( "Has data", aTopGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* strHasData = new char[ size ]; + aDataset->ReadFromDisk( strHasData ); + aDataset->CloseOnDisk(); + if ( strcmp( strHasData, "1") == 0 ) { + hasData = true; + } + delete [] strHasData; + } + + // Try to get applied ALGORITHMS (mesh is not cleared by algo addition because + // nodes and elements are not yet put into sub-meshes) + if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) { + aGroup = new HDFgroup( "Applied Algorithms", aTopGroup ); + aGroup->OpenOnDisk(); + // get number of applied algorithms + int aNbSubObjects = aGroup->nInternalObjects(); + if(MYDEBUG) MESSAGE( "VSR - number of applied algos " << aNbSubObjects ); + for ( int j = 0; j < aNbSubObjects; j++ ) { + char name_dataset[ HDF_NAME_MAX_LEN+1 ]; + aGroup->InternalObjectIndentify( j, name_dataset ); + // check if it is an algorithm + if ( string( name_dataset ).substr( 0, 4 ) == string( "Algo" ) ) { + aDataset = new HDFdataset( name_dataset, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* refFromFile = new char[ size ]; + aDataset->ReadFromDisk( refFromFile ); + aDataset->CloseOnDisk(); + // san - it is impossible to recover applied algorithms using their entries within Load() method + //SALOMEDS::SObject_wrap hypSO = aStudy->FindObjectID( refFromFile ); + //CORBA::Object_var hypObject = SObjectToObject( hypSO ); + int id = atoi( refFromFile ); + delete [] refFromFile; + string anIOR = myStudyContext->getIORbyOldId( id ); + if ( !anIOR.empty() ) { + CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() ); + if ( !CORBA::is_nil( hypObject ) ) { + SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject ); + if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil() + || !myNewMeshImpl->HasShapeToMesh()) ) + myNewMeshImpl->addHypothesis( aShapeObject, anHyp ); + } + } + } + } + aGroup->CloseOnDisk(); + } + + // try to get applied hypotheses + if ( aTopGroup->ExistInternalObject( "Applied Hypotheses" ) ) { + aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup ); + aGroup->OpenOnDisk(); + // get number of applied hypotheses + int aNbSubObjects = aGroup->nInternalObjects(); + for ( int j = 0; j < aNbSubObjects; j++ ) { + char name_dataset[ HDF_NAME_MAX_LEN+1 ]; + aGroup->InternalObjectIndentify( j, name_dataset ); + // check if it is a hypothesis + if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) { + aDataset = new HDFdataset( name_dataset, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* refFromFile = new char[ size ]; + aDataset->ReadFromDisk( refFromFile ); + aDataset->CloseOnDisk(); + // san - it is impossible to recover applied hypotheses using their entries within Load() method + //SALOMEDS::SObject_wrap hypSO = myStudy->FindObjectID( refFromFile ); + //CORBA::Object_var hypObject = SObjectToObject( hypSO ); + int id = atoi( refFromFile ); + delete [] refFromFile; + string anIOR = myStudyContext->getIORbyOldId( id ); + if ( !anIOR.empty() ) { + CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() ); + if ( !CORBA::is_nil( hypObject ) ) { + SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject ); + if ( !anHyp->_is_nil() && (!aShapeObject->_is_nil() + || !myNewMeshImpl->HasShapeToMesh()) ) + myNewMeshImpl->addHypothesis( aShapeObject, anHyp ); + } + } + } + } + aGroup->CloseOnDisk(); + } + + // --> try to find SUB-MESHES containers for each type of submesh + for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) { + const char* name_meshgroup = 0; + if ( j == GetSubMeshOnVertexTag() ) + name_meshgroup = "SubMeshes On Vertex"; + else if ( j == GetSubMeshOnEdgeTag() ) + name_meshgroup = "SubMeshes On Edge"; + else if ( j == GetSubMeshOnWireTag() ) + name_meshgroup = "SubMeshes On Wire"; + else if ( j == GetSubMeshOnFaceTag() ) + name_meshgroup = "SubMeshes On Face"; + else if ( j == GetSubMeshOnShellTag() ) + name_meshgroup = "SubMeshes On Shell"; + else if ( j == GetSubMeshOnSolidTag() ) + name_meshgroup = "SubMeshes On Solid"; + else if ( j == GetSubMeshOnCompoundTag() ) + name_meshgroup = "SubMeshes On Compound"; + + // try to get submeshes container HDF group + if ( aTopGroup->ExistInternalObject( name_meshgroup ) ) { + // open submeshes containers HDF group + aGroup = new HDFgroup( name_meshgroup, aTopGroup ); + aGroup->OpenOnDisk(); + + // get number of submeshes + int aNbSubMeshes = aGroup->nInternalObjects(); + for ( int k = 0; k < aNbSubMeshes; k++ ) { + // identify submesh + char name_submeshgroup[ HDF_NAME_MAX_LEN+1 ]; + aGroup->InternalObjectIndentify( k, name_submeshgroup ); + if ( strncmp( name_submeshgroup, "SubMesh", 7 ) == 0 ) { + // --> get submesh id + int subid = atoi( name_submeshgroup + 7 ); + if ( subid <= 0 ) + continue; + // open submesh HDF group + aSubGroup = new HDFgroup( name_submeshgroup, aGroup ); + aSubGroup->OpenOnDisk(); + + // try to read and set reference to subshape + GEOM::GEOM_Object_var aSubShapeObject; + SMESH::SMESH_subMesh_var aSubMesh; + + if ( aSubGroup->ExistInternalObject( "Ref on shape" ) ) { + // load submesh "Ref on shape" - it's an entry to SObject + aDataset = new HDFdataset( "Ref on shape", aSubGroup ); aDataset->OpenOnDisk(); - if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions - { - double* pos = new double [ aDataset->GetSize() ]; - aDataset->ReadFromDisk( pos ); - // which one? - if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 ) - aEpos = pos; - else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 ) - aFupos = pos; - else - aFvpos = pos; - } - else // NODE IDS - { - int aSize = aDataset->GetSize(); - - // for reading files, created from 18.07.2005 till 10.10.2005 - if (aDataset->GetType() == HDF_STRING) - aSize /= sizeof(int); - - int* ids = new int [aSize]; - aDataset->ReadFromDisk( ids ); - // on face or nodes? - if ( strncmp( aDSName, aEid_DSName, strlen( aEid_DSName )) == 0 ) { - aEids = ids; - nbEids = aSize; - } - else { - aFids = ids; - nbFids = aSize; + size = aDataset->GetSize(); + char* refFromFile = new char[ size ]; + aDataset->ReadFromDisk( refFromFile ); + aDataset->CloseOnDisk(); + if ( strlen( refFromFile ) > 0 ) { + SALOMEDS::SObject_wrap subShapeSO = aStudy->FindObjectID( refFromFile ); + CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO ); + if ( !CORBA::is_nil( subShapeObject ) ) { + aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject ); + if ( !aSubShapeObject->_is_nil() ) + aSubMesh = SMESH::SMESH_subMesh::_duplicate + ( myNewMeshImpl->createSubMesh( aSubShapeObject ) ); + if ( aSubMesh->_is_nil() ) + continue; + string iorSubString = GetORB()->object_to_string( aSubMesh ); + int newSubId = myStudyContext->findId( iorSubString ); + myStudyContext->mapOldToNew( subid, newSubId ); } } - } // loop on 5 datasets + delete [] refFromFile; + } - // Set node positions on edges or faces - for ( int onFace = 0; onFace < 2; onFace++ ) - { - int nbNodes = ( onFace ? nbFids : nbEids ); - if ( nbNodes == 0 ) continue; - int* aNodeIDs = ( onFace ? aFids : aEids ); - double* aUPos = ( onFace ? aFupos : aEpos ); - double* aVPos = ( onFace ? aFvpos : 0 ); - // loop on node IDs - for ( int iNode = 0; iNode < nbNodes; iNode++ ) - { - const SMDS_MeshNode* node = mySMESHDSMesh->FindNode( aNodeIDs[ iNode ]); - ASSERT( node ); - SMDS_PositionPtr aPos = node->GetPosition(); - ASSERT( aPos ) - if ( onFace ) { - ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_FACE ); - SMDS_FacePosition* fPos = const_cast - ( static_cast( aPos.get() )); - fPos->SetUParameter( aUPos[ iNode ]); - fPos->SetVParameter( aVPos[ iNode ]); - } - else { - ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE ); - SMDS_EdgePosition* fPos = const_cast - ( static_cast( aPos.get() )); - fPos->SetUParameter( aUPos[ iNode ]); + if ( aSubMesh->_is_nil() ) + continue; + + // try to get applied algorithms + if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) { + // open "applied algorithms" HDF group + aSubSubGroup = new HDFgroup( "Applied Algorithms", aSubGroup ); + aSubSubGroup->OpenOnDisk(); + // get number of applied algorithms + int aNbSubObjects = aSubSubGroup->nInternalObjects(); + for ( int l = 0; l < aNbSubObjects; l++ ) { + char name_dataset[ HDF_NAME_MAX_LEN+1 ]; + aSubSubGroup->InternalObjectIndentify( l, name_dataset ); + // check if it is an algorithm + if ( strncmp( name_dataset, "Algo", 4 ) == 0 ) { + aDataset = new HDFdataset( name_dataset, aSubSubGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* refFromFile = new char[ size ]; + aDataset->ReadFromDisk( refFromFile ); + aDataset->CloseOnDisk(); + + int id = atoi( refFromFile ); + string anIOR = myStudyContext->getIORbyOldId( id ); + if ( !anIOR.empty() ) { + CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() ); + if ( !CORBA::is_nil( hypObject ) ) { + SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject ); + if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() ) + myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp ); + } + } + delete [] refFromFile; } } + // close "applied algorithms" HDF group + aSubSubGroup->CloseOnDisk(); } - if ( aEids ) delete [] aEids; - if ( aFids ) delete [] aFids; - if ( aEpos ) delete [] aEpos; - if ( aFupos ) delete [] aFupos; - if ( aFvpos ) delete [] aFvpos; - - aGroup->CloseOnDisk(); - } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) ) - } // if ( hasData ) - - // Recompute State (as computed sub-meshes are restored from MED) - if ( !aShapeObject->_is_nil() ) { - MESSAGE("Compute State Engine ..."); - TopoDS_Shape myLocShape = GeomObjectToShape( aShapeObject ); - myNewMeshImpl->GetImpl().GetSubMesh(myLocShape)->ComputeStateEngine - (SMESH_subMesh::SUBMESH_RESTORED); - MESSAGE("Compute State Engine finished"); - } - - // try to get groups - for ( int ii = GetNodeGroupsTag(); ii <= GetVolumeGroupsTag(); ii++ ) { - char name_group[ 30 ]; - if ( ii == GetNodeGroupsTag() ) - strcpy( name_group, "Groups of Nodes" ); - else if ( ii == GetEdgeGroupsTag() ) - strcpy( name_group, "Groups of Edges" ); - else if ( ii == GetFaceGroupsTag() ) - strcpy( name_group, "Groups of Faces" ); - else if ( ii == GetVolumeGroupsTag() ) - strcpy( name_group, "Groups of Volumes" ); - - if ( aTopGroup->ExistInternalObject( name_group ) ) { - aGroup = new HDFgroup( name_group, aTopGroup ); - aGroup->OpenOnDisk(); - // get number of groups - int aNbSubObjects = aGroup->nInternalObjects(); - for ( int j = 0; j < aNbSubObjects; j++ ) { - char name_dataset[ HDF_NAME_MAX_LEN+1 ]; - aGroup->InternalObjectIndentify( j, name_dataset ); - // check if it is an group - if ( string( name_dataset ).substr( 0, 5 ) == string( "Group" ) ) { - // --> get group id - int subid = atoi( string( name_dataset ).substr( 5 ).c_str() ); - if ( subid <= 0 ) - continue; - aDataset = new HDFdataset( name_dataset, aGroup ); - aDataset->OpenOnDisk(); - - // Retrieve actual group name - size = aDataset->GetSize(); - char* nameFromFile = new char[ size ]; - aDataset->ReadFromDisk( nameFromFile ); - aDataset->CloseOnDisk(); - - // Try to find a shape reference - TopoDS_Shape aShape; - char aRefName[ 30 ]; - sprintf( aRefName, "Ref on shape %d", subid); - if ( aGroup->ExistInternalObject( aRefName ) ) { - // load mesh "Ref on shape" - it's an entry to SObject - aDataset = new HDFdataset( aRefName, aGroup ); + // try to get applied hypotheses + if ( aSubGroup->ExistInternalObject( "Applied Hypotheses" ) ) { + // open "applied hypotheses" HDF group + aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup ); + aSubSubGroup->OpenOnDisk(); + // get number of applied hypotheses + int aNbSubObjects = aSubSubGroup->nInternalObjects(); + for ( int l = 0; l < aNbSubObjects; l++ ) { + char name_dataset[ HDF_NAME_MAX_LEN+1 ]; + aSubSubGroup->InternalObjectIndentify( l, name_dataset ); + // check if it is a hypothesis + if ( string( name_dataset ).substr( 0, 3 ) == string( "Hyp" ) ) { + aDataset = new HDFdataset( name_dataset, aSubSubGroup ); aDataset->OpenOnDisk(); size = aDataset->GetSize(); char* refFromFile = new char[ size ]; aDataset->ReadFromDisk( refFromFile ); aDataset->CloseOnDisk(); - if ( strlen( refFromFile ) > 0 ) { - SALOMEDS::SObject_var shapeSO = myCurrentStudy->FindObjectID( refFromFile ); - CORBA::Object_var shapeObject = SObjectToObject( shapeSO ); - if ( !CORBA::is_nil( shapeObject ) ) { - aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject ); - if ( !aShapeObject->_is_nil() ) - aShape = GeomObjectToShape( aShapeObject ); + + int id = atoi( refFromFile ); + string anIOR = myStudyContext->getIORbyOldId( id ); + if ( !anIOR.empty() ) { + CORBA::Object_var hypObject = GetORB()->string_to_object( anIOR.c_str() ); + if ( !CORBA::is_nil( hypObject ) ) { + SMESH::SMESH_Hypothesis_var anHyp = SMESH::SMESH_Hypothesis::_narrow( hypObject ); + if ( !anHyp->_is_nil() && !aShapeObject->_is_nil() ) + myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp ); } } + delete [] refFromFile; + } + } + // close "APPLIED HYPOTHESES" hdf group + aSubSubGroup->CloseOnDisk(); + } + + // close SUB-MESH hdf group + aSubGroup->CloseOnDisk(); + } + } + // close SUB-MESHES containers hdf group + aGroup->CloseOnDisk(); + } + } + + // try to get GROUPS + for ( int ii = GetNodeGroupsTag(); ii <= GetBallElementsGroupsTag(); ii++ ) { + char name_group[ 30 ]; + if ( ii == GetNodeGroupsTag() ) + strcpy( name_group, "Groups of Nodes" ); + else if ( ii == GetEdgeGroupsTag() ) + strcpy( name_group, "Groups of Edges" ); + else if ( ii == GetFaceGroupsTag() ) + strcpy( name_group, "Groups of Faces" ); + else if ( ii == GetVolumeGroupsTag() ) + strcpy( name_group, "Groups of Volumes" ); + else if ( ii == Get0DElementsGroupsTag() ) + strcpy( name_group, "Groups of 0D Elements" ); + else if ( ii == GetBallElementsGroupsTag() ) + strcpy( name_group, "Groups of Balls" ); + + if ( aTopGroup->ExistInternalObject( name_group ) ) { + aGroup = new HDFgroup( name_group, aTopGroup ); + aGroup->OpenOnDisk(); + // PAL23514: get all names from the HDFgroup to avoid iteration on its contents + // within aGroup->ExistInternalObject( name ) + std::vector< std::string > subNames; + TColStd_MapOfAsciiString mapOfNames; + aGroup->GetAllObjects( subNames ); + for ( size_t iN = 0; iN < subNames.size(); ++iN ) + mapOfNames.Add( subNames[ iN ].c_str() ); + // loop on groups + for ( size_t j = 0; j < subNames.size(); j++ ) { + const std::string& name_dataset = subNames[ j ]; + // check if it is a group + if ( name_dataset.substr( 0, 5 ) == "Group" ) { + // --> get group id + char * endptr; + int subid = strtol( name_dataset.data() + 5, &endptr, 10 ); + if ( subid <= 0 ) + continue; + int groupID = -1; // group local ID (also persistent) + if ( *endptr ) + groupID = atoi( endptr + 1 ); + aDataset = new HDFdataset( name_dataset.c_str(), aGroup ); + aDataset->OpenOnDisk(); + + // Retrieve actual group name + size = aDataset->GetSize(); + char* nameFromFile = new char[ size ]; + aDataset->ReadFromDisk( nameFromFile ); + aDataset->CloseOnDisk(); + + // Try to find a shape reference + TopoDS_Shape aShape; + char aRefName[ 30 ]; + sprintf( aRefName, "Ref on shape %d", subid); + if ( mapOfNames.Contains( aRefName )) + { + // load mesh "Ref on shape" - it's an entry to SObject + aDataset = new HDFdataset( aRefName, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* refFromFile = new char[ size ]; + aDataset->ReadFromDisk( refFromFile ); + aDataset->CloseOnDisk(); + if ( strlen( refFromFile ) > 0 ) { + SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile ); + CORBA::Object_var shapeObject = SObjectToObject( shapeSO ); + if ( !CORBA::is_nil( shapeObject ) ) { + aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject ); + if ( !aShapeObject->_is_nil() ) + aShape = GeomObjectToShape( aShapeObject ); } - // Create group servant - SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1); - SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate - ( myNewMeshImpl->createGroup( type, nameFromFile, aShape ) ); - // Obtain a SMESHDS_Group object - if ( aNewGroup->_is_nil() ) - continue; - - string iorSubString = GetORB()->object_to_string( aNewGroup ); - int newSubId = myStudyContext->findId( iorSubString ); - myStudyContext->mapOldToNew( subid, newSubId ); - - SMESH_GroupBase_i* aGroupImpl = - dynamic_cast( GetServant( aNewGroup ).in() ); - if ( !aGroupImpl ) - continue; - - SMESH_Group* aLocalGroup = myLocMesh.GetGroup( aGroupImpl->GetLocalID() ); - if ( !aLocalGroup ) - continue; - - SMESHDS_GroupBase* aGroupBaseDS = aLocalGroup->GetGroupDS(); - aGroupBaseDS->SetStoreName( name_dataset ); - - // Fill group with contents from MED file - SMESHDS_Group* aGrp = dynamic_cast( aGroupBaseDS ); - if ( aGrp ) - myReader.GetGroup( aGrp ); - } - } - aGroup->CloseOnDisk(); - } - } - } - // close mesh group - aTopGroup->CloseOnDisk(); + } + delete [] refFromFile; + } + // Try to read a filter of SMESH_GroupOnFilter + SMESH::Filter_var filter; + SMESH_PredicatePtr predicate; + std::string hdfGrpName = ( SMESH_Comment( "Filter ") << subid ); + if ( mapOfNames.Contains( hdfGrpName.c_str() )) + { + aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + char* persistStr = new char[ size ]; + aDataset->ReadFromDisk( persistStr ); + aDataset->CloseOnDisk(); + if ( strlen( persistStr ) > 0 ) { + filter = SMESH_GroupOnFilter_i::StringToFilter( persistStr ); + predicate = SMESH_GroupOnFilter_i::GetPredicate( filter ); + filters.push_back( filter ); + } + delete [] persistStr; + } + + // Create group servant + SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1); + SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate + ( myNewMeshImpl->createGroup( type, nameFromFile, groupID, aShape, predicate ) ); + delete [] nameFromFile; + // Obtain a SMESHDS_Group object + if ( aNewGroup->_is_nil() ) + continue; + + string iorSubString = GetORB()->object_to_string( aNewGroup ); + int newSubId = myStudyContext->findId( iorSubString ); + myStudyContext->mapOldToNew( subid, newSubId ); + + SMESH_GroupBase_i* aGroupImpl = SMESH::DownCast< SMESH_GroupBase_i*>( aNewGroup ); + if ( !aGroupImpl ) + continue; + + if ( SMESH_GroupOnFilter_i* aFilterGroup = + dynamic_cast< SMESH_GroupOnFilter_i*>( aGroupImpl )) + { + aFilterGroup->SetFilter( filter ); + filter->UnRegister(); + } + SMESHDS_GroupBase* aGroupBaseDS = aGroupImpl->GetGroupDS(); + if ( !aGroupBaseDS ) + continue; + + aGroupBaseDS->SetStoreName( name_dataset.c_str() ); + + // ouv : NPAL12872 + // Read color of the group + char aGroupColorName[ 30 ]; + sprintf( aGroupColorName, "ColorGroup %d", subid); + if ( mapOfNames.Contains( aGroupColorName )) + { + aDataset = new HDFdataset( aGroupColorName, aGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + double* anRGB = new double[ size ]; + aDataset->ReadFromDisk( anRGB ); + aDataset->CloseOnDisk(); + Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB ); + aGroupBaseDS->SetColor( aColor ); + delete [] anRGB; + } + } + } + aGroup->CloseOnDisk(); + } + } // reading GROUPs + + // instead of reading mesh data, we read only brief information of all + // objects: mesh, groups, sub-meshes (issue 0021208) + if ( hasData ) + { + SMESH_PreMeshInfo::LoadFromFile( myNewMeshImpl, meshOldId, + meshfile.ToCString(), filename.ToCString(), + !isMultiFile ); } + + // read Sub-Mesh ORDER if any + if ( aTopGroup->ExistInternalObject( "Mesh Order" )) { + aDataset = new HDFdataset( "Mesh Order", aTopGroup ); + aDataset->OpenOnDisk(); + size = aDataset->GetSize(); + int* smIDs = new int[ size ]; + aDataset->ReadFromDisk( smIDs ); + aDataset->CloseOnDisk(); + TListOfListOfInt anOrderIds; + anOrderIds.push_back( TListOfInt() ); + for ( int i = 0; i < size; i++ ) + if ( smIDs[ i ] < 0 ) // is separator + anOrderIds.push_back( TListOfInt() ); + else + anOrderIds.back().push_back(smIDs[ i ]); + + myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds ); + delete [] smIDs; + } + } // loop on meshes + + // update hyps needing full mesh data restored (issue 20918) + for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data ) + { + SMESH_Hypothesis_i* hyp = hyp_data->first; + hyp->UpdateAsMeshesRestored(); } + + // notify algos on completed restoration to set sub-mesh event listeners + for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group ) + { + SMESH_Mesh_i* myNewMeshImpl = meshi_group->first; + ::SMESH_Mesh& myLocMesh = myNewMeshImpl->GetImpl(); + + TopoDS_Shape myLocShape; + if(myLocMesh.HasShapeToMesh()) + myLocShape = myLocMesh.GetShapeToMesh(); + else + myLocShape = SMESH_Mesh::PseudoShape(); + + myLocMesh.GetSubMesh(myLocShape)-> + ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED); + } + + // let filters detect dependency on mesh groups via FT_BelongToMeshGroup predicate (22877) + list< SMESH::Filter_var >::iterator f = filters.begin(); + for ( ; f != filters.end(); ++f ) + if ( SMESH::Filter_i * fi = SMESH::DownCast< SMESH::Filter_i*>( *f )) + fi->FindBaseObjects(); + + + // close mesh group + if(aTopGroup) + aTopGroup->CloseOnDisk(); } // close HDF file aFile->CloseOnDisk(); delete aFile; // Remove temporary files created from the stream - if ( !isMultiFile ) - SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true ); + if ( !isMultiFile ) + { + SMESH_File meshFile( meshfile.ToCString() ); + if ( !meshFile ) // no meshfile exists + { + SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq, true ); + } + else + { + Engines::Container_var container = GetContainerRef(); + if ( Engines_Container_i* container_i = SMESH::DownCast( container )) + { + container_i->registerTemporaryFile( filename.ToCString() ); + container_i->registerTemporaryFile( meshfile.ToCString() ); + container_i->registerTemporaryFile( tmpDir.ToCString() ); + } + } + } + pd << ""; // prevent optimizing pd out + + // creation of tree nodes for all data objects in the study + // to support tree representation customization and drag-n-drop: + SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = aStudy->GetUseCaseBuilder(); + if ( !useCaseBuilder->IsUseCaseNode( theComponent ) ) { + useCaseBuilder->SetRootCurrent(); + useCaseBuilder->Append( theComponent ); // component object is added as the top level item + SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( theComponent ); + for (it->InitEx(true); it->More(); it->Next()) { + useCaseBuilder->AppendTo( it->Value()->GetFather(), it->Value() ); + } + } - INFOS( "SMESH_Gen_i::Load completed" ); return true; } @@ -2684,16 +6068,39 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent, /*! * SMESH_Gen_i::LoadASCII * - * Load SMESH module's data in ASCII format (not implemented yet) + * Load SMESH module's data in ASCII format */ //============================================================================= bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent, - const SALOMEDS::TMPFile& theStream, - const char* theURL, - bool isMultiFile ) { + const SALOMEDS::TMPFile& theStream, + const char* theURL, + bool isMultiFile ) { if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LoadASCII" ); return Load( theComponent, theStream, theURL, isMultiFile ); + + //before call main ::Load method it's need for decipher text format to + //binary ( "|xx" => x' ) + int size = theStream.length(); + if ( int((size / 3 )*3) != size ) //error size of buffer + return false; + + int real_size = int(size / 3); + + _CORBA_Octet* buffer = new _CORBA_Octet[real_size]; + char tmp[3]; + tmp[2]='\0'; + unsigned int c = -1; + for ( int i = 0; i < real_size; i++ ) + { + memcpy( &(tmp[0]), &(theStream[i*3+1]), 2 ); + sscanf( tmp, "%x", &c ); + sprintf( (char*)&(buffer[i]), "%c", (char)c ); + } + + SALOMEDS::TMPFile_var aRealStreamFile = new SALOMEDS::TMPFile(real_size, real_size, buffer, 1); + + return Load( theComponent, *(aRealStreamFile._retn()), theURL, isMultiFile ); } //============================================================================= @@ -2709,18 +6116,21 @@ void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent ) if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Close" ); // Clear study contexts data - int studyId = GetCurrentStudyID(); - if ( myStudyContextMap.find( studyId ) != myStudyContextMap.end() ) { - delete myStudyContextMap[ studyId ]; - myStudyContextMap.erase( studyId ); - } + myStudyContext->Clear(); + + // remove the tmp files meshes are loaded from + SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD( theComponent ); + + // Clean trace of API methods calls + CleanPythonTrace(); + return; } //============================================================================= /*! * SMESH_Gen_i::ComponentDataType - * + * * Get component data type */ //============================================================================= @@ -2731,23 +6141,22 @@ char* SMESH_Gen_i::ComponentDataType() return CORBA::string_dup( "SMESH" ); } - + //============================================================================= /*! * SMESH_Gen_i::IORToLocalPersistentID - * + * * Transform data from transient form to persistent */ //============================================================================= char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/, - const char* IORString, - CORBA::Boolean /*isMultiFile*/, - CORBA::Boolean /*isASCII*/ ) + const char* IORString, + CORBA::Boolean /*isMultiFile*/, + CORBA::Boolean /*isASCII*/ ) { if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" ); - StudyContext* myStudyContext = GetCurrentStudyContext(); - + if ( myStudyContext && strcmp( IORString, "" ) != 0 ) { int anId = myStudyContext->findId( IORString ); if ( anId ) { @@ -2769,12 +6178,11 @@ char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/, //============================================================================= char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/, - const char* aLocalPersistentID, - CORBA::Boolean /*isMultiFile*/, - CORBA::Boolean /*isASCII*/ ) + const char* aLocalPersistentID, + CORBA::Boolean /*isMultiFile*/, + CORBA::Boolean /*isASCII*/ ) { if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID ); - StudyContext* myStudyContext = GetCurrentStudyContext(); if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) { int anId = atoi( aLocalPersistentID ); @@ -2785,34 +6193,347 @@ char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/, //======================================================================= //function : RegisterObject -//purpose : +//purpose : //======================================================================= int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject) { - StudyContext* myStudyContext = GetCurrentStudyContext(); + if ( myStudyContext && !CORBA::is_nil( theObject )) { + CORBA::String_var iorString = GetORB()->object_to_string( theObject ); + return myStudyContext->addObject( string( iorString.in() ) ); + } + return 0; +} + +//================================================================================ +/*! + * \brief Return id of registered object + * \param theObject - the Object + * \retval int - Object id + */ +//================================================================================ + +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->addObject( iorString ); + return myStudyContext->findId( iorString ); } return 0; } - + +//============================================================================= +/*! + * SMESH_Gen_i::SetName + * + * Set a new object name + */ +//============================================================================= +void SMESH_Gen_i::SetName(const char* theIOR, + const char* theName) +{ + if ( theIOR && strcmp( theIOR, "" ) ) { + CORBA::Object_var anObject = GetORB()->string_to_object( theIOR ); + SALOMEDS::SObject_wrap aSO = ObjectToSObject( anObject ); + if ( !aSO->_is_nil() ) { + SetName( aSO, theName ); + } + } +} + +// Version information +char* SMESH_Gen_i::getVersion() +{ +#if SMESH_DEVELOPMENT + return CORBA::string_dup(SMESH_VERSION_STR"dev"); +#else + return CORBA::string_dup(SMESH_VERSION_STR); +#endif +} + +//================================================================================= +// function : Move() +// purpose : Moves objects to the specified position. +// Is used in the drag-n-drop functionality. +//================================================================================= +void SMESH_Gen_i::Move( const SMESH::sobject_list& what, + SALOMEDS::SObject_ptr where, + CORBA::Long row ) +{ + if ( CORBA::is_nil( where ) ) return; + + SALOMEDS::StudyBuilder_var studyBuilder = getStudyServant()->NewBuilder(); + SALOMEDS::UseCaseBuilder_var useCaseBuilder = getStudyServant()->GetUseCaseBuilder(); + SALOMEDS::SComponent_var father = where->GetFatherComponent(); + std::string dataType = father->ComponentDataType(); + if ( dataType != "SMESH" ) return; // not a SMESH component + + SALOMEDS::SObject_var objAfter; + if ( row >= 0 && useCaseBuilder->HasChildren( where ) ) { + // insert at given row -> find insertion position + SALOMEDS::UseCaseIterator_var useCaseIt = useCaseBuilder->GetUseCaseIterator( where ); + int i; + for ( i = 0; i < row && useCaseIt->More(); i++, useCaseIt->Next() ); + if ( i == row && useCaseIt->More() ) { + objAfter = useCaseIt->Value(); + } + } + + for ( CORBA::ULong i = 0; i < what.length(); i++ ) { + SALOMEDS::SObject_var sobj = what[i]; + if ( CORBA::is_nil( sobj ) ) continue; // skip bad object + // insert the object to the use case tree + if ( !CORBA::is_nil( objAfter ) ) + useCaseBuilder->InsertBefore( sobj, objAfter ); // insert at given row + else + 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; + typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char*); + 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; +} + +//================================================================================= +// function : GetInsideSphere +// purpose : Collect indices of elements, which are located inside the sphere +//================================================================================= +SMESH::long_array* SMESH_Gen_i::GetInsideSphere( SMESH::SMESH_IDSource_ptr meshPart, + SMESH::ElementType theElemType, + CORBA::Double theX, + CORBA::Double theY, + CORBA::Double theZ, + CORBA::Double theR) +{ + SMESH::long_array_var aResult = new SMESH::long_array(); + if ( meshPart->_is_nil() ) + return aResult._retn(); + + // 1. Create geometrical object + gp_Pnt aP( theX, theY, theZ ); + TopoDS_Shape aShape = BRepPrimAPI_MakeSphere( aP, theR ).Shape(); + + std::vector lst =_GetInside(meshPart, theElemType, aShape); + + if ( lst.size() > 0 ) { + aResult->length( lst.size() ); + for ( size_t i = 0; i < lst.size(); i++ ) { + aResult[i] = lst[i]; + } + } + return aResult._retn(); +} + +SMESH::long_array* SMESH_Gen_i::GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart, + SMESH::ElementType theElemType, + CORBA::Double theX1, + CORBA::Double theY1, + CORBA::Double theZ1, + CORBA::Double theX2, + CORBA::Double theY2, + CORBA::Double theZ2) { + SMESH::long_array_var aResult = new SMESH::long_array(); + if( meshPart->_is_nil() ) + return aResult._retn(); + + TopoDS_Shape aShape = BRepPrimAPI_MakeBox( gp_Pnt( theX1, theY1, theZ1 ), gp_Pnt( theX2, theY2, theZ2 ) ).Shape(); + + std::vector lst =_GetInside(meshPart, theElemType, aShape); + + if( lst.size() > 0 ) { + aResult->length( lst.size() ); + for ( size_t i = 0; i < lst.size(); i++ ) { + aResult[i] = lst[i]; + } + } + return aResult._retn(); +} + +SMESH::long_array* SMESH_Gen_i::GetInsideCylinder( SMESH::SMESH_IDSource_ptr meshPart, + SMESH::ElementType theElemType, + CORBA::Double theX, + CORBA::Double theY, + CORBA::Double theZ, + CORBA::Double theDX, + CORBA::Double theDY, + CORBA::Double theDZ, + CORBA::Double theH, + CORBA::Double theR ){ + SMESH::long_array_var aResult = new SMESH::long_array(); + if( meshPart->_is_nil() ) + return aResult._retn(); + + gp_Pnt aP( theX, theY, theZ ); + gp_Vec aV( theDX, theDY, theDZ ); + gp_Ax2 anAxes (aP, aV); + + TopoDS_Shape aShape = BRepPrimAPI_MakeCylinder(anAxes, theR, Abs(theH)).Shape(); + + std::vector lst =_GetInside(meshPart, theElemType, aShape); + + if( lst.size() > 0 ) { + aResult->length( lst.size() ); + for ( size_t i = 0; i < lst.size(); i++ ) { + aResult[i] = lst[i]; + } + } + return aResult._retn(); +} + +SMESH::long_array* SMESH_Gen_i::GetInside( SMESH::SMESH_IDSource_ptr meshPart, + SMESH::ElementType theElemType, + GEOM::GEOM_Object_ptr theGeom, + CORBA::Double theTolerance ) { + SMESH::long_array_var aResult = new SMESH::long_array(); + if( meshPart->_is_nil() || theGeom->_is_nil() ) + return aResult._retn(); + + TopoDS_Shape aShape = GeomObjectToShape( theGeom ); + + std::vector lst =_GetInside(meshPart, theElemType, aShape, &theTolerance); + + if( lst.size() > 0 ) { + aResult->length( lst.size() ); + for ( size_t i = 0; i < lst.size(); i++ ) { + aResult[i] = lst[i]; + } + } + return aResult._retn(); +} + + + +std::vector SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart, + SMESH::ElementType theElemType, + TopoDS_Shape& aShape, + double* theTolerance) { + + std::vector res; + SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh(); + + if ( mesh->_is_nil() ) + return res; + + SMESH_Mesh_i* anImpl = dynamic_cast( GetServant( mesh ).in() ); + if ( !anImpl ) + return res; + + const SMDS_Mesh* meshDS = anImpl->GetImpl().GetMeshDS(); + + if ( !meshDS ) + return res; + + SMDSAbs_ElementType aType = SMDSAbs_ElementType(theElemType); + SMESH::Controls::ElementsOnShape* anElementsOnShape = new SMESH::Controls::ElementsOnShape(); + anElementsOnShape->SetAllNodes( true ); + anElementsOnShape->SetMesh( meshDS ); + anElementsOnShape->SetShape( aShape, aType ); + + if(theTolerance) + anElementsOnShape->SetTolerance(*theTolerance); + + SMESH::SMESH_Mesh_var msource = SMESH::SMESH_Mesh::_narrow(meshPart); + if ( !msource->_is_nil() ) { // Mesh case + SMDS_ElemIteratorPtr elemIt = meshDS->elementsIterator( aType ); + if ( elemIt ) { + while ( elemIt->more() ) { + const SMDS_MeshElement* anElem = elemIt->next(); + long anId = anElem->GetID(); + if ( anElementsOnShape->IsSatisfy( anId ) ) + res.push_back( anId ); + } + } + } + SMESH::SMESH_Group_var gsource = SMESH::SMESH_Group::_narrow(meshPart); + if ( !gsource->_is_nil() ) { + if(theElemType == SMESH::NODE) { + SMESH::long_array_var nodes = gsource->GetNodeIDs(); + for ( CORBA::ULong i = 0; i < nodes->length(); ++i ) { + if ( const SMDS_MeshNode* node = meshDS->FindNode( nodes[i] )) { + long anId = node->GetID(); + if ( anElementsOnShape->IsSatisfy( anId ) ) + res.push_back( anId ); + } + } + } else if (gsource->GetType() == theElemType || theElemType == SMESH::ALL ) { + SMESH::long_array_var elems = gsource->GetListOfID(); + for ( CORBA::ULong i = 0; i < elems->length(); ++i ) { + if ( const SMDS_MeshElement* elem = meshDS->FindElement( elems[i] )) { + long anId = elem->GetID(); + if ( anElementsOnShape->IsSatisfy( anId ) ) + res.push_back( anId ); + } + } + } + } + SMESH::SMESH_subMesh_var smsource = SMESH::SMESH_subMesh::_narrow(meshPart); + if ( !smsource->_is_nil() ) { + SMESH::long_array_var elems = smsource->GetElementsByType( theElemType ); + for ( CORBA::ULong i = 0; i < elems->length(); ++i ) { + const SMDS_MeshElement* elem = ( theElemType == SMESH::NODE ) ? meshDS->FindNode( elems[i] ) : meshDS->FindElement( elems[i] ); + if (elem) { + long anId = elem->GetID(); + if ( anElementsOnShape->IsSatisfy( anId ) ) + res.push_back( anId ); + } + } + } + return res; +} + + //============================================================================= -/*! +/*! * SMESHEngine_factory * - * C factory, accessible with dlsym, after dlopen + * C factory, accessible with dlsym, after dlopen */ //============================================================================= extern "C" -{ +{ SMESH_I_EXPORT PortableServer::ObjectId* SMESHEngine_factory( CORBA::ORB_ptr orb, - PortableServer::POA_ptr poa, - PortableServer::ObjectId* contId, - const char* instanceName, - const char* interfaceName ) + PortableServer::POA_ptr poa, + PortableServer::ObjectId* contId, + const char* instanceName, + const char* interfaceName ) { if(MYDEBUG) MESSAGE( "PortableServer::ObjectId* SMESHEngine_factory()" ); if(MYDEBUG) SCRUTE(interfaceName);