X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FSMESH_I%2FSMESH_2smeshpy.cxx;h=e8bc862a90dd119667e2afc63ddeaf5a8254f506;hp=7ff09306b48e375b64eb1f49dd9625c0637e0cc2;hb=5d0b75d9d1a9935ec419e820e6dde45a665dd978;hpb=0f7414545ba7ec49824d2aaa9fa10718f118ebdc diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 7ff09306b..e8bc862a9 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -44,44 +44,28 @@ #include -#ifdef WNT +#ifdef WIN32 #include #else #include #endif - -IMPLEMENT_STANDARD_HANDLE (_pyObject ,Standard_Transient); -IMPLEMENT_STANDARD_HANDLE (_pyCommand ,Standard_Transient); -IMPLEMENT_STANDARD_HANDLE (_pyHypothesisReader,Standard_Transient); -IMPLEMENT_STANDARD_HANDLE (_pyGen ,_pyObject); -IMPLEMENT_STANDARD_HANDLE (_pyMesh ,_pyObject); -IMPLEMENT_STANDARD_HANDLE (_pySubMesh ,_pyObject); -IMPLEMENT_STANDARD_HANDLE (_pyMeshEditor ,_pyObject); -IMPLEMENT_STANDARD_HANDLE (_pyHypothesis ,_pyObject); -IMPLEMENT_STANDARD_HANDLE (_pySelfEraser ,_pyObject); -IMPLEMENT_STANDARD_HANDLE (_pyGroup ,_pyObject); -IMPLEMENT_STANDARD_HANDLE (_pyFilter ,_pyObject); -IMPLEMENT_STANDARD_HANDLE (_pyAlgorithm ,_pyHypothesis); -IMPLEMENT_STANDARD_HANDLE (_pyComplexParamHypo,_pyHypothesis); -IMPLEMENT_STANDARD_HANDLE (_pyNumberOfSegmentsHyp,_pyHypothesis); - -IMPLEMENT_STANDARD_RTTIEXT(_pyObject ,Standard_Transient); -IMPLEMENT_STANDARD_RTTIEXT(_pyCommand ,Standard_Transient); -IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesisReader,Standard_Transient); -IMPLEMENT_STANDARD_RTTIEXT(_pyGen ,_pyObject); -IMPLEMENT_STANDARD_RTTIEXT(_pyMesh ,_pyObject); -IMPLEMENT_STANDARD_RTTIEXT(_pySubMesh ,_pyObject); -IMPLEMENT_STANDARD_RTTIEXT(_pyMeshEditor ,_pyObject); -IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis ,_pyObject); -IMPLEMENT_STANDARD_RTTIEXT(_pySelfEraser ,_pyObject); -IMPLEMENT_STANDARD_RTTIEXT(_pyGroup ,_pyObject); -IMPLEMENT_STANDARD_RTTIEXT(_pyFilter ,_pyObject); -IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm ,_pyHypothesis); -IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis); -IMPLEMENT_STANDARD_RTTIEXT(_pyNumberOfSegmentsHyp,_pyHypothesis); -IMPLEMENT_STANDARD_RTTIEXT(_pyLayerDistributionHypo,_pyHypothesis); -IMPLEMENT_STANDARD_RTTIEXT(_pySegmentLengthAroundVertexHyp,_pyHypothesis); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyObject ,Standard_Transient); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyCommand ,Standard_Transient); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesisReader,Standard_Transient); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyGen ,_pyObject); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyMesh ,_pyObject); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pySubMesh ,_pyObject); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyMeshEditor ,_pyObject); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis ,_pyObject); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pySelfEraser ,_pyObject); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyGroup ,_pyObject); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyFilter ,_pyObject); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm ,_pyHypothesis); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyNumberOfSegmentsHyp,_pyHypothesis); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pyLayerDistributionHypo,_pyHypothesis); +OCCT_IMPLEMENT_STANDARD_RTTIEXT(_pySegmentLengthAroundVertexHyp,_pyHypothesis); using namespace std; using SMESH::TPythonDump; @@ -183,7 +167,8 @@ namespace { if ( cmd->GetString().Location( TPythonDump::NotPublishedObjectName(), 1, cmd->Length() )) { bool isResultPublished = false; - for ( int i = 0; i < cmd->GetNbResultValues(); i++ ) + const int nbRes = cmd->GetNbResultValues(); + for ( int i = 0; i < nbRes; i++ ) { _pyID objID = cmd->GetResultValue( i+1 ); if ( cmd->IsStudyEntry( objID )) @@ -196,8 +181,25 @@ namespace { cmd->Clear(); return; } - // comment a command having not created args - for ( int iArg = cmd->GetNbArgs(); iArg; --iArg ) + // check if an Object was created in the script + _AString comment; + + _pyID obj = cmd->GetObject(); + if ( obj.Search( "print " ) == 1 ) + return; // print statement + + if ( !obj.IsEmpty() && obj.Value( obj.Length() ) == ')' ) + // remove an accessor method + obj = _pyCommand( obj ).GetObject(); + + const bool isMethodCall = cmd->IsMethodCall(); + if ( !obj.IsEmpty() && isMethodCall && !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 ) == '\'' ) @@ -207,34 +209,35 @@ 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"; - for ( int i = 0; i < cmd->GetNbResultValues(); i++ ) { - _pyID objID = cmd->GetResultValue( i+1 ); - theGen->ObjectCreationRemoved( objID ); // objID.SetName( name ) is not needed - } - return; + comment += *id + " has not been yet created"; + break; } + // if ( idList.empty() && cmd->IsID( arg ) && !presentObjects.count( arg )) + // comment += arg + " has not been yet created"; } - // comment a command having not created Object - 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 ) != '\'' ) { - cmd->Comment(); - cmd->GetString() += " ### not created object" ; - for ( int i = 0; i < cmd->GetNbResultValues(); i++ ) { - _pyID objID = cmd->GetResultValue( i+1 ); - theGen->ObjectCreationRemoved( objID ); // objID.SetName( name ) is not needed + 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 } + if ( idList.empty() && cmd->IsID( result )) + presentObjects.insert( result ); + } + // comment the command + if ( !comment.IsEmpty() ) + { + cmd->Comment(); + 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 ); } //================================================================================ @@ -287,6 +290,10 @@ namespace { // - FT_EntityType = 36 // v 7.3.0: FT_Undefined == 46, new items: // - FT_ConnectedElements = 39 + // v 7.6.0: FT_Undefined == 47, new items: + // - FT_BelongToMeshGroup = 22 + // v 8.1.0: FT_Undefined == 48, new items: + // - FT_NodeConnectivityNumber= 22 // // It's necessary to continue recording this history and to fill // undef2newItems (see below) accordingly. @@ -307,6 +314,10 @@ namespace { undef2newItems[ 44 ].push_back( 37 ); undef2newItems[ 45 ].push_back( 36 ); undef2newItems[ 46 ].push_back( 39 ); + undef2newItems[ 47 ].push_back( 22 ); + undef2newItems[ 48 ].push_back( 22 ); + + ASSERT( undef2newItems.rbegin()->first == SMESH::FT_Undefined ); } int iType = Type.IntegerValue(); @@ -342,12 +353,99 @@ namespace { BinaryOp = TCollection_AsciiString( iBinaryOp ); } } + + //================================================================================ + /*! + * \brief Replaces "SMESH.PointStruct(x,y,z)" and "SMESH.DirStruct( SMESH.PointStruct(x,y,z))" + * arguments of a given command by a list "[x,y,z]" if the list is accesible + * type of argument. + */ + //================================================================================ + + void StructToList( Handle( _pyCommand)& theCommand, const bool checkMethod=true ) + { + static TStringSet methodsAcceptingList; + if ( methodsAcceptingList.empty() ) { + const char * methodNames[] = { + "GetCriterion","Reorient2D","ExtrusionSweep","ExtrusionSweepMakeGroups0D", + "ExtrusionSweepMakeGroups","ExtrusionSweep0D", + "AdvancedExtrusion","AdvancedExtrusionMakeGroups", + "ExtrusionSweepObject","ExtrusionSweepObject0DMakeGroups", + "ExtrusionSweepObjectMakeGroups","ExtrusionSweepObject0D", + "ExtrusionSweepObject1D","ExtrusionSweepObject1DMakeGroups", + "ExtrusionSweepObject2D","ExtrusionSweepObject2DMakeGroups", + "ExtrusionSweepObjects","RotationSweepObjects","ExtrusionAlongPathObjects", + "Translate","TranslateMakeGroups","TranslateMakeMesh", + "TranslateObject","TranslateObjectMakeGroups", "TranslateObjectMakeMesh", + "ExtrusionAlongPathX","ExtrusionAlongPathObjX","SplitHexahedraIntoPrisms" + ,"" }; // <- mark of the end + methodsAcceptingList.Insert( methodNames ); + } + if ( !checkMethod || methodsAcceptingList.Contains( theCommand->GetMethod() )) + { + for ( int i = theCommand->GetNbArgs(); i > 0; --i ) + { + const _AString & arg = theCommand->GetArg( i ); + if ( arg.Search( "SMESH.PointStruct" ) == 1 || + arg.Search( "SMESH.DirStruct" ) == 1 ) + { + Handle(_pyCommand) workCmd = new _pyCommand( arg ); + if ( workCmd->GetNbArgs() == 1 ) // SMESH.DirStruct( SMESH.PointStruct(x,y,z)) + { + workCmd = new _pyCommand( workCmd->GetArg( 1 ) ); + } + if ( workCmd->GetNbArgs() == 3 ) // SMESH.PointStruct(x,y,z) + { + _AString newArg = "[ "; + newArg += ( workCmd->GetArg( 1 ) + ", " + + workCmd->GetArg( 2 ) + ", " + + workCmd->GetArg( 3 ) + " ]"); + theCommand->SetArg( i, newArg ); + } + } + } + } + } + //================================================================================ + /*! + * \brief Replaces "mesh.GetIDSource([id1,id2])" argument of a given command by + * a list "[id1,id2]" if the list is an accesible type of argument. + */ + //================================================================================ + + void GetIDSourceToList( Handle( _pyCommand)& theCommand ) + { + static TStringSet methodsAcceptingList; + if ( methodsAcceptingList.empty() ) { + const char * methodNames[] = { + "ExportPartToMED","ExportPartToDAT","ExportPartToUNV","ExportPartToSTL", + "ExportCGNS","ExportGMF", + "Create0DElementsOnAllNodes","Reorient2D","QuadTo4Tri", + "ScaleMakeGroups","Scale","ScaleMakeMesh", + "FindCoincidentNodesOnPartBut","DoubleElements", + "ExtrusionSweepObjects","RotationSweepObjects","ExtrusionAlongPathObjects" + ,"" }; // <- mark of the end + methodsAcceptingList.Insert( methodNames ); + } + if ( methodsAcceptingList.Contains( theCommand->GetMethod() )) + { + for ( int i = theCommand->GetNbArgs(); i > 0; --i ) + { + _pyCommand argCmd( theCommand->GetArg( i )); + if ( argCmd.GetMethod() == "GetIDSource" && + argCmd.GetNbArgs() == 2 ) + { + theCommand->SetArg( i, argCmd.GetArg( 1 )); + } + } + } + } } //================================================================================ /*! * \brief Convert a python script using commands of smeshBuilder.py - * \param theScript - Input script + * \param theScriptLines - Lines of the input script * \param theEntry2AccessorMethod - returns method names to access to * objects wrapped with python class * \param theObjectNames - names of objects @@ -358,48 +456,41 @@ namespace { */ //================================================================================ -TCollection_AsciiString -SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript, +void +SMESH_2smeshpy::ConvertScript(std::list< TCollection_AsciiString >& theScriptLines, Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod, Resource_DataMapOfAsciiStringAsciiString& theObjectNames, std::set< TCollection_AsciiString >& theRemovedObjIDs, SALOMEDS::Study_ptr& theStudy, const bool theToKeepAllCommands) { - theGen = new _pyGen( theEntry2AccessorMethod, - theObjectNames, - theRemovedObjIDs, - theStudy, - theToKeepAllCommands ); + std::list< TCollection_AsciiString >::iterator lineIt; + // process notebook variables + { + SMESH_NoteBook aNoteBook; - // split theScript into separate commands + for ( lineIt = theScriptLines.begin(); lineIt != theScriptLines.end(); ++lineIt ) + aNoteBook.AddCommand( *lineIt ); - SMESH_NoteBook * aNoteBook = new SMESH_NoteBook(); + theScriptLines.clear(); - int from = 1, end = theScript.Length(), to; - 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; + aNoteBook.ReplaceVariables(); + + aNoteBook.GetResultLines( theScriptLines ); } - aNoteBook->ReplaceVariables(); + // convert to smeshBuilder.py API + + theGen = new _pyGen( theEntry2AccessorMethod, + theObjectNames, + theRemovedObjIDs, + theStudy, + theToKeepAllCommands ); - TCollection_AsciiString aNoteScript = aNoteBook->GetResultScript(); - delete aNoteBook; - aNoteBook = 0; + for ( lineIt = theScriptLines.begin(); lineIt != theScriptLines.end(); ++lineIt ) + theGen->AddCommand( *lineIt ); - // split theScript into separate commands - from = 1, end = aNoteScript.Length(); - while ( from < end && ( to = aNoteScript.Location( "\n", from, end ))) - { - if ( to != from ) - // cut out and store a command - theGen->AddCommand( aNoteScript.SubString( from, to - 1 )); - from = to + 1; - } + theScriptLines.clear(); // finish conversion theGen->Flush(); @@ -421,8 +512,11 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScrip } while ( orderChanges ); // concat commands back into a script - TCollection_AsciiString aScript, aPrevCmd; + TCollection_AsciiString aPrevCmd; set<_pyID> createdObjects; + createdObjects.insert( "smeshBuilder" ); + createdObjects.insert( "smesh" ); + createdObjects.insert( "theStudy" ); for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd ) { #ifdef DUMP_CONVERSION @@ -430,17 +524,15 @@ SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScrip #endif if ( !(*cmd)->IsEmpty() && aPrevCmd != (*cmd)->GetString()) { CheckObjectPresence( *cmd, createdObjects ); - aPrevCmd = (*cmd)->GetString(); - aScript += "\n"; - aScript += aPrevCmd; + if ( !(*cmd)->IsEmpty() ) { + aPrevCmd = (*cmd)->GetString(); + theScriptLines.push_back( aPrevCmd ); + } } } - aScript += "\n"; theGen->Free(); theGen.Nullify(); - - return aScript; } //================================================================================ @@ -532,9 +624,43 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand // 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() )) + // if ( _pySubMesh::CanBeArgOfMethod( aCommand->GetMethod() )) + // { + // PlaceSubmeshAfterItsCreation( aCommand ); + // } + + // Method( SMESH.PointStruct(x,y,z)... -> Method( [x,y,z]... + StructToList( aCommand ); + + const TCollection_AsciiString& method = aCommand->GetMethod(); + + // not to erase _pySelfEraser's etc. used as args in some commands { - PlaceSubmeshAfterItsCreation( aCommand ); +#ifdef USE_STRING_FAMILY + std::list<_pyID> objIDs; + if ( myKeepAgrCmdsIDs.IsInArgs( aCommand, objIDs )) + { + std::list<_pyID>::iterator objID = objIDs.begin(); + for ( ; objID != objIDs.end(); ++objID ) + { + Handle(_pyObject) obj = FindObject( *objID ); + if ( !obj.IsNull() ) + { + obj->AddArgCmd( aCommand ); + //cout << objID << " found in " << theCommand << endl; + } + } + } +#else + std::list< _pyID >::const_iterator id = myKeepAgrCmdsIDs.begin(); + for ( ; id != myKeepAgrCmdsIDs.end(); ++id ) + if ( *id != objID && theCommand.Search( *id ) > id->Length() ) + { + Handle(_pyObject) obj = FindObject( *id ); + if ( !obj.IsNull() ) + obj->AddArgCmd( aCommand ); + } +#endif } // Find an object to process theCommand @@ -543,6 +669,7 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand if ( objID == this->GetID() || objID == SMESH_2smeshpy::GenName()) { this->Process( aCommand ); + //addFilterUser( aCommand, theGen ); // protect filters from clearing return aCommand; } @@ -552,6 +679,25 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand { //id_mesh->second->AddProcessedCmd( aCommand ); + // Wrap Export*() into try-except + if ( aCommand->MethodStartsFrom("Export")) + { + _AString tab = "\t"; + _AString indent = aCommand->GetIndentation(); + _AString tryStr = indent + "try:"; + _AString newCmd = indent + tab + ( aCommand->GetString().ToCString() + indent.Length() ); + _AString pasCmd = indent + tab + "pass"; // to keep valid if newCmd is erased + _AString excStr = indent + "except:"; + _AString msgStr = indent + "\tprint '"; msgStr += method + "() failed. Invalid file name?'"; + + myCommands.insert( --myCommands.end(), new _pyCommand( tryStr, myNbCommands )); + aCommand->Clear(); + aCommand->GetString() = newCmd; + aCommand->SetOrderNb( ++myNbCommands ); + myCommands.push_back( new _pyCommand( pasCmd, ++myNbCommands )); + myCommands.push_back( new _pyCommand( excStr, ++myNbCommands )); + myCommands.push_back( new _pyCommand( msgStr, ++myNbCommands )); + } // check for mesh editor object if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation _pyID editorID = aCommand->GetResultValue(); @@ -563,9 +709,14 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand else if ( aCommand->GetMethod() == "GetSubMesh" ) { // SubMesh creation _pyID subMeshID = aCommand->GetResultValue(); Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand ); - myObjects.insert( make_pair( subMeshID, subMesh )); + AddObject( subMesh ); } + // Method( mesh.GetIDSource([id1,id2]) -> Method( [id1,id2] + GetIDSourceToList( aCommand ); + + //addFilterUser( aCommand, theGen ); // protect filters from clearing + id_mesh->second->Process( aCommand ); id_mesh->second->AddProcessedCmd( aCommand ); return aCommand; @@ -575,7 +726,10 @@ 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(); + // Method( mesh.GetIDSource([id1,id2]) -> Method( [id1,id2] + GetIDSourceToList( aCommand ); + + //addFilterUser( aCommand, theGen ); // protect filters from clearing // some commands of SMESH_MeshEditor create meshes and groups _pyID meshID, groups; @@ -613,8 +767,9 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand !myMeshes.count( meshID ) && aCommand->IsStudyEntry( meshID )) { - TCollection_AsciiString processedCommand = aCommand->GetString(); + _AString processedCommand = aCommand->GetString(); Handle(_pyMesh) mesh = new _pyMesh( aCommand, meshID ); + CheckObjectIsReCreated( mesh ); myMeshes.insert( make_pair( meshID, mesh )); aCommand->Clear(); aCommand->GetString() = processedCommand; // discard changes made by _pyMesh @@ -640,13 +795,13 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand } // 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; - } + Handle(_pyHypothesis) hyp = FindHyp( objID ); + if ( !hyp.IsNull() && !hyp->IsAlgo() ) + { + hyp->Process( aCommand ); + hyp->AddProcessedCmd( aCommand ); + return aCommand; + } // aFilterManager.CreateFilter() ? if ( aCommand->GetMethod() == "CreateFilter" ) @@ -661,6 +816,14 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand Handle(_pyObject) filter( new _pyFilter( aCommand, newID )); AddObject( filter ); } + // aFreeNodes0x5011f80 = aFilterManager.CreateFreeNodes() ## issue 0020976 + else if ( theCommand.Search( "aFilterManager.Create" ) > 0 ) + { + // create _pySelfEraser for functors + Handle(_pySelfEraser) functor = new _pySelfEraser( aCommand ); + functor->IgnoreOwnCalls(); // to erase if not used as an argument + AddObject( functor ); + } // other object method? map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.find( objID ); @@ -719,6 +882,9 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand UnaryOp = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( UnaryOp.IntegerValue() )); BinaryOp = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( BinaryOp.IntegerValue() )); + if ( Compare == "SMESH.FT_EqualTo" ) + Compare = "'='"; + aCommand->RemoveArgs(); aCommand->SetObject( SMESH_2smeshpy::GenName() ); aCommand->SetMethod( "GetCriterion" ); @@ -733,17 +899,23 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand if ( Type == "SMESH.FT_ElemGeomType" ) { // set SMESH.GeometryType instead of a numerical Threshold - const char* types[SMESH::Geom_BALL+1] = { + const int nbTypes = SMESH::Geom_LAST; + const char* types[] = { "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 ) + if ( -1 < iGeom && iGeom < nbTypes ) Threshold = SMESH + types[ iGeom ]; +#ifdef _DEBUG_ + // is types complete? (compilation failure mains that enum GeometryType changed) + int _asrt[( sizeof(types) / sizeof(const char*) == nbTypes ) ? 2 : -1 ]; _asrt[0]=_asrt[1]; +#endif } if (Type == "SMESH.FT_EntityType") { // set SMESH.EntityType instead of a numerical Threshold - const char* types[SMESH::Entity_Ball+1] = { + const int nbTypes = SMESH::Entity_Last; + const char* types[] = { "Entity_Node", "Entity_0D", "Entity_Edge", "Entity_Quad_Edge", "Entity_Triangle", "Entity_Quad_Triangle", "Entity_BiQuad_Triangle", "Entity_Quadrangle", "Entity_Quad_Quadrangle", "Entity_BiQuad_Quadrangle", @@ -752,8 +924,12 @@ Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand "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 ) + if ( -1 < iGeom && iGeom < nbTypes ) Threshold = SMESH + types[ iGeom ]; +#ifdef _DEBUG_ + // is 'types' complete? (compilation failure mains that enum EntityType changed) + int _asrt[( sizeof(types) / sizeof(const char*) == nbTypes ) ? 2 : -1 ]; _asrt[0]=_asrt[1]; +#endif } } if ( ThresholdID.Length() != 2 ) // neither '' nor "" @@ -808,7 +984,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) if ( method == "CreateMesh" || method == "CreateEmptyMesh") { Handle(_pyMesh) mesh = new _pyMesh( theCommand ); - myMeshes.insert( make_pair( mesh->GetID(), mesh )); + AddObject( mesh ); return; } if ( method == "CreateMeshesFromUNV" || @@ -816,7 +992,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) method == "CopyMesh" ) // command result is a mesh { Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() ); - myMeshes.insert( make_pair( mesh->GetID(), mesh )); + AddObject( mesh ); return; } if( method == "CreateMeshesFromMED" || @@ -824,12 +1000,12 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) method == "CreateMeshesFromCGNS" || method == "CreateMeshesFromGMF" ) // command result is ( [mesh1,mesh2], status ) { - for ( int ind = 0; ind < theCommand->GetNbResultValues(); ind++ ) + std::list< _pyID > meshIDs = theCommand->GetStudyEntries( theCommand->GetResultValue() ); + std::list< _pyID >::iterator meshID = meshIDs.begin(); + for ( ; meshID != meshIDs.end(); ++meshID ) { - _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 )); + Handle(_pyMesh) mesh = new _pyMesh( theCommand, *meshID ); + AddObject( mesh ); } if ( method == "CreateMeshesFromGMF" ) { @@ -847,13 +1023,16 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) // issue 199929, remove standard library name (default parameter) const TCollection_AsciiString & aLibName = theCommand->GetArg( 2 ); if ( aLibName.Search( "StdMeshersEngine" ) != -1 ) { - // keep first argument + // keep the first argument TCollection_AsciiString arg = theCommand->GetArg( 1 ); theCommand->RemoveArgs(); theCommand->SetArg( 1, arg ); } - myHypos.push_back( _pyHypothesis::NewHypothesis( theCommand )); + Handle(_pyHypothesis) hyp = _pyHypothesis::NewHypothesis( theCommand ); + CheckObjectIsReCreated( hyp ); + myHypos.insert( make_pair( hyp->GetID(), hyp )); + return; } @@ -890,9 +1069,10 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) // SMESH_Pattern, FilterManager if ( method == "GetPattern" || method == "CreateFilterManager" || - method == "CreateMeasurements" ) { + method == "CreateMeasurements" ) + { Handle(_pyObject) obj = new _pySelfEraser( theCommand ); - if ( !myObjects.insert( make_pair( obj->GetID(), obj )).second ) + if ( !AddObject( obj ) ) theCommand->Clear(); // already created } // Concatenate( [mesh1, ...], ... ) @@ -903,7 +1083,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) theCommand->SetArg( theCommand->GetNbArgs() + 1, "True" ); } Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() ); - myMeshes.insert( make_pair( mesh->GetID(), mesh )); + AddObject( mesh ); AddMeshAccessorMethod( theCommand ); } else if ( method == "SetName" ) // SetName(obj,name) @@ -947,15 +1127,15 @@ void _pyGen::Flush() map< _pyID, Handle(_pyMesh) >::iterator id_mesh; map< _pyID, Handle(_pyObject) >::iterator id_obj; - list< Handle(_pyHypothesis) >::iterator hyp; + map< _pyID, Handle(_pyHypothesis) >::iterator id_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_hyp = myHypos.begin(); id_hyp != myHypos.end(); ++id_hyp ) + id_hyp->second->SetRemovedFromStudy( false ); for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj ) id_obj->second->SetRemovedFromStudy( false ); } @@ -964,9 +1144,9 @@ void _pyGen::Flush() // let hypotheses find referred objects in order to prevent clearing // not published referred hyps (it's needed for hyps like "LayerDistribution") list< Handle(_pyMesh) > fatherMeshes; - for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) - if ( !hyp->IsNull() ) - (*hyp)->GetReferredMeshesAndGeom( fatherMeshes ); + for ( id_hyp = myHypos.begin(); id_hyp != myHypos.end(); ++id_hyp ) + if ( !id_hyp->second.IsNull() ) + id_hyp->second->GetReferredMeshesAndGeom( fatherMeshes ); } // set myIsPublished = false to all objects depending on // meshes built on a removed geometry @@ -980,18 +1160,23 @@ void _pyGen::Flush() id_mesh->second->Flush(); // Flush hyps - for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) - if ( !hyp->IsNull() ) { - (*hyp)->Flush(); + for ( id_hyp = myHypos.begin(); id_hyp != myHypos.end(); ++id_hyp ) + if ( !id_hyp->second.IsNull() ) { + id_hyp->second->Flush(); // smeshgen.CreateHypothesis() --> smesh.CreateHypothesis() - if ( !(*hyp)->IsWrapped() ) - (*hyp)->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() ); + if ( !id_hyp->second->IsWrapped() ) + id_hyp->second->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() ); } - // Flush other objects - for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj ) - if ( ! id_obj->second.IsNull() ) - id_obj->second->Flush(); + // Flush other objects. 2 times, for objects depending on Flush() of later created objects + std::list< Handle(_pyObject) >::reverse_iterator robj = myOrderedObjects.rbegin(); + for ( ; robj != myOrderedObjects.rend(); ++robj ) + if ( ! robj->IsNull() ) + (*robj)->Flush(); + std::list< Handle(_pyObject) >::iterator obj = myOrderedObjects.begin(); + for ( ; obj != myOrderedObjects.end(); ++obj ) + if ( ! obj->IsNull() ) + (*obj)->Flush(); myLastCommand->SetOrderNb( ++myNbCommands ); myCommands.push_back( myLastCommand ); @@ -1006,23 +1191,23 @@ void _pyGen::Flush() 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 ); - } - } + // 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 ); + // } + // } } //================================================================================ @@ -1037,14 +1222,20 @@ void _pyGen::ClearCommands() 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(); + map< _pyID, Handle(_pyHypothesis) >::iterator id_hyp = myHypos.begin(); + for ( ; id_hyp != myHypos.end(); ++id_hyp ) + if ( !id_hyp->second.IsNull() ) + id_hyp->second->ClearCommands(); + + // Other objects. 2 times, for objects depending on ClearCommands() of later created objects + std::list< Handle(_pyObject) >::reverse_iterator robj = myOrderedObjects.rbegin(); + for ( ; robj != myOrderedObjects.rend(); ++robj ) + if ( ! robj->IsNull() ) + (*robj)->ClearCommands(); + std::list< Handle(_pyObject) >::iterator obj = myOrderedObjects.begin(); + for ( ; obj != myOrderedObjects.end(); ++obj ) + if ( ! obj->IsNull() ) + (*obj)->ClearCommands(); } //================================================================================ @@ -1070,13 +1261,15 @@ void _pyGen::Free() id_obj->second->Free(); myObjects.clear(); - list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); - for ( ; hyp != myHypos.end(); ++hyp ) - if ( !hyp->IsNull() ) - (*hyp)->Free(); + map< _pyID, Handle(_pyHypothesis) >::iterator id_hyp = myHypos.begin(); + for ( ; id_hyp != myHypos.end(); ++id_hyp ) + if ( !id_hyp->second.IsNull() ) + id_hyp->second->Free(); myHypos.clear(); myFile2ExportedMesh.clear(); + + //myKeepAgrCmdsIDs.Print(); } //================================================================================ @@ -1109,12 +1302,14 @@ bool _pyGen::AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const bool _pyGen::AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const { bool added = false; - list< Handle(_pyHypothesis) >::const_iterator hyp = myHypos.begin(); - for ( ; hyp != myHypos.end(); ++hyp ) { - if ( (*hyp)->IsAlgo() && /*(*hyp)->IsWrapped() &&*/ - theCmd->AddAccessorMethod( (*hyp)->GetID(), (*hyp)->AccessorMethod() )) + map< _pyID, Handle(_pyHypothesis) >::const_iterator id_hyp = myHypos.begin(); + for ( ; id_hyp != myHypos.end(); ++id_hyp ) + if ( !id_hyp->second.IsNull() && + id_hyp->second->IsAlgo() && /*(*hyp)->IsWrapped() &&*/ + theCmd->AddAccessorMethod( id_hyp->second->GetID(), + id_hyp->second->AccessorMethod() )) added = true; - } + return added; } @@ -1128,19 +1323,20 @@ bool _pyGen::AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID ) { - list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); - for ( ; hyp != myHypos.end(); ++hyp ) - if ( !hyp->IsNull() && theHypID == (*hyp)->GetID() ) - return *hyp; + map< _pyID, Handle(_pyHypothesis) >::iterator id_hyp = myHypos.find( theHypID ); + if ( id_hyp != myHypos.end() && + !id_hyp->second.IsNull() && + theHypID == id_hyp->second->GetID() ) + return id_hyp->second; return Handle(_pyHypothesis)(); } //================================================================================ /*! - * \brief Find algorithm the created algorithm + * \brief Find algorithm able to create a hypothesis * \param theGeom - The shape ID the algorithm was created on * \param theMesh - The mesh ID that created the algorithm - * \param dim - The algo dimension + * \param theHypothesis - The hypothesis the algorithm sould be able to create * \retval Handle(_pyHypothesis) - The found algo */ //================================================================================ @@ -1148,15 +1344,15 @@ Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID ) Handle(_pyHypothesis) _pyGen::FindAlgo( const _pyID& theGeom, const _pyID& theMesh, const Handle(_pyHypothesis)& theHypothesis ) { - list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin(); - for ( ; hyp != myHypos.end(); ++hyp ) - if ( !hyp->IsNull() && - (*hyp)->IsAlgo() && - theHypothesis->CanBeCreatedBy( (*hyp)->GetAlgoType() ) && - (*hyp)->GetGeom() == theGeom && - (*hyp)->GetMesh() == theMesh ) - return *hyp; - return 0; + map< _pyID, Handle(_pyHypothesis) >::iterator id_hyp = myHypos.begin(); + for ( ; id_hyp != myHypos.end(); ++id_hyp ) + if ( !id_hyp->second.IsNull() && + id_hyp->second->IsAlgo() && + theHypothesis->CanBeCreatedBy( id_hyp->second->GetAlgoType() ) && + id_hyp->second->GetGeom() == theGeom && + id_hyp->second->GetMesh() == theMesh ) + return id_hyp->second; + return Handle(_pyHypothesis)(); } //================================================================================ @@ -1250,6 +1446,37 @@ void _pyGen::setNeighbourCommand( Handle(_pyCommand)& theCmd, (*pos)->SetOrderNb( i++ ); } +//================================================================================ +/*! + * \brief Call _pyFilter.AddUser() if a filter is used as a command arg + */ +//================================================================================ + +// void _pyGen::addFilterUser( Handle(_pyCommand)& theCommand, const Handle(_pyObject)& user ) +// { + // No more needed after adding _pyObject::myArgCommands + +// const char filterPrefix[] = "aFilter0x"; +// if ( theCommand->GetString().Search( filterPrefix ) < 1 ) +// return; + +// for ( int i = theCommand->GetNbArgs(); i > 0; --i ) +// { +// const _AString & arg = theCommand->GetArg( i ); +// // NOT TREATED CASE: arg == "[something, aFilter0x36a2f60]" +// if ( arg.Search( filterPrefix ) != 1 ) +// continue; + +// Handle(_pyFilter) filter = Handle(_pyFilter)::DownCast( FindObject( arg )); +// if ( !filter.IsNull() ) +// { +// filter->AddUser( user ); +// if ( !filter->GetNewID().IsEmpty() ) +// theCommand->SetArg( i, filter->GetNewID() ); +// } +// } +//} + //================================================================================ /*! * \brief Set command be last in list of commands @@ -1291,9 +1518,10 @@ _pyID _pyGen::GenerateNewID( const _pyID& theID ) } while ( myObjectNames.IsBound( aNewID ) ); - myObjectNames.Bind( aNewID, myObjectNames.IsBound( theID ) - ? (myObjectNames.Find( theID ) + _pyID( "_" ) + _pyID( index-1 )) - : _pyID( "A" ) + aNewID ); + if ( myObjectNames.IsBound( theID ) ) + myObjectNames.Bind( aNewID, ( myObjectNames.Find( theID ) + _pyID( "_" ) + _pyID( index-1 ) ) ); + else + myObjectNames.Bind( aNewID, ( _pyID( "A" ) + aNewID ) ); return aNewID; } @@ -1303,18 +1531,65 @@ _pyID _pyGen::GenerateNewID( const _pyID& theID ) */ //================================================================================ -void _pyGen::AddObject( Handle(_pyObject)& theObj ) +bool _pyGen::AddObject( Handle(_pyObject)& theObj ) { - if ( theObj.IsNull() ) return; + if ( theObj.IsNull() ) return false; - if ( theObj->IsKind( STANDARD_TYPE( _pyMesh ))) - myMeshes.insert( make_pair( theObj->GetID(), Handle(_pyMesh)::DownCast( theObj ))); + CheckObjectIsReCreated( theObj ); - else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor ))) - myMeshEditors.insert( make_pair( theObj->GetID(), Handle(_pyMeshEditor)::DownCast( theObj ))); + bool add; + + if ( theObj->IsKind( STANDARD_TYPE( _pyMesh ))) { + add = myMeshes.insert( make_pair( theObj->GetID(), + Handle(_pyMesh)::DownCast( theObj ))).second; + } + else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor ))) { + add = myMeshEditors.insert( make_pair( theObj->GetID(), + Handle(_pyMeshEditor)::DownCast( theObj ))).second; + } + else { + add = myObjects.insert( make_pair( theObj->GetID(), theObj )).second; + if ( add ) myOrderedObjects.push_back( theObj ); + } + return add; +} + +//================================================================================ +/*! + * \brief Erases an existing object with the same ID. This method should be called + * before storing theObj in _pyGen + */ +//================================================================================ + +void _pyGen::CheckObjectIsReCreated( Handle(_pyObject)& theObj ) +{ + if ( theObj.IsNull() || !_pyCommand::IsStudyEntry( theObj->GetID() )) + return; + const bool isHyp = theObj->IsKind( STANDARD_TYPE( _pyHypothesis )); + Handle(_pyObject) existing; + if( isHyp ) + existing = FindHyp( theObj->GetID() ); else - myObjects.insert( make_pair( theObj->GetID(), theObj )); + existing = FindObject( theObj->GetID() ); + if ( !existing.IsNull() && existing != theObj ) + { + existing->SetRemovedFromStudy( true ); + existing->ClearCommands(); + if ( isHyp ) + { + if ( myHypos.count( theObj->GetID() )) + myHypos.erase( theObj->GetID() ); + } + else if ( myMeshes.count( theObj->GetID() )) + { + myMeshes.erase( theObj->GetID() ); + } + else if ( myObjects.count( theObj->GetID() )) + { + myObjects.erase( theObj->GetID() ); + } + } } //================================================================================ @@ -1352,7 +1627,8 @@ Handle(_pyObject) _pyGen::FindObject( const _pyID& theObjID ) const return id_obj->second; } { - map< _pyID, Handle(_pyMesh) >::const_iterator id_obj = myMeshes.find( theObjID ); + _pyGen* me = const_cast< _pyGen* >( this ); + map< _pyID, Handle(_pyMesh) >::iterator id_obj = me->myMeshes.find( theObjID ); if ( id_obj != myMeshes.end() ) return id_obj->second; } @@ -1541,10 +1817,29 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) list< Handle(_pyHypothesis) >::iterator hyp; if ( !myLastComputeCmd.IsNull() ) { - for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) - (*hyp)->ComputeDiscarded( myLastComputeCmd ); + // check if the previously computed mesh has been edited, + // if so then we do not clear the previous Compute() + bool toClear = true; + if ( myLastComputeCmd->GetMethod() == "Compute" ) + { + list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin(); + for ( ; e != myEditors.end() && toClear; ++e ) + { + list< Handle(_pyCommand)>& cmds = (*e)->GetProcessedCmds(); + list< Handle(_pyCommand) >::reverse_iterator cmd = cmds.rbegin(); + if ( cmd != cmds.rend() && + (*cmd)->GetOrderNb() > myLastComputeCmd->GetOrderNb() ) + toClear = false; + } + } + if ( toClear ) + { + // clear hyp commands called before myLastComputeCmd + for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp ) + (*hyp)->ComputeDiscarded( myLastComputeCmd ); - myLastComputeCmd->Clear(); + myLastComputeCmd->Clear(); + } } myLastComputeCmd = theCommand; @@ -1588,7 +1883,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) } } // ---------------------------------------------------------------------- - else if ( method == "GetSubMesh" ) { // collect submeshes of the mesh + else if ( method == "GetSubMesh" ) { // collect sub-meshes of the mesh Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetResultValue() ); if ( !subMesh.IsNull() ) { subMesh->SetCreator( this ); @@ -1596,6 +1891,10 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) } } // ---------------------------------------------------------------------- + else if ( method == "GetSubMeshes" ) { // clear as the command does nothing (0023156) + theCommand->Clear(); + } + // ---------------------------------------------------------------------- else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO ) myAddHypCmds.push_back( theCommand ); // set mesh to hypo @@ -1610,7 +1909,8 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) // ---------------------------------------------------------------------- else if ( method == "CreateGroup" || method == "CreateGroupFromGEOM" || - method == "CreateGroupFromFilter" ) + method == "CreateGroupFromFilter" || + method == "CreateDimGroup" ) { Handle(_pyGroup) group = new _pyGroup( theCommand ); myGroups.push_back( group ); @@ -1624,7 +1924,7 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) TCollection_AsciiString grIDs = theCommand->GetResultValue(); list< _pyID > idList = theCommand->GetStudyEntries( grIDs ); list< _pyID >::iterator grID = idList.begin(); - const int nbGroupsBefore = myGroups.size(); + const size_t nbGroupsBefore = myGroups.size(); Handle(_pyObject) obj; for ( ; grID != idList.end(); ++grID ) { @@ -1676,9 +1976,17 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) // ---------------------------------------------------------------------- else if ( theCommand->MethodStartsFrom( "Export" )) { - if ( method == "ExportToMED" || // ExportToMED() --> ExportMED() - method == "ExportToMEDX" ) { // ExportToMEDX() --> ExportMED() + if ( method == "ExportToMED" || // ExportToMED() --> ExportMED() + method == "ExportToMEDX" ) // ExportToMEDX() --> ExportMED() + { theCommand->SetMethod( "ExportMED" ); + if ( theCommand->GetNbArgs() == 5 ) + { + // ExportToMEDX(...,autoDimension) -> ExportToMEDX(...,meshPart=None,autoDimension) + _AString autoDimension = theCommand->GetArg( 5 ); + theCommand->SetArg( 5, "None" ); + theCommand->SetArg( 6, autoDimension ); + } } else if ( method == "ExportCGNS" ) { // ExportCGNS(part, ...) -> ExportCGNS(..., part) @@ -1701,11 +2009,11 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) // // remove "PartTo" from the method TCollection_AsciiString newMethod = method; - newMethod.Remove( 7, 6 ); + newMethod.Remove( /*where=*/7, /*howmany=*/6 ); theCommand->SetMethod( newMethod ); - // make the 1st arg be the last one + // make the 1st arg be the last one (or last but three for ExportMED()) _pyID partID = theCommand->GetArg( 1 ); - int nbArgs = theCommand->GetNbArgs(); + int nbArgs = theCommand->GetNbArgs() - 3 * (newMethod == "ExportMED"); for ( int i = 2; i <= nbArgs; ++i ) theCommand->SetArg( i-1, theCommand->GetArg( i )); theCommand->SetArg( nbArgs, partID ); @@ -1742,10 +2050,18 @@ void _pyMesh::Process( const Handle(_pyCommand)& theCommand ) { addCmd = *cmd; cmd = addHypCmds.erase( cmd ); - if ( !theGen->IsToKeepAllCommands() ) { + if ( !theGen->IsToKeepAllCommands() /*&& CanClear()*/ ) { addCmd->Clear(); theCommand->Clear(); } + else + { + // mesh.AddHypothesis(geom, hyp) --> mesh.AddHypothesis(hyp, geom=0) + addCmd->RemoveArgs(); + addCmd->SetArg( 1, hypID ); + if ( isLocal ) + addCmd->SetArg( 2, geomID ); + } } else { @@ -1805,8 +2121,8 @@ bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand ) if ( sameMethods.empty() ) { const char * names[] = { "ExportDAT","ExportUNV","ExportSTL","ExportSAUV", "RemoveGroup","RemoveGroupWithContents", - "GetGroups","UnionGroups","IntersectGroups","CutGroups","GetLog","GetId","ClearLog", - "GetStudyId","HasDuplicatedGroupNamesMED","GetMEDMesh","NbNodes","NbElements", + "GetGroups","UnionGroups","IntersectGroups","CutGroups","CreateDimGroup","GetLog","GetId", + "ClearLog","GetStudyId","HasDuplicatedGroupNamesMED","GetMEDMesh","NbNodes","NbElements", "NbEdges","NbEdgesOfOrder","NbFaces","NbFacesOfOrder","NbTriangles", "NbTrianglesOfOrder","NbQuadrangles","NbQuadranglesOfOrder","NbPolygons","NbVolumes", "NbVolumesOfOrder","NbTetras","NbTetrasOfOrder","NbHexas","NbHexasOfOrder", @@ -1815,6 +2131,7 @@ bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand ) "GetSubMeshElementsId","GetSubMeshNodesId","GetSubMeshElementType","Dump","GetNodeXYZ", "GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes", "GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces", + "GetElemFaceNodes", "GetFaceNormal", "FindElementByNodes", "IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", "SetAutoColor", "GetAutoColor", "Clear", "ConvertToStandalone", "GetMeshOrder", "SetMeshOrder" ,"" }; // <- mark of end @@ -2090,29 +2407,38 @@ _pyMeshEditor::_pyMeshEditor(const Handle(_pyCommand)& theCreationCmd): void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) { - // 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 + // Names of SMESH_MeshEditor methods fully equal to methods of the python class Mesh, so + // commands calling these methods are converted to calls of Mesh methods without + // additional modifs, only object is changed from MeshEditor to Mesh. static TStringSet sameMethods; if ( sameMethods.empty() ) { const char * names[] = { - "RemoveElements","RemoveNodes","RemoveOrphanNodes","AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace","AddBall", - "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","MoveNode", "MoveClosestNodeToPoint", - "InverseDiag","DeleteDiag","Reorient","ReorientObject", + "RemoveElements","RemoveNodes","RemoveOrphanNodes", + "AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace","AddBall", + "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces", + "MoveNode", "MoveClosestNodeToPoint", + "InverseDiag","DeleteDiag","Reorient","ReorientObject","Reorient2DBy3D", "TriToQuad","TriToQuadObject", "QuadTo4Tri", "SplitQuad","SplitQuadObject", "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject", "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements", "RotationSweep","RotationSweepObject","RotationSweepObject1D","RotationSweepObject2D", - "ExtrusionSweep","AdvancedExtrusion","ExtrusionSweepObject","ExtrusionSweepObject1D","ExtrusionSweepObject2D", - "ExtrusionAlongPath","ExtrusionAlongPathObject","ExtrusionAlongPathX", - "ExtrusionAlongPathObject1D","ExtrusionAlongPathObject2D", + "ExtrusionSweep","AdvancedExtrusion","ExtrusionSweepObject","ExtrusionSweepObject1D", + "ExtrusionByNormal", "ExtrusionSweepObject2D","ExtrusionAlongPath","ExtrusionAlongPathObject", + "ExtrusionAlongPathX","ExtrusionAlongPathObject1D","ExtrusionAlongPathObject2D", + "ExtrusionSweepObjects","RotationSweepObjects","ExtrusionAlongPathObjects", "Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject", - "FindCoincidentNodes",/*"FindCoincidentNodesOnPart",*/"MergeNodes","FindEqualElements", + "FindCoincidentNodes","MergeNodes","FindEqualElements", "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders", + "FindCoincidentFreeBorders", "SewCoincidentFreeBorders", "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes", "GetLastCreatedElems", "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh","TranslateObjectMakeMesh", "Scale","ScaleMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh", - "MakeBoundaryElements", "SplitVolumesIntoTetra" + "MakeBoundaryElements", "SplitVolumesIntoTetra","SplitHexahedraIntoPrisms", + "DoubleElements","DoubleNodes","DoubleNode","DoubleNodeGroup","DoubleNodeGroups", + "DoubleNodeElem","DoubleNodeElemInRegion","DoubleNodeElemGroup", + "DoubleNodeElemGroupInRegion","DoubleNodeElemGroups","DoubleNodeElemGroupsInRegion", + "DoubleNodesOnGroupBoundaries","CreateFlatElementsOnFacesGroups","CreateHoleSkin" ,"" }; // <- mark of the end sameMethods.Insert( names ); } @@ -2364,6 +2690,8 @@ Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& th hyp->SetConvMethodAndType( "SetGrid", "Cartesian_3D"); for ( int iArg = 0; iArg < 4; ++iArg ) hyp->setCreationArg( iArg+1, "[]"); + hyp->AddAccumulativeMethod( "SetGrid" ); + hyp->AddAccumulativeMethod( "SetGridSpacing" ); } else { @@ -2480,7 +2808,7 @@ void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand) myArgCommands.push_back( theCommand ); usedCommand = true; while ( crMethod.myArgs.size() < i+1 ) - crMethod.myArgs.push_back( "[]" ); + crMethod.myArgs.push_back( "None" ); crMethod.myArgs[ i ] = theCommand->GetArg( crMethod.myArgNb[i] ); } } @@ -2799,7 +3127,7 @@ void _pyHypothesis::setCreationArg( const int argNb, const _AString& arg ) { if ( myCurCrMethod ) { - while ( myCurCrMethod->myArgs.size() < argNb ) + while ( (int) myCurCrMethod->myArgs.size() < argNb ) myCurCrMethod->myArgs.push_back( "None" ); if ( arg.IsEmpty() ) myCurCrMethod->myArgs[ argNb-1 ] = "None"; @@ -2822,9 +3150,11 @@ void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand) { // CartesianParameters3D hyp - if ( theCommand->GetMethod() == "SetSizeThreshold" ) + if ( theCommand->GetMethod() == "SetSizeThreshold" || + theCommand->GetMethod() == "SetToAddEdges" ) { - setCreationArg( 4, theCommand->GetArg( 1 )); + int iEdges = ( theCommand->GetMethod().Value( 4 ) == 'T' ); + setCreationArg( 4+iEdges, theCommand->GetArg( 1 )); myArgCommands.push_back( theCommand ); return; } @@ -2846,7 +3176,9 @@ void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand) myCurCrMethod->myArgs[ iArg ] += "]"; } myArgCommands.push_back( theCommand ); - rememberCmdOfParameter( theCommand ); + //rememberCmdOfParameter( theCommand ); -- these commands are marked as + // accumulative, else, if the creation + // is not converted, commands for axes 1 and 2 are lost return; } } @@ -2862,7 +3194,7 @@ void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand) for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth ) { CreationMethod& crMethod = type2meth->second; - while ( crMethod.myArgs.size() < i+1 ) + while ( (int) crMethod.myArgs.size() < i+1 ) crMethod.myArgs.push_back( "[]" ); crMethod.myArgs[ i ] = theCommand->GetArg( 1 ); // arg value } @@ -2881,19 +3213,34 @@ void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand) void _pyComplexParamHypo::Flush() { + list < Handle(_pyCommand) >::iterator cmd; if ( IsWrapped() ) { - list < Handle(_pyCommand) >::iterator cmd = myUnusedCommands.begin(); - for ( ; cmd != myUnusedCommands.end(); ++cmd ) + for ( cmd = myUnusedCommands.begin(); cmd != myUnusedCommands.end(); ++cmd ) if ((*cmd)->GetMethod() == "SetObjectEntry" ) (*cmd)->Clear(); } + + // if ( GetAlgoType() == "Cartesian_3D" ) + // { + // _pyID algo = myCreationCmd->GetObject(); + // for ( cmd = myProcessedCmds.begin(); cmd != myProcessedCmds.end(); ++cmd ) + // { + // if ( IsWrapped() ) + // { + // StructToList( *cmd, /*checkMethod=*/false ); + // const _AString & method = (*cmd)->GetMethod(); + // if ( method == "SetFixedPoint" ) + // (*cmd)->SetObject( algo ); + // } + // } + // } } //================================================================================ /*! * \brief Convert methods of 1D hypotheses to my own methods - * \param theCommand - The called hypothesis method + * \param theCommand - The called hypothesis method */ //================================================================================ @@ -3129,28 +3476,31 @@ bool _pySegmentLengthAroundVertexHyp::Addition2Creation( const Handle(_pyCommand _pyID vertex = theCmd->GetArg( 1 ); - // the problem here is that segment algo will not be found + // the problem here is that segment algo can be not found // by pyHypothesis::Addition2Creation() for , so we try to find // geometry where segment algorithm is assigned - Handle(_pyHypothesis) algo; _pyID geom = vertex; + Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMeshID, this ); while ( algo.IsNull() && !geom.IsEmpty()) { // try to find geom as a father of geom = FatherID( geom ); algo = theGen->FindAlgo( geom, theMeshID, this ); } - if ( algo.IsNull() ) + if ( algo.IsNull() || geom.IsEmpty() ) return false; // also possible to find geom as brother of veretex... + // set geom instead of vertex theCmd->SetArg( 1, geom ); - // set vertex as a second arg - if ( myCurCrMethod->myArgs.size() < 1) setCreationArg( 1, "1" ); // :( - setCreationArg( 2, vertex ); - // mesh.AddHypothesis(vertex, SegmentLengthAroundVertex) --> - // theMeshID.LengthNearVertex( length, vertex ) - return _pyHypothesis::Addition2Creation( theCmd, theMeshID ); + // SegmentLengthAroundVertex = Regular_1D.LengthNearVertex( length ) + if ( _pyHypothesis::Addition2Creation( theCmd, theMeshID )) + { + // set vertex as a second arg + theCmd->SetArg( 2, vertex ); + + return true; + } } return false; } @@ -3196,12 +3546,13 @@ bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd, */ //================================================================================ -int _pyCommand::GetBegPos( int thePartIndex ) +int _pyCommand::GetBegPos( int thePartIndex ) const { if ( IsEmpty() ) return EMPTY; if ( myBegPos.Length() < thePartIndex ) return UNKNOWN; + ASSERT( thePartIndex > 0 ); return myBegPos( thePartIndex ); } @@ -3217,6 +3568,7 @@ void _pyCommand::SetBegPos( int thePartIndex, int thePosition ) { while ( myBegPos.Length() < thePartIndex ) myBegPos.Append( UNKNOWN ); + ASSERT( thePartIndex > 0 ); myBegPos( thePartIndex ) = thePosition; } @@ -3230,11 +3582,11 @@ void _pyCommand::SetBegPos( int thePartIndex, int thePosition ) TCollection_AsciiString _pyCommand::GetIndentation() { int end = 1; - if ( GetBegPos( RESULT_IND ) == UNKNOWN ) - GetWord( myString, end, true ); - else - end = GetBegPos( RESULT_IND ); - return myString.SubString( 1, end - 1 ); + //while ( end <= Length() && isblank( myString.Value( end ))) + //ANA: isblank() function isn't provided in VC2010 compiler + while ( end <= Length() && ( myString.Value( end ) == ' ' || myString.Value( end ) == '\t') ) + ++end; + return ( end == 1 ) ? _AString("") : myString.SubString( 1, end - 1 ); } //================================================================================ @@ -3274,16 +3626,8 @@ const TCollection_AsciiString & _pyCommand::GetResultValue() int _pyCommand::GetNbResultValues() { - int nb = 0; - int begPos = 1; - int endPos = myString.Location( "=", 1, Length() ); - while ( begPos < endPos ) - { - _AString str = GetWord( myString, begPos, true ); - begPos = begPos+ str.Length(); - nb++; - } - return (nb-1); + GetResultValue(1); + return myResults.Length(); } @@ -3294,32 +3638,38 @@ int _pyCommand::GetNbResultValues() * \retval const TCollection_AsciiString & - ResultValue with res index substring */ //================================================================================ -TCollection_AsciiString _pyCommand::GetResultValue(int res) +const _AString& _pyCommand::GetResultValue(int res) { - int begPos = 1; - if ( SkipSpaces( myString, begPos ) && myString.Value( begPos ) == '[' ) - ++begPos; // skip [, else the whole list is returned - int endPos = myString.Location( "=", 1, Length() ); - int Nb=0; - while ( begPos < endPos) { - _AString result = GetWord( myString, begPos, true ); - begPos = begPos + result.Length(); - Nb++; - if(res == Nb) { - result.RemoveAll('['); - result.RemoveAll(']'); - return result; + if ( GetResultValue().IsEmpty() ) + return theEmptyString; + + if ( myResults.IsEmpty() ) + { + int begPos = 1; + if ( SkipSpaces( myRes, begPos ) && myRes.Value( begPos ) == '[' ) + ++begPos; // skip [, else the whole list is returned + while ( begPos < myRes.Length() ) { + _AString result = GetWord( myRes, begPos, true ); + begPos += result.Length(); + // if(res == Nb) { + // result.RemoveAll('['); + // result.RemoveAll(']'); + // return result; + // } + // if(Nb>res) + // break; + myResults.Append( result ); } - if(Nb>res) - break; } + if ( res > 0 && res <= myResults.Length() ) + return myResults( res ); return theEmptyString; } //================================================================================ /*! * \brief Return substring of python command looking like ResVal = Object.Meth() - * \retval const TCollection_AsciiString & - Object substring + * \retval const TCollection_AsciiString & - Object substring */ //================================================================================ @@ -3328,7 +3678,7 @@ const TCollection_AsciiString & _pyCommand::GetObject() if ( GetBegPos( OBJECT_IND ) == UNKNOWN ) { // beginning - int begPos = GetBegPos( RESULT_IND ) + myRes.Length(); + int begPos = GetBegPos( RESULT_IND ); if ( begPos < 1 ) { begPos = myString.Location( "=", 1, Length() ) + 1; // is '=' in the string argument (for example, name) or not @@ -3345,6 +3695,9 @@ const TCollection_AsciiString & _pyCommand::GetObject() if ( nb1 % 2 != 0 || nb2 % 2 != 0 ) begPos = 1; } + else { + begPos += myRes.Length(); + } myObj = GetWord( myString, begPos, true ); if ( begPos != EMPTY ) { @@ -3388,12 +3741,15 @@ const TCollection_AsciiString & _pyCommand::GetMethod() if ( GetBegPos( METHOD_IND ) == UNKNOWN ) { // beginning - int begPos = GetBegPos( OBJECT_IND ) + myObj.Length(); + int begPos = GetBegPos( OBJECT_IND ); bool forward = true; if ( begPos < 1 ) { begPos = myString.Location( "(", 1, Length() ) - 1; forward = false; } + else { + begPos += myObj.Length(); + } // store myMeth = GetWord( myString, begPos, forward ); SetBegPos( METHOD_IND, begPos ); @@ -3402,6 +3758,20 @@ const TCollection_AsciiString & _pyCommand::GetMethod() return myMeth; } +//================================================================================ +/*! + * \brief Returns true if there are brackets after the method + */ +//================================================================================ + +bool _pyCommand::IsMethodCall() +{ + if ( GetMethod().IsEmpty() ) + return false; + const char* s = myString.ToCString() + GetBegPos( METHOD_IND ) + myMeth.Length() - 1; + return ( s[0] == '(' || s[1] == '(' ); +} + //================================================================================ /*! * \brief Return substring of python command looking like ResVal = Obj.Meth(Arg1,...) @@ -3485,6 +3855,24 @@ const TCollection_AsciiString & _pyCommand::GetArg( int index ) return myArgs( index ); } +//================================================================================ +/*! + * \brief Return position where arguments begin + */ +//================================================================================ + +int _pyCommand::GetArgBeginning() const +{ + int pos = GetBegPos( ARG1_IND ); + if ( pos == UNKNOWN ) + { + pos = GetBegPos( METHOD_IND ) + myMeth.Length(); + if ( pos < 1 ) + pos = myString.Location( "(", 4, Length() ); // 4 = strlen("b.c(") + } + return pos; +} + //================================================================================ /*! * \brief Check if char is a word part @@ -3588,6 +3976,26 @@ bool _pyCommand::IsStudyEntry( const TCollection_AsciiString& str ) return nbColons > 2 && str.Length()-nbColons > 2; } +//================================================================================ +/*! + * \brief Returns true if the string looks like an object ID but not like a list, + * string, command etc. + */ +//================================================================================ + +bool _pyCommand::IsID( const TCollection_AsciiString& str ) +{ + if ( str.Length() < 1 ) return false; + + const char* s = str.ToCString(); + + for ( int i = 0; i < str.Length(); ++i ) + if ( !IsIDChar( s[i] )) + return false; + + return true; +} + //================================================================================ /*! * \brief Finds entries in a sting @@ -3747,11 +4155,11 @@ 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 + 1 ); - if ( begPos != UNKNOWN ) - SetBegPos( iPart + 1, begPos + 1 ); + int begPos = GetBegPos( iPart ); + if ( begPos != UNKNOWN && begPos != EMPTY ) + SetBegPos( iPart, begPos + 1 ); } } } @@ -3799,7 +4207,8 @@ bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod // check that theObjectID is not just a part of a longer ID int afterEnd = beg + theObjectID.Length(); Standard_Character c = myString.Value( afterEnd ); - if ( !isalnum( c ) && c != ':' ) { + if ( !IsIDChar( c )) + { // check if accessor method already present if ( c != '.' || myString.Location( (char*) theAcsMethod, afterEnd, Length() ) != afterEnd+1) { @@ -3816,7 +4225,7 @@ bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod added = true; } } - beg = afterEnd; // is a part - next search + beg = afterEnd; // is a part -> next search } return added; } @@ -3891,23 +4300,89 @@ _pyID _pyObject::FatherID(const _pyID & childID) //================================================================================ /*! - * \brief SelfEraser erases creation command if no more it's commands invoked + * \brief SelfEraser erases creation command if none of it's commands invoked + * (e.g. filterManager) or it's not used as a command argument (e.g. a filter) */ //================================================================================ -void _pySelfEraser::Flush() +_pySelfEraser::_pySelfEraser(const Handle(_pyCommand)& theCreationCmd) + :_pyObject(theCreationCmd), myIgnoreOwnCalls(false) +{ + myIsPublished = true; // prevent clearing as a not published + theGen->KeepAgrCmds( GetID() ); // ask to fill myArgCmds +} + +//================================================================================ +/*! + * \brief SelfEraser erases creation command if none of it's commands invoked + * (e.g. filterManager) or it's not used as a command argument (e.g. a filter) + */ +//================================================================================ + +bool _pySelfEraser::CanClear() { - int nbCalls = GetNbCalls(); - if ( nbCalls > 0 ) + bool toErase = false; + if ( myIgnoreOwnCalls ) // check if this obj is used as argument + { + int nbArgUses = 0; + list< Handle(_pyCommand) >::iterator cmd = myArgCmds.begin(); + for ( ; cmd != myArgCmds.end(); ++cmd ) + nbArgUses += IsAliveCmd( *cmd ); + + toErase = ( nbArgUses < 1 ); + } + else { - // ignore cleared commands + int nbCalls = 0; std::list< Handle(_pyCommand) >& cmds = GetProcessedCmds(); - std::list< Handle(_pyCommand) >::const_iterator cmd = cmds.begin(); - for ( ; cmd != cmds.end(); ++cmd ) - nbCalls -= (*cmd)->IsEmpty(); + std::list< Handle(_pyCommand) >::iterator cmd = cmds.begin(); + for ( ; cmd != cmds.end(); ) + // check of cmd emptiness is not enough as object can change + if (( *cmd )->GetString().Search( GetID() ) > 0 ) + ++nbCalls, ++cmd; + else + cmd = cmds.erase( cmd ); // save the cmd from clearing + + toErase = ( nbCalls < 1 ); + } + return toErase; +} + +//================================================================================ +/*! + * \brief Check if a command is or can be cleared + */ +//================================================================================ + +bool _pySelfEraser::IsAliveCmd( const Handle(_pyCommand)& theCmd ) +{ + if ( theCmd->IsEmpty() ) + return false; + + if ( !theGen->IsToKeepAllCommands() ) + { + const _pyID& objID = theCmd->GetObject(); + Handle( _pyObject ) obj = theGen->FindObject( objID ); + if ( !obj.IsNull() ) + return !obj->CanClear(); + } + return true; +} + +//================================================================================ +/*! + * \brief SelfEraser erases creation command if none of it's commands invoked + * (e.g. filterManager) or it's not used as a command argument (e.g. a filter) + */ +//================================================================================ + +void _pySelfEraser::Flush() +{ + if ( CanClear() ) + { + myIsPublished = false; + _pyObject::ClearCommands(); } - if ( nbCalls < 1 ) - GetCreationCmd()->Clear(); } //================================================================================ @@ -3916,10 +4391,12 @@ void _pySelfEraser::Flush() */ //================================================================================ -_pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd): +_pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd, bool toKeepAgrCmds): _pyObject(theCreationCmd) { myMesh = ObjectToMesh( theGen->FindObject( theCreationCmd->GetObject() )); + if ( toKeepAgrCmds ) + theGen->KeepAgrCmds( GetID() ); // ask to fill myArgCmds } //================================================================================ @@ -3930,39 +4407,40 @@ _pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd): 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 ); + return false; +// // 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 ); } //================================================================================ @@ -3974,7 +4452,6 @@ bool _pySubMesh::CanBeArgOfMethod(const _AString& theMethodName) void _pySubMesh::Process( const Handle(_pyCommand)& theCommand ) { _pyObject::Process(theCommand); // count calls of Process() - GetCreationCmd()->AddDependantCmd( theCommand ); } //================================================================================ @@ -3985,11 +4462,17 @@ void _pySubMesh::Process( const Handle(_pyCommand)& theCommand ) void _pySubMesh::Flush() { - if ( GetNbCalls() == 0 ) // move to the end of all commands + if ( GetNbCalls() == 0 && myArgCmds.empty() ) // move to the end of all commands theGen->GetLastCommand()->AddDependantCmd( GetCreationCmd() ); else if ( !myCreator.IsNull() ) // move to be just after creator myCreator->GetCreationCmd()->AddDependantCmd( GetCreationCmd() ); + + // move sub-mesh usage after creation cmd + list< Handle(_pyCommand) >::iterator cmd = myArgCmds.begin(); + for ( ; cmd != myArgCmds.end(); ++cmd ) + if ( !(*cmd)->IsEmpty() ) + GetCreationCmd()->AddDependantCmd( *cmd ); } //================================================================================ @@ -3999,7 +4482,7 @@ void _pySubMesh::Flush() //================================================================================ _pyGroup::_pyGroup(const Handle(_pyCommand)& theCreationCmd, const _pyID & id) - :_pySubMesh(theCreationCmd) + :_pySubMesh(theCreationCmd, /*toKeepAgrCmds=*/false) { if ( !id.IsEmpty() ) setID( id ); @@ -4044,7 +4527,7 @@ _pyGroup::_pyGroup(const Handle(_pyCommand)& theCreationCmd, const _pyID & id) { if ( !filter->GetNewID().IsEmpty() ) theCreationCmd->SetArg( 3, filter->GetNewID() ); - filter->AddUser( this ); + //filter->AddUser( this ); } myFilter = filter; } @@ -4072,7 +4555,9 @@ bool _pyGroup::CanClear() if ( IsInStudy() ) return false; - if ( !myCanClearCreationCmd && myCreationCmd->GetMethod() == "GetGroups" ) + if ( !myCanClearCreationCmd && + !myCreationCmd.IsNull() && + myCreationCmd->GetMethod() == "GetGroups" ) { TCollection_AsciiString grIDs = myCreationCmd->GetResultValue(); list< _pyID > idList = myCreationCmd->GetStudyEntries( grIDs ); @@ -4158,6 +4643,7 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) makeGroupCmd->SetMethod( "MakeGroupByFilter" ); makeGroupCmd->SetArg( 1, name ); makeGroupCmd->SetArg( 2, idSource ); + filter->AddArgCmd( makeGroupCmd ); } } else if ( theCommand->GetMethod() == "SetFilter" ) @@ -4182,8 +4668,8 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) } } - if ( !filter.IsNull() ) - filter->AddUser( this ); + // if ( !filter.IsNull() ) + // filter->AddUser( this ); theGen->AddMeshAccessorMethod( theCommand ); } @@ -4197,7 +4683,7 @@ void _pyGroup::Process( const Handle(_pyCommand)& theCommand) void _pyGroup::Flush() { if ( !theGen->IsToKeepAllCommands() && - myCreationCmd && !myCanClearCreationCmd ) + !myCreationCmd.IsNull() && !myCanClearCreationCmd ) { myCreationCmd.Nullify(); // this way myCreationCmd won't be cleared } @@ -4212,6 +4698,8 @@ void _pyGroup::Flush() _pyFilter::_pyFilter(const Handle(_pyCommand)& theCreationCmd, const _pyID& newID/*=""*/) :_pyObject(theCreationCmd), myNewID( newID ) { + //myIsPublished = true; // prevent clearing as a not published + theGen->KeepAgrCmds( GetID() ); // ask to fill myArgCmds } //================================================================================ @@ -4244,8 +4732,13 @@ void _pyFilter::Process( const Handle(_pyCommand)& theCommand) theCommand->SetObject( SMESH_2smeshpy::GenName() ); theCommand->SetMethod( "GetFilterFromCriteria" ); - // Clear aFilterManager.CreateFilter() + // Swap "aFilterManager.CreateFilter()" and "smesh.GetFilterFromCriteria(criteria)" GetCreationCmd()->Clear(); + GetCreationCmd()->GetString() = theCommand->GetString(); + theCommand->Clear(); + theCommand->AddDependantCmd( GetCreationCmd() ); + // why swap? -- it's needed + //GetCreationCmd()->Clear(); } else if ( theCommand->GetMethod() == "SetMesh" ) { @@ -4259,13 +4752,31 @@ void _pyFilter::Process( const Handle(_pyCommand)& theCommand) //================================================================================ /*! - * \brief Set new filter name to the creation command + * \brief Set new filter name to the creation command and to myArgCmds */ //================================================================================ void _pyFilter::Flush() { - if ( !myNewID.IsEmpty() && !GetCreationCmd()->IsEmpty() ) + if ( myNewID.IsEmpty() ) return; + + list< Handle(_pyCommand) >::iterator cmd = myArgCmds.begin(); + for ( ; cmd != myArgCmds.end(); ++cmd ) + if ( !(*cmd)->IsEmpty() ) + { + _AString cmdStr = (*cmd)->GetString(); + _AString id = GetID(); + int pos = cmdStr.Search( id ); + if ( pos > 0 ) + { + cmdStr.Remove( pos, id.Length() ); + cmdStr.Insert( pos, myNewID ); + } + (*cmd)->Clear(); + (*cmd)->GetString() = cmdStr; + } + + if ( !GetCreationCmd()->IsEmpty() ) GetCreationCmd()->SetResultValue( myNewID ); } @@ -4275,14 +4786,17 @@ void _pyFilter::Flush() */ //================================================================================ -bool _pyFilter::CanClear() +bool _pyObject::CanClear() { - list< Handle(_pyObject) >::iterator obj = myUsers.begin(); - for ( ; obj != myUsers.end(); ++obj ) - if ( !(*obj)->CanClear() ) - return false; - - return true; + list< Handle(_pyCommand) >::iterator cmd = myArgCmds.begin(); + for ( ; cmd != myArgCmds.end(); ++cmd ) + if ( !(*cmd)->IsEmpty() ) + { + Handle(_pyObject) obj = theGen->FindObject( (*cmd)->GetObject() ); + if ( !obj.IsNull() && !obj->CanClear() ) + return false; + } + return ( !myIsPublished ); } //================================================================================ @@ -4447,3 +4961,219 @@ _pyHypothesisReader::GetHypothesis(const _AString& hypType, } return resHyp; } + +//================================================================================ +/*! + * \brief Adds an object ID to some family of IDs with a common prefix + * \param [in] str - the object ID + * \return bool - \c false if \a str does not have the same prefix as \a this family + * (for internal usage) + */ +//================================================================================ + +bool _pyStringFamily::Add( const char* str ) +{ + if ( strncmp( str, _prefix.ToCString(), _prefix.Length() ) != 0 ) + return false; // expected prefix is missing + + str += _prefix.Length(); // skip _prefix + + // try to add to some of child falimies + std::list< _pyStringFamily >::iterator itSub = _subFams.begin(); + for ( ; itSub != _subFams.end(); ++itSub ) + if ( itSub->Add( str )) + return true; + + // no suitable family found - add str to _strings or create a new child family + + // look for a proper place within sorted _strings + std::list< _AString >::iterator itStr = _strings.begin(); + while ( itStr != _strings.end() && itStr->IsLess( str )) + ++itStr; + if ( itStr != _strings.end() && itStr->IsEqual( str )) + return true; // same ID already kept + + const int minPrefixSize = 4; + + // count "smaller" strings with the same prefix + std::list< _AString >::iterator itLess = itStr; --itLess; + int nbLess = 0; + for ( ; itLess != _strings.end(); --itLess ) + if ( strncmp( str, itLess->ToCString(), minPrefixSize ) == 0 ) + ++nbLess; + else + break; + ++itLess; + // count "greater" strings with the same prefix + std::list< _AString >::iterator itMore = itStr; + int nbMore = 0; + for ( ; itMore != _strings.end(); ++itMore ) + if ( strncmp( str, itMore->ToCString(), minPrefixSize ) == 0 ) + ++nbMore; + else + break; + --itMore; + if ( nbLess + nbMore > 1 ) // ------- ADD a NEW CHILD FAMILY ------------- + { + // look for a maximal prefix length + // int lessPrefSize = 3, morePrefSize = 3; + // if ( nbLess > 0 ) + // while( itLess->ToCString()[ lessPrefSize ] == str[ lessPrefSize ] ) + // ++lessPrefSize; + // if ( nbMore > 0 ) + // while ( itMore->ToCString()[ morePrefSize ] == str[ morePrefSize ] ) + // ++morePrefSize; + // int prefixSize = 3; + // if ( nbLess == 0 ) + // prefixSize = morePrefSize; + // else if ( nbMore == 0 ) + // prefixSize = lessPrefSize; + // else + // prefixSize = Min( lessPrefSize, morePrefSize ); + int prefixSize = minPrefixSize; + _AString newPrefix ( str, prefixSize ); + + // look for a proper place within _subFams sorted by _prefix + for ( itSub = _subFams.begin(); itSub != _subFams.end(); ++itSub ) + if ( !itSub->_prefix.IsLess( newPrefix )) + break; + + // add the new _pyStringFamily + itSub = _subFams.insert( itSub, _pyStringFamily()); + _pyStringFamily& newSubFam = *itSub; + newSubFam._prefix = newPrefix; + + // pass this->_strings to newSubFam._strings + for ( itStr = itLess; nbLess > 0; --nbLess, ++itStr ) + newSubFam._strings.push_back( itStr->ToCString() + prefixSize ); + newSubFam._strings.push_back( str + prefixSize ); + for ( ; nbMore > 0; --nbMore, ++itStr ) + newSubFam._strings.push_back( itStr->ToCString() + prefixSize ); + + _strings.erase( itLess, ++itMore ); + } + else // to few string to make a family fot them + { + _strings.insert( itStr, str ); + } + return true; +} + +//================================================================================ +/*! + * \brief Finds an object ID in the command + * \param [in] longStr - the command string + * \param [out] subStr - the found object ID + * \return bool - \c true if the object ID found + */ +//================================================================================ + +bool _pyStringFamily::IsInArgs( Handle( _pyCommand)& cmd, std::list<_AString>& subStr ) +{ + const _AString& longStr = cmd->GetString(); + const char* s = longStr.ToCString(); + + // look in _subFams + std::list< _pyStringFamily >::iterator itSub = _subFams.begin(); + int nbFound = 0, pos, len, from, argBeg = cmd->GetArgBeginning(); + if ( argBeg < 4 || argBeg > longStr.Length() ) + return false; + for ( ; itSub != _subFams.end(); ++itSub ) + { + from = argBeg; + while (( pos = longStr.Location( itSub->_prefix, from, longStr.Length() ))) + if (( len = itSub->isIn( s + pos-1 + itSub->_prefix.Length() )) >= 0 ) + { + subStr.push_back( _AString( s + pos-1, len + itSub->_prefix.Length() )); + from = pos + len + itSub->_prefix.Length(); + nbFound++; + } + else + { + from += itSub->_prefix.Length(); + } + } + // look among _strings + std::list< _AString >::iterator itStr = _strings.begin(); + for ( ; itStr != _strings.end(); ++itStr ) + if (( pos = longStr.Location( *itStr, argBeg, longStr.Length() ))) + // check that object ID does not continue after len + if ( !cmd->IsIDChar( s[ pos + itStr->Length() - 1 ] )) + { + subStr.push_back( *itStr ); + nbFound++; + } + return nbFound; +} + +//================================================================================ +/*! + * \brief Return remainder length of the object ID after my _prefix + * \param [in] str - remainder of the command after my _prefix + * \return int - length of the object ID or -1 if not found + */ +//================================================================================ + +int _pyStringFamily::isIn( const char* str ) +{ + std::list< _pyStringFamily >::iterator itSub = _subFams.begin(); + int len = -1; + for ( ; itSub != _subFams.end(); ++itSub ) + { + int cmp = strncmp( str, itSub->_prefix.ToCString(), itSub->_prefix.Length() ); + if ( cmp == 0 ) + { + if (( len = itSub->isIn( str + itSub->_prefix.Length() )) >= 0 ) + return itSub->_prefix.Length() + len; + } + else if ( cmp > 0 ) + break; + } + if ( !_strings.empty() ) + { + std::list< _AString >::iterator itStr = _strings.begin(); + bool firstEmpty = itStr->IsEmpty(); + if ( firstEmpty ) + ++itStr, len = 0; + for ( ; itStr != _strings.end(); ++itStr ) + { + int cmp = strncmp( str, itStr->ToCString(), itStr->Length() ); + if ( cmp == 0 ) + { + len = itStr->Length(); + break; + } + else if ( cmp < 0 ) + { + break; + } + } + + // check that object ID does not continue after len + if ( len >= 0 && _pyCommand::IsIDChar( str[len] )) + len = -1; + } + + return len; +} + +//================================================================================ +/*! + * \brief DEBUG + */ +//================================================================================ + +void _pyStringFamily::Print( int level ) +{ + cout << string( level, ' ' ) << "prefix = '" << _prefix << "' : "; + std::list< _AString >::iterator itStr = _strings.begin(); + for ( ; itStr != _strings.end(); ++itStr ) + cout << *itStr << " | "; + cout << endl; + std::list< _pyStringFamily >::iterator itSub = _subFams.begin(); + for ( ; itSub != _subFams.end(); ++itSub ) + itSub->Print( level + 1 ); + if ( level == 0 ) + cout << string( 70, '-' ) << endl; +} +