X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH_I%2FSMESH_2smeshpy.cxx;h=c8fe9b6abea9ba8dbc92ee6e5c43778a3611ac2a;hb=7468bfdc0b49e60009c985c917ed2bf652031b79;hp=2d5ee24f1031f8ead9562b5fccb35c59a7fdc5b8;hpb=493747e8ea338a2d88204a5f12ba924d72ecbb5b;p=modules%2Fsmesh.git diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 2d5ee24f1..c8fe9b6ab 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -33,9 +33,10 @@ #include "SMESH_Filter_i.hxx" #include +#include #include "SMESH_Gen_i.hxx" -/* SALOME headers that include CORBA headers that include windows.h +/* SALOME headers that include CORBA headers that include windows.h * that defines GetObject symbol as GetObjectA should stand before SALOME headers * that declare methods named GetObject - to apply the same rules of GetObject renaming * and thus to avoid mess with GetObject symbol on Windows */ @@ -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,22 +179,26 @@ 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 SMESH_NoteBook * aNoteBook = new SMESH_NoteBook(); - + int from = 1, end = theScript.Length(), to; while ( from < end && ( to = theScript.Location( "\n", from, end ))) { @@ -143,13 +207,13 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, aNoteBook->AddCommand( theScript.SubString( from, to - 1 )); from = to + 1; } - + aNoteBook->ReplaceVariables(); TCollection_AsciiString aNoteScript = aNoteBook->GetResultScript(); delete aNoteBook; aNoteBook = 0; - + // split theScript into separate commands from = 1, end = aNoteScript.Length(); while ( from < end && ( to = aNoteScript.Location( "\n", from, end ))) @@ -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; @@ -175,21 +242,25 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, if ( (*cmd)->SetDependentCmdsAfter() ) orderChanges = true; } 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,15 +273,49 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, //================================================================================ _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod, - Resource_DataMapOfAsciiStringAsciiString& theObjectNames) - : _pyObject( new _pyCommand( TPythonDump::SMESHGenName(), 0 )), + 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; + } + } } //================================================================================ @@ -241,7 +346,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand MESSAGE ( "## COM " << myNbCommands << ": "<< aCommand->GetString() ); #endif - _pyID objID = aCommand->GetObject(); + const _pyID& objID = aCommand->GetObject(); if ( objID.IsEmpty() ) return aCommand; @@ -249,7 +354,8 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand // Find an object to process theCommand // SMESH_Gen method? - if ( objID == this->GetID() || objID == SMESH_2smeshpy::GenName()) { + if ( objID == this->GetID() || objID == SMESH_2smeshpy::GenName()) + { this->Process( aCommand ); return aCommand; } @@ -258,21 +364,24 @@ 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 ); + // check for mesh editor object if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation _pyID editorID = aCommand->GetResultValue(); Handle(_pyMeshEditor) editor = new _pyMeshEditor( aCommand ); myMeshEditors.insert( make_pair( editorID, editor )); return aCommand; - } + } // check for SubMesh objects else if ( aCommand->GetMethod() == "GetSubMesh" ) { // SubMesh creation _pyID subMeshID = aCommand->GetResultValue(); Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand ); myObjects.insert( make_pair( subMeshID, subMesh )); } - + id_mesh->second->Process( aCommand ); + id_mesh->second->AddProcessedCmd( aCommand ); return aCommand; } @@ -280,30 +389,68 @@ 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 ); - TCollection_AsciiString processedCommand = aCommand->GetString(); - // some commands of SMESH_MeshEditor create meshes - if ( aCommand->GetMethod().Search("MakeMesh") != -1 ) { - Handle(_pyMesh) mesh = new _pyMesh( aCommand, aCommand->GetResultValue() ); + id_editor->second->AddProcessedCmd( aCommand ); + + if ( !meshID.IsEmpty() && + !myMeshes.count( meshID ) && + aCommand->IsStudyEntry( meshID )) + { + TCollection_AsciiString processedCommand = aCommand->GetString(); + Handle(_pyMesh) mesh = new _pyMesh( aCommand, meshID ); + myMeshes.insert( make_pair( meshID, mesh )); + aCommand->Clear(); aCommand->GetString() = processedCommand; // discard changes made by _pyMesh - myMeshes.insert( make_pair( mesh->GetID(), mesh )); } - 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 ) if ( !(*hyp)->IsAlgo() && objID == (*hyp)->GetID() ) { (*hyp)->Process( aCommand ); + (*hyp)->AddProcessedCmd( aCommand ); return aCommand; } @@ -325,6 +472,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.find( objID ); if ( id_obj != myObjects.end() ) { id_obj->second->Process( aCommand ); + id_obj->second->AddProcessedCmd( aCommand ); return aCommand; } @@ -389,13 +537,16 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand // set SMESH.GeometryType instead of a numerical Threshold const char* types[SMESH::Geom_POLYHEDRA+1] = { "Geom_POINT", "Geom_EDGE", "Geom_TRIANGLE", "Geom_QUADRANGLE", "Geom_POLYGON", - "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_POLYHEDRA" + "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_HEXAGONAL_PRISM", + "Geom_POLYHEDRA" }; int iGeom = Threshold.IntegerValue(); if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 ) Threshold = SMESH + types[ iGeom ]; } - if ( ThresholdStr.Length() != 2 ) // not '' or "" + if ( ThresholdID.Length() != 2 && ThresholdStr.Length() != 2) // not '' or "" + aCommand->SetArg( 4, ThresholdID.SubString( 2, ThresholdID.Length()-1 )); // shape entry + else if ( ThresholdStr.Length() != 2 ) aCommand->SetArg( 4, ThresholdStr ); else if ( ThresholdID.Length() != 2 ) aCommand->SetArg( 4, ThresholdID ); @@ -461,8 +612,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 )); } } @@ -490,7 +643,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; } } @@ -505,6 +659,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; } } @@ -518,9 +673,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" ); @@ -530,6 +684,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 @@ -558,16 +720,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() @@ -575,8 +757,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(); @@ -584,6 +766,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 @@ -810,7 +1046,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 )); } //================================================================================ @@ -821,106 +1066,139 @@ void _pyGen::AddObject( Handle(_pyObject)& theObj ) Handle(_pyObject) _pyGen::FindObject( const _pyID& theObjID ) const { - std::map< _pyID, Handle(_pyObject) >::const_iterator id_obj = myObjects.find( theObjID ); - return ( id_obj == myObjects.end() ) ? Handle(_pyObject)() : id_obj->second; + { + map< _pyID, Handle(_pyObject) >::const_iterator id_obj = myObjects.find( theObjID ); + if ( id_obj != myObjects.end() ) + return id_obj->second; + } + { + map< _pyID, Handle(_pyMesh) >::const_iterator id_obj = myMeshes.find( theObjID ); + 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 Find out type of geom group - * \param grpID - The geom group entry - * \retval int - The type + * \brief Check if a study entry is under GEOM component */ //================================================================================ -// static bool sameGroupType( const _pyID& grpID, -// const TCollection_AsciiString& theType) -// { -// // define group type as smesh.Mesh.Group() does -// int type = -1; -// SALOMEDS::Study_var study = SMESH_Gen_i::GetSMESHGen()->GetCurrentStudy(); -// SALOMEDS::SObject_var aSObj = study->FindObjectID( grpID.ToCString() ); -// if ( !aSObj->_is_nil() ) { -// GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow( aSObj->GetObject() ); -// if ( !aGeomObj->_is_nil() ) { -// switch ( aGeomObj->GetShapeType() ) { -// case GEOM::VERTEX: type = SMESH::NODE; break; -// case GEOM::EDGE: type = SMESH::EDGE; break; -// case GEOM::FACE: type = SMESH::FACE; break; -// case GEOM::SOLID: -// case GEOM::SHELL: type = SMESH::VOLUME; break; -// case GEOM::COMPOUND: { -// GEOM::GEOM_Gen_ptr aGeomGen = SMESH_Gen_i::GetSMESHGen()->GetGeomEngine(); -// if ( !aGeomGen->_is_nil() ) { -// GEOM::GEOM_IGroupOperations_var aGrpOp = -// aGeomGen->GetIGroupOperations( study->StudyId() ); -// if ( !aGrpOp->_is_nil() ) { -// switch ( aGrpOp->GetType( aGeomObj )) { -// case TopAbs_VERTEX: type = SMESH::NODE; break; -// case TopAbs_EDGE: type = SMESH::EDGE; break; -// case TopAbs_FACE: type = SMESH::FACE; break; -// case TopAbs_SOLID: type = SMESH::VOLUME; break; -// default:; -// } -// } -// } -// } -// default:; -// } -// } -// } -// if ( type < 0 ) { -// MESSAGE("Type of the group " << grpID << " not found"); -// return false; -// } -// if ( theType.IsIntegerValue() ) -// return type == theType.IntegerValue(); - -// switch ( type ) { -// case SMESH::NODE: return theType.Location( "NODE", 1, theType.Length() ); -// case SMESH::EDGE: return theType.Location( "EDGE", 1, theType.Length() ); -// case SMESH::FACE: return theType.Location( "FACE", 1, theType.Length() ); -// case SMESH::VOLUME: return theType.Location( "VOLUME", 1, theType.Length() ); -// default:; -// } -// return false; -// } +bool _pyGen::IsGeomObject(const _pyID& theObjID) const +{ + if ( myGeomIDNb ) + { + return ( myGeomIDIndex <= theObjID.Length() && + int( theObjID.Value( myGeomIDIndex )) == myGeomIDNb); + } + return false; +} //================================================================================ /*! - * \brief - * \param theCreationCmd - + * \brief Returns true if an object is not present in a study + */ +//================================================================================ + +bool _pyGen::IsNotPublished(const _pyID& theObjID) const +{ + if ( theObjID.IsEmpty() ) return false; + + 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 +} + +//================================================================================ +/*! + * \brief Mesh created by SMESH_Gen */ //================================================================================ _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(); - //TCollection_AsciiString str = creationCmd->GetMethod(); -// if(str != "CreateMeshesFromUNV" && -// str != "CreateMeshesFromMED" && -// str != "CreateMeshesFromSTL") creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() ); creationCmd->SetMethod( "Mesh" ); - - theGen->SetAccessorMethod( GetID(), "GetMesh()" ); + theGen->SetAccessorMethod( GetID(), _pyMesh::AccessorMethod() ); } //================================================================================ /*! - * \brief - * \param theCreationCmd - + * \brief Mesh created by SMESH_MeshEditor */ //================================================================================ -_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, "GetMesh()" ); + theGen->SetAccessorMethod( meshId, _pyMesh::AccessorMethod() ); } //================================================================================ @@ -945,15 +1223,75 @@ 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 ); mySubmeshes.push_back( subMesh ); } } + else if ( method == "RemoveSubMesh" ) { // move submesh creation before its removal + Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetArg(1) ); + if ( !subMesh.IsNull() ) + subMesh->Process( theCommand ); + AddMeshAccess( theCommand ); + } // ---------------------------------------------------------------------- else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO ) myAddHypCmds.push_back( theCommand ); @@ -967,6 +1305,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 @@ -986,64 +1332,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) @@ -1079,25 +1420,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 ); } } } @@ -1151,6 +1503,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: @@ -1167,7 +1536,7 @@ void _pyMesh::Flush() // check and create new algorithm instance if it is already wrapped if ( algo->IsWrapped() ) { _pyID localAlgoID = theGen->GenerateNewID( algoID ); - TCollection_AsciiString aNewCmdStr = localAlgoID + + TCollection_AsciiString aNewCmdStr = addCmd->GetIndentation() + localAlgoID + TCollection_AsciiString( " = " ) + theGen->GetID() + TCollection_AsciiString( ".CreateHypothesis( \"" ) + algo->GetAlgoType() + TCollection_AsciiString( "\" )" ); @@ -1180,6 +1549,10 @@ void _pyMesh::Flush() algo = newAlgo; // set algorithm creation theGen->SetCommandBefore( newCmd, addCmd ); + myHypos.push_back( newAlgo ); + if ( !myLastComputeCmd.IsNull() && + newCmd->GetOrderNb() == myLastComputeCmd->GetOrderNb() + 1) + newAlgo->MeshComputed( myLastComputeCmd ); } else newCmd->Clear(); @@ -1190,7 +1563,7 @@ void _pyMesh::Flush() // try to convert if ( algo->Addition2Creation( addCmd, this->GetID() )) // OK { - // wrapped algo is created atfer mesh creation + // wrapped algo is created after mesh creation GetCreationCmd()->AddDependantCmd( addCmd ); if ( isLocalAlgo ) { @@ -1240,21 +1613,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 @@ -1267,6 +1745,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 ); } //================================================================================ @@ -1326,19 +1808,36 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) if( pos != -1) { isPyMeshMethod = true; + bool is0DmethId = ( method == "ExtrusionSweepMakeGroups0D" ); + bool is0DmethObj = ( method == "ExtrusionSweepObject0DMakeGroups"); // 1. Remove "MakeGroups" from the Command TCollection_AsciiString aMethod = theCommand->GetMethod(); int nbArgsToAdd = diffLastTwoArgsMethods.Contains(aMethod) ? 2 : 1; + + if(is0DmethObj) + pos = pos-2; //Remove "0D" from the Command too aMethod.Trunc(pos-1); theCommand->SetMethod(aMethod); // 2. And add last "True" argument(s) while(nbArgsToAdd--) theCommand->SetArg(theCommand->GetNbArgs()+1,"True"); + if( is0DmethId || is0DmethObj ) + theCommand->SetArg(theCommand->GetNbArgs()+1,"True"); } } + // ExtrusionSweep0D() -> ExtrusionSweep() + // ExtrusionSweepObject0D() -> ExtrusionSweepObject() + if ( !isPyMeshMethod && ( method == "ExtrusionSweep0D" || + method == "ExtrusionSweepObject0D" )) + { + isPyMeshMethod=true; + theCommand->SetMethod( method.SubString( 1, method.Length()-2)); + theCommand->SetArg(theCommand->GetNbArgs()+1,"False"); //sets flag "MakeGroups = False" + theCommand->SetArg(theCommand->GetNbArgs()+1,"True"); //sets flag "IsNode = True" + } // set "ExtrusionAlongPathX()" instead of "ExtrusionAlongPathObjX()" if ( !isPyMeshMethod && method == "ExtrusionAlongPathObjX") { @@ -1411,6 +1910,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 @@ -1616,7 +2127,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 --------- @@ -1639,6 +2150,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 ); @@ -1683,6 +2195,24 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th return algo->IsValid() ? algo : hyp; } +//================================================================================ +/*! + * \brief Returns true if addition of this hypothesis to a given mesh can be + * wrapped into hypothesis creation + */ +//================================================================================ + +bool _pyHypothesis::IsWrappable(const _pyID& theMesh) const +{ + if ( !myIsWrapped && myMesh == theMesh && IsInStudy() ) + { + Handle(_pyObject) pyMesh = theGen->FindObject( myMesh ); + if ( !pyMesh.IsNull() && pyMesh->IsInStudy() ) + return true; + } + return false; +} + //================================================================================ /*! * \brief Convert the command adding a hypothesis to mesh into a smesh command @@ -1758,6 +2288,8 @@ bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd, void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand) { ASSERT( !myIsAlgo ); + if ( !theGen->IsToKeepAllCommands() ) + rememberCmdOfParameter( theCommand ); // set args int nbArgs = 0; for ( int i = 1; i <= myArgMethods.Length(); ++i ) { @@ -1782,9 +2314,8 @@ void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand) void _pyHypothesis::Flush() { - if ( IsWrapped() ) { - } - else { + if ( !IsAlgo() ) + { list < Handle(_pyCommand) >::iterator cmd = myArgCommands.begin(); for ( ; cmd != myArgCommands.end(); ++cmd ) { // Add access to a wrapped mesh @@ -1846,6 +2377,227 @@ 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 ) +{ + // parameters are discriminated by method name + TCollection_AsciiString method = theCommand->GetMethod(); + + // discriminate commands setting different parameters via one method + // by passing parameter names like e.g. SetOption("size", "0.2") + if ( theCommand->GetString().FirstLocationInSet( "'\"", 1, theCommand->Length() ) && + theCommand->GetNbArgs() > 1 ) + { + // mangle method by appending a 1st textual arg (what if it's a variable name?!!!) + for ( int iArg = 1; iArg <= theCommand->GetNbArgs(); ++iArg ) + { + const TCollection_AsciiString& arg = theCommand->GetArg( iArg ); + if ( arg.Value(1) != '\"' && arg.Value(1) != '\'' ) continue; + if ( !isalpha( arg.Value(2))) continue; + method += arg; + break; + } + } + // 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 @@ -1883,13 +2635,14 @@ void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand) myArgs( iArg ) += "]"; } myArgCommands.push_back( theCommand ); + rememberCmdOfParameter( theCommand ); return; } } if( theCommand->GetMethod() == "SetLength" ) { - // NOW it becomes OBSOLETE + // NOW it is OBSOLETE // ex: hyp.SetLength(start, 1) // hyp.SetLength(end, 0) ASSERT(( theCommand->GetArg( 2 ).IsIntegerValue() )); @@ -2245,12 +2998,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 && isspace( myString.Value( begPos ))) ++begPos; + if ( begPos < endPos ) + { + SetBegPos( RESULT_IND, begPos ); + --endPos; + while ( begPos < endPos && isspace( myString.Value( endPos ))) --endPos; + myRes = myString.SubString( begPos, endPos ); + } + } } return myRes; } @@ -2402,7 +3163,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 ) { @@ -2523,10 +3284,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 { @@ -2540,6 +3302,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 @@ -2661,6 +3469,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() && isspace( 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 @@ -2726,6 +3558,49 @@ bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod return added; } +//================================================================================ +/*! + * \brief Creates pyObject + */ +//================================================================================ + +_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 ( !CanClear() ) + return; + + if ( !myCreationCmd.IsNull() ) + myCreationCmd->Clear(); + + list< Handle(_pyCommand) >::iterator cmd = myProcessedCmds.begin(); + for ( ; cmd != myProcessedCmds.end(); ++cmd ) + (*cmd)->Clear(); +} + //================================================================================ /*! * \brief Return method name giving access to an interaface object wrapped by python class @@ -2763,6 +3638,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 @@ -2777,7 +3664,7 @@ void _pySubMesh::Process( const Handle(_pyCommand)& theCommand ) //================================================================================ /*! - * \brief Clear creation command if no commands invoked + * \brief Move creation command depending on invoked commands */ //================================================================================ @@ -2802,12 +3689,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(); @@ -2816,7 +3704,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") { @@ -2838,10 +3726,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 ); } //================================================================================ @@ -2885,7 +3776,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) -> @@ -2917,3 +3808,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; +}