X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSMESH_I%2FSMESH_2smeshpy.cxx;h=f42b7a476068802ad920e45fd411da02409dc8db;hb=8a6fe1afd18da7f1692be6ab41d2e4ceff724721;hp=21fca4ed9ac0b93c4da2d7d59c2a9852a59ebff5;hpb=d4a710ce52f6e76786a7b3845e2f7975dc9a00b1;p=modules%2Fsmesh.git diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 21fca4ed9..f42b7a476 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -20,18 +20,18 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses // File : SMESH_2smeshpy.cxx // Created : Fri Nov 18 13:20:10 2005 // Author : Edward AGAPOV (eap) // #include "SMESH_2smeshpy.hxx" -#include "utilities.h" #include "SMESH_PythonDump.hxx" #include "SMESH_NoteBook.hxx" #include "SMESH_Filter_i.hxx" +#include + #include #include @@ -125,6 +125,31 @@ namespace { } }; + //================================================================================ + /*! + * \brief Map of TCollection_AsciiString initialized by C array of C strings. + * Odd items of the C array are map keys, and even items are values + */ + //================================================================================ + + struct TStringMap: public map + { + /*! + * \brief Filling. The last string must be "" + */ + void Insert(const char* names_values[]) { + for ( int i = 0; names_values[i][0] ; i += 2 ) + insert( make_pair( (char*) names_values[i], names_values[i+1] )); + } + /*! + * \brief Check if a string is in + */ + TCollection_AsciiString Value(const TCollection_AsciiString& name ) { + map< _AString, _AString >::iterator it = find( name ); + return it == end() ? "" : it->second; + } + }; + //================================================================================ /*! * \brief Returns a mesh by object @@ -153,7 +178,33 @@ namespace { void CheckObjectPresence( const Handle(_pyCommand)& cmd, set<_pyID> & presentObjects) { - for ( int iArg = cmd->GetNbArgs(); iArg; --iArg ) + // either comment or erase a command including NotPublishedObjectName() + if ( cmd->GetString().Location( TPythonDump::NotPublishedObjectName(), 1, cmd->Length() )) + { + bool isResultPublished = false; + for ( int i = 0; i < cmd->GetNbResultValues(); i++ ) + { + _pyID objID = cmd->GetResultValue( i+1 ); + if ( cmd->IsStudyEntry( objID )) + isResultPublished = (! theGen->IsNotPublished( objID )); + theGen->ObjectCreationRemoved( objID ); // objID.SetName( name ) is not needed + } + if ( isResultPublished ) + cmd->Comment(); + else + cmd->Clear(); + return; + } + // check if an Object was created in the script + _AString comment; + const _pyID& obj = cmd->GetObject(); + if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj )) + { + comment = "not created Object"; + theGen->ObjectCreationRemoved( obj ); + } + // check if a command has not created args + for ( int iArg = cmd->GetNbArgs(); iArg && comment.IsEmpty(); --iArg ) { const _pyID& arg = cmd->GetArg( iArg ); if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' ) @@ -163,25 +214,29 @@ namespace { 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; + comment += *id + " has not been yet created"; + break; } } - const _pyID& obj = cmd->GetObject(); - if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj )) + // treat result objects + const _pyID& result = cmd->GetResultValue(); + if ( !result.IsEmpty() && result.Value( 1 ) != '"' && result.Value( 1 ) != '\'' ) + { + list< _pyID > idList = cmd->GetStudyEntries( result ); + list< _pyID >::iterator id = idList.begin(); + for ( ; id != idList.end(); ++id ) + if ( comment.IsEmpty() ) + presentObjects.insert( *id ); + else + theGen->ObjectCreationRemoved( *id ); // objID.SetName( name ) is not needed + } + // comment the command + if ( !comment.IsEmpty() ) { cmd->Comment(); - cmd->GetString() += " ### not created object" ; + cmd->GetString() += " ### "; + cmd->GetString() += comment; } - 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 ); } //================================================================================ @@ -228,6 +283,13 @@ namespace { // - FT_EqualEdges = 15 // - FT_EqualFaces = 16 // - FT_EqualVolumes = 17 + // v 6.6.0: FT_Undefined == 44, new items: + // - FT_BallDiameter = 37 + // v 6.7.1: FT_Undefined == 45, new items: + // - FT_EntityType = 36 + // + // It's necessary to continue recording this history and to fill + // undef2newItems (see below) accordingly. typedef map< int, vector< int > > TUndef2newItems; static TUndef2newItems undef2newItems; @@ -242,6 +304,11 @@ namespace { undef2newItems[ 39 ].assign( items, items+6 ); } { int items[] = { 14, 15, 16, 17 }; undef2newItems[ 43 ].assign( items, items+4 ); } + { int items[] = { 37 }; + undef2newItems[ 44 ].assign( items, items+1 ); } + // { int items[] = { 36 }; + //undef2newItems[ 45 ].assign( items, items+1 ); } + ASSERT( undef2newItems.rbegin()->first == SMESH::FT_Undefined ); } int iType = Type.IntegerValue(); @@ -281,13 +348,15 @@ 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 + * \brief Convert a python script using commands of smesh.py + * \param theScript - Input script + * \param theEntry2AccessorMethod - returns method names to access to + * objects wrapped with python class + * \param theObjectNames - names of objects + * \param theRemovedObjIDs - entries of objects whose created commands were removed + * \param theHistoricalDump - true means to keep all commands, false means + * to exclude commands relating to objects removed from study + * \retval TCollection_AsciiString - Convertion result */ //================================================================================ @@ -295,10 +364,15 @@ TCollection_AsciiString SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod, Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + std::set< TCollection_AsciiString >& theRemovedObjIDs, SALOMEDS::Study_ptr& theStudy, const bool theToKeepAllCommands) { - theGen = new _pyGen( theEntry2AccessorMethod, theObjectNames, theStudy, theToKeepAllCommands ); + theGen = new _pyGen( theEntry2AccessorMethod, + theObjectNames, + theRemovedObjIDs, + theStudy, + theToKeepAllCommands ); // split theScript into separate commands @@ -308,9 +382,9 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScrip while ( from < end && ( to = theScript.Location( "\n", from, end ))) { if ( to != from ) - // cut out and store a command - aNoteBook->AddCommand( theScript.SubString( from, to - 1 )); - from = to + 1; + // cut out and store a command + aNoteBook->AddCommand( theScript.SubString( from, to - 1 )); + from = to + 1; } aNoteBook->ReplaceVariables(); @@ -379,12 +453,14 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScrip _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod, Resource_DataMapOfAsciiStringAsciiString& theObjectNames, + std::set< TCollection_AsciiString >& theRemovedObjIDs, SALOMEDS::Study_ptr& theStudy, const bool theToKeepAllCommands) : _pyObject( new _pyCommand( "", 0 )), myNbCommands( 0 ), myID2AccessorMethod( theEntry2AccessorMethod ), myObjectNames( theObjectNames ), + myRemovedObjIDs( theRemovedObjIDs ), myNbFilters( 0 ), myToKeepAllCommands( theToKeepAllCommands ), myStudy( SALOMEDS::Study::_duplicate( theStudy )), @@ -456,6 +532,13 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand if ( objID.IsEmpty() ) return aCommand; + // Prevent moving a command creating a sub-mesh to the end of the script + // if the sub-mesh is used in theCommand as argument + if ( _pySubMesh::CanBeArgOfMethod( aCommand->GetMethod() )) + { + PlaceSubmeshAfterItsCreation( aCommand ); + } + // Find an object to process theCommand // SMESH_Gen method? @@ -520,10 +603,14 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand groups = aCommand->GetResultValue(2); else if ( method == "MakeBoundaryElements") groups = aCommand->GetResultValue(3); + else if ( method == "Create0DElementsOnAllNodes" && + aCommand->GetArg(2).Length() > 2 ) // group name != '' + groups = aCommand->GetResultValue(); id_editor->second->Process( aCommand ); id_editor->second->AddProcessedCmd( aCommand ); + // create meshes if ( !meshID.IsEmpty() && !myMeshes.count( meshID ) && aCommand->IsStudyEntry( meshID )) @@ -534,6 +621,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand aCommand->Clear(); aCommand->GetString() = processedCommand; // discard changes made by _pyMesh } + // create groups if ( !groups.IsEmpty() ) { if ( !aCommand->IsStudyEntry( meshID )) @@ -615,7 +703,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand // 1 2 3 4 5 6 7 8 9 10 // in order to avoid the problem of type mismatch of long and FunctorType const TCollection_AsciiString - SMESH("SMESH."), dfltFunctor = "SMESH.FT_Undefined", dftlTol = "1e-07", dftlPreci = "-1"; + SMESH("SMESH."), dfltFunctor("SMESH.FT_Undefined"), dftlTol("1e-07"), dftlPreci("-1"); TCollection_AsciiString Type = aCommand->GetArg(1), // long Compare = aCommand->GetArg(2), // long @@ -641,17 +729,34 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand aCommand->SetArg( 2, Type ); aCommand->SetArg( 3, Compare ); - if ( Type == "SMESH.FT_ElemGeomType" && Threshold.IsIntegerValue() ) + if ( Threshold.IsIntegerValue() ) { - // 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_HEXAGONAL_PRISM", - "Geom_POLYHEDRA" - }; int iGeom = Threshold.IntegerValue(); - if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 ) - Threshold = SMESH + types[ iGeom ]; + if ( Type == "SMESH.FT_ElemGeomType" ) + { + // set SMESH.GeometryType instead of a numerical Threshold + const char* types[SMESH::Geom_BALL+1] = { + "Geom_POINT", "Geom_EDGE", "Geom_TRIANGLE", "Geom_QUADRANGLE", "Geom_POLYGON", + "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_HEXAGONAL_PRISM", + "Geom_POLYHEDRA", "Geom_BALL" }; + if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 ) + Threshold = SMESH + types[ iGeom ]; + } + if (Type == "SMESH.FT_EntityType") + { + // set SMESH.EntityType instead of a numerical Threshold + const char* types[SMESH::Entity_Ball+1] = { + "Entity_Node", "Entity_0D", "Entity_Edge", "Entity_Quad_Edge", + "Entity_Triangle", "Entity_Quad_Triangle", + "Entity_Quadrangle", "Entity_Quad_Quadrangle", "Entity_BiQuad_Quadrangle", + "Entity_Polygon", "Entity_Quad_Polygon", "Entity_Tetra", "Entity_Quad_Tetra", + "Entity_Pyramid", "Entity_Quad_Pyramid", + "Entity_Hexa", "Entity_Quad_Hexa", "Entity_TriQuad_Hexa", + "Entity_Penta", "Entity_Quad_Penta", "Entity_Hexagonal_Prism", + "Entity_Polyhedra", "Entity_Quad_Polyhedra", "Entity_Ball" }; + if ( -1 < iGeom && iGeom < SMESH::Entity_Quad_Polyhedra+1 ) + Threshold = SMESH + types[ iGeom ]; + } } if ( ThresholdID.Length() != 2 && ThresholdStr.Length() != 2) // not '' or "" aCommand->SetArg( 4, ThresholdID.SubString( 2, ThresholdID.Length()-1 )); // shape entry @@ -717,15 +822,25 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) myMeshes.insert( make_pair( mesh->GetID(), mesh )); return; } - if( method == "CreateMeshesFromMED" || method == "CreateMeshesFromSAUV") + if( method == "CreateMeshesFromMED" || + method == "CreateMeshesFromSAUV"|| + method == "CreateMeshesFromGMF" ) { - for(int ind = 0;indGetNbResultValues();ind++) + for ( int ind = 0; ind < theCommand->GetNbResultValues(); ind++ ) { _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 )); } + if ( method == "CreateMeshesFromGMF" ) + { + // CreateMeshesFromGMF( theFileName, theMakeRequiredGroups ) -> + // CreateMeshesFromGMF( theFileName ) + _AString file = theCommand->GetArg(1); + theCommand->RemoveArgs(); + theCommand->SetArg( 1, file ); + } } // CreateHypothesis() @@ -773,7 +888,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) } } - // objects erasing creation command if no more it's commands invoked: + // objects erasing creation command if no more its commands invoked: // SMESH_Pattern, FilterManager if ( method == "GetPattern" || method == "CreateFilterManager" || @@ -884,6 +999,34 @@ void _pyGen::Flush() myCommands.push_back( myLastCommand ); } +//================================================================================ +/*! + * \brief Prevent moving a command creating a sub-mesh to the end of the script + * if the sub-mesh is used in theCmdUsingSubmesh as argument + */ +//================================================================================ + +void _pyGen::PlaceSubmeshAfterItsCreation( Handle(_pyCommand) theCmdUsingSubmesh ) const +{ + map< _pyID, Handle(_pyObject) >::const_iterator id_obj = myObjects.begin(); + for ( ; id_obj != myObjects.end(); ++id_obj ) + { + if ( !id_obj->second->IsKind( STANDARD_TYPE( _pySubMesh ))) continue; + for ( int iArg = theCmdUsingSubmesh->GetNbArgs(); iArg; --iArg ) + { + const _pyID& arg = theCmdUsingSubmesh->GetArg( iArg ); + if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' ) + continue; + list< _pyID > idList = theCmdUsingSubmesh->GetStudyEntries( arg ); + list< _pyID >::iterator id = idList.begin(); + for ( ; id != idList.end(); ++id ) + if ( id_obj->first == *id ) + // _pySubMesh::Process() does what we need + Handle(_pySubMesh)::DownCast( id_obj->second )->Process( theCmdUsingSubmesh ); + } + } +} + //================================================================================ /*! * \brief Clean commmands of removed objects depending on myIsPublished flag @@ -1264,6 +1407,19 @@ bool _pyGen::IsNotPublished(const _pyID& theObjID) const return true; // SMESH object not in study } +//================================================================================ +/*! + * \brief Remove object name from myObjectNames that leads to that SetName() for + * this object is not dumped + * \param [in] theObjID - entry of the object whose creation command was eliminated + */ +//================================================================================ + +void _pyGen::ObjectCreationRemoved(const _pyID& theObjID) +{ + myRemovedObjIDs.insert( theObjID ); +} + //================================================================================ /*! * \brief Return reader of hypotheses of plugins @@ -1441,12 +1597,6 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) 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 ); @@ -1468,6 +1618,33 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) myGroups.push_back( group ); theGen->AddObject( group ); } + // 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 ); + } + } + } + // notify a group about full removal + else if ( method == "RemoveGroupWithContents" ) + { + if ( !theGen->IsToKeepAllCommands() ) { // snapshot mode + const _pyID groupID = theCommand->GetArg( 1 ); + Handle(_pyGroup) grp = Handle(_pyGroup)::DownCast( theGen->FindObject( groupID )); + if ( !grp.IsNull() ) + grp->RemovedWithContents(); + } + } // ---------------------------------------------------------------------- else if ( theCommand->MethodStartsFrom( "Export" )) { @@ -1483,6 +1660,14 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) theCommand->SetArg( i-1, theCommand->GetArg( i )); theCommand->SetArg( nbArgs, partID ); } + else if ( method == "ExportGMF" ) + { // ExportGMF(part,file,bool) -> ExportCGNS(file, part) + _pyID partID = theCommand->GetArg( 1 ); + _AString file = theCommand->GetArg( 2 ); + theCommand->RemoveArgs(); + theCommand->SetArg( 1, file ); + theCommand->SetArg( 2, partID ); + } else if ( theCommand->MethodStartsFrom( "ExportPartTo" )) { // ExportPartTo*(part, ...) -> Export*(..., part) // @@ -1504,26 +1689,44 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) // ---------------------------------------------------------------------- else if ( method == "RemoveHypothesis" ) // (geom, hyp) { - _pyID hypID = theCommand->GetArg( 2 ); + _pyID hypID = theCommand->GetArg( 2 ); + _pyID geomID = theCommand->GetArg( 1 ); + bool isLocal = ( geomID != GetGeom() ); // check if this mesh still has corresponding addition command - bool hasAddCmd = false; - list< Handle(_pyCommand) >::iterator cmd = myAddHypCmds.begin(); - while ( cmd != myAddHypCmds.end() ) + Handle(_pyCommand) addCmd; + list< Handle(_pyCommand) >::iterator cmd; + list< Handle(_pyCommand) >* addCmds[2] = { &myAddHypCmds, &myNotConvertedAddHypCmds }; + for ( int i = 0; i < 2; ++i ) { - // AddHypothesis(geom, hyp) - if ( hypID == (*cmd)->GetArg( 2 )) { // erase both (add and remove) commands - theCommand->Clear(); - (*cmd)->Clear(); - cmd = myAddHypCmds.erase( cmd ); - hasAddCmd = true; - } - else { - ++cmd; + list< Handle(_pyCommand )> & addHypCmds = *(addCmds[i]); + for ( cmd = addHypCmds.begin(); cmd != addHypCmds.end(); ) + { + bool sameHyp = true; + if ( hypID != (*cmd)->GetArg( 1 ) && hypID != (*cmd)->GetArg( 2 )) + sameHyp = false; // other hyp + if ( (*cmd)->GetNbArgs() == 2 && + geomID != (*cmd)->GetArg( 1 ) && geomID != (*cmd)->GetArg( 2 )) + sameHyp = false; // other geom + if ( (*cmd)->GetNbArgs() == 1 && isLocal ) + sameHyp = false; // other geom + if ( sameHyp ) + { + addCmd = *cmd; + cmd = addHypCmds.erase( cmd ); + if ( !theGen->IsToKeepAllCommands() ) { + addCmd->Clear(); + theCommand->Clear(); + } + } + else + { + ++cmd; + } } } Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID ); - if ( ! hasAddCmd && hypID.Length() != 0 ) { // hypo addition already wrapped + if ( !theCommand->IsEmpty() && !hypID.IsEmpty() ) { // RemoveHypothesis(geom, hyp) --> RemoveHypothesis( hyp, geom=0 ) _pyID geom = theCommand->GetArg( 1 ); theCommand->RemoveArgs(); @@ -1551,23 +1754,6 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) 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 ); - } - } - } // add accessor method if necessary else { @@ -1705,6 +1891,7 @@ void _pyMesh::Flush() addCmd->SetArg( 1, algoID ); if ( isLocalAlgo ) addCmd->SetArg( 2, geom ); + myNotConvertedAddHypCmds.push_back( addCmd ); } } @@ -1725,6 +1912,7 @@ void _pyMesh::Flush() addCmd->SetArg( 1, hypID ); if ( geom != GetGeom() ) addCmd->SetArg( 2, geom ); + myNotConvertedAddHypCmds.push_back( addCmd ); } } @@ -1874,14 +2062,15 @@ _pyMeshEditor::_pyMeshEditor(const Handle(_pyCommand)& theCreationCmd): void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) { - // names of SMESH_MeshEditor methods fully equal to methods of python class Mesh, so - // commands calling this methods are converted to calls of methods of Mesh + // names of SMESH_MeshEditor methods fully equal to methods of the python class Mesh, so + // commands calling this methods are converted to calls of Mesh methods static TStringSet sameMethods; if ( sameMethods.empty() ) { const char * names[] = { - "RemoveElements","RemoveNodes","RemoveOrphanNodes","AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace", + "RemoveElements","RemoveNodes","RemoveOrphanNodes","AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace","AddBall", "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","MoveNode", "MoveClosestNodeToPoint", - "InverseDiag","DeleteDiag","Reorient","ReorientObject","TriToQuad","SplitQuad","SplitQuadObject", + "InverseDiag","DeleteDiag","Reorient","ReorientObject", + "TriToQuad","TriToQuadObject", "SplitQuad","SplitQuadObject", "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject", "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements", "RotationSweep","RotationSweepObject","RotationSweepObject1D","RotationSweepObject2D", @@ -1895,12 +2084,26 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) "GetLastCreatedElems", "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh", "TranslateObjectMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh", - "MakeBoundaryElements" + "MakeBoundaryElements", "SplitVolumesIntoTetra" ,"" }; // <- mark of the end sameMethods.Insert( names ); } - // names of SMESH_MeshEditor methods which differ from methods of class Mesh + // names of SMESH_MeshEditor commands in which only a method name must be replaced + TStringMap diffMethods; + if ( diffMethods.empty() ) { + const char * orig2newName[] = { + // original name --------------> new name + "ExtrusionAlongPathObjX" , "ExtrusionAlongPathX", + "FindCoincidentNodesOnPartBut", "FindCoincidentNodesOnPart", + "ConvertToQuadraticObject" , "ConvertToQuadratic", + "ConvertFromQuadraticObject" , "ConvertFromQuadratic", + "Create0DElementsOnAllNodes" , "Add0DElementsToAllNodes", + ""};// <- mark of the end + diffMethods.Insert( orig2newName ); + } + + // names of SMESH_MeshEditor methods which differ from methods of Mesh class // only by last two arguments static TStringSet diffLastTwoArgsMethods; if (diffLastTwoArgsMethods.empty() ) { @@ -1912,13 +2115,28 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) diffLastTwoArgsMethods.Insert( names ); } + // only a method name is to change? const TCollection_AsciiString & method = theCommand->GetMethod(); bool isPyMeshMethod = sameMethods.Contains( method ); if ( !isPyMeshMethod ) { - //Replace SMESH_MeshEditor "MakeGroups" functions by the Mesh - //functions with the flag "theMakeGroups = True" like: - //SMESH_MeshEditor.CmdMakeGroups => Mesh.Cmd(...,True) + TCollection_AsciiString newMethod = diffMethods.Value( method ); + if (( isPyMeshMethod = ( newMethod.Length() > 0 ))) + theCommand->SetMethod( newMethod ); + } + // ConvertToBiQuadratic(...) -> ConvertToQuadratic(...,True) + if ( !isPyMeshMethod && (method == "ConvertToBiQuadratic" || method == "ConvertToBiQuadraticObject") ) + { + isPyMeshMethod = true; + theCommand->SetMethod( method.SubString( 1, 9) + method.SubString( 12, method.Length())); + theCommand->SetArg( theCommand->GetNbArgs() + 1, "True" ); + } + + if ( !isPyMeshMethod ) + { + // Replace SMESH_MeshEditor "*MakeGroups" functions by the Mesh + // functions with the flag "theMakeGroups = True" like: + // SMESH_MeshEditor.CmdMakeGroups => Mesh.Cmd(...,True) int pos = method.Search("MakeGroups"); if( pos != -1) { @@ -1943,29 +2161,17 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) } } - // ExtrusionSweep0D() -> ExtrusionSweep() + // ExtrusionSweep0D() -> ExtrusionSweep() // ExtrusionSweepObject0D() -> ExtrusionSweepObject() if ( !isPyMeshMethod && ( method == "ExtrusionSweep0D" || method == "ExtrusionSweepObject0D" )) { - isPyMeshMethod=true; + 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") - { - isPyMeshMethod=true; - theCommand->SetMethod("ExtrusionAlongPathX"); - } - // set "FindCoincidentNodesOnPart()" instead of "FindCoincidentNodesOnPartBut()" - if ( !isPyMeshMethod && method == "FindCoincidentNodesOnPartBut") - { - isPyMeshMethod=true; - theCommand->SetMethod("FindCoincidentNodesOnPart"); - } // DoubleNode...New(...) -> DoubleNode...(...,True) if ( !isPyMeshMethod && ( method == "DoubleNodeElemGroupNew" || method == "DoubleNodeElemGroupsNew" || @@ -1974,7 +2180,7 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) method == "DoubleNodeElemGroup2New" || method == "DoubleNodeElemGroups2New")) { - isPyMeshMethod=true; + isPyMeshMethod = true; const int excessLen = 3 + int( method.Value( method.Length()-3 ) == '2' ); theCommand->SetMethod( method.SubString( 1, method.Length()-excessLen)); if ( excessLen == 3 ) @@ -1990,24 +2196,11 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) theCommand->SetResultValue( groupID ); } } - // ConvertToQuadraticObject(bool,obj) -> ConvertToQuadratic(bool,obj) - // ConvertFromQuadraticObject(obj) -> ConvertFromQuadratic(obj) - if ( !isPyMeshMethod && ( method == "ConvertToQuadraticObject" || - method == "ConvertFromQuadraticObject" )) - { - isPyMeshMethod=true; - theCommand->SetMethod( method.SubString( 1, method.Length()-6)); - // prevent moving creation of the converted sub-mesh to the end of the script - bool isFromQua = ( method.Value( 8 ) == 'F' ); - Handle(_pySubMesh) sm = theGen->FindSubMesh( theCommand->GetArg( isFromQua ? 1 : 2 )); - if ( !sm.IsNull() ) - sm->Process( theCommand ); - } // FindAmongElementsByPoint(meshPart, x, y, z, elementType) -> // FindElementsByPoint(x, y, z, elementType, meshPart) if ( !isPyMeshMethod && method == "FindAmongElementsByPoint" ) { - isPyMeshMethod=true; + isPyMeshMethod = true; theCommand->SetMethod( "FindElementsByPoint" ); // make the 1st arg be the last one _pyID partID = theCommand->GetArg( 1 ); @@ -2016,11 +2209,32 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) theCommand->SetArg( i-1, theCommand->GetArg( i )); theCommand->SetArg( nbArgs, partID ); } + // Reorient2D( mesh, dir, face, point ) -> Reorient2D( mesh, dir, faceORpoint ) + if ( !isPyMeshMethod && method == "Reorient2D" ) + { + isPyMeshMethod = true; + _AString mesh = theCommand->GetArg( 1 ); + _AString dir = theCommand->GetArg( 2 ); + _AString face = theCommand->GetArg( 3 ); + _AString point = theCommand->GetArg( 4 ); + theCommand->RemoveArgs(); + theCommand->SetArg( 1, mesh ); + theCommand->SetArg( 2, dir ); + if ( face.Value(1) == '-' || face.Value(1) == '0' ) // invalid: face <= 0 + theCommand->SetArg( 3, point ); + else + theCommand->SetArg( 3, face ); + } + + if ( method == "QuadToTri" || method == "QuadToTriObject" ) + { + isPyMeshMethod = true; + int crit_arg = theCommand->GetNbArgs(); + const _AString& crit = theCommand->GetArg(crit_arg); + if (crit.Search("MaxElementLength2D") != -1) + theCommand->SetArg(crit_arg, ""); + } - // meshes made by *MakeMesh() methods are not wrapped by _pyMesh, - // so let _pyMesh care of it (TMP?) - // if ( theCommand->GetMethod().Search("MakeMesh") != -1 ) - // _pyMesh( new _pyCommand( theCommand->GetString(), 0 )); // for theGen->SetAccessorMethod() if ( isPyMeshMethod ) { theCommand->SetObject( myMesh ); @@ -2028,7 +2242,7 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) else { // editor creation command is needed only if any editor function is called - theGen->AddMeshAccessorMethod( theCommand ); // for *Object() + theGen->AddMeshAccessorMethod( theCommand ); // for *Object() methods if ( !myCreationCmdStr.IsEmpty() ) { GetCreationCmd()->GetString() = myCreationCmdStr; myCreationCmdStr.Clear(); @@ -2310,7 +2524,7 @@ void _pyHypothesis::Assign( const Handle(_pyHypothesis)& theOther, myGeom = theOther->myGeom; myMesh = theMesh; myAlgoType2CreationMethod = theOther->myAlgoType2CreationMethod; - //myArgCommands = theOther->myArgCommands; + myAccumulativeMethods = theOther->myAccumulativeMethods; //myUnusedCommands = theOther->myUnusedCommands; // init myCurCrMethod GetCreationMethod( theOther->GetAlgoType() ); @@ -2439,7 +2653,9 @@ bool _pyHypothesis::GetReferredMeshesAndGeom( list< Handle(_pyMesh) >& meshes ) void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theCommand ) { // parameters are discriminated by method name - TCollection_AsciiString method = theCommand->GetMethod(); + _AString method = theCommand->GetMethod(); + if ( myAccumulativeMethods.count( method )) + return; // this method adds values and not override the previus value // discriminate commands setting different parameters via one method // by passing parameter names like e.g. SetOption("size", "0.2") @@ -2457,7 +2673,7 @@ void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theComman } } // parameters are discriminated by method name - list< Handle(_pyCommand)>& cmds = myMeth2Commands[ theCommand->GetMethod() ]; + list< Handle(_pyCommand)>& cmds = myMeth2Commands[ method /*theCommand->GetMethod()*/ ]; if ( !cmds.empty() && !isCmdUsedForCompute( cmds.back() )) { cmds.back()->Clear(); // previous parameter value has not been used @@ -2953,6 +3169,7 @@ int _pyCommand::GetBegPos( int thePartIndex ) return EMPTY; if ( myBegPos.Length() < thePartIndex ) return UNKNOWN; + ASSERT( thePartIndex > 0 ); return myBegPos( thePartIndex ); } @@ -2968,6 +3185,7 @@ void _pyCommand::SetBegPos( int thePartIndex, int thePosition ) { while ( myBegPos.Length() < thePartIndex ) myBegPos.Append( UNKNOWN ); + ASSERT( thePartIndex > 0 ); myBegPos( thePartIndex ) = thePosition; } @@ -3020,22 +3238,21 @@ const TCollection_AsciiString & _pyCommand::GetResultValue() //================================================================================ /*! * \brief Return number of python command result value ResultValue = Obj.Meth() - * \retval const int */ //================================================================================ -const int _pyCommand::GetNbResultValues() +int _pyCommand::GetNbResultValues() { + int nb = 0; int begPos = 1; - int Nb=0; int endPos = myString.Location( "=", 1, Length() ); - TCollection_AsciiString str = ""; - while ( begPos < endPos) { - str = GetWord( myString, begPos, true ); + while ( begPos < endPos ) + { + _AString str = GetWord( myString, begPos, true ); begPos = begPos+ str.Length(); - Nb++; + nb++; } - return (Nb-1); + return (nb-1); } @@ -3258,10 +3475,10 @@ static inline bool isWord(const char c, const bool dotIsWord) */ //================================================================================ -TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString, - int & theStartPos, - const bool theForward, - const bool dotIsWord ) +TCollection_AsciiString _pyCommand::GetWord( const _AString & theString, + int & theStartPos, + const bool theForward, + const bool dotIsWord ) { int beg = theStartPos, end = theStartPos; theStartPos = EMPTY; @@ -3473,7 +3690,7 @@ void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg) void _pyCommand::RemoveArgs() { - if ( int pos = myString.Location( '(', 1, Length() )) + if ( int pos = myString.Location( '(', Max( 1, GetBegPos( METHOD_IND )), Length() )) myString.Trunc( pos ); myString += ")"; myArgs.Clear(); @@ -3496,7 +3713,7 @@ void _pyCommand::Comment() if ( i <= Length() ) { myString.Insert( i, "#" ); - for ( int iPart = 0; iPart < myBegPos.Length(); ++iPart ) + for ( int iPart = 1; iPart <= myBegPos.Length(); ++iPart ) { int begPos = GetBegPos( iPart ); if ( begPos != UNKNOWN ) @@ -3662,6 +3879,49 @@ _pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd): myMesh = ObjectToMesh( theGen->FindObject( theCreationCmd->GetObject() )); } +//================================================================================ +/*! + * \brief Return true if a sub-mesh can be used as argument of the given method + */ +//================================================================================ + +bool _pySubMesh::CanBeArgOfMethod(const _AString& theMethodName) +{ + // names of all methods where a sub-mesh can be used as argument + static TStringSet methods; + if ( methods.empty() ) { + const char * names[] = { + // methods of SMESH_Gen + "CopyMesh", + // methods of SMESH_Group + "AddFrom", + // methods of SMESH_Measurements + "MinDistance", + // methods of SMESH_Mesh + "ExportPartToMED","ExportCGNS","ExportPartToDAT","ExportPartToUNV","ExportPartToSTL", + "RemoveSubMesh", + // methods of SMESH_MeshEditor + "ReorientObject","Reorient2D","TriToQuadObject","QuadToTriObject","SplitQuadObject", + "SplitVolumesIntoTetra","SmoothObject","SmoothParametricObject","ConvertFromQuadraticObject", + "RotationSweepObject","RotationSweepObjectMakeGroups","RotationSweepObject1D", + "RotationSweepObject1DMakeGroups","RotationSweepObject2D","RotationSweepObject2DMakeGroups", + "ExtrusionSweepObject","ExtrusionSweepObjectMakeGroups","ExtrusionSweepObject0D", + "ExtrusionSweepObject0DMakeGroups","ExtrusionSweepObject1D","ExtrusionSweepObject2D", + "ExtrusionSweepObject1DMakeGroups","ExtrusionSweepObject2DMakeGroups", + "ExtrusionAlongPathObjX","ExtrusionAlongPathObject","ExtrusionAlongPathObjectMakeGroups", + "ExtrusionAlongPathObject1D","ExtrusionAlongPathObject1DMakeGroups", + "ExtrusionAlongPathObject2D","ExtrusionAlongPathObject2DMakeGroups","MirrorObject", + "MirrorObjectMakeGroups","MirrorObjectMakeMesh","TranslateObject","Scale", + "TranslateObjectMakeGroups","TranslateObjectMakeMesh","ScaleMakeGroups","ScaleMakeMesh", + "RotateObject","RotateObjectMakeGroups","RotateObjectMakeMesh","FindCoincidentNodesOnPart", + "FindCoincidentNodesOnPartBut","FindEqualElements","FindAmongElementsByPoint", + "MakeBoundaryMesh","Create0DElementsOnAllNodes", + "" }; // <- mark of end + methods.Insert( names ); + } + return methods.Contains( theMethodName ); +} + //================================================================================ /*! * \brief count invoked commands @@ -3753,6 +4013,21 @@ _pyGroup::_pyGroup(const Handle(_pyCommand)& theCreationCmd, const _pyID & id) } } +//================================================================================ +/*! + * \brief set myCanClearCreationCmd = true if the main action of the creation + * command is discarded + */ +//================================================================================ + +void _pyGroup::RemovedWithContents() +{ + // this code would be appropriate if Add0DElementsToAllNodes() returned only new nodes + // via a created group + //if ( GetCreationCmd()->GetMethod() == "Add0DElementsToAllNodes") + // myCanClearCreationCmd = true; +} + //================================================================================ /*! * \brief To convert creation of a group by filter @@ -3830,8 +4105,6 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) //================================================================================ /*! * \brief Prevent clearing "DoubleNode...() command if a group created by it is removed - * - * */ //================================================================================ @@ -3934,73 +4207,8 @@ bool _pyFilter::CanClear() _pyHypothesisReader::_pyHypothesisReader() { - // Get paths to xml files of plugins - vector< string > xmlPaths; - string sep; - if ( const char* meshersList = getenv("SMESH_MeshersList") ) - { - string meshers = meshersList, plugin; - string::size_type from = 0, pos; - while ( from < meshers.size() ) - { - // cut off plugin name - pos = meshers.find( ':', from ); - if ( pos != string::npos ) - plugin = meshers.substr( from, pos-from ); - else - plugin = meshers.substr( from ), pos = meshers.size(); - from = pos + 1; - - // get PLUGIN_ROOT_DIR path - string rootDirVar, pluginSubDir = plugin; - if ( plugin == "StdMeshers" ) - rootDirVar = "SMESH", pluginSubDir = "smesh"; - else - for ( pos = 0; pos < plugin.size(); ++pos ) - rootDirVar += toupper( plugin[pos] ); - rootDirVar += "_ROOT_DIR"; - - const char* rootDir = getenv( rootDirVar.c_str() ); - if ( !rootDir || strlen(rootDir) == 0 ) - { - rootDirVar = plugin + "_ROOT_DIR"; // HexoticPLUGIN_ROOT_DIR - rootDir = getenv( rootDirVar.c_str() ); - if ( !rootDir || strlen(rootDir) == 0 ) continue; - } - - // get a separator from rootDir - for ( pos = strlen( rootDir )-1; pos >= 0 && sep.empty(); --pos ) - if ( rootDir[pos] == '/' || rootDir[pos] == '\\' ) - { - sep = rootDir[pos]; - break; - } -#ifdef WNT - if (sep.empty() ) sep = "\\"; -#else - if (sep.empty() ) sep = "/"; -#endif - - // get a path to resource file - string xmlPath = rootDir; - if ( xmlPath[ xmlPath.size()-1 ] != sep[0] ) - xmlPath += sep; - xmlPath += "share" + sep + "salome" + sep + "resources" + sep; - for ( pos = 0; pos < pluginSubDir.size(); ++pos ) - xmlPath += tolower( pluginSubDir[pos] ); - xmlPath += sep + plugin + ".xml"; - bool fileOK; -#ifdef WNT - fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES); -#else - fileOK = (access(xmlPath.c_str(), F_OK) == 0); -#endif - if ( fileOK ) - xmlPaths.push_back( xmlPath ); - } - } - // Read xml files + vector< string > xmlPaths = SMESH_Gen::GetPluginXMLPaths(); LDOMParser xmlParser; for ( size_t i = 0; i < xmlPaths.size(); ++i ) { @@ -4022,7 +4230,7 @@ _pyHypothesisReader::_pyHypothesisReader() LDOM_NodeList algoNodeList = xmlDoc.getElementsByTagName( "algorithm" ); for ( int i = 0; i < algoNodeList.getLength(); ++i ) { - LDOM_Node algoNode = algoNodeList.item( i ); + LDOM_Node algoNode = algoNodeList.item( i ); LDOM_Element& algoElem = (LDOM_Element&) algoNode; LDOM_NodeList pyAlgoNodeList = algoElem.getElementsByTagName( "algo" ); if ( pyAlgoNodeList.getLength() < 1 ) continue; @@ -4084,7 +4292,43 @@ _pyHypothesisReader::_pyHypothesisReader() } } } - } + // + // + // + // SetEnforcedVertex, + // SetEnforcedVertexNamed + // + // + // + // + LDOM_NodeList hypNodeList = xmlDoc.getElementsByTagName( "hypothesis" ); + for ( int i = 0; i < hypNodeList.getLength(); ++i ) + { + LDOM_Node hypNode = hypNodeList.item( i ); + LDOM_Element& hypElem = (LDOM_Element&) hypNode; + _AString hypType = hypElem.getAttribute("type"); + LDOM_NodeList methNodeList = hypElem.getElementsByTagName( "accumulative-methods" ); + if ( methNodeList.getLength() != 1 || hypType.IsEmpty() ) continue; + + map<_AString, Handle(_pyHypothesis)>::const_iterator type2hyp = myType2Hyp.find( hypType ); + if ( type2hyp == myType2Hyp.end() ) continue; + + LDOM_Node methNode = methNodeList.item( 0 ); + LDOM_Node textNode = methNode.getFirstChild(); + _AString text = textNode.getNodeValue(); + _AString method; + int pos = 1; + do { + method = _pyCommand::GetWord( text, pos, /*forward= */true ); + pos += method.Length(); + type2hyp->second->AddAccumulativeMethod( method ); + } + while ( !method.IsEmpty() ); + } + + } // loop on xmlPaths } //================================================================================