From: eap Date: Thu, 9 Feb 2012 13:16:35 +0000 (+0000) Subject: 0021375: EDF 1671 SMESH: Dump study of current state X-Git-Tag: V6_5_0a1~147 X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=commitdiff_plain;h=f6cd6404d7ac4b733b1be7c38368815cbba5a70b;hp=693476070cd5ea1df5c118b4b037bed503d1ef42 0021375: EDF 1671 SMESH: Dump study of current state --- diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index c43ffae0b..30e9a7348 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -33,6 +33,7 @@ #include "SMESH_Filter_i.hxx" #include +#include #include "SMESH_Gen_i.hxx" /* SALOME headers that include CORBA headers that include windows.h @@ -112,6 +113,65 @@ namespace { return find( name ) != end(); } }; + + //================================================================================ + /*! + * \brief Returns a mesh by object + */ + //================================================================================ + + Handle(_pyMesh) ObjectToMesh( const Handle( _pyObject )& obj ) + { + if ( !obj.IsNull() ) + { + if ( obj->IsKind( STANDARD_TYPE( _pyMesh ))) + return Handle(_pyMesh)::DownCast( obj ); + else if ( obj->IsKind( STANDARD_TYPE( _pySubMesh ))) + return Handle(_pySubMesh)::DownCast( obj )->GetMesh(); + else if ( obj->IsKind( STANDARD_TYPE( _pyGroup ))) + return Handle(_pyGroup)::DownCast( obj )->GetMesh(); + } + return Handle(_pyMesh)(); + } + + //================================================================================ + /*! + * \brief Check if objects used as args have been created by previous commands + */ + //================================================================================ + + void CheckObjectPresence( const Handle(_pyCommand)& cmd, set<_pyID> & presentObjects) + { + for ( int iArg = cmd->GetNbArgs(); iArg; --iArg ) + { + const _pyID& arg = cmd->GetArg( iArg ); + if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' ) + continue; + list< _pyID > idList = cmd->GetStudyEntries( arg ); + list< _pyID >::iterator id = idList.begin(); + for ( ; id != idList.end(); ++id ) + if ( !theGen->IsGeomObject( *id ) && !presentObjects.count( *id )) + { + cmd->Comment(); + cmd->GetString() += " ### " ; + cmd->GetString() += *id + " has not been yet created"; + return; + } + } + const _pyID& obj = cmd->GetObject(); + if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj )) + { + cmd->Comment(); + cmd->GetString() += " ### not created object" ; + } + const _pyID& result = cmd->GetResultValue(); + if ( result.IsEmpty() || result.Value( 1 ) == '"' || result.Value( 1 ) == '\'' ) + return; + list< _pyID > idList = cmd->GetStudyEntries( result ); + list< _pyID >::iterator id = idList.begin(); + for ( ; id != idList.end(); ++id ) + presentObjects.insert( *id ); + } } //================================================================================ @@ -119,17 +179,21 @@ namespace { * \brief Convert python script using commands of smesh.py * \param theScript - Input script * \retval TCollection_AsciiString - Convertion result + * \param theToKeepAllCommands - to keep all commands or + * to exclude commands relating to objects removed from study * * Class SMESH_2smeshpy declared in SMESH_PythonDump.hxx */ //================================================================================ TCollection_AsciiString -SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, +SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod, - Resource_DataMapOfAsciiStringAsciiString& theObjectNames) + Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + SALOMEDS::Study_ptr& theStudy, + const bool theToKeepAllCommands) { - theGen = new _pyGen( theEntry2AccessorMethod, theObjectNames ); + theGen = new _pyGen( theEntry2AccessorMethod, theObjectNames, theStudy, theToKeepAllCommands ); // split theScript into separate commands @@ -166,6 +230,9 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, MESSAGE_BEGIN ( std::endl << " ######## RESULT ######## " << std::endl<< std::endl ); #endif + // clean commmands of removed objects depending on myIsPublished flag + theGen->ClearCommands(); + // reorder commands after conversion list< Handle(_pyCommand) >::iterator cmd; bool orderChanges; @@ -177,19 +244,23 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, } while ( orderChanges ); // concat commands back into a script - TCollection_AsciiString aScript; + TCollection_AsciiString aScript, aPrevCmd; + set<_pyID> createdObjects; for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd ) { #ifdef DUMP_CONVERSION MESSAGE_ADD ( "## COM " << (*cmd)->GetOrderNb() << ": "<< (*cmd)->GetString() << std::endl ); #endif - if ( !(*cmd)->IsEmpty() ) { + if ( !(*cmd)->IsEmpty() && aPrevCmd != (*cmd)->GetString()) { + CheckObjectPresence( *cmd, createdObjects ); + aPrevCmd = (*cmd)->GetString(); aScript += "\n"; - aScript += (*cmd)->GetString(); + aScript += aPrevCmd; } } aScript += "\n"; + theGen->Free(); theGen.Nullify(); return aScript; @@ -202,17 +273,49 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, //================================================================================ _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod, - Resource_DataMapOfAsciiStringAsciiString& theObjectNames) + Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + SALOMEDS::Study_ptr& theStudy, + const bool theToKeepAllCommands) : _pyObject( new _pyCommand( "", 0 )), myNbCommands( 0 ), myID2AccessorMethod( theEntry2AccessorMethod ), myObjectNames( theObjectNames ), - myNbFilters( 0 ) + myNbFilters( 0 ), + myToKeepAllCommands( theToKeepAllCommands ), + myStudy( SALOMEDS::Study::_duplicate( theStudy )), + myGeomIDNb(0), myGeomIDIndex(-1) { // make that GetID() to return TPythonDump::SMESHGenName() GetCreationCmd()->Clear(); GetCreationCmd()->GetString() = TPythonDump::SMESHGenName(); GetCreationCmd()->GetString() += "="; + + // Find 1st digit of study entry by which a GEOM object differs from a SMESH object + if ( !theObjectNames.IsEmpty() && !CORBA::is_nil( theStudy )) + { + // find a GEOM entry + _pyID geomID; + SALOMEDS::SComponent_var geomComp = theStudy->FindComponent("GEOM"); + if ( geomComp->_is_nil() ) return; + CORBA::String_var entry = geomComp->GetID(); + geomID = entry.in(); + + // find a SMESH entry + _pyID smeshID; + Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString e2n( theObjectNames ); + for ( ; e2n.More() && smeshID.IsEmpty(); e2n.Next() ) + if ( _pyCommand::IsStudyEntry( e2n.Key() )) + smeshID = e2n.Key(); + + // find 1st difference between smeshID and geomID + if ( !geomID.IsEmpty() && !smeshID.IsEmpty() ) + for ( int i = 1; i <= geomID.Length() && i <= smeshID.Length(); ++i ) + if ( geomID.Value( i ) != smeshID.Value( i )) + { + myGeomIDNb = geomID.Value( i ); + myGeomIDIndex = i; + } + } } //================================================================================ @@ -261,7 +364,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( objID ); if ( id_mesh != myMeshes.end() ) { - id_mesh->second->AddProcessedCmd( aCommand ); + //id_mesh->second->AddProcessedCmd( aCommand ); // check for mesh editor object if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation @@ -278,6 +381,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand } id_mesh->second->Process( aCommand ); + id_mesh->second->AddProcessedCmd( aCommand ); return aCommand; } @@ -285,28 +389,62 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand map< _pyID, Handle(_pyMeshEditor) >::iterator id_editor = myMeshEditors.find( objID ); if ( id_editor != myMeshEditors.end() ) { + const TCollection_AsciiString& method = aCommand->GetMethod(); + + // some commands of SMESH_MeshEditor create meshes and groups + _pyID meshID, groups; + if ( method.Search("MakeMesh") != -1 ) + meshID = aCommand->GetResultValue(); + else if ( method == "MakeBoundaryMesh") + meshID = aCommand->GetResultValue(1); + else if ( method == "MakeBoundaryElements") + meshID = aCommand->GetResultValue(2); + + if ( method.Search("MakeGroups") != -1 || + method == "ExtrusionAlongPathX" || + method == "ExtrusionAlongPathObjX" || + method == "DoubleNodeGroupNew" || + method == "DoubleNodeGroupsNew" || + method == "DoubleNodeElemGroupNew" || + method == "DoubleNodeElemGroupsNew" ) + groups = aCommand->GetResultValue(); + else if ( method == "MakeBoundaryMesh" ) + groups = aCommand->GetResultValue(2); + else if ( method == "MakeBoundaryElements") + groups = aCommand->GetResultValue(3); + id_editor->second->Process( aCommand ); id_editor->second->AddProcessedCmd( aCommand ); - TCollection_AsciiString processedCommand = aCommand->GetString(); - // some commands of SMESH_MeshEditor create meshes - if ( aCommand->GetMethod().Search("MakeMesh") != -1 ) { - _pyID meshID = aCommand->GetResultValue(); + if ( !meshID.IsEmpty() && + !myMeshes.count( meshID ) && + aCommand->IsStudyEntry( meshID )) + { + TCollection_AsciiString processedCommand = aCommand->GetString(); Handle(_pyMesh) mesh = new _pyMesh( aCommand, meshID ); - aCommand->GetString() = processedCommand; // discard changes made by _pyMesh myMeshes.insert( make_pair( meshID, mesh )); + aCommand->Clear(); + aCommand->GetString() = processedCommand; // discard changes made by _pyMesh } - if ( aCommand->GetMethod() == "MakeBoundaryMesh") { - _pyID meshID = aCommand->GetResultValue(0); - if ( !myMeshes.count( meshID ) ) - { - Handle(_pyMesh) mesh = new _pyMesh( aCommand, meshID ); - aCommand->GetString() = processedCommand; // discard changes made by _pyMesh - myMeshes.insert( make_pair( meshID, mesh )); - } + if ( !groups.IsEmpty() ) + { + if ( !aCommand->IsStudyEntry( meshID )) + meshID = id_editor->second->GetMesh(); + Handle(_pyMesh) mesh = myMeshes[ meshID ]; + + list< _pyID > idList = aCommand->GetStudyEntries( groups ); + list< _pyID >::iterator grID = idList.begin(); + for ( ; grID != idList.end(); ++grID ) + if ( !myObjects.count( *grID )) + { + Handle(_pyGroup) group = new _pyGroup( aCommand, *grID ); + AddObject( group ); + if ( !mesh.IsNull() ) mesh->AddGroup( group ); + } } return aCommand; - } + } // SMESH_MeshEditor methods + // SMESH_Hypothesis method? list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); for ( ; hyp != myHypos.end(); ++hyp ) @@ -472,8 +610,10 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) { for(int ind = 0;indGetNbResultValues();ind++) { - Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue(ind)); - myMeshes.insert( make_pair( theCommand->GetResultValue(ind), mesh )); + const _pyID& meshID = theCommand->GetResultValue(ind+1); + if ( !theCommand->IsStudyEntry( meshID ) ) continue; + Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue(ind+1)); + myMeshes.insert( make_pair( mesh->GetID(), mesh )); } } @@ -501,7 +641,8 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) if ( id_mesh != myMeshes.end() ) { theCommand->SetObject( meshID ); theCommand->RemoveArgs(); - id_mesh->second->Flush(); + id_mesh->second->Process( theCommand ); + id_mesh->second->AddProcessedCmd( theCommand ); return; } } @@ -516,6 +657,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) _pyID geom = theCommand->GetArg( 2 ); theCommand->RemoveArgs(); theCommand->SetArg( 1, geom ); + id_mesh->second->AddProcessedCmd( theCommand ); return; } } @@ -529,9 +671,8 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) if ( !myObjects.insert( make_pair( obj->GetID(), obj )).second ) theCommand->Clear(); // already created } - // Concatenate( [mesh1, ...], ... ) - if ( method == "Concatenate" || method == "ConcatenateWithGroups") + else if ( method == "Concatenate" || method == "ConcatenateWithGroups") { if ( method == "ConcatenateWithGroups" ) { theCommand->SetMethod( "Concatenate" ); @@ -541,6 +682,14 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) myMeshes.insert( make_pair( mesh->GetID(), mesh )); AddMeshAccessorMethod( theCommand ); } + else if ( method == "SetName" ) // SetName(obj,name) + { + // store theCommand as one of object commands to erase it along with the object + const _pyID& objID = theCommand->GetArg( 1 ); + Handle(_pyObject) obj = FindObject( objID ); + if ( !obj.IsNull() ) + obj->AddProcessedCmd( theCommand ); + } // Replace name of SMESH_Gen @@ -569,16 +718,36 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) void _pyGen::Flush() { - // create empty command + // create an empty command myLastCommand = new _pyCommand(); - map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin(); - for ( ; id_mesh != myMeshes.end(); ++id_mesh ) + map< _pyID, Handle(_pyMesh) >::iterator id_mesh; + map< _pyID, Handle(_pyObject) >::iterator id_obj; + list< Handle(_pyHypothesis) >::iterator hyp; + + if ( IsToKeepAllCommands() ) // historical dump + { + // set myIsPublished = true to all objects + for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh ) + id_mesh->second->SetRemovedFromStudy( false ); + for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) + (*hyp)->SetRemovedFromStudy( false ); + for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj ) + id_obj->second->SetRemovedFromStudy( false ); + } + // set myIsPublished = false to all objects depending on + // meshes built on a removed geometry + for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh ) + if ( id_mesh->second->IsNotGeomPublished() ) + id_mesh->second->SetRemovedFromStudy( true ); + + // Flush meshes + for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh ) if ( ! id_mesh->second.IsNull() ) id_mesh->second->Flush(); - list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); - for ( ; hyp != myHypos.end(); ++hyp ) + // Flush hyps + for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) if ( !hyp->IsNull() ) { (*hyp)->Flush(); // smeshgen.CreateHypothesis() --> smesh.smesh.CreateHypothesis() @@ -586,8 +755,8 @@ void _pyGen::Flush() (*hyp)->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() ); } - map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin(); - for ( ; id_obj != myObjects.end(); ++id_obj ) + // Flush other objects + for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj ) if ( ! id_obj->second.IsNull() ) id_obj->second->Flush(); @@ -595,6 +764,60 @@ void _pyGen::Flush() myCommands.push_back( myLastCommand ); } +//================================================================================ +/*! + * \brief Clean commmands of removed objects depending on myIsPublished flag + */ +//================================================================================ + +void _pyGen::ClearCommands() +{ + map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin(); + for ( ; id_mesh != myMeshes.end(); ++id_mesh ) + id_mesh->second->ClearCommands(); + + list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); + for ( ; hyp != myHypos.end(); ++hyp ) + if ( !hyp->IsNull() ) + (*hyp)->ClearCommands(); + + map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin(); + for ( ; id_obj != myObjects.end(); ++id_obj ) + id_obj->second->ClearCommands(); +} + +//================================================================================ +/*! + * \brief Release mutual handles of objects + */ +//================================================================================ + +void _pyGen::Free() +{ + map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin(); + for ( ; id_mesh != myMeshes.end(); ++id_mesh ) + id_mesh->second->Free(); + myMeshes.clear(); + + map< _pyID, Handle(_pyMeshEditor) >::iterator id_ed = myMeshEditors.begin(); + for ( ; id_ed != myMeshEditors.end(); ++id_ed ) + id_ed->second->Free(); + myMeshEditors.clear(); + + map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin(); + for ( ; id_obj != myObjects.end(); ++id_obj ) + id_obj->second->Free(); + myObjects.clear(); + + list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); + for ( ; hyp != myHypos.end(); ++hyp ) + if ( !hyp->IsNull() ) + (*hyp)->Free(); + myHypos.clear(); + + myFile2ExportedMesh.clear(); +} + //================================================================================ /*! * \brief Add access method to mesh that is an argument @@ -821,7 +1044,16 @@ _pyID _pyGen::GenerateNewID( const _pyID& theID ) void _pyGen::AddObject( Handle(_pyObject)& theObj ) { - myObjects.insert( make_pair( theObj->GetID(), theObj )); + if ( theObj.IsNull() ) return; + + if ( theObj->IsKind( STANDARD_TYPE( _pyMesh ))) + myMeshes.insert( make_pair( theObj->GetID(), Handle(_pyMesh)::DownCast( theObj ))); + + else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor ))) + myMeshEditors.insert( make_pair( theObj->GetID(), Handle(_pyMeshEditor)::DownCast( theObj ))); + + else + myObjects.insert( make_pair( theObj->GetID(), theObj )); } //================================================================================ @@ -842,25 +1074,52 @@ Handle(_pyObject) _pyGen::FindObject( const _pyID& theObjID ) const if ( id_obj != myMeshes.end() ) return id_obj->second; } + // { + // map< _pyID, Handle(_pyMeshEditor) >::const_iterator id_obj = myMeshEditors.find( theObjID ); + // if ( id_obj != myMeshEditors.end() ) + // return id_obj->second; + // } + return Handle(_pyObject)(); +} + +//================================================================================ +/*! + * \brief Check if a study entry is under GEOM component + */ +//================================================================================ + +bool _pyGen::IsGeomObject(const _pyID& theObjID) const +{ + if ( myGeomIDNb ) { - map< _pyID, Handle(_pyMeshEditor) >::const_iterator id_obj = myMeshEditors.find( theObjID ); - if ( id_obj != myMeshEditors.end() ) - return id_obj->second; + return ( myGeomIDIndex <= theObjID.Length() && + int( theObjID.Value( myGeomIDIndex )) == myGeomIDNb); } - return Handle(_pyObject)(); + return false; } //================================================================================ /*! - * \brief Returns true if an object is removed from study + * \brief Returns true if an object is not present in a study */ //================================================================================ -bool _pyGen::IsDead(const _pyID& theObjID) const +bool _pyGen::IsNotPublished(const _pyID& theObjID) const { if ( theObjID.IsEmpty() ) return false; - const bool hasStudyName = myObjectNames.IsBound( theObjID ); - return !hasStudyName; + + if ( myObjectNames.IsBound( theObjID )) + return false; // SMESH object is in study + + // either the SMESH object is not in study or it is a GEOM object + if ( IsGeomObject( theObjID )) + { + SALOMEDS::SObject_var so = myStudy->FindObjectID( theObjID.ToCString() ); + if ( so->_is_nil() ) return true; + CORBA::Object_var obj = so->GetObject(); + return CORBA::is_nil( obj ); + } + return true; // SMESH object not in study } //================================================================================ @@ -870,13 +1129,15 @@ bool _pyGen::IsDead(const _pyID& theObjID) const //================================================================================ _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd) - : _pyObject(theCreationCmd), myHasEditor(false) + : _pyObject( theCreationCmd ), myGeomNotInStudy( false ) { - // convert my creation command + if ( theCreationCmd->GetMethod() == "CreateMesh" && theGen->IsNotPublished( GetGeom() )) + myGeomNotInStudy = true; + + // convert my creation command --> smeshpy.Mesh(...) Handle(_pyCommand) creationCmd = GetCreationCmd(); creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() ); creationCmd->SetMethod( "Mesh" ); - theGen->SetAccessorMethod( GetID(), _pyMesh::AccessorMethod() ); } @@ -886,13 +1147,56 @@ _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd) */ //================================================================================ -_pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd, const TCollection_AsciiString& id): - _pyObject(theCreationCmd), myHasEditor(false) +_pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd, const _pyID& meshId): + _pyObject(theCreationCmd,meshId), myGeomNotInStudy(false ) { + if ( theCreationCmd->MethodStartsFrom( "CreateMeshesFrom" )) + { + // this mesh depends on the exported mesh + const TCollection_AsciiString& file = theCreationCmd->GetArg( 1 ); + if ( !file.IsEmpty() ) + { + ExportedMeshData& exportData = theGen->FindExportedMesh( file ); + addFatherMesh( exportData.myMesh ); + if ( !exportData.myLastComputeCmd.IsNull() ) + { + // restore cleared Compute() by which the exported mesh was generated + exportData.myLastComputeCmd->GetString() = exportData.myLastComputeCmdString; + // protect that Compute() cmd from clearing + if ( exportData.myMesh->myLastComputeCmd == exportData.myLastComputeCmd ) + exportData.myMesh->myLastComputeCmd.Nullify(); + } + } + } + else if ( theCreationCmd->MethodStartsFrom( "Concatenate" )) + { + // this mesh depends on concatenated meshes + const TCollection_AsciiString& meshIDs = theCreationCmd->GetArg( 1 ); + list< _pyID > idList = theCreationCmd->GetStudyEntries( meshIDs ); + list< _pyID >::iterator meshID = idList.begin(); + for ( ; meshID != idList.end(); ++meshID ) + addFatherMesh( *meshID ); + } + else if ( theCreationCmd->GetMethod() == "CopyMesh" ) + { + // this mesh depends on a copied IdSource + const _pyID& objID = theCreationCmd->GetArg( 1 ); + addFatherMesh( objID ); + } + else if ( theCreationCmd->GetMethod().Search("MakeMesh") != -1 || + theCreationCmd->GetMethod() == "MakeBoundaryMesh" || + theCreationCmd->GetMethod() == "MakeBoundaryElements" ) + { + // this mesh depends on a source mesh + // (theCreationCmd is already Process()ed by _pyMeshEditor) + const _pyID& meshID = theCreationCmd->GetObject(); + addFatherMesh( meshID ); + } + // convert my creation command Handle(_pyCommand) creationCmd = GetCreationCmd(); creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() ); - theGen->SetAccessorMethod( id, _pyMesh::AccessorMethod() ); + theGen->SetAccessorMethod( meshId, _pyMesh::AccessorMethod() ); } //================================================================================ @@ -917,9 +1221,63 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) // --> in Mesh.ExportMED( f, auto_groups, version ) // 5. etc - const TCollection_AsciiString method = theCommand->GetMethod(); + const TCollection_AsciiString& method = theCommand->GetMethod(); // ---------------------------------------------------------------------- - if ( method == "GetSubMesh" ) { // collect submeshes of the mesh + if ( method == "Compute" ) // in snapshot mode, clear the previous Compute() + { + if ( !theGen->IsToKeepAllCommands() ) // !historical + { + list< Handle(_pyHypothesis) >::iterator hyp; + if ( !myLastComputeCmd.IsNull() ) + { + for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) + (*hyp)->ComputeDiscarded( myLastComputeCmd ); + + myLastComputeCmd->Clear(); + } + myLastComputeCmd = theCommand; + + for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) + (*hyp)->MeshComputed( myLastComputeCmd ); + } + Flush(); + } + // ---------------------------------------------------------------------- + else if ( method == "Clear" ) // in snapshot mode, clear all previous commands + { + if ( !theGen->IsToKeepAllCommands() ) // !historical + { + int untilCmdNb = + myChildMeshes.empty() ? 0 : myChildMeshes.back()->GetCreationCmd()->GetOrderNb(); + // list< Handle(_pyCommand) >::reverse_iterator cmd = myProcessedCmds.rbegin(); + // for ( ; cmd != myProcessedCmds.rend() && (*cmd)->GetOrderNb() > untilCmdNb; ++cmd ) + // (*cmd)->Clear(); + if ( !myLastComputeCmd.IsNull() ) + { + list< Handle(_pyHypothesis) >::iterator hyp; + for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) + (*hyp)->ComputeDiscarded( myLastComputeCmd ); + + myLastComputeCmd->Clear(); + } + + list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin(); + for ( ; e != myEditors.end(); ++e ) + { + list< Handle(_pyCommand)>& cmds = (*e)->GetProcessedCmds(); + list< Handle(_pyCommand) >::reverse_iterator cmd = cmds.rbegin(); + for ( ; cmd != cmds.rend() && (*cmd)->GetOrderNb() > untilCmdNb; ++cmd ) + if ( !(*cmd)->IsEmpty() ) + { + if ( (*cmd)->GetStudyEntries( (*cmd)->GetResultValue() ).empty() ) // no object created + (*cmd)->Clear(); + } + } + myLastComputeCmd = theCommand; // to clear Clear() the same way as Compute() + } + } + // ---------------------------------------------------------------------- + else if ( method == "GetSubMesh" ) { // collect submeshes of the mesh Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetResultValue() ); if ( !subMesh.IsNull() ) { subMesh->SetCreator( this ); @@ -945,6 +1303,14 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) } } // ---------------------------------------------------------------------- + else if ( method == "CreateGroup" ) // CreateGroup() --> CreateEmptyGroup() + { + theCommand->SetMethod( "CreateEmptyGroup" ); + Handle(_pyGroup) group = new _pyGroup( theCommand ); + myGroups.push_back( group ); + theGen->AddObject( group ); + } + // ---------------------------------------------------------------------- else if ( method == "CreateGroupFromGEOM" ) {// (type, name, grp) _pyID grp = theCommand->GetArg( 3 ); // VSR 24/12/2010. PAL21106: always use GroupOnGeom() function on dump @@ -964,64 +1330,59 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) theCommand->SetArg( 2, name ); theCommand->SetArg( 3, type ); //} + Handle(_pyGroup) group = new _pyGroup( theCommand ); + myGroups.push_back( group ); + theGen->AddObject( group ); } // ---------------------------------------------------------------------- else if ( method == "CreateGroupFromFilter" ) // --> GroupOnFilter() { theCommand->SetMethod( "GroupOnFilter" ); Handle(_pyGroup) group = new _pyGroup( theCommand ); + myGroups.push_back( group ); theGen->AddObject( group ); // GroupOnFilter(typ, name, aFilter0x4743dc0 -> aFilter_1) _pyID filterID = theCommand->GetArg(3); - Handle(_pyObject) filter = theGen->FindObject( filterID ); - if ( !filter.IsNull() && filter->IsKind(STANDARD_TYPE(_pyFilter))) - filter->Process( theCommand ); - } - // ---------------------------------------------------------------------- - else if ( method == "GetIdsFromFilter" ) - { - // GetIdsFromFilter( aFilter0x4743dc0) -> GetIdsFromFilter( aFilter_1) - _pyID filterID = theCommand->GetArg(1); - Handle(_pyObject) filter = theGen->FindObject( filterID ); - if ( !filter.IsNull() && filter->IsKind(STANDARD_TYPE(_pyFilter))) + Handle(_pyFilter) filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID )); + if ( !filter.IsNull()) + { filter->Process( theCommand ); + filter->AddUser( group ); + } } // ---------------------------------------------------------------------- - else if ( method == "CreateGroup" ) // CreateGroup() --> CreateEmptyGroup() + else if ( theCommand->MethodStartsFrom( "Export" )) { - theCommand->SetMethod( "CreateEmptyGroup" ); - Handle(_pyGroup) group = new _pyGroup( theCommand ); - theGen->AddObject( group ); - } - // ---------------------------------------------------------------------- - else if ( method == "ExportToMED" || // ExportToMED() --> ExportMED() - method == "ExportToMEDX" ) { // ExportToMEDX() --> ExportMED() - theCommand->SetMethod( "ExportMED" ); - } - // ---------------------------------------------------------------------- - else if ( method == "ExportCGNS" ) - { // ExportCGNS(part, ...) -> ExportCGNS(..., part) - _pyID partID = theCommand->GetArg( 1 ); - int nbArgs = theCommand->GetNbArgs(); - for ( int i = 2; i <= nbArgs; ++i ) - theCommand->SetArg( i-1, theCommand->GetArg( i )); - theCommand->SetArg( nbArgs, partID ); - } - // ---------------------------------------------------------------------- - else if ( method.Location( "ExportPartTo", 1, method.Length() ) == 1 ) - { // ExportPartTo*(part, ...) -> Export*(..., part) - // - // remove "PartTo" from the method - TCollection_AsciiString newMethod = method; - newMethod.Remove( 7, 6 ); - theCommand->SetMethod( newMethod ); - // make the 1st arg be the last one - _pyID partID = theCommand->GetArg( 1 ); - int nbArgs = theCommand->GetNbArgs(); - for ( int i = 2; i <= nbArgs; ++i ) - theCommand->SetArg( i-1, theCommand->GetArg( i )); - theCommand->SetArg( nbArgs, partID ); + if ( method == "ExportToMED" || // ExportToMED() --> ExportMED() + method == "ExportToMEDX" ) { // ExportToMEDX() --> ExportMED() + theCommand->SetMethod( "ExportMED" ); + } + else if ( method == "ExportCGNS" ) + { // ExportCGNS(part, ...) -> ExportCGNS(..., part) + _pyID partID = theCommand->GetArg( 1 ); + int nbArgs = theCommand->GetNbArgs(); + for ( int i = 2; i <= nbArgs; ++i ) + theCommand->SetArg( i-1, theCommand->GetArg( i )); + theCommand->SetArg( nbArgs, partID ); + } + else if ( theCommand->MethodStartsFrom( "ExportPartTo" )) + { // ExportPartTo*(part, ...) -> Export*(..., part) + // + // remove "PartTo" from the method + TCollection_AsciiString newMethod = method; + newMethod.Remove( 7, 6 ); + theCommand->SetMethod( newMethod ); + // make the 1st arg be the last one + _pyID partID = theCommand->GetArg( 1 ); + int nbArgs = theCommand->GetNbArgs(); + for ( int i = 2; i <= nbArgs; ++i ) + theCommand->SetArg( i-1, theCommand->GetArg( i )); + theCommand->SetArg( nbArgs, partID ); + } + // remember file name + theGen->AddExportedMesh( theCommand->GetArg( 1 ), + ExportedMeshData( this, myLastComputeCmd )); } // ---------------------------------------------------------------------- else if ( method == "RemoveHypothesis" ) // (geom, hyp) @@ -1057,25 +1418,36 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) myHypos.remove( hyp ); } // check for SubMesh order commands - else if ( theCommand->GetMethod() == "GetMeshOrder" || - theCommand->GetMethod() == "SetMeshOrder" ) + else if ( method == "GetMeshOrder" || method == "SetMeshOrder" ) { // make commands GetSubMesh() returning sub-meshes be before using sub-meshes // by GetMeshOrder() and SetMeshOrder(), since by defalut GetSubMesh() // commands are moved at the end of the script - const bool isArg = theCommand->GetMethod() == "SetMeshOrder"; - const TCollection_AsciiString& cmdStr = theCommand->GetString(); - int begPos = (/*isArg ? cmdStr.Search( "(" ) :*/ cmdStr.Search( "[" )) + 1; - int endPos = (isArg ? cmdStr.Search( ")" ) : cmdStr.Search( "=" )) - 1; - if ( begPos != -1 && begPos < endPos && endPos <= cmdStr.Length() ) { - TCollection_AsciiString aSubStr = cmdStr.SubString( begPos, endPos ); - Standard_Integer index = 1; - TCollection_AsciiString anIDStr = aSubStr.Token("\t ,[]", index++); - while ( !anIDStr.IsEmpty() ) { - Handle(_pySubMesh) subMesh = theGen->FindSubMesh( anIDStr ); - if ( !subMesh.IsNull() ) - subMesh->Process( theCommand ); // it moves GetSubMesh() before theCommand - anIDStr = aSubStr.Token("\t ,[]", index++); + TCollection_AsciiString subIDs = + ( method == "SetMeshOrder" ) ? theCommand->GetArg(1) : theCommand->GetResultValue(); + list< _pyID > idList = theCommand->GetStudyEntries( subIDs ); + list< _pyID >::iterator subID = idList.begin(); + for ( ; subID != idList.end(); ++subID ) + { + Handle(_pySubMesh) subMesh = theGen->FindSubMesh( *subID ); + if ( !subMesh.IsNull() ) + subMesh->Process( theCommand ); // it moves GetSubMesh() before theCommand + } + } + // update list of groups + else if ( method == "GetGroups" ) + { + TCollection_AsciiString grIDs = theCommand->GetResultValue(); + list< _pyID > idList = theCommand->GetStudyEntries( grIDs ); + list< _pyID >::iterator grID = idList.begin(); + for ( ; grID != idList.end(); ++grID ) + { + Handle(_pyObject) obj = theGen->FindObject( *grID ); + if ( obj.IsNull() ) + { + Handle(_pyGroup) group = new _pyGroup( theCommand, *grID ); + theGen->AddObject( group ); + myGroups.push_back( group ); } } } @@ -1129,6 +1501,23 @@ bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand ) void _pyMesh::Flush() { + { + // get the meshes this mesh depends on via hypotheses + list< Handle(_pyMesh) > fatherMeshes; + list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); + for ( ; hyp != myHypos.end(); ++hyp ) + if ( ! (*hyp)->GetReferredMeshesAndGeom( fatherMeshes )) + myGeomNotInStudy = true; + + list< Handle(_pyMesh) >::iterator m = fatherMeshes.begin(); + for ( ; m != fatherMeshes.end(); ++m ) + addFatherMesh( *m ); + // if ( removedGeom ) + // SetRemovedFromStudy(); // as reffered geometry not in study + } + if ( myGeomNotInStudy ) + return; + list < Handle(_pyCommand) >::iterator cmd; // try to convert algo addition like this: @@ -1218,21 +1607,126 @@ void _pyMesh::Flush() } } - // sm = mesh.GetSubMesh(geom, name) --> sm = mesh.GetMesh().GetSubMesh(geom, name) -// for ( cmd = mySubmeshes.begin(); cmd != mySubmeshes.end(); ++cmd ) { -// Handle(_pyCommand) subCmd = *cmd; -// if ( subCmd->GetNbArgs() > 0 ) -// AddMeshAccess( subCmd ); -// } myAddHypCmds.clear(); mySubmeshes.clear(); // flush hypotheses list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); - for ( ; hyp != myHypos.end(); ++hyp ) + for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) (*hyp)->Flush(); } +//================================================================================ +/*! + * \brief Sets myIsPublished of me and of all objects depending on me. + */ +//================================================================================ + +void _pyMesh::SetRemovedFromStudy(const bool isRemoved) +{ + _pyObject::SetRemovedFromStudy(isRemoved); + + list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin(); + for ( ; sm != mySubmeshes.end(); ++sm ) + (*sm)->SetRemovedFromStudy(isRemoved); + + list< Handle(_pyGroup) >::iterator gr = myGroups.begin(); + for ( ; gr != myGroups.end(); ++gr ) + (*gr)->SetRemovedFromStudy(isRemoved); + + list< Handle(_pyMesh) >::iterator m = myChildMeshes.begin(); + for ( ; m != myChildMeshes.end(); ++m ) + (*m)->SetRemovedFromStudy(isRemoved); + + list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin(); + for ( ; e != myEditors.end(); ++e ) + (*e)->SetRemovedFromStudy(isRemoved); +} + +//================================================================================ +/*! + * \brief Return true if none of myChildMeshes is in study + */ +//================================================================================ + +bool _pyMesh::CanClear() +{ + if ( IsInStudy() ) + return false; + + list< Handle(_pyMesh) >::iterator m = myChildMeshes.begin(); + for ( ; m != myChildMeshes.end(); ++m ) + if ( !(*m)->CanClear() ) + return false; + + return true; +} + +//================================================================================ +/*! + * \brief Clear my commands and commands of mesh editor + */ +//================================================================================ + +void _pyMesh::ClearCommands() +{ + if ( !CanClear() ) + { + if ( !IsInStudy() ) + { + // mark all sub-objects as not removed, except child meshes + list< Handle(_pyMesh) > children; + children.swap( myChildMeshes ); + SetRemovedFromStudy( false ); + children.swap( myChildMeshes ); + } + return; + } + _pyObject::ClearCommands(); + + list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin(); + for ( ; sm != mySubmeshes.end(); ++sm ) + (*sm)->ClearCommands(); + + list< Handle(_pyGroup) >::iterator gr = myGroups.begin(); + for ( ; gr != myGroups.end(); ++gr ) + (*gr)->ClearCommands(); + + list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin(); + for ( ; e != myEditors.end(); ++e ) + (*e)->ClearCommands(); +} + +//================================================================================ +/*! + * \brief Add a father mesh by ID + */ +//================================================================================ + +void _pyMesh::addFatherMesh( const _pyID& meshID ) +{ + if ( !meshID.IsEmpty() ) + addFatherMesh( Handle(_pyMesh)::DownCast( theGen->FindObject( meshID ))); +} + +//================================================================================ +/*! + * \brief Add a father mesh + */ +//================================================================================ + +void _pyMesh::addFatherMesh( const Handle(_pyMesh)& mesh ) +{ + if ( !mesh.IsNull() ) + { + //myFatherMeshes.push_back( mesh ); + mesh->myChildMeshes.push_back( this ); + + // protect last Compute() from clearing by the next Compute() + mesh->myLastComputeCmd.Nullify(); + } +} + //================================================================================ /*! * \brief MeshEditor convert its commands to ones of mesh @@ -1245,6 +1739,10 @@ _pyMeshEditor::_pyMeshEditor(const Handle(_pyCommand)& theCreationCmd): myMesh = theCreationCmd->GetObject(); myCreationCmdStr = theCreationCmd->GetString(); theCreationCmd->Clear(); + + Handle(_pyMesh) mesh = ObjectToMesh( theGen->FindObject( myMesh )); + if ( !mesh.IsNull() ) + mesh->AddEditor( this ); } //================================================================================ @@ -1389,6 +1887,18 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) } } +//================================================================================ +/*! + * \brief Return true if my mesh can be removed + */ +//================================================================================ + +bool _pyMeshEditor::CanClear() +{ + Handle(_pyMesh) mesh = ObjectToMesh( theGen->FindObject( myMesh )); + return mesh.IsNull() ? true : mesh->CanClear(); +} + //================================================================================ /*! * \brief _pyHypothesis constructor @@ -1594,7 +2104,7 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th hyp->SetConvMethodAndType( "Parameters", "GHS3D_3D"); } // Hexa_3D --------- - else if ( hypType == "BLSURF" ) { + else if ( hypType == "Hexa_3D" ) { algo->SetConvMethodAndType( "Hexahedron", hypType.ToCString()); } // Repetitive Projection_1D --------- @@ -1617,6 +2127,7 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th } else if ( hypType == "ProjectionSource2D" ) { hyp->SetConvMethodAndType( "SourceFace", "Projection_2D"); + hyp->SetConvMethodAndType( "SourceFace", "Projection_1D2D"); hyp->AddArgMethod( "SetSourceFace"); hyp->AddArgMethod( "SetSourceMesh"); hyp->AddArgMethod( "SetVertexAssociation", 4 ); @@ -1670,10 +2181,10 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th bool _pyHypothesis::IsWrappable(const _pyID& theMesh) const { - if ( !myIsWrapped && myMesh == theMesh && !IsRemovedFromStudy() ) + if ( !myIsWrapped && myMesh == theMesh && IsInStudy() ) { Handle(_pyObject) pyMesh = theGen->FindObject( myMesh ); - if ( !pyMesh.IsNull() && !pyMesh->IsRemovedFromStudy() ) + if ( !pyMesh.IsNull() && pyMesh->IsInStudy() ) return true; } return false; @@ -1754,6 +2265,7 @@ bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd, void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand) { ASSERT( !myIsAlgo ); + rememberCmdOfParameter( theCommand ); // set args int nbArgs = 0; for ( int i = 1; i <= myArgMethods.Length(); ++i ) { @@ -1842,6 +2354,215 @@ void _pyHypothesis::Assign( const Handle(_pyHypothesis)& theOther, myUnknownCommands = theOther->myUnknownCommands; } +//================================================================================ +/*! + * \brief Analyze my erasability depending on myReferredObjs + */ +//================================================================================ + +bool _pyHypothesis::CanClear() +{ + if ( IsInStudy() ) + { + list< Handle(_pyObject) >::iterator obj = myReferredObjs.begin(); + for ( ; obj != myReferredObjs.end(); ++obj ) + if ( (*obj)->CanClear() ) + return true; + return false; + } + return true; +} + +//================================================================================ +/*! + * \brief Clear my commands depending on usage by meshes + */ +//================================================================================ + +void _pyHypothesis::ClearCommands() +{ + if ( !theGen->IsToKeepAllCommands() ) + { + bool isUsed = false; + int lastComputeOrder = 0; + list::iterator cmd = myComputeCmds.begin(); + for ( ; cmd != myComputeCmds.end(); ++cmd ) + if ( ! (*cmd)->IsEmpty() ) + { + isUsed = true; + if ( (*cmd)->GetOrderNb() > lastComputeOrder ) + lastComputeOrder = (*cmd)->GetOrderNb(); + } + if ( !isUsed ) + { + SetRemovedFromStudy( true ); + } + else + { + // clear my commands invoked after lastComputeOrder + map >::iterator m2c; + for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c ) + { + list< Handle(_pyCommand)> & cmds = m2c->second; + if ( !cmds.empty() && cmds.back()->GetOrderNb() > lastComputeOrder ) + cmds.back()->Clear(); + } + } + } + _pyObject::ClearCommands(); +} + +//================================================================================ +/*! + * \brief Find arguments that are objects like mesh, group, geometry + * \param meshes - referred meshes (directly or indirrectly) + * \retval bool - false if a referred geometry is not in the study + */ +//================================================================================ + +bool _pyHypothesis::GetReferredMeshesAndGeom( list< Handle(_pyMesh) >& meshes ) +{ + if ( IsAlgo() ) return true; + + bool geomPublished = true; + TColStd_SequenceOfAsciiString args; args = myArgs; + + list::iterator cmd = myUnknownCommands.begin(); + for ( ; cmd != myUnknownCommands.end(); ++cmd ) { + for ( int nb = (*cmd)->GetNbArgs(); nb; --nb ) + args.Append( (*cmd)->GetArg( nb )); + } + + for ( int i = 1; i <= args.Length(); ++i ) + { + list< _pyID > idList = _pyCommand::GetStudyEntries( args( i )); + list< _pyID >::iterator id = idList.begin(); + for ( ; id != idList.end(); ++id ) + { + Handle(_pyObject) obj = theGen->FindObject( *id ); + if ( obj.IsNull() ) + { + if ( theGen->IsGeomObject( *id ) && theGen->IsNotPublished( *id )) + geomPublished = false; + } + else + { + myReferredObjs.push_back( obj ); + Handle(_pyMesh) mesh = ObjectToMesh( obj ); + if ( !mesh.IsNull() ) + meshes.push_back( mesh ); + } + } + } + return geomPublished; +} + +//================================================================================ +/*! + * \brief Remember theCommand setting a parameter + */ +//================================================================================ + +void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theCommand ) +{ + // not to clear commands setting different parameters via one method + // by passing parameter names like e.g. SetOption("size", "0.2") + int quotePos = theCommand->GetString().FirstLocationInSet( "'\"", 1, theCommand->Length() ); + if ( !quotePos ) + { + // parameters are discriminated by method name + list< Handle(_pyCommand)>& cmds = myMeth2Commands[ theCommand->GetMethod() ]; + if ( !cmds.empty() && !isCmdUsedForCompute( cmds.back() )) + { + cmds.back()->Clear(); // previous parameter value has not been used + cmds.back() = theCommand; + } + else + { + cmds.push_back( theCommand ); + } + } +} + +//================================================================================ +/*! + * \brief Return true if a setting parameter command ha been used to compute mesh + */ +//================================================================================ + +bool _pyHypothesis::isCmdUsedForCompute( const Handle(_pyCommand) & cmd, + _pyCommand::TAddr avoidComputeAddr ) const +{ + bool isUsed = false; + map< _pyCommand::TAddr, list >::const_iterator addr2cmds = + myComputeAddr2Cmds.begin(); + for ( ; addr2cmds != myComputeAddr2Cmds.end() && !isUsed; ++addr2cmds ) + { + if ( addr2cmds->first == avoidComputeAddr ) continue; + const list & cmds = addr2cmds->second; + isUsed = ( std::find( cmds.begin(), cmds.end(), cmd ) != cmds.end() ); + } + return isUsed; +} + +//================================================================================ +/*! + * \brief Save commands setting parameters as they are used for a mesh computation + */ +//================================================================================ + +void _pyHypothesis::MeshComputed( const Handle(_pyCommand)& theComputeCmd ) +{ + myComputeCmds.push_back( theComputeCmd ); + list& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ]; + + map >::iterator m2c; + for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c ) + savedCmds.push_back( m2c->second.back() ); +} + +//================================================================================ +/*! + * \brief Clear commands setting parameters as a mesh computed using them is cleared + */ +//================================================================================ + +void _pyHypothesis::ComputeDiscarded( const Handle(_pyCommand)& theComputeCmd ) +{ + list& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ]; + + list::iterator cmd = savedCmds.begin(); + for ( ; cmd != savedCmds.end(); ++cmd ) + { + // check if a cmd has been used to compute another mesh + if ( isCmdUsedForCompute( *cmd, theComputeCmd->GetAddress() )) + continue; + // check if a cmd is a sole command setting its parameter; + // don't use method name for search as it can change + map >::iterator + m2cmds = myMeth2Commands.begin(); + for ( ; m2cmds != myMeth2Commands.end(); ++m2cmds ) + { + list< Handle(_pyCommand)>& cmds = m2cmds->second; + list< Handle(_pyCommand)>::iterator cmdIt = std::find( cmds.begin(), cmds.end(), *cmd ); + if ( cmdIt != cmds.end() ) + { + if ( cmds.back() != *cmd ) + { + cmds.erase( cmdIt ); + (*cmd)->Clear(); + } + break; + } + } + } + myComputeAddr2Cmds.erase( theComputeCmd->GetAddress() ); +} +// void _pyHypothesis::ComputeSaved( const Handle(_pyCommand)& theComputeCommand ) +// { +// } + + //================================================================================ /*! * \brief Remember hypothesis parameter values @@ -1879,6 +2600,7 @@ void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand) myArgs( iArg ) += "]"; } myArgCommands.push_back( theCommand ); + rememberCmdOfParameter( theCommand ); return; } } @@ -2241,12 +2963,20 @@ const TCollection_AsciiString & _pyCommand::GetResultValue() { if ( GetBegPos( RESULT_IND ) == UNKNOWN ) { - int begPos = myString.Location( "=", 1, Length() ); - if ( begPos ) - myRes = GetWord( myString, begPos, false ); - else - begPos = EMPTY; - SetBegPos( RESULT_IND, begPos ); + SetBegPos( RESULT_IND, EMPTY ); + int begPos, endPos = myString.Location( "=", 1, Length() ); + if ( endPos ) + { + begPos = 1; + while ( begPos < endPos && isblank( myString.Value( begPos ))) ++begPos; + if ( begPos < endPos ) + { + SetBegPos( RESULT_IND, begPos ); + --endPos; + while ( begPos < endPos && isblank( myString.Value( endPos ))) --endPos; + myRes = myString.SubString( begPos, endPos ); + } + } } return myRes; } @@ -2398,7 +3128,7 @@ const TCollection_AsciiString & _pyCommand::GetArg( int index ) // we are at or before '(', skip it if present if ( pos > 0 ) { while ( pos <= Length() && myString.Value( pos ) != '(' ) ++pos; - if ( myString.Value( pos ) != '(' ) + if ( pos > Length() ) pos = 0; } if ( pos < 1 ) { @@ -2519,10 +3249,11 @@ TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & the return theEmptyString; // no word found beg = end - 1; char endChar = theString.Value( end ); - if ( endChar == '"' || endChar == '\'' ) { + if ( endChar == '"' || endChar == '\'' || endChar == ']') { + char begChar = ( endChar == ']' ) ? '[' : endChar; // beg is at the corresponding quoting mark while ( beg > 1 && - ( theString.Value( beg ) != endChar || theString.Value( beg-1 ) == '\\')) + ( theString.Value( beg ) != begChar || theString.Value( beg-1 ) == '\\')) --beg; } else { @@ -2536,6 +3267,52 @@ TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & the return theString.SubString( beg, end ); } +//================================================================================ +/*! + * \brief Returns true if the string looks like a study entry + */ +//================================================================================ + +bool _pyCommand::IsStudyEntry( const TCollection_AsciiString& str ) +{ + if ( str.Length() < 5 ) return false; + + int nbColons = 0, isColon; + for ( int i = 1; i <= str.Length(); ++i ) + { + char c = str.Value(i); + if (!( isColon = (c == ':')) && ( c < '0' || c > '9' )) + return false; + nbColons += isColon; + } + return nbColons > 2 && str.Length()-nbColons > 2; +} + +//================================================================================ +/*! + * \brief Finds entries in a sting + */ +//================================================================================ + +std::list< _pyID > _pyCommand::GetStudyEntries( const TCollection_AsciiString& str ) +{ + std::list< _pyID > resList; + int pos = 0; + while ( ++pos <= str.Length() ) + { + if ( !isdigit( str.Value( pos ))) continue; + if ( pos != 1 && ( isalpha( str.Value( pos-1 ) || str.Value( pos-1 ) == ':'))) continue; + + int end = pos; + while ( ++end <= str.Length() && ( isdigit( str.Value( end )) || str.Value( end ) == ':' )); + _pyID entry = str.SubString( pos, end-1 ); + pos = end; + if ( IsStudyEntry( entry )) + resList.push_back( entry ); + } + return resList; +} + //================================================================================ /*! * \brief Look for position where not space char is @@ -2657,6 +3434,30 @@ void _pyCommand::RemoveArgs() myBegPos.Remove( ARG1_IND, myBegPos.Length() ); } +//================================================================================ +/*! + * \brief Comment a python command + */ +//================================================================================ + +void _pyCommand::Comment() +{ + if ( IsEmpty() ) return; + + int i = 1; + while ( i <= Length() && isblank( myString.Value(i) )) ++i; + if ( i <= Length() ) + { + myString.Insert( i, "#" ); + for ( int iPart = 0; iPart < myBegPos.Length(); ++iPart ) + { + int begPos = GetBegPos( iPart ); + if ( begPos != UNKNOWN ) + SetBegPos( iPart, begPos + 1 ); + } + } +} + //================================================================================ /*! * \brief Set dependent commands after this one @@ -2728,11 +3529,41 @@ bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod */ //================================================================================ -_pyObject::_pyObject(const Handle(_pyCommand)& theCreationCmd) - : myCreationCmd(theCreationCmd), myNbCalls(0), myIsRemoved(false) +_pyObject::_pyObject(const Handle(_pyCommand)& theCreationCmd, const _pyID& theID) + : myID(theID), myCreationCmd(theCreationCmd), myIsPublished(false) +{ + setID( theID ); +} + +//================================================================================ +/*! + * \brief Set up myID and myIsPublished + */ +//================================================================================ + +void _pyObject::setID(const _pyID& theID) +{ + myID = theID; + myIsPublished = !theGen->IsNotPublished( GetID() ); +} + +//================================================================================ +/*! + * \brief Clear myCreationCmd and myProcessedCmds + */ +//================================================================================ + +void _pyObject::ClearCommands() { - if ( !theCreationCmd.IsNull() && !theCreationCmd->IsEmpty() ) - myIsRemoved = theGen->IsDead( theCreationCmd->GetResultValue() ); + if ( !CanClear() ) + return; + + if ( !myCreationCmd.IsNull() ) + myCreationCmd->Clear(); + + list< Handle(_pyCommand) >::iterator cmd = myProcessedCmds.begin(); + for ( ; cmd != myProcessedCmds.end(); ++cmd ) + (*cmd)->Clear(); } //================================================================================ @@ -2772,6 +3603,18 @@ void _pySelfEraser::Flush() GetCreationCmd()->Clear(); } +//================================================================================ +/*! + * \brief _pySubMesh constructor + */ +//================================================================================ + +_pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd): + _pyObject(theCreationCmd) +{ + myMesh = ObjectToMesh( theGen->FindObject( theCreationCmd->GetObject() )); +} + //================================================================================ /*! * \brief count invoked commands @@ -2811,12 +3654,13 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) // group = mesh.CreateEmptyGroup( elemType, groupName ) // aFilter.SetMesh(mesh) // nbAdd = group.AddFrom( aFilter ) + Handle(_pyFilter) filter; if ( theCommand->GetMethod() == "AddFrom" ) { _pyID idSource = theCommand->GetArg(1); // check if idSource is a filter - Handle(_pyObject) filter = theGen->FindObject( idSource ); - if ( filter.IsNull() || !filter->IsKind(STANDARD_TYPE(_pyFilter))) + filter = Handle(_pyFilter)::DownCast( theGen->FindObject( idSource )); + if ( filter.IsNull() ) return; // find aFilter.SetMesh(mesh) to clear it, it should be just before theCommand list< Handle(_pyCommand) >::reverse_iterator cmdIt = theGen->GetCommands().rbegin(); @@ -2825,7 +3669,7 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) { const Handle(_pyCommand)& setMeshCmd = *(++cmdIt); if ((setMeshCmd->GetObject() == idSource || - setMeshCmd->GetObject() == Handle(_pyFilter)::DownCast(filter)->GetNewID() ) + setMeshCmd->GetObject() == filter->GetNewID() ) && setMeshCmd->GetMethod() == "SetMesh") { @@ -2847,10 +3691,13 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) { // set new name of a filter _pyID filterID = theCommand->GetArg(1); - Handle(_pyObject) filter = theGen->FindObject( filterID ); + filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID )); if ( !filter.IsNull() ) filter->Process( theCommand ); } + + if ( !filter.IsNull() ) + filter->AddUser( this ); } //================================================================================ @@ -2894,7 +3741,7 @@ void _pyFilter::Process( const Handle(_pyCommand)& theCommand) // Convert the following set of commands into smesh.GetFilterFromCriteria(criteria) // aFilter0x2aaab0487080 = aFilterManager.CreateFilter() // aFilter0x2aaab0487080.SetCriteria(aCriteria) - if ( GetNbCalls() == 0 && // none method was called before SetCriteria() + if ( GetNbCalls() == 1 && // none method was called before this SetCriteria() call theCommand->GetMethod() == "SetCriteria") { // aFilter.SetCriteria(aCriteria) -> @@ -2926,3 +3773,19 @@ void _pyFilter::Flush() if ( !myNewID.IsEmpty() && !GetCreationCmd()->IsEmpty() ) GetCreationCmd()->SetResultValue( myNewID ); } + +//================================================================================ +/*! + * \brief Return true if all my users can be cleared + */ +//================================================================================ + +bool _pyFilter::CanClear() +{ + list< Handle(_pyObject) >::iterator obj = myUsers.begin(); + for ( ; obj != myUsers.end(); ++obj ) + if ( !(*obj)->CanClear() ) + return false; + + return true; +} diff --git a/src/SMESH_I/SMESH_2smeshpy.hxx b/src/SMESH_I/SMESH_2smeshpy.hxx index b286b187a..e1e5f1e8d 100644 --- a/src/SMESH_I/SMESH_2smeshpy.hxx +++ b/src/SMESH_I/SMESH_2smeshpy.hxx @@ -37,6 +37,8 @@ #include #include +#include CORBA_SERVER_HEADER(SALOMEDS) + // =========================================================================================== /*! * This file was created in order to respond to requirement of bug PAL10494: @@ -75,6 +77,7 @@ DEFINE_STANDARD_HANDLE (_pyObject ,Standard_Transient); DEFINE_STANDARD_HANDLE (_pyGen ,_pyObject); DEFINE_STANDARD_HANDLE (_pyMesh ,_pyObject); DEFINE_STANDARD_HANDLE (_pySubMesh ,_pyObject); +DEFINE_STANDARD_HANDLE (_pyGroup ,_pySubMesh); DEFINE_STANDARD_HANDLE (_pyMeshEditor,_pyObject); DEFINE_STANDARD_HANDLE (_pyHypothesis,_pyObject); DEFINE_STANDARD_HANDLE (_pyAlgorithm ,_pyHypothesis); @@ -111,6 +114,8 @@ public: TCollection_AsciiString & GetString() { return myString; } int GetOrderNb() const { return myOrderNb; } void SetOrderNb( int theNb ) { myOrderNb = theNb; } + typedef void* TAddr; + TAddr GetAddress() const { return (void*) this; } int Length() { return myString.Length(); } void Clear() { myString.Clear(); myBegPos.Clear(); myArgs.Clear(); } bool IsEmpty() const { return myString.IsEmpty(); } @@ -122,6 +127,8 @@ public: const TCollection_AsciiString & GetMethod(); const TCollection_AsciiString & GetArg( int index ); int GetNbArgs() { FindAllArgs(); return myArgs.Length(); } + bool MethodStartsFrom(const TCollection_AsciiString& beg) + { GetMethod(); return ( myMeth.Location( beg, 1, myMeth.Length() ) == 1 ); } //Handle(TColStd_HSequenceOfAsciiString) GetArgs(); void SetResultValue( const TCollection_AsciiString& theResult ) { GetResultValue(); SetPart( RESULT_IND, theResult, myRes ); } @@ -131,10 +138,13 @@ public: { GetMethod(); SetPart( METHOD_IND, theMethod, myMeth ); } void SetArg( int index, const TCollection_AsciiString& theArg); void RemoveArgs(); + void Comment(); static bool SkipSpaces( const TCollection_AsciiString & theSring, int & thePos ); static TCollection_AsciiString GetWord( const TCollection_AsciiString & theSring, int & theStartPos, const bool theForward, const bool dotIsWord = false); + static bool IsStudyEntry( const TCollection_AsciiString& str ); + static std::list< _pyID > GetStudyEntries( const TCollection_AsciiString& str ); void AddDependantCmd( Handle(_pyCommand) cmd, bool prepend = false) { if (prepend) myDependentCmds.push_front( cmd ); else myDependentCmds.push_back( cmd ); } bool SetDependentCmdsAfter() const; @@ -152,28 +162,56 @@ public: class _pyObject: public Standard_Transient { - Handle(_pyCommand) myCreationCmd; - int myNbCalls; - bool myIsRemoved, myIsProtected; +protected: + _pyID myID; + Handle(_pyCommand) myCreationCmd; std::list< Handle(_pyCommand) > myProcessedCmds; + bool myIsPublished; + + void setID(const _pyID& theID); public: - _pyObject(const Handle(_pyCommand)& theCreationCmd); - const _pyID& GetID() { return myCreationCmd->GetResultValue(); } + _pyObject(const Handle(_pyCommand)& theCreationCmd, const _pyID& theID=_pyID()); + const _pyID& GetID() { return myID.IsEmpty() ? myCreationCmd->GetResultValue() : myID; } static _pyID FatherID(const _pyID & childID); const Handle(_pyCommand)& GetCreationCmd() { return myCreationCmd; } - int GetNbCalls() const { return myNbCalls; } - bool IsRemovedFromStudy() const { return myIsRemoved; } - void SetCreationCmd( Handle(_pyCommand) cmd ) { myCreationCmd = cmd; } + int GetNbCalls() const { return myProcessedCmds.size(); } + bool IsInStudy() const { return myIsPublished; } + virtual void SetRemovedFromStudy(const bool isRemoved) { myIsPublished = !isRemoved; } + void SetCreationCmd( Handle(_pyCommand) cmd ) { myCreationCmd = cmd; } int GetCommandNb() { return myCreationCmd->GetOrderNb(); } void AddProcessedCmd( const Handle(_pyCommand) & cmd ) - { if ( !cmd.IsNull() ) myProcessedCmds.push_back( cmd ); } - virtual void Process(const Handle(_pyCommand) & theCommand) { myNbCalls++; } + { if (myProcessedCmds.empty() || myProcessedCmds.back()!=cmd) myProcessedCmds.push_back( cmd );} + std::list< Handle(_pyCommand) >& GetProcessedCmds() { return myProcessedCmds; } + virtual void Process(const Handle(_pyCommand) & cmd) { AddProcessedCmd(cmd); } virtual void Flush() = 0; virtual const char* AccessorMethod() const; + virtual bool CanClear() { return !myIsPublished; } + virtual void ClearCommands(); + virtual void Free() {} DEFINE_STANDARD_RTTI (_pyObject) }; +// ------------------------------------------------------------------------------------- +/*! + * \brief Data used to restore cleared Compute() command of an exported mesh + * when an imported mesh is created + */ +// ------------------------------------------------------------------------------------- +struct ExportedMeshData +{ + Handle(_pyMesh) myMesh; + Handle(_pyCommand) myLastComputeCmd; + TCollection_AsciiString myLastComputeCmdString; + ExportedMeshData() {} + ExportedMeshData( const Handle(_pyMesh)& mesh, Handle(_pyCommand) computeCmd): + myMesh( mesh ), myLastComputeCmd( computeCmd ) + { + if ( !myLastComputeCmd.IsNull()) + myLastComputeCmdString = myLastComputeCmd->GetString(); + } +}; + // ------------------------------------------------------------------------------------- /*! * \brief Class corresponding to SMESH_Gen. It holds info on existing @@ -184,27 +222,41 @@ class _pyGen: public _pyObject { public: _pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod, - Resource_DataMapOfAsciiStringAsciiString& theObjectNames); + Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + SALOMEDS::Study_ptr& theStudy, + const bool theToKeepAllCommands); Handle(_pyCommand) AddCommand( const TCollection_AsciiString& theCommand ); - void Process( const Handle(_pyCommand)& theCommand ); - void Flush(); - Handle(_pyHypothesis) FindHyp( const _pyID& theHypID ); - Handle(_pyHypothesis) FindAlgo( const _pyID& theGeom, const _pyID& theMesh, - const Handle(_pyHypothesis)& theHypothesis); - Handle(_pySubMesh) FindSubMesh( const _pyID& theSubMeshID ); void ExchangeCommands( Handle(_pyCommand) theCmd1, Handle(_pyCommand) theCmd2 ); void SetCommandAfter( Handle(_pyCommand) theCmd, Handle(_pyCommand) theAfterCmd ); void SetCommandBefore( Handle(_pyCommand) theCmd, Handle(_pyCommand) theBeforeCmd ); Handle(_pyCommand)& GetLastCommand(); std::list< Handle(_pyCommand) >& GetCommands() { return myCommands; } - void SetAccessorMethod(const _pyID& theID, const char* theMethod ); - bool AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const; - bool AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const; - const char* AccessorMethod() const; + _pyID GenerateNewID( const _pyID& theID ); void AddObject( Handle(_pyObject)& theObj ); Handle(_pyObject) FindObject( const _pyID& theObjID ) const; - bool IsDead(const _pyID& theObjID) const; + Handle(_pySubMesh) FindSubMesh( const _pyID& theSubMeshID ); + Handle(_pyHypothesis) FindHyp( const _pyID& theHypID ); + Handle(_pyHypothesis) FindAlgo( const _pyID& theGeom, const _pyID& theMesh, + const Handle(_pyHypothesis)& theHypothesis); + + void SetAccessorMethod(const _pyID& theID, const char* theMethod ); + bool AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const; + bool AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const; + virtual const char* AccessorMethod() const; + + bool IsGeomObject(const _pyID& theObjID) const; + bool IsNotPublished(const _pyID& theObjID) const; + bool IsToKeepAllCommands() const { return myToKeepAllCommands; } + void AddExportedMesh(const TCollection_AsciiString& file, const ExportedMeshData& mesh ) + { myFile2ExportedMesh[ file ] = mesh; } + ExportedMeshData& FindExportedMesh( const TCollection_AsciiString& file ) + { return myFile2ExportedMesh[ file ]; } + + virtual void Process( const Handle(_pyCommand)& theCommand ); + virtual void Flush(); + virtual void ClearCommands(); + virtual void Free(); private: void setNeighbourCommand( Handle(_pyCommand)& theCmd, @@ -222,6 +274,10 @@ private: Resource_DataMapOfAsciiStringAsciiString& myObjectNames; Handle(_pyCommand) myLastCommand; int myNbFilters; + bool myToKeepAllCommands; + SALOMEDS::Study_var myStudy; + int myGeomIDNb, myGeomIDIndex; + std::map< TCollection_AsciiString, ExportedMeshData > myFile2ExportedMesh; DEFINE_STANDARD_RTTI (_pyGen) }; @@ -237,15 +293,29 @@ class _pyMesh: public _pyObject std::list< Handle(_pyHypothesis) > myHypos; std::list< Handle(_pyCommand) > myAddHypCmds; std::list< Handle(_pySubMesh) > mySubmeshes; - bool myHasEditor; + std::list< Handle(_pyGroup) > myGroups; + std::list< Handle(_pyMeshEditor)> myEditors; + //d::list< Handle(_pyMesh) > myFatherMeshes; // this mesh depends on + std::list< Handle(_pyMesh) > myChildMeshes; // depending on me + bool myGeomNotInStudy; + Handle(_pyCommand) myLastComputeCmd; public: _pyMesh(const Handle(_pyCommand) creationCmd); - _pyMesh(const Handle(_pyCommand) theCreationCmd, const TCollection_AsciiString & id); + _pyMesh(const Handle(_pyCommand) theCreationCmd, const _pyID & id); const _pyID& GetGeom() { return GetCreationCmd()->GetArg(1); } - void Process( const Handle(_pyCommand)& theCommand); - void Flush(); - const char* AccessorMethod() const { return _pyMesh_ACCESS_METHOD; } + void AddGroup( const Handle(_pyGroup)& g ) { myGroups.push_back( g ); } + void AddEditor( const Handle(_pyMeshEditor)& e ) { myEditors.push_back( e ); } + bool IsNotGeomPublished() { return myGeomNotInStudy; } + virtual void Process( const Handle(_pyCommand)& theCommand); + virtual void Flush(); + virtual void SetRemovedFromStudy(const bool isRemoved); + virtual bool CanClear(); + virtual void ClearCommands(); + virtual void Free() { /*myFatherMeshes.clear();*/ myChildMeshes.clear(); } + virtual const char* AccessorMethod() const { return _pyMesh_ACCESS_METHOD; } private: + void addFatherMesh( const Handle(_pyMesh)& mesh ); + void addFatherMesh( const _pyID& meshID ); static bool NeedMeshAccess( const Handle(_pyCommand)& theCommand ); static void AddMeshAccess( const Handle(_pyCommand)& theCommand ) { theCommand->SetObject( theCommand->GetObject() + "." _pyMesh_ACCESS_METHOD ); } @@ -265,8 +335,10 @@ class _pyMeshEditor: public _pyObject TCollection_AsciiString myCreationCmdStr; public: _pyMeshEditor(const Handle(_pyCommand)& theCreationCmd); - void Process( const Handle(_pyCommand)& theCommand); + _pyID GetMesh() const { return myMesh; } + virtual void Process( const Handle(_pyCommand)& theCommand); virtual void Flush() {} + virtual bool CanClear(); DEFINE_STANDARD_RTTI (_pyMesh) }; @@ -300,6 +372,15 @@ protected: TColStd_SequenceOfInteger myNbArgsByMethod; // nb args set by each method std::list myArgCommands; std::list myUnknownCommands; + std::list myReferredObjs; + // maps used to clear commands setting parameters if result of setting is not + // used (no mesh.Compute()) or discared (e.g. by mesh.Clear()) + std::map > myMeth2Commands; + std::map< _pyCommand::TAddr, std::list > myComputeAddr2Cmds; + std::list myComputeCmds; + void rememberCmdOfParameter( const Handle(_pyCommand) & cmd ); + bool isCmdUsedForCompute( const Handle(_pyCommand) & cmd, + _pyCommand::TAddr avoidComputeAddr=NULL ) const; public: _pyHypothesis(const Handle(_pyCommand)& theCreationCmd); void SetConvMethodAndType(const char* creationMethod, const char* type) @@ -323,14 +404,24 @@ public: { return myType2CreationMethod.find( algoType ) != myType2CreationMethod.end(); } const TCollection_AsciiString& GetCreationMethod(const TCollection_AsciiString& algoType) const { return myType2CreationMethod.find( algoType )->second; } + static Handle(_pyHypothesis) NewHypothesis( const Handle(_pyCommand)& theCreationCmd); + virtual bool IsWrappable(const _pyID& theMesh) const; virtual bool Addition2Creation( const Handle(_pyCommand)& theAdditionCmd, const _pyID& theMesh); - static Handle(_pyHypothesis) NewHypothesis( const Handle(_pyCommand)& theCreationCmd); - void Process( const Handle(_pyCommand)& theCommand); - void Flush(); + virtual void Process( const Handle(_pyCommand)& theCommand); + virtual void Flush(); + virtual void Free() { myReferredObjs.clear(); } virtual void Assign( const Handle(_pyHypothesis)& theOther, const _pyID& theMesh ); + virtual bool CanClear(); + virtual void ClearCommands(); + virtual bool GetReferredMeshesAndGeom( std::list< Handle(_pyMesh) >& meshes ); + + void MeshComputed ( const Handle(_pyCommand)& theComputeCommand ); + void ComputeDiscarded( const Handle(_pyCommand)& theComputeCommand ); + //void ComputeSaved ( const Handle(_pyCommand)& theComputeCommand ); + DEFINE_STANDARD_RTTI (_pyHypothesis) }; @@ -346,7 +437,7 @@ public: _pyAlgorithm(const Handle(_pyCommand)& theCreationCmd); virtual bool Addition2Creation( const Handle(_pyCommand)& theAdditionCmd, const _pyID& theMesh); - const char* AccessorMethod() const { return "GetAlgorithm()"; } + virtual const char* AccessorMethod() const { return "GetAlgorithm()"; } virtual bool IsWrappable(const _pyID& theMesh) { return !myIsWrapped; } DEFINE_STANDARD_RTTI (_pyAlgorithm) @@ -361,8 +452,8 @@ class _pyComplexParamHypo: public _pyHypothesis { public: _pyComplexParamHypo(const Handle(_pyCommand)& theCreationCmd): _pyHypothesis(theCreationCmd) {} - void Process( const Handle(_pyCommand)& theCommand); - void Flush(); + virtual void Process( const Handle(_pyCommand)& theCommand); + virtual void Flush(); DEFINE_STANDARD_RTTI (_pyComplexParamHypo) }; @@ -380,10 +471,11 @@ class _pyLayerDistributionHypo: public _pyHypothesis public: _pyLayerDistributionHypo(const Handle(_pyCommand)& theCreationCmd, const char* algoMethod): _pyHypothesis(theCreationCmd), myAlgoMethod((char*)algoMethod) {} - void Process( const Handle(_pyCommand)& theCommand); - void Flush(); - bool Addition2Creation( const Handle(_pyCommand)& theAdditionCmd, - const _pyID& theMesh); + virtual void Process( const Handle(_pyCommand)& theCommand); + virtual void Flush(); + virtual bool Addition2Creation( const Handle(_pyCommand)& theAdditionCmd, + const _pyID& theMesh); + virtual void Free() { my1dHyp.Nullify(); } DEFINE_STANDARD_RTTI (_pyLayerDistributionHypo) }; @@ -443,31 +535,33 @@ DEFINE_STANDARD_HANDLE (_pySelfEraser, _pyObject); // ------------------------------------------------------------------------------------- class _pySubMesh: public _pyObject { + Handle(_pyObject) myCreator; + Handle(_pyMesh) myMesh; public: - _pySubMesh(const Handle(_pyCommand)& theCreationCmd):_pyObject(theCreationCmd) {} - void Process( const Handle(_pyCommand)& theCommand); + _pySubMesh(const Handle(_pyCommand)& theCreationCmd); + virtual void Process( const Handle(_pyCommand)& theCommand); virtual void Flush(); + virtual Handle(_pyMesh) GetMesh() { return myMesh; } + virtual void Free() { myCreator.Nullify(); myMesh.Nullify(); } void SetCreator( const Handle(_pyObject)& theCreator ) { myCreator = theCreator; } DEFINE_STANDARD_RTTI (_pySubMesh) -private: - Handle(_pyObject) myCreator; }; // ------------------------------------------------------------------------------------- /*! * \brief To convert creation of a group by filter */ // ------------------------------------------------------------------------------------- -class _pyGroup: public _pyObject +class _pyGroup: public _pySubMesh { public: - _pyGroup(const Handle(_pyCommand)& theCreationCmd):_pyObject(theCreationCmd) {} - void Process( const Handle(_pyCommand)& theCommand); + _pyGroup(const Handle(_pyCommand)& theCreationCmd, const _pyID & id=_pyID()) + :_pySubMesh(theCreationCmd) { setID( id ); } + virtual void Process( const Handle(_pyCommand)& theCommand); virtual void Flush() {} DEFINE_STANDARD_RTTI (_pyGroup) }; -DEFINE_STANDARD_HANDLE (_pyGroup, _pyObject); // ------------------------------------------------------------------------------------- /*! @@ -477,10 +571,14 @@ DEFINE_STANDARD_HANDLE (_pyGroup, _pyObject); class _pyFilter: public _pyObject { _pyID myNewID; + std::list< Handle(_pyObject) > myUsers; public: _pyFilter(const Handle(_pyCommand)& theCreationCmd, const _pyID& newID=""); - void Process( const Handle(_pyCommand)& theCommand); + void AddUser( const Handle(_pyObject)& user) { myUsers.push_back( user ); } + virtual void Process( const Handle(_pyCommand)& theCommand); virtual void Flush(); + virtual bool CanClear(); + virtual void Free() { myUsers.clear(); } const _pyID& GetNewID() const { return myNewID; } DEFINE_STANDARD_RTTI (_pyFilter) diff --git a/src/SMESH_I/SMESH_DumpPython.cxx b/src/SMESH_I/SMESH_DumpPython.cxx index 87d876758..1815d4227 100644 --- a/src/SMESH_I/SMESH_DumpPython.cxx +++ b/src/SMESH_I/SMESH_DumpPython.cxx @@ -571,8 +571,8 @@ Engines::TMPFile* SMESH_Gen_i::DumpPython (CORBA::Object_ptr theStudy, // Add trace of API methods calls and replace study entries by names TCollection_AsciiString aScript; - aScript += DumpPython_impl(aStudy, aMap, aMapNames, - isPublished, isMultiFile, isValidScript, aSavedTrace); + aScript += DumpPython_impl(aStudy, aMap, aMapNames, isPublished, isMultiFile, + myIsHistoricalPythonDump, isValidScript, aSavedTrace); int aLen = aScript.Length(); unsigned char* aBuffer = new unsigned char[aLen+1]; @@ -714,7 +714,7 @@ namespace { (p = aName.FirstLocationNotInSet(allowedChars, p, aName.Length()))) { if ( p == 1 || p == aName.Length() || aName.Value(p-1) == '_') - aName.Remove( p, 1 ); // remove double _ and from the start and the end + aName.Remove( p, 1 ); // remove double _ from the start and the end else aName.SetValue(p, '_'), nbUnderscore++; isValidName = false; @@ -745,6 +745,7 @@ TCollection_AsciiString SMESH_Gen_i::DumpPython_impl Resource_DataMapOfAsciiStringAsciiString& theNames, bool isPublished, bool isMultiFile, + bool isHistoricalDump, bool& aValidScript, const TCollection_AsciiString& theSavedTrace) { @@ -812,13 +813,15 @@ TCollection_AsciiString SMESH_Gen_i::DumpPython_impl // Some objects are wrapped with python classes and // Resource_DataMapOfAsciiStringAsciiString holds methods returning wrapped objects Resource_DataMapOfAsciiStringAsciiString anEntry2AccessorMethod; - aScript = SMESH_2smeshpy::ConvertScript( aScript, anEntry2AccessorMethod, theObjectNames ); + if ( !getenv("NO_2smeshpy_conversion")) + aScript = SMESH_2smeshpy::ConvertScript( aScript, anEntry2AccessorMethod, + theObjectNames, theStudy, isHistoricalDump ); // Find entries to be replaced by names Handle(TColStd_HSequenceOfInteger) aSeq = FindEntries(aScript); Standard_Integer aLen = aSeq->Length(); - if (aLen == 0) + if (aLen == 0 && isMultiFile) return aScript; // Replace entries by the names @@ -828,7 +831,7 @@ TCollection_AsciiString SMESH_Gen_i::DumpPython_impl Standard_Integer objectCounter = 0, aStart = 1, aScriptLength = aScript.Length(); TCollection_AsciiString anUpdatedScript, anEntry, aName, aBaseName("smeshObj_"); - // Collect names of GEOM objects to exclude same names for SMESH objects + // Collect names of GEOM objects to exclude same names of SMESH objects GEOM::string_array_var aGeomNames = geom->GetAllDumpNames(); int ign = 0, nbgn = aGeomNames->length(); for (; ign < nbgn; ign++) { @@ -896,7 +899,7 @@ TCollection_AsciiString SMESH_Gen_i::DumpPython_impl anUpdatedScript.Insert ( 1, initPart ); // add final part of aScript - if (aSeq->Value(aLen) < aScriptLength) + if (aLen && aSeq->Value(aLen) < aScriptLength) anUpdatedScript += aScript.SubString(aSeq->Value(aLen) + 1, aScriptLength); // Remove removed objects