Back to index

salome-smesh  6.5.0
SMESH_2smeshpy.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
00024 // File      : SMESH_2smeshpy.cxx
00025 // Created   : Fri Nov 18 13:20:10 2005
00026 // Author    : Edward AGAPOV (eap)
00027 //
00028 #include "SMESH_2smeshpy.hxx"
00029 
00030 #include "utilities.h"
00031 #include "SMESH_PythonDump.hxx"
00032 #include "SMESH_NoteBook.hxx"
00033 #include "SMESH_Filter_i.hxx"
00034 
00035 #include <Resource_DataMapOfAsciiStringAsciiString.hxx>
00036 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
00037 
00038 #include "SMESH_Gen_i.hxx"
00039 /* SALOME headers that include CORBA headers that include windows.h
00040  * that defines GetObject symbol as GetObjectA should stand before SALOME headers
00041  * that declare methods named GetObject - to apply the same rules of GetObject renaming
00042  * and thus to avoid mess with GetObject symbol on Windows */
00043 
00044 #include <LDOMParser.hxx>
00045 
00046 #ifdef WNT
00047 #include <windows.h>
00048 #else
00049 #include <unistd.h>
00050 #endif
00051 
00052 
00053 IMPLEMENT_STANDARD_HANDLE (_pyObject          ,Standard_Transient);
00054 IMPLEMENT_STANDARD_HANDLE (_pyCommand         ,Standard_Transient);
00055 IMPLEMENT_STANDARD_HANDLE (_pyHypothesisReader,Standard_Transient);
00056 IMPLEMENT_STANDARD_HANDLE (_pyGen             ,_pyObject);
00057 IMPLEMENT_STANDARD_HANDLE (_pyMesh            ,_pyObject);
00058 IMPLEMENT_STANDARD_HANDLE (_pySubMesh         ,_pyObject);
00059 IMPLEMENT_STANDARD_HANDLE (_pyMeshEditor      ,_pyObject);
00060 IMPLEMENT_STANDARD_HANDLE (_pyHypothesis      ,_pyObject);
00061 IMPLEMENT_STANDARD_HANDLE (_pySelfEraser      ,_pyObject);
00062 IMPLEMENT_STANDARD_HANDLE (_pyGroup           ,_pyObject);
00063 IMPLEMENT_STANDARD_HANDLE (_pyFilter          ,_pyObject);
00064 IMPLEMENT_STANDARD_HANDLE (_pyAlgorithm       ,_pyHypothesis);
00065 IMPLEMENT_STANDARD_HANDLE (_pyComplexParamHypo,_pyHypothesis);
00066 IMPLEMENT_STANDARD_HANDLE (_pyNumberOfSegmentsHyp,_pyHypothesis);
00067 
00068 IMPLEMENT_STANDARD_RTTIEXT(_pyObject          ,Standard_Transient);
00069 IMPLEMENT_STANDARD_RTTIEXT(_pyCommand         ,Standard_Transient);
00070 IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesisReader,Standard_Transient);
00071 IMPLEMENT_STANDARD_RTTIEXT(_pyGen             ,_pyObject);
00072 IMPLEMENT_STANDARD_RTTIEXT(_pyMesh            ,_pyObject);
00073 IMPLEMENT_STANDARD_RTTIEXT(_pySubMesh         ,_pyObject);
00074 IMPLEMENT_STANDARD_RTTIEXT(_pyMeshEditor      ,_pyObject);
00075 IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis      ,_pyObject);
00076 IMPLEMENT_STANDARD_RTTIEXT(_pySelfEraser      ,_pyObject);
00077 IMPLEMENT_STANDARD_RTTIEXT(_pyGroup           ,_pyObject);
00078 IMPLEMENT_STANDARD_RTTIEXT(_pyFilter          ,_pyObject);
00079 IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm       ,_pyHypothesis);
00080 IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis);
00081 IMPLEMENT_STANDARD_RTTIEXT(_pyNumberOfSegmentsHyp,_pyHypothesis);
00082 IMPLEMENT_STANDARD_RTTIEXT(_pyLayerDistributionHypo,_pyHypothesis);
00083 IMPLEMENT_STANDARD_RTTIEXT(_pySegmentLengthAroundVertexHyp,_pyHypothesis);
00084 
00085 using namespace std;
00086 using SMESH::TPythonDump;
00087 
00092 static Handle(_pyGen) theGen;
00093 
00094 static TCollection_AsciiString theEmptyString;
00095 
00096 //#define DUMP_CONVERSION
00097 
00098 #if !defined(_DEBUG_) && defined(DUMP_CONVERSION)
00099 #undef DUMP_CONVERSION
00100 #endif
00101 
00102 
00103 namespace {
00104 
00105   //================================================================================
00109   //================================================================================
00110 
00111   struct TStringSet: public set<TCollection_AsciiString>
00112   {
00116     void Insert(const char* names[]) {
00117       for ( int i = 0; names[i][0] ; ++i )
00118         insert( (char*) names[i] );
00119     }
00123     bool Contains(const TCollection_AsciiString& name ) {
00124       return find( name ) != end();
00125     }
00126   };
00127 
00128   //================================================================================
00132   //================================================================================
00133 
00134   Handle(_pyMesh) ObjectToMesh( const Handle( _pyObject )& obj )
00135   {
00136     if ( !obj.IsNull() )
00137     {
00138       if ( obj->IsKind( STANDARD_TYPE( _pyMesh )))
00139         return Handle(_pyMesh)::DownCast( obj );
00140       else if ( obj->IsKind( STANDARD_TYPE( _pySubMesh )))
00141         return Handle(_pySubMesh)::DownCast( obj )->GetMesh();
00142       else if ( obj->IsKind( STANDARD_TYPE( _pyGroup )))
00143         return Handle(_pyGroup)::DownCast( obj )->GetMesh();
00144     }
00145     return Handle(_pyMesh)();
00146   }
00147 
00148   //================================================================================
00152   //================================================================================
00153 
00154   void CheckObjectPresence( const Handle(_pyCommand)& cmd, set<_pyID> & presentObjects)
00155   {
00156     for ( int iArg = cmd->GetNbArgs(); iArg; --iArg )
00157     {
00158       const _pyID& arg = cmd->GetArg( iArg );
00159       if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' )
00160         continue;
00161       list< _pyID > idList = cmd->GetStudyEntries( arg );
00162       list< _pyID >::iterator id = idList.begin();
00163       for ( ; id != idList.end(); ++id )
00164         if ( !theGen->IsGeomObject( *id ) && !presentObjects.count( *id ))
00165         {
00166           cmd->Comment();
00167           cmd->GetString() += " ### " ;
00168           cmd->GetString() += *id + " has not been yet created";
00169           return;
00170         }
00171     }
00172     const _pyID& obj = cmd->GetObject();
00173     if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj ))
00174     {
00175       cmd->Comment();
00176       cmd->GetString() += " ### not created object" ;
00177     }
00178     const _pyID& result = cmd->GetResultValue();
00179     if ( result.IsEmpty() || result.Value( 1 ) == '"' || result.Value( 1 ) == '\'' )
00180       return;
00181     list< _pyID > idList = cmd->GetStudyEntries( result );
00182     list< _pyID >::iterator id = idList.begin();
00183     for ( ; id != idList.end(); ++id )
00184       presentObjects.insert( *id );
00185   }
00186 
00187   //================================================================================
00191   //================================================================================
00192 
00193   void fixFunctorType( TCollection_AsciiString& Type,
00194                        TCollection_AsciiString& Compare,
00195                        TCollection_AsciiString& UnaryOp,
00196                        TCollection_AsciiString& BinaryOp )
00197   {
00198     // The problem is that dumps of old studies created using filters becomes invalid
00199     // when new items are inserted in the enum SMESH::FunctorType since values
00200     // of this enum are dumped as integer values.
00201     // This function corrects enum values of old studies given as args (Type,Compare,...)
00202     // We can find out how to correct them by value of BinaryOp which can have only two
00203     // values: FT_Undefined or FT_LogicalNOT.
00204     // Hereafter is the history of the enum SMESH::FunctorType since v3.0.0
00205     // where PythonDump appeared
00206     // v 3.0.0: FT_Undefined == 25
00207     // v 3.1.0: FT_Undefined == 26, new items:
00208     //   - FT_Volume3D              = 7
00209     // v 4.1.2: FT_Undefined == 27, new items:
00210     //   - FT_BelongToGenSurface    = 17
00211     // v 5.1.1: FT_Undefined == 32, new items:
00212     //   - FT_FreeNodes             = 10
00213     //   - FT_FreeFaces             = 11
00214     //   - FT_LinearOrQuadratic     = 23
00215     //   - FT_GroupColor            = 24
00216     //   - FT_ElemGeomType          = 25
00217     // v 5.1.5: FT_Undefined == 33, new items:
00218     //   - FT_CoplanarFaces         = 26
00219     // v 6.2.0: FT_Undefined == 39, new items:
00220     //   - FT_MaxElementLength2D    = 8
00221     //   - FT_MaxElementLength3D    = 9
00222     //   - FT_BareBorderVolume      = 25
00223     //   - FT_BareBorderFace        = 26
00224     //   - FT_OverConstrainedVolume = 27
00225     //   - FT_OverConstrainedFace   = 28
00226     // v 6.5.0: FT_Undefined == 43, new items:
00227     //   - FT_EqualNodes            = 14
00228     //   - FT_EqualEdges            = 15
00229     //   - FT_EqualFaces            = 16
00230     //   - FT_EqualVolumes          = 17
00231 
00232     typedef map< int, vector< int > > TUndef2newItems;
00233     static TUndef2newItems undef2newItems;
00234     if ( undef2newItems.empty() )
00235     {
00236       undef2newItems[ 26 ].push_back( 7 );
00237       undef2newItems[ 27 ].push_back( 17 );
00238       { int items[] = { 10, 11, 23, 24, 25 };
00239         undef2newItems[ 32 ].assign( items, items+5 ); }
00240       undef2newItems[ 33 ].push_back( 26 );
00241       { int items[] = { 8, 9, 25, 26, 27, 28 };
00242         undef2newItems[ 39 ].assign( items, items+6 ); }
00243       { int items[] = { 14, 15, 16, 17 };
00244         undef2newItems[ 43 ].assign( items, items+4 ); }
00245     }
00246 
00247     int iType     = Type.IntegerValue();
00248     int iCompare  = Compare.IntegerValue();
00249     int iUnaryOp  = UnaryOp.IntegerValue();
00250     int iBinaryOp = BinaryOp.IntegerValue();
00251 
00252     // find out integer value of FT_Undefined at the moment of dump
00253     int oldUndefined = iBinaryOp;
00254     if ( iBinaryOp < iUnaryOp ) // BinaryOp was FT_LogicalNOT
00255       oldUndefined += 3;
00256 
00257     // apply history to args
00258     TUndef2newItems::const_iterator undef_items =
00259       undef2newItems.upper_bound( oldUndefined );
00260     if ( undef_items != undef2newItems.end() )
00261     {
00262       int* pArg[4] = { &iType, &iCompare, &iUnaryOp, &iBinaryOp };
00263       for ( ; undef_items != undef2newItems.end(); ++undef_items )
00264       {
00265         const vector< int > & addedItems = undef_items->second;
00266         for ( size_t i = 0; i < addedItems.size(); ++i )
00267           for ( int iArg = 0; iArg < 4; ++iArg )
00268           {
00269             int& arg = *pArg[iArg];
00270             if ( arg >= addedItems[i] )
00271               arg++;
00272           }
00273       }
00274       Type     = TCollection_AsciiString( iType     );
00275       Compare  = TCollection_AsciiString( iCompare  );
00276       UnaryOp  = TCollection_AsciiString( iUnaryOp  );
00277       BinaryOp = TCollection_AsciiString( iBinaryOp );
00278     }
00279   }
00280 }
00281 
00282 //================================================================================
00292 //================================================================================
00293 
00294 TCollection_AsciiString
00295 SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString&            theScript,
00296                               Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
00297                               Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
00298                               SALOMEDS::Study_ptr&                      theStudy,
00299                               const bool                                theToKeepAllCommands)
00300 {
00301   theGen = new _pyGen( theEntry2AccessorMethod, theObjectNames, theStudy, theToKeepAllCommands );
00302 
00303   // split theScript into separate commands
00304 
00305   SMESH_NoteBook * aNoteBook = new SMESH_NoteBook();
00306 
00307   int from = 1, end = theScript.Length(), to;
00308   while ( from < end && ( to = theScript.Location( "\n", from, end )))
00309   {
00310     if ( to != from )
00311         // cut out and store a command
00312         aNoteBook->AddCommand( theScript.SubString( from, to - 1 ));
00313       from = to + 1;
00314   }
00315 
00316   aNoteBook->ReplaceVariables();
00317 
00318   TCollection_AsciiString aNoteScript = aNoteBook->GetResultScript();
00319   delete aNoteBook;
00320   aNoteBook = 0;
00321 
00322   // split theScript into separate commands
00323   from = 1, end = aNoteScript.Length();
00324   while ( from < end && ( to = aNoteScript.Location( "\n", from, end )))
00325   {
00326     if ( to != from )
00327       // cut out and store a command
00328       theGen->AddCommand( aNoteScript.SubString( from, to - 1 ));
00329     from = to + 1;
00330   }
00331 
00332   // finish conversion
00333   theGen->Flush();
00334 #ifdef DUMP_CONVERSION
00335   MESSAGE_BEGIN ( std::endl << " ######## RESULT ######## " << std::endl<< std::endl );
00336 #endif
00337 
00338   // clean commmands of removed objects depending on myIsPublished flag
00339   theGen->ClearCommands();
00340 
00341   // reorder commands after conversion
00342   list< Handle(_pyCommand) >::iterator cmd;
00343   bool orderChanges;
00344   do {
00345     orderChanges = false;
00346     for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
00347       if ( (*cmd)->SetDependentCmdsAfter() )
00348         orderChanges = true;
00349   } while ( orderChanges );
00350 
00351   // concat commands back into a script
00352   TCollection_AsciiString aScript, aPrevCmd;
00353   set<_pyID> createdObjects;
00354   for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
00355   {
00356 #ifdef DUMP_CONVERSION
00357     MESSAGE_ADD ( "## COM " << (*cmd)->GetOrderNb() << ": "<< (*cmd)->GetString() << std::endl );
00358 #endif
00359     if ( !(*cmd)->IsEmpty() && aPrevCmd != (*cmd)->GetString()) {
00360       CheckObjectPresence( *cmd, createdObjects );
00361       aPrevCmd = (*cmd)->GetString();
00362       aScript += "\n";
00363       aScript += aPrevCmd;
00364     }
00365   }
00366   aScript += "\n";
00367 
00368   theGen->Free();
00369   theGen.Nullify();
00370 
00371   return aScript;
00372 }
00373 
00374 //================================================================================
00378 //================================================================================
00379 
00380 _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
00381                Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
00382                SALOMEDS::Study_ptr&                      theStudy,
00383                const bool                                theToKeepAllCommands)
00384   : _pyObject( new _pyCommand( "", 0 )),
00385     myNbCommands( 0 ),
00386     myID2AccessorMethod( theEntry2AccessorMethod ),
00387     myObjectNames( theObjectNames ),
00388     myNbFilters( 0 ),
00389     myToKeepAllCommands( theToKeepAllCommands ),
00390     myStudy( SALOMEDS::Study::_duplicate( theStudy )),
00391     myGeomIDNb(0), myGeomIDIndex(-1)
00392 {
00393   // make that GetID() to return TPythonDump::SMESHGenName()
00394   GetCreationCmd()->Clear();
00395   GetCreationCmd()->GetString() = TPythonDump::SMESHGenName();
00396   GetCreationCmd()->GetString() += "=";
00397 
00398   // Find 1st digit of study entry by which a GEOM object differs from a SMESH object
00399   if ( !theObjectNames.IsEmpty() && !CORBA::is_nil( theStudy ))
00400   {
00401     // find a GEOM entry
00402     _pyID geomID;
00403     SALOMEDS::SComponent_var geomComp = theStudy->FindComponent("GEOM");
00404     if ( geomComp->_is_nil() ) return;
00405     CORBA::String_var entry = geomComp->GetID();
00406     geomID = entry.in();
00407 
00408     // find a SMESH entry
00409     _pyID smeshID;
00410     Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString e2n( theObjectNames );
00411     for ( ; e2n.More() && smeshID.IsEmpty(); e2n.Next() )
00412       if ( _pyCommand::IsStudyEntry( e2n.Key() ))
00413         smeshID = e2n.Key();
00414 
00415     // find 1st difference between smeshID and geomID
00416     if ( !geomID.IsEmpty() && !smeshID.IsEmpty() )
00417       for ( int i = 1; i <= geomID.Length() && i <= smeshID.Length(); ++i )
00418         if ( geomID.Value( i ) != smeshID.Value( i ))
00419         {
00420           myGeomIDNb = geomID.Value( i );
00421           myGeomIDIndex = i;
00422         }
00423   }
00424 }
00425 
00426 //================================================================================
00430 //================================================================================
00431 
00432 const char* _pyGen::AccessorMethod() const
00433 {
00434   return SMESH_2smeshpy::GenName();
00435 }
00436 
00437 //================================================================================
00442 //================================================================================
00443 
00444 Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand)
00445 {
00446   // store theCommand in the sequence
00447   myCommands.push_back( new _pyCommand( theCommand, ++myNbCommands ));
00448 
00449   Handle(_pyCommand) aCommand = myCommands.back();
00450 #ifdef DUMP_CONVERSION
00451   MESSAGE ( "## COM " << myNbCommands << ": "<< aCommand->GetString() );
00452 #endif
00453 
00454   const _pyID& objID = aCommand->GetObject();
00455 
00456   if ( objID.IsEmpty() )
00457     return aCommand;
00458 
00459   // Find an object to process theCommand
00460 
00461   // SMESH_Gen method?
00462   if ( objID == this->GetID() || objID == SMESH_2smeshpy::GenName())
00463   {
00464     this->Process( aCommand );
00465     return aCommand;
00466   }
00467 
00468   // SMESH_Mesh method?
00469   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( objID );
00470   if ( id_mesh != myMeshes.end() )
00471   {
00472     //id_mesh->second->AddProcessedCmd( aCommand );
00473 
00474     // check for mesh editor object
00475     if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation
00476       _pyID editorID = aCommand->GetResultValue();
00477       Handle(_pyMeshEditor) editor = new _pyMeshEditor( aCommand );
00478       myMeshEditors.insert( make_pair( editorID, editor ));
00479       return aCommand;
00480     }
00481     // check for SubMesh objects
00482     else if ( aCommand->GetMethod() == "GetSubMesh" ) { // SubMesh creation
00483       _pyID subMeshID = aCommand->GetResultValue();
00484       Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand );
00485       myObjects.insert( make_pair( subMeshID, subMesh ));
00486     }
00487 
00488     id_mesh->second->Process( aCommand );
00489     id_mesh->second->AddProcessedCmd( aCommand );
00490     return aCommand;
00491   }
00492 
00493   // SMESH_MeshEditor method?
00494   map< _pyID, Handle(_pyMeshEditor) >::iterator id_editor = myMeshEditors.find( objID );
00495   if ( id_editor != myMeshEditors.end() )
00496   {
00497     const TCollection_AsciiString& method = aCommand->GetMethod();
00498 
00499     // some commands of SMESH_MeshEditor create meshes and groups
00500     _pyID meshID, groups;
00501     if ( method.Search("MakeMesh") != -1 )
00502       meshID = aCommand->GetResultValue();
00503     else if ( method == "MakeBoundaryMesh")
00504       meshID = aCommand->GetResultValue(1);
00505     else if ( method == "MakeBoundaryElements")
00506       meshID = aCommand->GetResultValue(2);
00507 
00508     if ( method.Search("MakeGroups") != -1  ||
00509          method == "ExtrusionAlongPathX"    ||
00510          method == "ExtrusionAlongPathObjX" ||
00511          method == "DoubleNodeGroupNew"     ||
00512          method == "DoubleNodeGroupsNew"    ||
00513          method == "DoubleNodeElemGroupNew" ||
00514          method == "DoubleNodeElemGroupsNew"||
00515          method == "DoubleNodeElemGroup2New"||
00516          method == "DoubleNodeElemGroups2New"
00517          )
00518       groups = aCommand->GetResultValue();
00519     else if ( method == "MakeBoundaryMesh" )
00520       groups = aCommand->GetResultValue(2);
00521     else if ( method == "MakeBoundaryElements")
00522       groups = aCommand->GetResultValue(3);
00523 
00524     id_editor->second->Process( aCommand );
00525     id_editor->second->AddProcessedCmd( aCommand );
00526 
00527     if ( !meshID.IsEmpty() &&
00528          !myMeshes.count( meshID ) &&
00529          aCommand->IsStudyEntry( meshID ))
00530     {
00531       TCollection_AsciiString processedCommand = aCommand->GetString();
00532       Handle(_pyMesh) mesh = new _pyMesh( aCommand, meshID );
00533       myMeshes.insert( make_pair( meshID, mesh ));
00534       aCommand->Clear();
00535       aCommand->GetString() = processedCommand; // discard changes made by _pyMesh
00536     }
00537     if ( !groups.IsEmpty() )
00538     {
00539       if ( !aCommand->IsStudyEntry( meshID ))
00540         meshID = id_editor->second->GetMesh();
00541       Handle(_pyMesh) mesh = myMeshes[ meshID ];
00542 
00543       list< _pyID > idList = aCommand->GetStudyEntries( groups );
00544       list< _pyID >::iterator grID = idList.begin();
00545       for ( ; grID != idList.end(); ++grID )
00546         if ( !myObjects.count( *grID ))
00547         {
00548           Handle(_pyGroup) group = new _pyGroup( aCommand, *grID );
00549           AddObject( group );
00550           if ( !mesh.IsNull() ) mesh->AddGroup( group );
00551         }
00552     }
00553     return aCommand;
00554   } // SMESH_MeshEditor methods
00555 
00556   // SMESH_Hypothesis method?
00557   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
00558   for ( ; hyp != myHypos.end(); ++hyp )
00559     if ( !(*hyp)->IsAlgo() && objID == (*hyp)->GetID() ) {
00560       (*hyp)->Process( aCommand );
00561       (*hyp)->AddProcessedCmd( aCommand );
00562       return aCommand;
00563     }
00564 
00565   // aFilterManager.CreateFilter() ?
00566   if ( aCommand->GetMethod() == "CreateFilter" )
00567   {
00568     // Set a more human readable name to a filter
00569     // aFilter0x7fbf6c71cfb0 -> aFilter_nb
00570     _pyID newID, filterID = aCommand->GetResultValue();
00571     int pos = filterID.Search( "0x" );
00572     if ( pos > 1 )
00573       newID = (filterID.SubString(1,pos-1) + "_") + _pyID( ++myNbFilters );
00574 
00575     Handle(_pyObject) filter( new _pyFilter( aCommand, newID ));
00576     AddObject( filter );
00577   }
00578 
00579   // other object method?
00580   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.find( objID );
00581   if ( id_obj != myObjects.end() ) {
00582     id_obj->second->Process( aCommand );
00583     id_obj->second->AddProcessedCmd( aCommand );
00584     return aCommand;
00585   }
00586 
00587   // Add access to a wrapped mesh
00588   AddMeshAccessorMethod( aCommand );
00589 
00590   // Add access to a wrapped algorithm
00591   //  AddAlgoAccessorMethod( aCommand ); // ??? what if algo won't be wrapped at all ???
00592 
00593   // PAL12227. PythonDump was not updated at proper time; result is
00594   //     aCriteria.append(SMESH.Filter.Criterion(17,26,0,'L1',26,25,1e-07,SMESH.EDGE,-1))
00595   // TypeError: __init__() takes exactly 11 arguments (10 given)
00596   const char wrongCommand[] = "SMESH.Filter.Criterion(";
00597   if ( int beg = theCommand.Location( wrongCommand, 1, theCommand.Length() ))
00598   {
00599     _pyCommand tmpCmd( theCommand.SubString( beg, theCommand.Length() ), -1);
00600     // there must be 10 arguments, 5-th arg ThresholdID is missing,
00601     const int wrongNbArgs = 9, missingArg = 5;
00602     if ( tmpCmd.GetNbArgs() == wrongNbArgs )
00603     {
00604       for ( int i = wrongNbArgs; i > missingArg; --i )
00605         tmpCmd.SetArg( i + 1, tmpCmd.GetArg( i ));
00606       tmpCmd.SetArg(  missingArg, "''");
00607       aCommand->GetString().Trunc( beg - 1 );
00608       aCommand->GetString() += tmpCmd.GetString();
00609     }
00610     // IMP issue 0021014
00611     // set GetCriterion(elementType,CritType,Compare,Treshold,UnaryOp,BinaryOp,Tolerance)
00612     //                  1           2        3       4        5       6        7
00613     // instead of "SMESH.Filter.Criterion(
00614     // Type,Compare,Threshold,ThresholdStr,ThresholdID,UnaryOp,BinaryOp,Tolerance,TypeOfElement,Precision)
00615     // 1    2       3         4            5           6       7        8         9             10
00616     // in order to avoid the problem of type mismatch of long and FunctorType
00617     const TCollection_AsciiString
00618       SMESH("SMESH."), dfltFunctor = "SMESH.FT_Undefined", dftlTol = "1e-07", dftlPreci = "-1";
00619     TCollection_AsciiString
00620       Type          = aCommand->GetArg(1),  // long
00621       Compare       = aCommand->GetArg(2),  // long
00622       Threshold     = aCommand->GetArg(3),  // double
00623       ThresholdStr  = aCommand->GetArg(4),  // string
00624       ThresholdID   = aCommand->GetArg(5),  // string
00625       UnaryOp       = aCommand->GetArg(6),  // long
00626       BinaryOp      = aCommand->GetArg(7),  // long
00627       Tolerance     = aCommand->GetArg(8),  // double
00628       TypeOfElement = aCommand->GetArg(9),  // ElementType
00629       Precision     = aCommand->GetArg(10); // long
00630     fixFunctorType( Type, Compare, UnaryOp, BinaryOp );
00631     Type     = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( Type.IntegerValue() ));
00632     Compare  = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( Compare.IntegerValue() ));
00633     UnaryOp  = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( UnaryOp.IntegerValue() ));
00634     BinaryOp = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( BinaryOp.IntegerValue() ));
00635 
00636     aCommand->RemoveArgs();
00637     aCommand->SetObject( SMESH_2smeshpy::GenName() );
00638     aCommand->SetMethod( "GetCriterion" );
00639 
00640     aCommand->SetArg( 1, TypeOfElement );
00641     aCommand->SetArg( 2, Type );
00642     aCommand->SetArg( 3, Compare );
00643 
00644     if ( Type == "SMESH.FT_ElemGeomType" && Threshold.IsIntegerValue() )
00645     {
00646       // set SMESH.GeometryType instead of a numerical Threshold
00647       const char* types[SMESH::Geom_POLYHEDRA+1] = {
00648         "Geom_POINT", "Geom_EDGE", "Geom_TRIANGLE", "Geom_QUADRANGLE", "Geom_POLYGON",
00649         "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_HEXAGONAL_PRISM",
00650         "Geom_POLYHEDRA"
00651       };
00652       int iGeom = Threshold.IntegerValue();
00653       if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 )
00654         Threshold = SMESH + types[ iGeom ];
00655     }
00656     if ( ThresholdID.Length() != 2 && ThresholdStr.Length() != 2) // not '' or ""
00657       aCommand->SetArg( 4, ThresholdID.SubString( 2, ThresholdID.Length()-1 )); // shape entry
00658     else if ( ThresholdStr.Length() != 2 )
00659       aCommand->SetArg( 4, ThresholdStr );
00660     else if ( ThresholdID.Length() != 2 )
00661       aCommand->SetArg( 4, ThresholdID );
00662     else
00663       aCommand->SetArg( 4, Threshold );
00664     // find the last not default arg
00665     int lastDefault = 8;
00666     if ( Tolerance == dftlTol ) {
00667       lastDefault = 7;
00668       if ( BinaryOp == dfltFunctor ) {
00669         lastDefault = 6;
00670         if ( UnaryOp == dfltFunctor )
00671           lastDefault = 5;
00672       }
00673     }
00674     if ( 5 < lastDefault ) aCommand->SetArg( 5, UnaryOp );
00675     if ( 6 < lastDefault ) aCommand->SetArg( 6, BinaryOp );
00676     if ( 7 < lastDefault ) aCommand->SetArg( 7, Tolerance );
00677     if ( Precision != dftlPreci )
00678     {
00679       TCollection_AsciiString crit = aCommand->GetResultValue();
00680       aCommand->GetString() += "; ";
00681       aCommand->GetString() += crit + ".Precision = " + Precision;
00682     }
00683   }
00684   return aCommand;
00685 }
00686 
00687 //================================================================================
00692 //================================================================================
00693 
00694 void _pyGen::Process( const Handle(_pyCommand)& theCommand )
00695 {
00696   // there are methods to convert:
00697   // CreateMesh( shape )
00698   // Concatenate( [mesh1, ...], ... )
00699   // CreateHypothesis( theHypType, theLibName )
00700   // Compute( mesh, geom )
00701   // Evaluate( mesh, geom )
00702   // mesh creation
00703   TCollection_AsciiString method = theCommand->GetMethod();
00704 
00705   if ( method == "CreateMesh" || method == "CreateEmptyMesh")
00706   {
00707     Handle(_pyMesh) mesh = new _pyMesh( theCommand );
00708     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
00709     return;
00710   }
00711   if ( method == "CreateMeshesFromUNV" ||
00712        method == "CreateMeshesFromSTL" ||
00713        method == "CreateMeshesFromCGNS" ||
00714        method == "CopyMesh" )
00715   {
00716     Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
00717     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
00718     return;
00719   }
00720   if( method == "CreateMeshesFromMED" || method == "CreateMeshesFromSAUV")
00721   {
00722     for(int ind = 0;ind<theCommand->GetNbResultValues();ind++)
00723     {
00724       _pyID meshID = theCommand->GetResultValue(ind+1);
00725       if ( !theCommand->IsStudyEntry( meshID ) ) continue;
00726       Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue(ind+1));
00727       myMeshes.insert( make_pair( mesh->GetID(), mesh ));
00728     }
00729   }
00730 
00731   // CreateHypothesis()
00732   if ( method == "CreateHypothesis" )
00733   {
00734     // issue 199929, remove standard library name (default parameter)
00735     const TCollection_AsciiString & aLibName = theCommand->GetArg( 2 );
00736     if ( aLibName.Search( "StdMeshersEngine" ) != -1 ) {
00737       // keep first argument
00738       TCollection_AsciiString arg = theCommand->GetArg( 1 );
00739       theCommand->RemoveArgs();
00740       theCommand->SetArg( 1, arg );
00741     }
00742 
00743     myHypos.push_back( _pyHypothesis::NewHypothesis( theCommand ));
00744     return;
00745   }
00746 
00747   // smeshgen.Compute( mesh, geom ) --> mesh.Compute()
00748   if ( method == "Compute" )
00749   {
00750     const _pyID& meshID = theCommand->GetArg( 1 );
00751     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
00752     if ( id_mesh != myMeshes.end() ) {
00753       theCommand->SetObject( meshID );
00754       theCommand->RemoveArgs();
00755       id_mesh->second->Process( theCommand );
00756       id_mesh->second->AddProcessedCmd( theCommand );
00757       return;
00758     }
00759   }
00760 
00761   // smeshgen.Evaluate( mesh, geom ) --> mesh.Evaluate(geom)
00762   if ( method == "Evaluate" )
00763   {
00764     const _pyID& meshID = theCommand->GetArg( 1 );
00765     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
00766     if ( id_mesh != myMeshes.end() ) {
00767       theCommand->SetObject( meshID );
00768       _pyID geom = theCommand->GetArg( 2 );
00769       theCommand->RemoveArgs();
00770       theCommand->SetArg( 1, geom );
00771       id_mesh->second->AddProcessedCmd( theCommand );
00772       return;
00773     }
00774   }
00775 
00776   // objects erasing creation command if no more it's commands invoked:
00777   // SMESH_Pattern, FilterManager
00778   if ( method == "GetPattern" ||
00779        method == "CreateFilterManager" ||
00780        method == "CreateMeasurements" ) {
00781     Handle(_pyObject) obj = new _pySelfEraser( theCommand );
00782     if ( !myObjects.insert( make_pair( obj->GetID(), obj )).second )
00783       theCommand->Clear(); // already created
00784   }
00785   // Concatenate( [mesh1, ...], ... )
00786   else if ( method == "Concatenate" || method == "ConcatenateWithGroups")
00787   {
00788     if ( method == "ConcatenateWithGroups" ) {
00789       theCommand->SetMethod( "Concatenate" );
00790       theCommand->SetArg( theCommand->GetNbArgs() + 1, "True" );
00791     }
00792     Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
00793     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
00794     AddMeshAccessorMethod( theCommand );
00795   }
00796   else if ( method == "SetName" ) // SetName(obj,name)
00797   {
00798     // store theCommand as one of object commands to erase it along with the object
00799     const _pyID& objID = theCommand->GetArg( 1 );
00800     Handle(_pyObject) obj = FindObject( objID );
00801     if ( !obj.IsNull() )
00802       obj->AddProcessedCmd( theCommand );
00803   }
00804 
00805   // Replace name of SMESH_Gen
00806 
00807   // names of SMESH_Gen methods fully equal to methods defined in smesh.py
00808   static TStringSet smeshpyMethods;
00809   if ( smeshpyMethods.empty() ) {
00810     const char * names[] =
00811       { "SetEmbeddedMode","IsEmbeddedMode","SetCurrentStudy","GetCurrentStudy",
00812         "GetPattern","GetSubShapesId",
00813         "" }; // <- mark of array end
00814     smeshpyMethods.Insert( names );
00815   }
00816   if ( smeshpyMethods.Contains( theCommand->GetMethod() ))
00817     // smeshgen.Method() --> smesh.Method()
00818     theCommand->SetObject( SMESH_2smeshpy::SmeshpyName() );
00819   else
00820     // smeshgen.Method() --> smesh.smesh.Method()
00821     theCommand->SetObject( SMESH_2smeshpy::GenName() );
00822 }
00823 
00824 //================================================================================
00828 //================================================================================
00829 
00830 void _pyGen::Flush()
00831 {
00832   // create an empty command
00833   myLastCommand = new _pyCommand();
00834 
00835   map< _pyID, Handle(_pyMesh) >::iterator id_mesh;
00836   map< _pyID, Handle(_pyObject) >::iterator id_obj;
00837   list< Handle(_pyHypothesis) >::iterator hyp;
00838 
00839   if ( IsToKeepAllCommands() ) // historical dump
00840   {
00841     // set myIsPublished = true to all objects
00842     for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
00843       id_mesh->second->SetRemovedFromStudy( false );
00844     for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
00845       (*hyp)->SetRemovedFromStudy( false );
00846     for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj )
00847       id_obj->second->SetRemovedFromStudy( false );
00848   }
00849   else
00850   {
00851     // let hypotheses find referred objects in order to prevent clearing
00852     // not published referred hyps (it's needed for hyps like "LayerDistribution")
00853     list< Handle(_pyMesh) > fatherMeshes;
00854     for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
00855       if ( !hyp->IsNull() )
00856         (*hyp)->GetReferredMeshesAndGeom( fatherMeshes );
00857   }
00858   // set myIsPublished = false to all objects depending on
00859   // meshes built on a removed geometry
00860   for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
00861     if ( id_mesh->second->IsNotGeomPublished() )
00862       id_mesh->second->SetRemovedFromStudy( true );
00863 
00864   // Flush meshes
00865   for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
00866     if ( ! id_mesh->second.IsNull() )
00867       id_mesh->second->Flush();
00868 
00869   // Flush hyps
00870   for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
00871     if ( !hyp->IsNull() ) {
00872       (*hyp)->Flush();
00873       // smeshgen.CreateHypothesis() --> smesh.smesh.CreateHypothesis()
00874       if ( !(*hyp)->IsWrapped() )
00875         (*hyp)->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() );
00876     }
00877 
00878   // Flush other objects
00879   for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj )
00880     if ( ! id_obj->second.IsNull() )
00881       id_obj->second->Flush();
00882 
00883   myLastCommand->SetOrderNb( ++myNbCommands );
00884   myCommands.push_back( myLastCommand );
00885 }
00886 
00887 //================================================================================
00891 //================================================================================
00892 
00893 void _pyGen::ClearCommands()
00894 {
00895   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
00896   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
00897     id_mesh->second->ClearCommands();
00898 
00899   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
00900   for ( ; hyp != myHypos.end(); ++hyp )
00901     if ( !hyp->IsNull() )
00902       (*hyp)->ClearCommands();
00903 
00904   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin();
00905   for ( ; id_obj != myObjects.end(); ++id_obj )
00906     id_obj->second->ClearCommands();
00907 }
00908 
00909 //================================================================================
00913 //================================================================================
00914 
00915 void _pyGen::Free()
00916 {
00917   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
00918   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
00919     id_mesh->second->Free();
00920   myMeshes.clear();
00921 
00922   map< _pyID, Handle(_pyMeshEditor) >::iterator id_ed = myMeshEditors.begin();
00923   for ( ; id_ed != myMeshEditors.end(); ++id_ed )
00924     id_ed->second->Free();
00925   myMeshEditors.clear();
00926 
00927   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin();
00928   for ( ; id_obj != myObjects.end(); ++id_obj )
00929     id_obj->second->Free();
00930   myObjects.clear();
00931 
00932   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
00933   for ( ; hyp != myHypos.end(); ++hyp )
00934     if ( !hyp->IsNull() )
00935       (*hyp)->Free();
00936   myHypos.clear();
00937 
00938   myFile2ExportedMesh.clear();
00939 }
00940 
00941 //================================================================================
00947 //================================================================================
00948 
00949 bool _pyGen::AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const
00950 {
00951   bool added = false;
00952   map< _pyID, Handle(_pyMesh) >::const_iterator id_mesh = myMeshes.begin();
00953   for ( ; id_mesh != myMeshes.end(); ++id_mesh ) {
00954     if ( theCmd->AddAccessorMethod( id_mesh->first, id_mesh->second->AccessorMethod() ))
00955       added = true;
00956   }
00957   return added;
00958 }
00959 
00960 //================================================================================
00966 //================================================================================
00967 
00968 bool _pyGen::AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const
00969 {
00970   bool added = false;
00971   list< Handle(_pyHypothesis) >::const_iterator hyp = myHypos.begin();
00972   for ( ; hyp != myHypos.end(); ++hyp ) {
00973     if ( (*hyp)->IsAlgo() && /*(*hyp)->IsWrapped() &&*/
00974          theCmd->AddAccessorMethod( (*hyp)->GetID(), (*hyp)->AccessorMethod() ))
00975       added = true;
00976   }
00977   return added;
00978 }
00979 
00980 //================================================================================
00986 //================================================================================
00987 
00988 Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID )
00989 {
00990   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
00991   for ( ; hyp != myHypos.end(); ++hyp )
00992     if ( !hyp->IsNull() && theHypID == (*hyp)->GetID() )
00993       return *hyp;
00994   return Handle(_pyHypothesis)();
00995 }
00996 
00997 //================================================================================
01005 //================================================================================
01006 
01007 Handle(_pyHypothesis) _pyGen::FindAlgo( const _pyID& theGeom, const _pyID& theMesh,
01008                                         const Handle(_pyHypothesis)& theHypothesis )
01009 {
01010   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
01011   for ( ; hyp != myHypos.end(); ++hyp )
01012     if ( !hyp->IsNull() &&
01013          (*hyp)->IsAlgo() &&
01014          theHypothesis->CanBeCreatedBy( (*hyp)->GetAlgoType() ) &&
01015          (*hyp)->GetGeom() == theGeom &&
01016          (*hyp)->GetMesh() == theMesh )
01017       return *hyp;
01018   return 0;
01019 }
01020 
01021 //================================================================================
01027 //================================================================================
01028 
01029 Handle(_pySubMesh) _pyGen::FindSubMesh( const _pyID& theSubMeshID )
01030 {
01031   map< _pyID, Handle(_pyObject) >::iterator id_subMesh = myObjects.find(theSubMeshID);
01032   if ( id_subMesh != myObjects.end() )
01033     return Handle(_pySubMesh)::DownCast( id_subMesh->second );
01034   return Handle(_pySubMesh)();
01035 }
01036 
01037 
01038 //================================================================================
01044 //================================================================================
01045 
01046 void _pyGen::ExchangeCommands( Handle(_pyCommand) theCmd1, Handle(_pyCommand) theCmd2 )
01047 {
01048   list< Handle(_pyCommand) >::iterator pos1, pos2;
01049   pos1 = find( myCommands.begin(), myCommands.end(), theCmd1 );
01050   pos2 = find( myCommands.begin(), myCommands.end(), theCmd2 );
01051   myCommands.insert( pos1, theCmd2 );
01052   myCommands.insert( pos2, theCmd1 );
01053   myCommands.erase( pos1 );
01054   myCommands.erase( pos2 );
01055 
01056   int nb1 = theCmd1->GetOrderNb();
01057   theCmd1->SetOrderNb( theCmd2->GetOrderNb() );
01058   theCmd2->SetOrderNb( nb1 );
01059 //   cout << "BECOME " << theCmd1->GetOrderNb() << "\t" << theCmd1->GetString() << endl
01060 //        << "BECOME " << theCmd2->GetOrderNb() << "\t" << theCmd2->GetString() << endl << endl;
01061 }
01062 
01063 //================================================================================
01069 //================================================================================
01070 
01071 void _pyGen::SetCommandAfter( Handle(_pyCommand) theCmd, Handle(_pyCommand) theAfterCmd )
01072 {
01073   setNeighbourCommand( theCmd, theAfterCmd, true );
01074 }
01075 
01076 //================================================================================
01082 //================================================================================
01083 
01084 void _pyGen::SetCommandBefore( Handle(_pyCommand) theCmd, Handle(_pyCommand) theBeforeCmd )
01085 {
01086   setNeighbourCommand( theCmd, theBeforeCmd, false );
01087 }
01088 
01089 //================================================================================
01095 //================================================================================
01096 
01097 void _pyGen::setNeighbourCommand( Handle(_pyCommand)& theCmd,
01098                                   Handle(_pyCommand)& theOtherCmd,
01099                                   const bool theIsAfter )
01100 {
01101   list< Handle(_pyCommand) >::iterator pos;
01102   pos = find( myCommands.begin(), myCommands.end(), theCmd );
01103   myCommands.erase( pos );
01104   pos = find( myCommands.begin(), myCommands.end(), theOtherCmd );
01105   myCommands.insert( (theIsAfter ? ++pos : pos), theCmd );
01106 
01107   int i = 1;
01108   for ( pos = myCommands.begin(); pos != myCommands.end(); ++pos)
01109     (*pos)->SetOrderNb( i++ );
01110 }
01111 
01112 //================================================================================
01117 //================================================================================
01118 
01119 Handle(_pyCommand)& _pyGen::GetLastCommand()
01120 {
01121   return myLastCommand;
01122 }
01123 
01124 //================================================================================
01130 //================================================================================
01131 
01132 void _pyGen::SetAccessorMethod(const _pyID& theID, const char* theMethod )
01133 {
01134   myID2AccessorMethod.Bind( theID, (char*) theMethod );
01135 }
01136 
01137 //================================================================================
01142 //================================================================================
01143 
01144 _pyID _pyGen::GenerateNewID( const _pyID& theID )
01145 {
01146   int index = 1;
01147   _pyID aNewID;
01148   do {
01149     aNewID = theID + _pyID( ":" ) + _pyID( index++ );
01150   }
01151   while ( myObjectNames.IsBound( aNewID ) );
01152 
01153   myObjectNames.Bind( aNewID, myObjectNames.IsBound( theID )
01154                       ? (myObjectNames.Find( theID ) + _pyID( "_" ) + _pyID( index-1 ))
01155                       : _pyID( "A" ) + aNewID );
01156   return aNewID;
01157 }
01158 
01159 //================================================================================
01163 //================================================================================
01164 
01165 void _pyGen::AddObject( Handle(_pyObject)& theObj )
01166 {
01167   if ( theObj.IsNull() ) return;
01168 
01169   if ( theObj->IsKind( STANDARD_TYPE( _pyMesh )))
01170     myMeshes.insert( make_pair( theObj->GetID(), Handle(_pyMesh)::DownCast( theObj )));
01171 
01172   else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor )))
01173     myMeshEditors.insert( make_pair( theObj->GetID(), Handle(_pyMeshEditor)::DownCast( theObj )));
01174 
01175   else
01176     myObjects.insert( make_pair( theObj->GetID(), theObj ));
01177 }
01178 
01179 //================================================================================
01184 //================================================================================
01185 
01186 void _pyGen::SetProxyObject( const _pyID& theID, Handle(_pyObject)& theObj )
01187 {
01188   if ( theObj.IsNull() ) return;
01189 
01190   if ( theObj->IsKind( STANDARD_TYPE( _pyMesh )))
01191     myMeshes.insert( make_pair( theID, Handle(_pyMesh)::DownCast( theObj )));
01192 
01193   else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor )))
01194     myMeshEditors.insert( make_pair( theID, Handle(_pyMeshEditor)::DownCast( theObj )));
01195 
01196   else
01197     myObjects.insert( make_pair( theID, theObj ));
01198 }
01199 
01200 //================================================================================
01204 //================================================================================
01205 
01206 Handle(_pyObject) _pyGen::FindObject( const _pyID& theObjID )  const
01207 {
01208   {
01209     map< _pyID, Handle(_pyObject) >::const_iterator id_obj = myObjects.find( theObjID );
01210     if ( id_obj != myObjects.end() )
01211       return id_obj->second;
01212   }
01213   {
01214     map< _pyID, Handle(_pyMesh) >::const_iterator id_obj = myMeshes.find( theObjID );
01215     if ( id_obj != myMeshes.end() )
01216       return id_obj->second;
01217   }
01218   // {
01219   //   map< _pyID, Handle(_pyMeshEditor) >::const_iterator id_obj = myMeshEditors.find( theObjID );
01220   //   if ( id_obj != myMeshEditors.end() )
01221   //     return id_obj->second;
01222   // }
01223   return Handle(_pyObject)();
01224 }
01225 
01226 //================================================================================
01230 //================================================================================
01231 
01232 bool _pyGen::IsGeomObject(const _pyID& theObjID) const
01233 {
01234   if ( myGeomIDNb )
01235   {
01236     return ( myGeomIDIndex <= theObjID.Length() &&
01237              int( theObjID.Value( myGeomIDIndex )) == myGeomIDNb &&
01238              _pyCommand::IsStudyEntry( theObjID ));
01239   }
01240   return false;
01241 }
01242 
01243 //================================================================================
01247 //================================================================================
01248 
01249 bool _pyGen::IsNotPublished(const _pyID& theObjID) const
01250 {
01251   if ( theObjID.IsEmpty() ) return false;
01252 
01253   if ( myObjectNames.IsBound( theObjID ))
01254     return false; // SMESH object is in study
01255 
01256   // either the SMESH object is not in study or it is a GEOM object
01257   if ( IsGeomObject( theObjID ))
01258   {
01259     SALOMEDS::SObject_var so = myStudy->FindObjectID( theObjID.ToCString() );
01260     if ( so->_is_nil() ) return true;
01261     CORBA::Object_var obj = so->GetObject();
01262     return CORBA::is_nil( obj );
01263   }
01264   return true; // SMESH object not in study
01265 }
01266 
01267 //================================================================================
01271 //================================================================================
01272 
01273 Handle( _pyHypothesisReader ) _pyGen::GetHypothesisReader() const
01274 {
01275   if (myHypReader.IsNull() )
01276     ((_pyGen*) this)->myHypReader = new _pyHypothesisReader;
01277 
01278   return myHypReader;
01279 }
01280 
01281 
01282 //================================================================================
01286 //================================================================================
01287 
01288 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd)
01289   : _pyObject( theCreationCmd ), myGeomNotInStudy( false )
01290 {
01291   if ( theCreationCmd->GetMethod() == "CreateMesh" && theGen->IsNotPublished( GetGeom() ))
01292     myGeomNotInStudy = true;
01293 
01294   // convert my creation command --> smeshpy.Mesh(...)
01295   Handle(_pyCommand) creationCmd = GetCreationCmd();
01296   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
01297   creationCmd->SetMethod( "Mesh" );
01298   theGen->SetAccessorMethod( GetID(), _pyMesh::AccessorMethod() );
01299 }
01300 
01301 //================================================================================
01305 //================================================================================
01306 
01307 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd, const _pyID& meshId):
01308   _pyObject(theCreationCmd,meshId), myGeomNotInStudy(false )
01309 {
01310   if ( theCreationCmd->MethodStartsFrom( "CreateMeshesFrom" ))
01311   {
01312     // this mesh depends on the exported mesh
01313     const TCollection_AsciiString& file = theCreationCmd->GetArg( 1 );
01314     if ( !file.IsEmpty() )
01315     {
01316       ExportedMeshData& exportData = theGen->FindExportedMesh( file );
01317       addFatherMesh( exportData.myMesh );
01318       if ( !exportData.myLastComputeCmd.IsNull() )
01319       {
01320         // restore cleared Compute() by which the exported mesh was generated
01321         exportData.myLastComputeCmd->GetString() = exportData.myLastComputeCmdString;
01322         // protect that Compute() cmd from clearing
01323         if ( exportData.myMesh->myLastComputeCmd == exportData.myLastComputeCmd )
01324           exportData.myMesh->myLastComputeCmd.Nullify();
01325       }
01326     }
01327   }
01328   else if ( theCreationCmd->MethodStartsFrom( "Concatenate" ))
01329   {
01330     // this mesh depends on concatenated meshes
01331     const TCollection_AsciiString& meshIDs = theCreationCmd->GetArg( 1 );
01332     list< _pyID > idList = theCreationCmd->GetStudyEntries( meshIDs );
01333     list< _pyID >::iterator meshID = idList.begin();
01334     for ( ; meshID != idList.end(); ++meshID )
01335       addFatherMesh( *meshID );
01336   }
01337   else if ( theCreationCmd->GetMethod() == "CopyMesh" )
01338   {
01339     // this mesh depends on a copied IdSource
01340     const _pyID& objID = theCreationCmd->GetArg( 1 );
01341     addFatherMesh( objID );
01342   }
01343   else if ( theCreationCmd->GetMethod().Search("MakeMesh") != -1 ||
01344             theCreationCmd->GetMethod() == "MakeBoundaryMesh" ||
01345             theCreationCmd->GetMethod() == "MakeBoundaryElements" )
01346   {
01347     // this mesh depends on a source mesh
01348     // (theCreationCmd is already Process()ed by _pyMeshEditor)
01349     const _pyID& meshID = theCreationCmd->GetObject();
01350     addFatherMesh( meshID );
01351   }
01352     
01353   // convert my creation command
01354   Handle(_pyCommand) creationCmd = GetCreationCmd();
01355   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
01356   theGen->SetAccessorMethod( meshId, _pyMesh::AccessorMethod() );
01357 }
01358 
01359 //================================================================================
01364 //================================================================================
01365 
01366 void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
01367 {
01368   // some methods of SMESH_Mesh interface needs special conversion
01369   // to methods of Mesh python class
01370   //
01371   // 1. GetSubMesh(geom, name) + AddHypothesis(geom, algo)
01372   //     --> in Mesh_Algorithm.Create(mesh, geom, hypo, so)
01373   // 2. AddHypothesis(geom, hyp)
01374   //     --> in Mesh_Algorithm.Hypothesis(hyp, args, so)
01375   // 3. CreateGroupFromGEOM(type, name, grp)
01376   //     --> in Mesh.Group(grp, name="")
01377   // 4. ExportToMED(f, auto_groups, version)
01378   //     --> in Mesh.ExportMED( f, auto_groups, version )
01379   // 5. etc
01380 
01381   const TCollection_AsciiString& method = theCommand->GetMethod();
01382   // ----------------------------------------------------------------------
01383   if ( method == "Compute" ) // in snapshot mode, clear the previous Compute()
01384   {
01385     if ( !theGen->IsToKeepAllCommands() ) // !historical
01386     {
01387       list< Handle(_pyHypothesis) >::iterator hyp;
01388       if ( !myLastComputeCmd.IsNull() )
01389       {
01390         for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
01391           (*hyp)->ComputeDiscarded( myLastComputeCmd );
01392 
01393         myLastComputeCmd->Clear();
01394       }
01395       myLastComputeCmd = theCommand;
01396 
01397       for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
01398         (*hyp)->MeshComputed( myLastComputeCmd );
01399     }
01400     Flush();
01401   }
01402   // ----------------------------------------------------------------------
01403   else if ( method == "Clear" ) // in snapshot mode, clear all previous commands
01404   {
01405     if ( !theGen->IsToKeepAllCommands() ) // !historical
01406     {
01407       int untilCmdNb =
01408         myChildMeshes.empty() ? 0 : myChildMeshes.back()->GetCreationCmd()->GetOrderNb();
01409       // list< Handle(_pyCommand) >::reverse_iterator cmd = myProcessedCmds.rbegin();
01410       // for ( ; cmd != myProcessedCmds.rend() && (*cmd)->GetOrderNb() > untilCmdNb; ++cmd )
01411       //   (*cmd)->Clear();
01412       if ( !myLastComputeCmd.IsNull() )
01413       {
01414         list< Handle(_pyHypothesis) >::iterator hyp;
01415         for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
01416           (*hyp)->ComputeDiscarded( myLastComputeCmd );
01417 
01418         myLastComputeCmd->Clear();
01419       }
01420 
01421       list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
01422       for ( ; e != myEditors.end(); ++e )
01423       {
01424         list< Handle(_pyCommand)>& cmds = (*e)->GetProcessedCmds();
01425         list< Handle(_pyCommand) >::reverse_iterator cmd = cmds.rbegin();
01426         for ( ; cmd != cmds.rend() && (*cmd)->GetOrderNb() > untilCmdNb; ++cmd )
01427           if ( !(*cmd)->IsEmpty() )
01428           {
01429             if ( (*cmd)->GetStudyEntries( (*cmd)->GetResultValue() ).empty() ) // no object created
01430               (*cmd)->Clear();
01431           }
01432       }
01433       myLastComputeCmd = theCommand; // to clear Clear() the same way as Compute()
01434     }
01435   }
01436   // ----------------------------------------------------------------------
01437   else if ( method == "GetSubMesh" ) { // collect submeshes of the mesh
01438     Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetResultValue() );
01439     if ( !subMesh.IsNull() ) {
01440       subMesh->SetCreator( this );
01441       mySubmeshes.push_back( subMesh );
01442     }
01443   }
01444   else if ( method == "RemoveSubMesh" ) { // move submesh creation before its removal
01445     Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetArg(1) );
01446     if ( !subMesh.IsNull() )
01447       subMesh->Process( theCommand );
01448     AddMeshAccess( theCommand );
01449   }
01450   // ----------------------------------------------------------------------
01451   else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO )
01452     myAddHypCmds.push_back( theCommand );
01453     // set mesh to hypo
01454     const _pyID& hypID = theCommand->GetArg( 2 );
01455     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
01456     if ( !hyp.IsNull() ) {
01457       myHypos.push_back( hyp );
01458       if ( hyp->GetMesh().IsEmpty() )
01459         hyp->SetMesh( this->GetID() );
01460     }
01461   }
01462   // ----------------------------------------------------------------------
01463   else if ( method == "CreateGroup" ||
01464             method == "CreateGroupFromGEOM" ||
01465             method == "CreateGroupFromFilter" )
01466   {
01467     Handle(_pyGroup) group = new _pyGroup( theCommand );
01468     myGroups.push_back( group );
01469     theGen->AddObject( group );
01470   }
01471   // ----------------------------------------------------------------------
01472   else if ( theCommand->MethodStartsFrom( "Export" ))
01473   {
01474     if ( method == "ExportToMED" ||   // ExportToMED()  --> ExportMED()
01475          method == "ExportToMEDX" ) { // ExportToMEDX() --> ExportMED()
01476       theCommand->SetMethod( "ExportMED" );
01477     }
01478     else if ( method == "ExportCGNS" )
01479     { // ExportCGNS(part, ...) -> ExportCGNS(..., part)
01480       _pyID partID = theCommand->GetArg( 1 );
01481       int nbArgs = theCommand->GetNbArgs();
01482       for ( int i = 2; i <= nbArgs; ++i )
01483         theCommand->SetArg( i-1, theCommand->GetArg( i ));
01484       theCommand->SetArg( nbArgs, partID );
01485     }
01486     else if ( theCommand->MethodStartsFrom( "ExportPartTo" ))
01487     { // ExportPartTo*(part, ...) -> Export*(..., part)
01488       //
01489       // remove "PartTo" from the method
01490       TCollection_AsciiString newMethod = method;
01491       newMethod.Remove( 7, 6 );
01492       theCommand->SetMethod( newMethod );
01493       // make the 1st arg be the last one
01494       _pyID partID = theCommand->GetArg( 1 );
01495       int nbArgs = theCommand->GetNbArgs();
01496       for ( int i = 2; i <= nbArgs; ++i )
01497         theCommand->SetArg( i-1, theCommand->GetArg( i ));
01498       theCommand->SetArg( nbArgs, partID );
01499     }
01500     // remember file name
01501     theGen->AddExportedMesh( theCommand->GetArg( 1 ),
01502                              ExportedMeshData( this, myLastComputeCmd ));
01503   }
01504   // ----------------------------------------------------------------------
01505   else if ( method == "RemoveHypothesis" ) // (geom, hyp)
01506   {
01507     _pyID hypID = theCommand->GetArg( 2 );
01508 
01509     // check if this mesh still has corresponding addition command
01510     bool hasAddCmd = false;
01511     list< Handle(_pyCommand) >::iterator cmd = myAddHypCmds.begin();
01512     while ( cmd != myAddHypCmds.end() )
01513     {
01514       // AddHypothesis(geom, hyp)
01515       if ( hypID == (*cmd)->GetArg( 2 )) { // erase both (add and remove) commands
01516         theCommand->Clear();
01517         (*cmd)->Clear();
01518         cmd = myAddHypCmds.erase( cmd );
01519         hasAddCmd = true;
01520       }
01521       else {
01522         ++cmd;
01523       }
01524     }
01525     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
01526     if ( ! hasAddCmd && hypID.Length() != 0 ) { // hypo addition already wrapped
01527       // RemoveHypothesis(geom, hyp) --> RemoveHypothesis( hyp, geom=0 )
01528       _pyID geom = theCommand->GetArg( 1 );
01529       theCommand->RemoveArgs();
01530       theCommand->SetArg( 1, hypID );
01531       if ( geom != GetGeom() )
01532         theCommand->SetArg( 2, geom );
01533     }
01534     // remove hyp from myHypos
01535     myHypos.remove( hyp );
01536   }
01537   // check for SubMesh order commands
01538   else if ( method == "GetMeshOrder" || method == "SetMeshOrder" )
01539   {
01540     // make commands GetSubMesh() returning sub-meshes be before using sub-meshes
01541     // by GetMeshOrder() and SetMeshOrder(), since by defalut GetSubMesh()
01542     // commands are moved at the end of the script
01543     TCollection_AsciiString subIDs =
01544       ( method == "SetMeshOrder" ) ? theCommand->GetArg(1) : theCommand->GetResultValue();
01545     list< _pyID > idList = theCommand->GetStudyEntries( subIDs );
01546     list< _pyID >::iterator subID = idList.begin();
01547     for ( ; subID != idList.end(); ++subID )
01548     {
01549       Handle(_pySubMesh) subMesh = theGen->FindSubMesh( *subID );
01550       if ( !subMesh.IsNull() )
01551         subMesh->Process( theCommand ); // it moves GetSubMesh() before theCommand
01552     }
01553   }
01554   // update list of groups
01555   else if ( method == "GetGroups" )
01556   {
01557     TCollection_AsciiString grIDs = theCommand->GetResultValue();
01558     list< _pyID > idList = theCommand->GetStudyEntries( grIDs );
01559     list< _pyID >::iterator grID = idList.begin();
01560     for ( ; grID != idList.end(); ++grID )
01561     {
01562       Handle(_pyObject) obj = theGen->FindObject( *grID );
01563       if ( obj.IsNull() )
01564       {
01565         Handle(_pyGroup) group = new _pyGroup( theCommand, *grID );
01566         theGen->AddObject( group );
01567         myGroups.push_back( group );
01568       }
01569     }
01570   }
01571   // add accessor method if necessary
01572   else
01573   {
01574     if ( NeedMeshAccess( theCommand ))
01575       // apply theCommand to the mesh wrapped by smeshpy mesh
01576       AddMeshAccess( theCommand );
01577   }
01578 }
01579 
01580 //================================================================================
01584 //================================================================================
01585 
01586 bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand )
01587 {
01588   // names of SMESH_Mesh methods fully equal to methods of python class Mesh,
01589   // so no conversion is needed for them at all:
01590   static TStringSet sameMethods;
01591   if ( sameMethods.empty() ) {
01592     const char * names[] =
01593       { "ExportDAT","ExportUNV","ExportSTL","ExportSAUV", "RemoveGroup","RemoveGroupWithContents",
01594         "GetGroups","UnionGroups","IntersectGroups","CutGroups","GetLog","GetId","ClearLog",
01595         "GetStudyId","HasDuplicatedGroupNamesMED","GetMEDMesh","NbNodes","NbElements",
01596         "NbEdges","NbEdgesOfOrder","NbFaces","NbFacesOfOrder","NbTriangles",
01597         "NbTrianglesOfOrder","NbQuadrangles","NbQuadranglesOfOrder","NbPolygons","NbVolumes",
01598         "NbVolumesOfOrder","NbTetras","NbTetrasOfOrder","NbHexas","NbHexasOfOrder",
01599         "NbPyramids","NbPyramidsOfOrder","NbPrisms","NbPrismsOfOrder","NbPolyhedrons",
01600         "NbSubMesh","GetElementsId","GetElementsByType","GetNodesId","GetElementType",
01601         "GetSubMeshElementsId","GetSubMeshNodesId","GetSubMeshElementType","Dump","GetNodeXYZ",
01602         "GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes",
01603         "GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces",
01604         "IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", "SetAutoColor", "GetAutoColor",
01605         "Clear", "ConvertToStandalone", "GetMeshOrder", "SetMeshOrder"
01606         ,"" }; // <- mark of end
01607     sameMethods.Insert( names );
01608   }
01609 
01610   return !sameMethods.Contains( theCommand->GetMethod() );
01611 }
01612 
01613 //================================================================================
01617 //================================================================================
01618 
01619 void _pyMesh::Flush()
01620 {
01621   {
01622     // get the meshes this mesh depends on via hypotheses
01623     list< Handle(_pyMesh) > fatherMeshes;
01624     list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
01625     for ( ; hyp != myHypos.end(); ++hyp )
01626       if ( ! (*hyp)->GetReferredMeshesAndGeom( fatherMeshes ))
01627         myGeomNotInStudy = true;
01628 
01629     list< Handle(_pyMesh) >::iterator m = fatherMeshes.begin();
01630     for ( ; m != fatherMeshes.end(); ++m )
01631       addFatherMesh( *m );
01632     // if ( removedGeom )
01633     //     SetRemovedFromStudy(); // as reffered geometry not in study
01634   }
01635   if ( myGeomNotInStudy )
01636     return;
01637 
01638   list < Handle(_pyCommand) >::iterator cmd;
01639 
01640   // try to convert algo addition like this:
01641   // mesh.AddHypothesis(geom, ALGO ) --> ALGO = mesh.Algo()
01642   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
01643   {
01644     Handle(_pyCommand) addCmd = *cmd;
01645 
01646     _pyID algoID = addCmd->GetArg( 2 );
01647     Handle(_pyHypothesis) algo = theGen->FindHyp( algoID );
01648     if ( algo.IsNull() || !algo->IsAlgo() )
01649       continue;
01650 
01651     // check and create new algorithm instance if it is already wrapped
01652     if ( algo->IsWrapped() ) {
01653       _pyID localAlgoID = theGen->GenerateNewID( algoID );
01654       TCollection_AsciiString aNewCmdStr = addCmd->GetIndentation() + localAlgoID +
01655         TCollection_AsciiString( " = " ) + theGen->GetID() +
01656         TCollection_AsciiString( ".CreateHypothesis( \"" ) + algo->GetAlgoType() +
01657         TCollection_AsciiString( "\" )" );
01658 
01659       Handle(_pyCommand) newCmd = theGen->AddCommand( aNewCmdStr );
01660       Handle(_pyAlgorithm) newAlgo = Handle(_pyAlgorithm)::DownCast(theGen->FindHyp( localAlgoID ));
01661       if ( !newAlgo.IsNull() ) {
01662         newAlgo->Assign( algo, this->GetID() );
01663         newAlgo->SetCreationCmd( newCmd );
01664         algo = newAlgo;
01665         // set algorithm creation
01666         theGen->SetCommandBefore( newCmd, addCmd );
01667         myHypos.push_back( newAlgo );
01668         if ( !myLastComputeCmd.IsNull() &&
01669              newCmd->GetOrderNb() == myLastComputeCmd->GetOrderNb() + 1)
01670           newAlgo->MeshComputed( myLastComputeCmd );
01671       }
01672       else
01673         newCmd->Clear();
01674     }
01675     _pyID geom = addCmd->GetArg( 1 );
01676     bool isLocalAlgo = ( geom != GetGeom() );
01677 
01678     // try to convert
01679     if ( algo->Addition2Creation( addCmd, this->GetID() )) // OK
01680     {
01681       // wrapped algo is created after mesh creation
01682       GetCreationCmd()->AddDependantCmd( addCmd );
01683 
01684       if ( isLocalAlgo ) {
01685         // mesh.AddHypothesis(geom, ALGO ) --> mesh.AlgoMethod(geom)
01686         addCmd->SetArg( addCmd->GetNbArgs() + 1,
01687                         TCollection_AsciiString( "geom=" ) + geom );
01688         // sm = mesh.GetSubMesh(geom, name) --> sm = ALGO.GetSubMesh()
01689         list < Handle(_pySubMesh) >::iterator smIt;
01690         for ( smIt = mySubmeshes.begin(); smIt != mySubmeshes.end(); ++smIt ) {
01691           Handle(_pySubMesh) subMesh = *smIt;
01692           Handle(_pyCommand) subCmd = subMesh->GetCreationCmd();
01693           if ( geom == subCmd->GetArg( 1 )) {
01694             subCmd->SetObject( algo->GetID() );
01695             subCmd->RemoveArgs();
01696             subMesh->SetCreator( algo );
01697           }
01698         }
01699       }
01700     }
01701     else // KO - ALGO was already created
01702     {
01703       // mesh.AddHypothesis(geom, ALGO) --> mesh.AddHypothesis(ALGO, geom=0)
01704       addCmd->RemoveArgs();
01705       addCmd->SetArg( 1, algoID );
01706       if ( isLocalAlgo )
01707         addCmd->SetArg( 2, geom );
01708     }
01709   }
01710 
01711   // try to convert hypo addition like this:
01712   // mesh.AddHypothesis(geom, HYPO ) --> HYPO = algo.Hypo()
01713   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
01714   {
01715     Handle(_pyCommand) addCmd = *cmd;
01716     _pyID hypID = addCmd->GetArg( 2 );
01717     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
01718     if ( hyp.IsNull() || hyp->IsAlgo() )
01719       continue;
01720     bool converted = hyp->Addition2Creation( addCmd, this->GetID() );
01721     if ( !converted ) {
01722       // mesh.AddHypothesis(geom, HYP) --> mesh.AddHypothesis(HYP, geom=0)
01723       _pyID geom = addCmd->GetArg( 1 );
01724       addCmd->RemoveArgs();
01725       addCmd->SetArg( 1, hypID );
01726       if ( geom != GetGeom() )
01727         addCmd->SetArg( 2, geom );
01728     }
01729   }
01730 
01731   myAddHypCmds.clear();
01732   mySubmeshes.clear();
01733 
01734   // flush hypotheses
01735   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
01736   for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
01737     (*hyp)->Flush();
01738 }
01739 
01740 //================================================================================
01744 //================================================================================
01745 
01746 void _pyMesh::SetRemovedFromStudy(const bool isRemoved)
01747 {
01748   _pyObject::SetRemovedFromStudy(isRemoved);
01749 
01750   list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin();
01751   for ( ; sm != mySubmeshes.end(); ++sm )
01752     (*sm)->SetRemovedFromStudy(isRemoved);
01753 
01754   list< Handle(_pyGroup) >::iterator gr = myGroups.begin();
01755   for ( ; gr != myGroups.end(); ++gr )
01756     (*gr)->SetRemovedFromStudy(isRemoved);
01757 
01758   list< Handle(_pyMesh) >::iterator m = myChildMeshes.begin();
01759   for ( ; m != myChildMeshes.end(); ++m )
01760     (*m)->SetRemovedFromStudy(isRemoved);
01761 
01762   list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
01763   for ( ; e != myEditors.end(); ++e )
01764     (*e)->SetRemovedFromStudy(isRemoved);
01765 }
01766 
01767 //================================================================================
01771 //================================================================================
01772 
01773 bool _pyMesh::CanClear()
01774 {
01775   if ( IsInStudy() )
01776     return false;
01777 
01778   list< Handle(_pyMesh) >::iterator m = myChildMeshes.begin();
01779   for ( ; m != myChildMeshes.end(); ++m )
01780     if ( !(*m)->CanClear() )
01781       return false;
01782 
01783   return true;
01784 }
01785 
01786 //================================================================================
01790 //================================================================================
01791 
01792 void _pyMesh::ClearCommands()
01793 {
01794   if ( !CanClear() )
01795   {
01796     if ( !IsInStudy() )
01797     {
01798       // mark all sub-objects as not removed, except child meshes
01799       list< Handle(_pyMesh) > children;
01800       children.swap( myChildMeshes );
01801       SetRemovedFromStudy( false );
01802       children.swap( myChildMeshes );
01803     }
01804     return;
01805   }
01806   _pyObject::ClearCommands();
01807 
01808   list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin();
01809   for ( ; sm != mySubmeshes.end(); ++sm )
01810     (*sm)->ClearCommands();
01811   
01812   list< Handle(_pyGroup) >::iterator gr = myGroups.begin();
01813   for ( ; gr != myGroups.end(); ++gr )
01814     (*gr)->ClearCommands();
01815 
01816   list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
01817   for ( ; e != myEditors.end(); ++e )
01818     (*e)->ClearCommands();
01819 }
01820 
01821 //================================================================================
01825 //================================================================================
01826 
01827 void _pyMesh::addFatherMesh( const _pyID& meshID )
01828 {
01829   if ( !meshID.IsEmpty() )
01830     addFatherMesh( Handle(_pyMesh)::DownCast( theGen->FindObject( meshID )));
01831 }
01832 
01833 //================================================================================
01837 //================================================================================
01838 
01839 void _pyMesh::addFatherMesh( const Handle(_pyMesh)& mesh )
01840 {
01841   if ( !mesh.IsNull() )
01842   {
01843     //myFatherMeshes.push_back( mesh );
01844     mesh->myChildMeshes.push_back( this );
01845 
01846     // protect last Compute() from clearing by the next Compute()
01847     mesh->myLastComputeCmd.Nullify();
01848   }
01849 }
01850 
01851 //================================================================================
01855 //================================================================================
01856 
01857 _pyMeshEditor::_pyMeshEditor(const Handle(_pyCommand)& theCreationCmd):
01858   _pyObject( theCreationCmd )
01859 {
01860   myMesh = theCreationCmd->GetObject();
01861   myCreationCmdStr = theCreationCmd->GetString();
01862   theCreationCmd->Clear();
01863 
01864   Handle(_pyMesh) mesh = ObjectToMesh( theGen->FindObject( myMesh ));
01865   if ( !mesh.IsNull() )
01866     mesh->AddEditor( this );
01867 }
01868 
01869 //================================================================================
01873 //================================================================================
01874 
01875 void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
01876 {
01877   // names of SMESH_MeshEditor methods fully equal to methods of python class Mesh, so
01878   // commands calling this methods are converted to calls of methods of Mesh
01879   static TStringSet sameMethods;
01880   if ( sameMethods.empty() ) {
01881     const char * names[] = {
01882       "RemoveElements","RemoveNodes","RemoveOrphanNodes","AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace",
01883       "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","MoveNode", "MoveClosestNodeToPoint",
01884       "InverseDiag","DeleteDiag","Reorient","ReorientObject","TriToQuad","SplitQuad","SplitQuadObject",
01885       "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject",
01886       "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements",
01887       "RotationSweep","RotationSweepObject","RotationSweepObject1D","RotationSweepObject2D",
01888       "ExtrusionSweep","AdvancedExtrusion","ExtrusionSweepObject","ExtrusionSweepObject1D","ExtrusionSweepObject2D",
01889       "ExtrusionAlongPath","ExtrusionAlongPathObject","ExtrusionAlongPathX",
01890       "ExtrusionAlongPathObject1D","ExtrusionAlongPathObject2D",
01891       "Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject",
01892       "FindCoincidentNodes",/*"FindCoincidentNodesOnPart",*/"MergeNodes","FindEqualElements",
01893       "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders",
01894       "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes",
01895       "GetLastCreatedElems",
01896       "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh",
01897       "TranslateObjectMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh",
01898       "MakeBoundaryElements"
01899       ,"" }; // <- mark of the end
01900     sameMethods.Insert( names );
01901   }
01902 
01903   // names of SMESH_MeshEditor methods which differ from methods of class Mesh
01904   // only by last two arguments
01905   static TStringSet diffLastTwoArgsMethods;
01906   if (diffLastTwoArgsMethods.empty() ) {
01907     const char * names[] = {
01908       "MirrorMakeGroups","MirrorObjectMakeGroups",
01909       "TranslateMakeGroups","TranslateObjectMakeGroups",
01910       "RotateMakeGroups","RotateObjectMakeGroups",
01911       ""};// <- mark of the end
01912     diffLastTwoArgsMethods.Insert( names );
01913   }
01914 
01915   const TCollection_AsciiString & method = theCommand->GetMethod();
01916   bool isPyMeshMethod = sameMethods.Contains( method );
01917   if ( !isPyMeshMethod )
01918   {
01919     //Replace SMESH_MeshEditor "MakeGroups" functions by the Mesh
01920     //functions with the flag "theMakeGroups = True" like:
01921     //SMESH_MeshEditor.CmdMakeGroups => Mesh.Cmd(...,True)
01922     int pos = method.Search("MakeGroups");
01923     if( pos != -1)
01924     {
01925       isPyMeshMethod = true;
01926       bool is0DmethId  = ( method == "ExtrusionSweepMakeGroups0D" );
01927       bool is0DmethObj = ( method == "ExtrusionSweepObject0DMakeGroups");
01928 
01929       // 1. Remove "MakeGroups" from the Command
01930       TCollection_AsciiString aMethod = theCommand->GetMethod();
01931       int nbArgsToAdd = diffLastTwoArgsMethods.Contains(aMethod) ? 2 : 1;
01932       
01933       if(is0DmethObj)
01934         pos = pos-2;  //Remove "0D" from the Command too
01935       aMethod.Trunc(pos-1);
01936       theCommand->SetMethod(aMethod);
01937 
01938       // 2. And add last "True" argument(s)
01939       while(nbArgsToAdd--)
01940         theCommand->SetArg(theCommand->GetNbArgs()+1,"True");
01941       if( is0DmethId || is0DmethObj )
01942         theCommand->SetArg(theCommand->GetNbArgs()+1,"True");
01943     }
01944   }
01945 
01946   // ExtrusionSweep0D() -> ExtrusionSweep()
01947   // ExtrusionSweepObject0D() -> ExtrusionSweepObject()
01948   if ( !isPyMeshMethod && ( method == "ExtrusionSweep0D"  ||
01949                             method == "ExtrusionSweepObject0D" ))
01950   {
01951     isPyMeshMethod=true;
01952     theCommand->SetMethod( method.SubString( 1, method.Length()-2));
01953     theCommand->SetArg(theCommand->GetNbArgs()+1,"False");  //sets flag "MakeGroups = False"
01954     theCommand->SetArg(theCommand->GetNbArgs()+1,"True");  //sets flag "IsNode = True"
01955   }
01956   // set "ExtrusionAlongPathX()" instead of "ExtrusionAlongPathObjX()"
01957   if ( !isPyMeshMethod && method == "ExtrusionAlongPathObjX")
01958   {
01959     isPyMeshMethod=true;
01960     theCommand->SetMethod("ExtrusionAlongPathX");
01961   }
01962 
01963   // set "FindCoincidentNodesOnPart()" instead of "FindCoincidentNodesOnPartBut()"
01964   if ( !isPyMeshMethod && method == "FindCoincidentNodesOnPartBut")
01965   {
01966     isPyMeshMethod=true;
01967     theCommand->SetMethod("FindCoincidentNodesOnPart");
01968   }
01969   // DoubleNode...New(...) -> DoubleNode...(...,True)
01970   if ( !isPyMeshMethod && ( method == "DoubleNodeElemGroupNew"  ||
01971                             method == "DoubleNodeElemGroupsNew" ||
01972                             method == "DoubleNodeGroupNew"      ||
01973                             method == "DoubleNodeGroupsNew"     ||
01974                             method == "DoubleNodeElemGroup2New" ||
01975                             method == "DoubleNodeElemGroups2New"))
01976   {
01977     isPyMeshMethod=true;
01978     const int excessLen = 3 + int( method.Value( method.Length()-3 ) == '2' );
01979     theCommand->SetMethod( method.SubString( 1, method.Length()-excessLen));
01980     if ( excessLen == 3 )
01981     {
01982       theCommand->SetArg(theCommand->GetNbArgs()+1,"True");
01983     }
01984     else if ( theCommand->GetArg(4) == "0" ||
01985               theCommand->GetArg(5) == "0" )
01986     {
01987       // [ nothing, Group ] = DoubleNodeGroup2New(,,,False, True) ->
01988       // Group = DoubleNodeGroup2New(,,,False, True)
01989       _pyID groupID = theCommand->GetResultValue( 1 + int( theCommand->GetArg(4) == "0"));
01990       theCommand->SetResultValue( groupID );
01991     }
01992   }
01993   // ConvertToQuadraticObject(bool,obj) -> ConvertToQuadratic(bool,obj)
01994   // ConvertFromQuadraticObject(obj) -> ConvertFromQuadratic(obj)
01995   if ( !isPyMeshMethod && ( method == "ConvertToQuadraticObject" ||
01996                             method == "ConvertFromQuadraticObject" ))
01997   {
01998     isPyMeshMethod=true;
01999     theCommand->SetMethod( method.SubString( 1, method.Length()-6));
02000     // prevent moving creation of the converted sub-mesh to the end of the script
02001     bool isFromQua = ( method.Value( 8 ) == 'F' );
02002     Handle(_pySubMesh) sm = theGen->FindSubMesh( theCommand->GetArg( isFromQua ? 1 : 2 ));
02003     if ( !sm.IsNull() )
02004       sm->Process( theCommand );
02005   }
02006   // FindAmongElementsByPoint(meshPart, x, y, z, elementType) ->
02007   // FindElementsByPoint(x, y, z, elementType, meshPart)
02008   if ( !isPyMeshMethod && method == "FindAmongElementsByPoint" )
02009   {
02010     isPyMeshMethod=true;
02011     theCommand->SetMethod( "FindElementsByPoint" );
02012     // make the 1st arg be the last one
02013     _pyID partID = theCommand->GetArg( 1 );
02014     int nbArgs = theCommand->GetNbArgs();
02015     for ( int i = 2; i <= nbArgs; ++i )
02016       theCommand->SetArg( i-1, theCommand->GetArg( i ));
02017     theCommand->SetArg( nbArgs, partID );
02018   }
02019 
02020   // meshes made by *MakeMesh() methods are not wrapped by _pyMesh,
02021   // so let _pyMesh care of it (TMP?)
02022   //     if ( theCommand->GetMethod().Search("MakeMesh") != -1 )
02023   //       _pyMesh( new _pyCommand( theCommand->GetString(), 0 )); // for theGen->SetAccessorMethod()
02024   if ( isPyMeshMethod )
02025   {
02026     theCommand->SetObject( myMesh );
02027   }
02028   else
02029   {
02030     // editor creation command is needed only if any editor function is called
02031     theGen->AddMeshAccessorMethod( theCommand ); // for *Object()
02032     if ( !myCreationCmdStr.IsEmpty() ) {
02033       GetCreationCmd()->GetString() = myCreationCmdStr;
02034       myCreationCmdStr.Clear();
02035     }
02036   }
02037 }
02038 
02039 //================================================================================
02043 //================================================================================
02044 
02045 bool _pyMeshEditor::CanClear()
02046 {
02047   Handle(_pyMesh) mesh = ObjectToMesh( theGen->FindObject( myMesh ));
02048   return mesh.IsNull() ? true : mesh->CanClear();
02049 }
02050 
02051 //================================================================================
02056 //================================================================================
02057 
02058 _pyHypothesis::_pyHypothesis(const Handle(_pyCommand)& theCreationCmd):
02059   _pyObject( theCreationCmd ), myCurCrMethod(0)
02060 {
02061   myIsAlgo = myIsWrapped = /*myIsConverted = myIsLocal = myDim = */false;
02062 }
02063 
02064 //================================================================================
02070 //================================================================================
02071 
02072 Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& theCreationCmd)
02073 {
02074   // theCreationCmd: CreateHypothesis( "theHypType", "theLibName" )
02075   ASSERT (( theCreationCmd->GetMethod() == "CreateHypothesis"));
02076 
02077   Handle(_pyHypothesis) hyp, algo;
02078 
02079   // "theHypType"
02080   const TCollection_AsciiString & hypTypeQuoted = theCreationCmd->GetArg( 1 );
02081   if ( hypTypeQuoted.IsEmpty() )
02082     return hyp;
02083   // theHypType
02084   TCollection_AsciiString  hypType =
02085     hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
02086 
02087   algo = new _pyAlgorithm( theCreationCmd );
02088   hyp  = new _pyHypothesis( theCreationCmd );
02089 
02090   if ( hypType == "NumberOfSegments" ) {
02091     hyp = new _pyNumberOfSegmentsHyp( theCreationCmd );
02092     hyp->SetConvMethodAndType( "NumberOfSegments", "Regular_1D");
02093     // arg of SetNumberOfSegments() will become the 1-st arg of hyp creation command
02094     hyp->AddArgMethod( "SetNumberOfSegments" );
02095     // arg of SetScaleFactor() will become the 2-nd arg of hyp creation command
02096     hyp->AddArgMethod( "SetScaleFactor" );
02097     hyp->AddArgMethod( "SetReversedEdges" );
02098     // same for ""CompositeSegment_1D:
02099     hyp->SetConvMethodAndType( "NumberOfSegments", "CompositeSegment_1D");
02100     hyp->AddArgMethod( "SetNumberOfSegments" );
02101     hyp->AddArgMethod( "SetScaleFactor" );
02102     hyp->AddArgMethod( "SetReversedEdges" );
02103   }
02104   else if ( hypType == "SegmentLengthAroundVertex" ) {
02105     hyp = new _pySegmentLengthAroundVertexHyp( theCreationCmd );
02106     hyp->SetConvMethodAndType( "LengthNearVertex", "Regular_1D" );
02107     hyp->AddArgMethod( "SetLength" );
02108     // same for ""CompositeSegment_1D:
02109     hyp->SetConvMethodAndType( "LengthNearVertex", "CompositeSegment_1D");
02110     hyp->AddArgMethod( "SetLength" );
02111   }
02112   else if ( hypType == "LayerDistribution2D" ) {
02113     hyp = new _pyLayerDistributionHypo( theCreationCmd, "Get2DHypothesis" );
02114     hyp->SetConvMethodAndType( "LayerDistribution", "RadialQuadrangle_1D2D");
02115   }
02116   else if ( hypType == "LayerDistribution" ) {
02117     hyp = new _pyLayerDistributionHypo( theCreationCmd, "Get3DHypothesis" );
02118     hyp->SetConvMethodAndType( "LayerDistribution", "RadialPrism_3D");
02119   }
02120   else if ( hypType == "CartesianParameters3D" ) {
02121     hyp = new _pyComplexParamHypo( theCreationCmd );
02122     hyp->SetConvMethodAndType( "SetGrid", "Cartesian_3D");
02123     for ( int iArg = 0; iArg < 4; ++iArg )
02124       hyp->setCreationArg( iArg+1, "[]");
02125   }
02126   else
02127   {
02128     hyp = theGen->GetHypothesisReader()->GetHypothesis( hypType, theCreationCmd );
02129   }
02130 
02131   return algo->IsValid() ? algo : hyp;
02132 }
02133 
02134 //================================================================================
02139 //================================================================================
02140 
02141 bool _pyHypothesis::IsWrappable(const _pyID& theMesh) const
02142 {
02143   if ( !myIsWrapped && myMesh == theMesh && IsInStudy() )
02144   {
02145     Handle(_pyObject) pyMesh = theGen->FindObject( myMesh );
02146     if ( !pyMesh.IsNull() && pyMesh->IsInStudy() )
02147       return true;
02148   }
02149   return false;
02150 }
02151 
02152 //================================================================================
02159 //================================================================================
02160 
02161 bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd,
02162                                        const _pyID&              theMesh)
02163 {
02164   ASSERT(( theCmd->GetMethod() == "AddHypothesis" ));
02165 
02166   if ( !IsWrappable( theMesh ))
02167     return false;
02168 
02169   myGeom = theCmd->GetArg( 1 );
02170 
02171   Handle(_pyHypothesis) algo;
02172   if ( !IsAlgo() ) {
02173     // find algo created on myGeom in theMesh
02174     algo = theGen->FindAlgo( myGeom, theMesh, this );
02175     if ( algo.IsNull() )
02176       return false;
02177     // attach hypothesis creation command to be after algo creation command
02178     // because it can be new created instance of algorithm
02179     algo->GetCreationCmd()->AddDependantCmd( theCmd );
02180   }
02181   myIsWrapped = true;
02182 
02183   // mesh.AddHypothesis(geom,hyp) --> hyp = <theMesh or algo>.myCreationMethod(args)
02184   theCmd->SetResultValue( GetID() );
02185   theCmd->SetObject( IsAlgo() ? theMesh : algo->GetID());
02186   theCmd->SetMethod( IsAlgo() ? GetAlgoCreationMethod() : GetCreationMethod( algo->GetAlgoType() ));
02187   // set args (geom will be set by _pyMesh calling this method)
02188   theCmd->RemoveArgs();
02189   for ( size_t i = 0; i < myCurCrMethod->myArgs.size(); ++i ) {
02190     if ( !myCurCrMethod->myArgs[ i ].IsEmpty() )
02191       theCmd->SetArg( i+1, myCurCrMethod->myArgs[ i ]);
02192     else
02193       theCmd->SetArg( i+1, "[]");
02194   }
02195   // set a new creation command
02196   GetCreationCmd()->Clear();
02197   // replace creation command by wrapped instance
02198   // please note, that hypothesis attaches to algo creation command (see upper)
02199   SetCreationCmd( theCmd );
02200 
02201 
02202   // clear commands setting arg values
02203   list < Handle(_pyCommand) >::iterator argCmd = myArgCommands.begin();
02204   for ( ; argCmd != myArgCommands.end(); ++argCmd )
02205     (*argCmd)->Clear();
02206 
02207   // set unknown arg commands after hypo creation
02208   Handle(_pyCommand) afterCmd = myIsWrapped ? theCmd : GetCreationCmd();
02209   list<Handle(_pyCommand)>::iterator cmd = myUnusedCommands.begin();
02210   for ( ; cmd != myUnusedCommands.end(); ++cmd ) {
02211     afterCmd->AddDependantCmd( *cmd );
02212   }
02213 
02214   return myIsWrapped;
02215 }
02216 
02217 //================================================================================
02222 //================================================================================
02223 
02224 void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand)
02225 {
02226   ASSERT( !myIsAlgo );
02227   if ( !theGen->IsToKeepAllCommands() )
02228     rememberCmdOfParameter( theCommand );
02229   // set args
02230   bool usedCommand = false;
02231   TType2CrMethod::iterator type2meth = myAlgoType2CreationMethod.begin();
02232   for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth )
02233   {
02234     CreationMethod& crMethod = type2meth->second;
02235     for ( size_t i = 0; i < crMethod.myArgMethods.size(); ++i ) {
02236       if ( crMethod.myArgMethods[ i ] == theCommand->GetMethod() ) {
02237         if ( !usedCommand )
02238           myArgCommands.push_back( theCommand );
02239         usedCommand = true;
02240         while ( crMethod.myArgs.size() < i+1 )
02241           crMethod.myArgs.push_back( "[]" );
02242         crMethod.myArgs[ i ] = theCommand->GetArg( crMethod.myArgNb[i] );
02243       }
02244     }
02245   }
02246   if ( !usedCommand )
02247     myUnusedCommands.push_back( theCommand );
02248 }
02249 
02250 //================================================================================
02254 //================================================================================
02255 
02256 void _pyHypothesis::Flush()
02257 {
02258   if ( !IsAlgo() )
02259   {
02260     list < Handle(_pyCommand) >::iterator cmd = myArgCommands.begin();
02261     for ( ; cmd != myArgCommands.end(); ++cmd ) {
02262       // Add access to a wrapped mesh
02263       theGen->AddMeshAccessorMethod( *cmd );
02264       // Add access to a wrapped algorithm
02265       theGen->AddAlgoAccessorMethod( *cmd );
02266     }
02267     cmd = myUnusedCommands.begin();
02268     for ( ; cmd != myUnusedCommands.end(); ++cmd ) {
02269       // Add access to a wrapped mesh
02270       theGen->AddMeshAccessorMethod( *cmd );
02271       // Add access to a wrapped algorithm
02272       theGen->AddAlgoAccessorMethod( *cmd );
02273     }
02274   }
02275   // forget previous hypothesis modifications
02276   myArgCommands.clear();
02277   myUnusedCommands.clear();
02278 }
02279 
02280 //================================================================================
02284 //================================================================================
02285 
02286 void _pyHypothesis::ClearAllCommands()
02287 {
02288   GetCreationCmd()->Clear();
02289   list<Handle(_pyCommand)>::iterator cmd = myArgCommands.begin();
02290   for ( ; cmd != myArgCommands.end(); ++cmd )
02291     ( *cmd )->Clear();
02292   cmd = myUnusedCommands.begin();
02293   for ( ; cmd != myUnusedCommands.end(); ++cmd )
02294     ( *cmd )->Clear();
02295 }
02296 
02297 
02298 //================================================================================
02302 //================================================================================
02303 
02304 void _pyHypothesis::Assign( const Handle(_pyHypothesis)& theOther,
02305                             const _pyID&                 theMesh )
02306 {
02307   // myCreationCmd = theOther->myCreationCmd;
02308   myIsAlgo                  = theOther->myIsAlgo;
02309   myIsWrapped               = false;
02310   myGeom                    = theOther->myGeom;
02311   myMesh                    = theMesh;
02312   myAlgoType2CreationMethod = theOther->myAlgoType2CreationMethod;
02313   //myArgCommands             = theOther->myArgCommands;
02314   //myUnusedCommands          = theOther->myUnusedCommands;
02315   // init myCurCrMethod
02316   GetCreationMethod( theOther->GetAlgoType() );
02317 }
02318 
02319 //================================================================================
02323 //================================================================================
02324 
02325 bool _pyHypothesis::CanClear()
02326 {
02327   if ( IsInStudy() )
02328   {
02329     list< Handle(_pyObject) >::iterator obj = myReferredObjs.begin();
02330     for ( ; obj != myReferredObjs.end(); ++obj )
02331       if ( (*obj)->CanClear() )
02332         return true;
02333     return false;
02334   }
02335   return true;
02336 }
02337 
02338 //================================================================================
02342 //================================================================================
02343 
02344 void _pyHypothesis::ClearCommands()
02345 {
02346   // if ( !theGen->IsToKeepAllCommands() )
02347   // {
02348   //   bool isUsed = false;
02349   //   int lastComputeOrder = 0;
02350   //   list<Handle(_pyCommand) >::iterator cmd = myComputeCmds.begin();
02351   //   for ( ; cmd != myComputeCmds.end(); ++cmd )
02352   //     if ( ! (*cmd)->IsEmpty() )
02353   //     {
02354   //       isUsed = true;
02355   //       if ( (*cmd)->GetOrderNb() > lastComputeOrder )
02356   //         lastComputeOrder = (*cmd)->GetOrderNb();
02357   //     }
02358   //   if ( !isUsed )
02359   //   {
02360   //     SetRemovedFromStudy( true );
02361   //   }
02362   //   else
02363   //   {
02364   //     // clear my commands invoked after lastComputeOrder
02365   //     // map<TCollection_AsciiString, list< Handle(_pyCommand) > >::iterator m2c;
02366   //     // for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c )
02367   //     // {
02368   //     //   list< Handle(_pyCommand)> & cmds = m2c->second;
02369   //     //   if ( !cmds.empty() && cmds.back()->GetOrderNb() > lastComputeOrder )
02370   //     //     cmds.back()->Clear();
02371   //     // }
02372   //   }
02373   // }
02374   _pyObject::ClearCommands();
02375 }
02376 
02377 //================================================================================
02383 //================================================================================
02384 
02385 bool _pyHypothesis::GetReferredMeshesAndGeom( list< Handle(_pyMesh) >& meshes )
02386 {
02387   if ( IsAlgo() ) return true;
02388 
02389   bool geomPublished = true;
02390   vector< _AString > args;
02391   TType2CrMethod::iterator type2meth = myAlgoType2CreationMethod.begin();
02392   for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth )
02393   {
02394     CreationMethod& crMethod = type2meth->second;
02395     args.insert( args.end(), crMethod.myArgs.begin(), crMethod.myArgs.end());
02396   }
02397   list<Handle(_pyCommand)>::iterator cmd = myUnusedCommands.begin();
02398   for ( ; cmd != myUnusedCommands.end(); ++cmd ) {
02399     for ( int nb = (*cmd)->GetNbArgs(); nb; --nb )
02400       args.push_back( (*cmd)->GetArg( nb ));
02401   }
02402 
02403   for ( size_t i = 0; i < args.size(); ++i )
02404   {
02405     list< _pyID > idList = _pyCommand::GetStudyEntries( args[ i ]);
02406     if ( idList.empty() && !args[ i ].IsEmpty() )
02407       idList.push_back( args[ i ]);
02408     list< _pyID >::iterator id = idList.begin();
02409     for ( ; id != idList.end(); ++id )
02410     {
02411       Handle(_pyObject)   obj = theGen->FindObject( *id );
02412       if ( obj.IsNull() ) obj = theGen->FindHyp( *id );
02413       if ( obj.IsNull() )
02414       {
02415         if ( theGen->IsGeomObject( *id ) && theGen->IsNotPublished( *id ))
02416           geomPublished = false;
02417       }
02418       else
02419       {
02420         myReferredObjs.push_back( obj );
02421         Handle(_pyMesh) mesh = ObjectToMesh( obj );
02422         if ( !mesh.IsNull() )
02423           meshes.push_back( mesh );
02424         // prevent clearing not published hyps referred e.g. by "LayerDistribution"
02425         else if ( obj->IsKind( STANDARD_TYPE( _pyHypothesis )) && this->IsInStudy() )
02426           obj->SetRemovedFromStudy( false );
02427       }
02428     }
02429   }
02430   return geomPublished;
02431 }
02432 
02433 //================================================================================
02437 //================================================================================
02438 
02439 void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theCommand )
02440 {
02441   // parameters are discriminated by method name
02442   TCollection_AsciiString method = theCommand->GetMethod();
02443 
02444   // discriminate commands setting different parameters via one method
02445   // by passing parameter names like e.g. SetOption("size", "0.2")
02446   if ( theCommand->GetString().FirstLocationInSet( "'\"", 1, theCommand->Length() ) &&
02447        theCommand->GetNbArgs() > 1 )
02448   {
02449     // mangle method by appending a 1st textual arg
02450     for ( int iArg = 1; iArg <= theCommand->GetNbArgs(); ++iArg )
02451     {
02452       const TCollection_AsciiString& arg = theCommand->GetArg( iArg );
02453       if ( arg.Value(1) != '\"' && arg.Value(1) != '\'' ) continue;
02454       if ( !isalpha( arg.Value(2))) continue;
02455       method += arg;
02456       break;
02457     }
02458   }
02459   // parameters are discriminated by method name
02460   list< Handle(_pyCommand)>& cmds = myMeth2Commands[ theCommand->GetMethod() ];
02461   if ( !cmds.empty() && !isCmdUsedForCompute( cmds.back() ))
02462   {
02463     cmds.back()->Clear(); // previous parameter value has not been used
02464     cmds.back() = theCommand;
02465   }
02466   else
02467   {
02468     cmds.push_back( theCommand );
02469   }
02470 }
02471 
02472 //================================================================================
02476 //================================================================================
02477 
02478 bool _pyHypothesis::isCmdUsedForCompute( const Handle(_pyCommand) & cmd,
02479                                          _pyCommand::TAddr          avoidComputeAddr ) const
02480 {
02481   bool isUsed = false;
02482   map< _pyCommand::TAddr, list<Handle(_pyCommand) > >::const_iterator addr2cmds =
02483     myComputeAddr2Cmds.begin();
02484   for ( ; addr2cmds != myComputeAddr2Cmds.end() && !isUsed; ++addr2cmds )
02485   {
02486     if ( addr2cmds->first == avoidComputeAddr ) continue;
02487     const list<Handle(_pyCommand)> & cmds = addr2cmds->second;
02488     isUsed = ( std::find( cmds.begin(), cmds.end(), cmd ) != cmds.end() );
02489   }
02490   return isUsed;
02491 }
02492 
02493 //================================================================================
02497 //================================================================================
02498 
02499 void _pyHypothesis::MeshComputed( const Handle(_pyCommand)& theComputeCmd )
02500 {
02501   myComputeCmds.push_back( theComputeCmd );
02502   list<Handle(_pyCommand)>& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ];
02503 
02504   map<TCollection_AsciiString, list< Handle(_pyCommand) > >::iterator m2c;
02505   for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c )
02506     savedCmds.push_back( m2c->second.back() );
02507 }
02508 
02509 //================================================================================
02513 //================================================================================
02514 
02515 void _pyHypothesis::ComputeDiscarded( const Handle(_pyCommand)& theComputeCmd )
02516 {
02517   list<Handle(_pyCommand)>& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ];
02518 
02519   list<Handle(_pyCommand)>::iterator cmd = savedCmds.begin();
02520   for ( ; cmd != savedCmds.end(); ++cmd )
02521   {
02522     // check if a cmd has been used to compute another mesh
02523     if ( isCmdUsedForCompute( *cmd, theComputeCmd->GetAddress() ))
02524       continue;
02525     // check if a cmd is a sole command setting its parameter;
02526     // don't use method name for search as it can change
02527     map<TCollection_AsciiString, list<Handle(_pyCommand)> >::iterator
02528       m2cmds = myMeth2Commands.begin();
02529     for ( ; m2cmds != myMeth2Commands.end(); ++m2cmds )
02530     {
02531       list< Handle(_pyCommand)>& cmds = m2cmds->second;
02532       list< Handle(_pyCommand)>::iterator cmdIt = std::find( cmds.begin(), cmds.end(), *cmd );
02533       if ( cmdIt != cmds.end() )
02534       {
02535         if ( cmds.back() != *cmd )
02536         {
02537           cmds.erase( cmdIt );
02538           (*cmd)->Clear();
02539         }
02540         break;
02541       }
02542     }
02543   }
02544   myComputeAddr2Cmds.erase( theComputeCmd->GetAddress() );
02545 }
02546 
02547 //================================================================================
02552 //================================================================================
02553 
02554 void _pyHypothesis::setCreationArg( const int argNb, const _AString& arg )
02555 {
02556   if ( myCurCrMethod )
02557   {
02558     while ( myCurCrMethod->myArgs.size() < argNb )
02559       myCurCrMethod->myArgs.push_back( "None" );
02560     if ( arg.IsEmpty() )
02561       myCurCrMethod->myArgs[ argNb-1 ] = "None";
02562     else
02563       myCurCrMethod->myArgs[ argNb-1 ] = arg;
02564   }
02565 }
02566 
02567 
02568 //================================================================================
02573 //================================================================================
02574 
02575 void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
02576 {
02577   if ( GetAlgoType() == "Cartesian_3D" )
02578   {
02579     // CartesianParameters3D hyp
02580 
02581     if ( theCommand->GetMethod() == "SetSizeThreshold" )
02582     {
02583       setCreationArg( 4, theCommand->GetArg( 1 ));
02584       myArgCommands.push_back( theCommand );
02585       return;
02586     }
02587     if ( theCommand->GetMethod() == "SetGrid" ||
02588          theCommand->GetMethod() == "SetGridSpacing" )
02589     {
02590       TCollection_AsciiString axis = theCommand->GetArg( theCommand->GetNbArgs() );
02591       int iArg = axis.Value(1) - '0';
02592       if ( theCommand->GetMethod() == "SetGrid" )
02593       {
02594         setCreationArg( 1+iArg, theCommand->GetArg( 1 ));
02595       }
02596       else
02597       {
02598         myCurCrMethod->myArgs[ iArg ] = "[ ";
02599         myCurCrMethod->myArgs[ iArg ] += theCommand->GetArg( 1 );
02600         myCurCrMethod->myArgs[ iArg ] += ", ";
02601         myCurCrMethod->myArgs[ iArg ] += theCommand->GetArg( 2 );
02602         myCurCrMethod->myArgs[ iArg ] += "]";
02603       }
02604       myArgCommands.push_back( theCommand );
02605       rememberCmdOfParameter( theCommand );
02606       return;
02607     }
02608   }
02609 
02610   if( theCommand->GetMethod() == "SetLength" )
02611   {
02612     // NOW it is OBSOLETE
02613     // ex: hyp.SetLength(start, 1)
02614     //     hyp.SetLength(end,   0)
02615     ASSERT(( theCommand->GetArg( 2 ).IsIntegerValue() ));
02616     int i = 1 - theCommand->GetArg( 2 ).IntegerValue();
02617     TType2CrMethod::iterator type2meth = myAlgoType2CreationMethod.begin();
02618     for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth )
02619     {
02620       CreationMethod& crMethod = type2meth->second;
02621         while ( crMethod.myArgs.size() < i+1 )
02622           crMethod.myArgs.push_back( "[]" );
02623         crMethod.myArgs[ i ] = theCommand->GetArg( 1 ); // arg value
02624     }
02625     myArgCommands.push_back( theCommand );
02626   }
02627   else
02628   {
02629     _pyHypothesis::Process( theCommand );
02630   }
02631 }
02632 //================================================================================
02636 //================================================================================
02637 
02638 void _pyComplexParamHypo::Flush()
02639 {
02640   if ( IsWrapped() )
02641   {
02642     list < Handle(_pyCommand) >::iterator cmd = myUnusedCommands.begin();
02643     for ( ; cmd != myUnusedCommands.end(); ++cmd )
02644       if ((*cmd)->GetMethod() == "SetObjectEntry" )
02645         (*cmd)->Clear();
02646   }
02647 }
02648 
02649 //================================================================================
02654 //================================================================================
02655 
02656 void _pyLayerDistributionHypo::Process( const Handle(_pyCommand)& theCommand)
02657 {
02658   if ( theCommand->GetMethod() != "SetLayerDistribution" )
02659     return;
02660 
02661   const _pyID& hyp1dID = theCommand->GetArg( 1 );
02662   // Handle(_pyHypothesis) hyp1d = theGen->FindHyp( hyp1dID );
02663   // if ( hyp1d.IsNull() && ! my1dHyp.IsNull()) // apparently hypId changed at study restoration
02664   // {
02665   //   TCollection_AsciiString cmd =
02666   //     my1dHyp->GetCreationCmd()->GetIndentation() + hyp1dID + " = " + my1dHyp->GetID();
02667   //   Handle(_pyCommand) newCmd = theGen->AddCommand( cmd );
02668   //   theGen->SetCommandAfter( newCmd, my1dHyp->GetCreationCmd() );
02669   //   hyp1d = my1dHyp;
02670   // }
02671   // else if ( !my1dHyp.IsNull() && hyp1dID != my1dHyp->GetID() )
02672   // {
02673   //   // 1D hypo is already set, so distribution changes and the old
02674   //   // 1D hypo is thrown away
02675   //   my1dHyp->ClearAllCommands();
02676   // }
02677   // my1dHyp = hyp1d;
02678   // //my1dHyp->SetRemovedFromStudy( false );
02679 
02680   // if ( !myArgCommands.empty() )
02681   //   myArgCommands.back()->Clear();
02682   myCurCrMethod->myArgs.push_back( hyp1dID );
02683   myArgCommands.push_back( theCommand );
02684 }
02685 
02686 //================================================================================
02693 //================================================================================
02694 
02695 bool _pyLayerDistributionHypo::Addition2Creation( const Handle(_pyCommand)& theAdditionCmd,
02696                                                   const _pyID&              theMesh)
02697 {
02698   myIsWrapped = false;
02699 
02700   if ( my1dHyp.IsNull() )
02701     return false;
02702 
02703   // set "SetLayerDistribution()" after addition cmd
02704   theAdditionCmd->AddDependantCmd( myArgCommands.front() );
02705 
02706   _pyID geom = theAdditionCmd->GetArg( 1 );
02707 
02708   Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMesh, this );
02709   if ( !algo.IsNull() )
02710   {
02711     my1dHyp->SetMesh( theMesh );
02712     my1dHyp->SetConvMethodAndType(my1dHyp->GetAlgoCreationMethod().ToCString(),
02713                                   algo->GetAlgoType().ToCString());
02714     if ( !my1dHyp->Addition2Creation( theAdditionCmd, theMesh ))
02715       return false;
02716 
02717     // clear "SetLayerDistribution()" cmd
02718     myArgCommands.back()->Clear();
02719 
02720     // Convert my creation => me = RadialPrismAlgo.Get3DHypothesis()
02721 
02722     // find RadialPrism algo created on <geom> for theMesh
02723     GetCreationCmd()->SetObject( algo->GetID() );
02724     GetCreationCmd()->SetMethod( myAlgoMethod );
02725     GetCreationCmd()->RemoveArgs();
02726     theAdditionCmd->AddDependantCmd( GetCreationCmd() );
02727     myIsWrapped = true;
02728   }
02729   return myIsWrapped;
02730 }
02731 
02732 //================================================================================
02736 //================================================================================
02737 
02738 void _pyLayerDistributionHypo::Flush()
02739 {
02740   // as creation of 1D hyp was written later then it's edition,
02741   // we need to find all it's edition calls and process them
02742   list< Handle(_pyCommand) >::iterator cmd = myArgCommands.begin();
02743   _pyID prevNewName;
02744   for ( cmd = myArgCommands.begin(); cmd != myArgCommands.end(); ++cmd )
02745   {    
02746     const _pyID& hyp1dID = (*cmd)->GetArg( 1 );
02747     if ( hyp1dID.IsEmpty() ) continue;
02748 
02749     Handle(_pyHypothesis) hyp1d = theGen->FindHyp( hyp1dID );
02750 
02751     // make a new name for 1D hyp = "HypType" + "_Distribution"
02752     _pyID newName;
02753     if ( hyp1d.IsNull() ) // apparently hypId changed at study restoration
02754     {
02755       if ( prevNewName.IsEmpty() ) continue;
02756       newName = prevNewName;
02757     }
02758     else
02759     {
02760       if ( hyp1d->IsWrapped() ) {
02761         newName = hyp1d->GetCreationCmd()->GetMethod();
02762       }
02763       else {
02764         TCollection_AsciiString hypTypeQuoted = hyp1d->GetCreationCmd()->GetArg(1);
02765         newName = hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
02766       }
02767       newName += "_Distribution";
02768       prevNewName = newName;
02769     
02770       hyp1d->GetCreationCmd()->SetResultValue( newName );
02771     }
02772     list< Handle(_pyCommand) >& cmds = theGen->GetCommands();
02773     list< Handle(_pyCommand) >::iterator cmdIt = cmds.begin();
02774     for ( ; cmdIt != cmds.end(); ++cmdIt ) {
02775       const _pyID& objID = (*cmdIt)->GetObject();
02776       if ( objID == hyp1dID ) {
02777         if ( !hyp1d.IsNull() )
02778         {
02779           hyp1d->Process( *cmdIt );
02780           hyp1d->GetCreationCmd()->AddDependantCmd( *cmdIt );
02781         }
02782         ( *cmdIt )->SetObject( newName );
02783       }
02784     }
02785     // Set new hyp name to SetLayerDistribution(hyp1dID) cmd
02786     (*cmd)->SetArg( 1, newName );
02787   }
02788 }
02789 
02790 //================================================================================
02797 //================================================================================
02798 
02799 bool _pyNumberOfSegmentsHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
02800                                                 const _pyID&              theMesh)
02801 {
02802   if ( IsWrappable( theMesh ) && myCurCrMethod->myArgs.size() > 1 ) {
02803     // scale factor (2-nd arg) is provided: clear SetDistrType(1) command
02804     bool scaleDistrType = false;
02805     list<Handle(_pyCommand)>::reverse_iterator cmd = myUnusedCommands.rbegin();
02806     for ( ; cmd != myUnusedCommands.rend(); ++cmd ) {
02807       if ( (*cmd)->GetMethod() == "SetDistrType" ) {
02808         if ( (*cmd)->GetArg( 1 ) == "1" ) {
02809           scaleDistrType = true;
02810           (*cmd)->Clear();
02811         }
02812         else if ( !scaleDistrType ) {
02813           // distribution type changed: remove scale factor from args
02814           TType2CrMethod::iterator type2meth = myAlgoType2CreationMethod.begin();
02815           for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth )
02816           {
02817             CreationMethod& crMethod = type2meth->second;
02818             if ( crMethod.myArgs.size() == 2 )
02819               crMethod.myArgs.pop_back();
02820           }
02821           break;
02822         }
02823       }
02824     }
02825   }
02826   return _pyHypothesis::Addition2Creation( theCmd, theMesh );
02827 }
02828 
02829 //================================================================================
02833 //================================================================================
02834 
02835 void _pyNumberOfSegmentsHyp::Flush()
02836 {
02837   // find number of the last SetDistrType() command
02838   list<Handle(_pyCommand)>::reverse_iterator cmd = myUnusedCommands.rbegin();
02839   int distrTypeNb = 0;
02840   for ( ; !distrTypeNb && cmd != myUnusedCommands.rend(); ++cmd )
02841     if ( (*cmd)->GetMethod() == "SetDistrType" )
02842       distrTypeNb = (*cmd)->GetOrderNb();
02843     else if (IsWrapped() && (*cmd)->GetMethod() == "SetObjectEntry" )
02844       (*cmd)->Clear();
02845 
02846   // clear commands before the last SetDistrType()
02847   list<Handle(_pyCommand)> * cmds[2] = { &myArgCommands, &myUnusedCommands };
02848   for ( int i = 0; i < 2; ++i ) {
02849     set<TCollection_AsciiString> uniqueMethods;
02850     list<Handle(_pyCommand)> & cmdList = *cmds[i];
02851     for ( cmd = cmdList.rbegin(); cmd != cmdList.rend(); ++cmd )
02852     {
02853       bool clear = ( (*cmd)->GetOrderNb() < distrTypeNb );
02854       const TCollection_AsciiString& method = (*cmd)->GetMethod();
02855       if ( !clear || method == "SetNumberOfSegments" ) {
02856         bool isNewInSet = uniqueMethods.insert( method ).second;
02857         clear = !isNewInSet;
02858       }
02859       if ( clear )
02860         (*cmd)->Clear();
02861     }
02862     cmdList.clear();
02863   }
02864 }
02865 
02866 //================================================================================
02874 //================================================================================
02875 
02876 bool _pySegmentLengthAroundVertexHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
02877                                                          const _pyID&              theMeshID)
02878 {
02879   if ( IsWrappable( theMeshID )) {
02880 
02881     _pyID vertex = theCmd->GetArg( 1 );
02882 
02883     // the problem here is that segment algo will not be found
02884     // by pyHypothesis::Addition2Creation() for <vertex>, so we try to find
02885     // geometry where segment algorithm is assigned
02886     Handle(_pyHypothesis) algo;
02887     _pyID geom = vertex;
02888     while ( algo.IsNull() && !geom.IsEmpty()) {
02889       // try to find geom as a father of <vertex>
02890       geom = FatherID( geom );
02891       algo = theGen->FindAlgo( geom, theMeshID, this );
02892     }
02893     if ( algo.IsNull() )
02894       return false; // also possible to find geom as brother of veretex...
02895     // set geom instead of vertex
02896     theCmd->SetArg( 1, geom );
02897 
02898     // set vertex as a second arg
02899     if ( myCurCrMethod->myArgs.size() < 1) setCreationArg( 1, "1" ); // :(
02900     setCreationArg( 2, vertex );
02901 
02902     // mesh.AddHypothesis(vertex, SegmentLengthAroundVertex) -->
02903     // theMeshID.LengthNearVertex( length, vertex )
02904     return _pyHypothesis::Addition2Creation( theCmd, theMeshID );
02905   }
02906   return false;
02907 }
02908 
02909 //================================================================================
02914 //================================================================================
02915 
02916 _pyAlgorithm::_pyAlgorithm(const Handle(_pyCommand)& theCreationCmd)
02917   : _pyHypothesis( theCreationCmd )
02918 {
02919   myIsAlgo = true;
02920 }
02921 
02922 //================================================================================
02929 //================================================================================
02930 
02931 bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd,
02932                                       const _pyID&              theMeshID)
02933 {
02934   // mesh.AddHypothesis(geom,algo) --> theMeshID.myCreationMethod()
02935   if ( _pyHypothesis::Addition2Creation( theCmd, theMeshID )) {
02936     theGen->SetAccessorMethod( GetID(), "GetAlgorithm()" );
02937     return true;
02938   }
02939   return false;
02940 }
02941 
02942 //================================================================================
02948 //================================================================================
02949 
02950 int _pyCommand::GetBegPos( int thePartIndex )
02951 {
02952   if ( IsEmpty() )
02953     return EMPTY;
02954   if ( myBegPos.Length() < thePartIndex )
02955     return UNKNOWN;
02956   return myBegPos( thePartIndex );
02957 }
02958 
02959 //================================================================================
02965 //================================================================================
02966 
02967 void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
02968 {
02969   while ( myBegPos.Length() < thePartIndex )
02970     myBegPos.Append( UNKNOWN );
02971   myBegPos( thePartIndex ) = thePosition;
02972 }
02973 
02974 //================================================================================
02979 //================================================================================
02980 
02981 TCollection_AsciiString _pyCommand::GetIndentation()
02982 {
02983   int end = 1;
02984   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
02985     GetWord( myString, end, true );
02986   else
02987     end = GetBegPos( RESULT_IND );
02988   return myString.SubString( 1, end - 1 );
02989 }
02990 
02991 //================================================================================
02996 //================================================================================
02997 
02998 const TCollection_AsciiString & _pyCommand::GetResultValue()
02999 {
03000   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
03001   {
03002     SetBegPos( RESULT_IND, EMPTY );
03003     int begPos, endPos = myString.Location( "=", 1, Length() );
03004     if ( endPos )
03005     {
03006       begPos = 1;
03007       while ( begPos < endPos && isspace( myString.Value( begPos ))) ++begPos;
03008       if ( begPos < endPos )
03009       {
03010         SetBegPos( RESULT_IND, begPos );
03011         --endPos;
03012         while ( begPos < endPos && isspace( myString.Value( endPos ))) --endPos;
03013         myRes = myString.SubString( begPos, endPos );
03014       }
03015     }
03016   }
03017   return myRes;
03018 }
03019 
03020 //================================================================================
03025 //================================================================================
03026 
03027 const int _pyCommand::GetNbResultValues()
03028 {
03029   int begPos = 1;
03030   int Nb=0;
03031   int endPos = myString.Location( "=", 1, Length() );
03032   TCollection_AsciiString str = "";
03033   while ( begPos < endPos) {
03034     str = GetWord( myString, begPos, true );
03035     begPos = begPos+ str.Length();
03036     Nb++;
03037   }
03038   return (Nb-1);
03039 }
03040 
03041 
03042 //================================================================================
03048 //================================================================================
03049 TCollection_AsciiString _pyCommand::GetResultValue(int res)
03050 {
03051   int begPos = 1;
03052   if ( SkipSpaces( myString, begPos ) && myString.Value( begPos ) == '[' )
03053     ++begPos; // skip [, else the whole list is returned
03054   int endPos = myString.Location( "=", 1, Length() );
03055   int Nb=0;
03056   while ( begPos < endPos) {
03057     _AString result = GetWord( myString, begPos, true );
03058     begPos = begPos + result.Length();
03059     Nb++;
03060     if(res == Nb) {
03061       result.RemoveAll('[');
03062       result.RemoveAll(']');
03063       return result;
03064     }
03065     if(Nb>res)
03066       break;
03067   }
03068   return theEmptyString;
03069 }
03070 
03071 //================================================================================
03076 //================================================================================
03077 
03078 const TCollection_AsciiString & _pyCommand::GetObject()
03079 {
03080   if ( GetBegPos( OBJECT_IND ) == UNKNOWN )
03081   {
03082     // beginning
03083     int begPos = GetBegPos( RESULT_IND ) + myRes.Length();
03084     if ( begPos < 1 ) {
03085       begPos = myString.Location( "=", 1, Length() ) + 1;
03086       // is '=' in the string argument (for example, name) or not
03087       int nb1 = 0; // number of ' character at the left of =
03088       int nb2 = 0; // number of " character at the left of =
03089       for ( int i = 1; i < begPos-1; i++ ) {
03090         if ( myString.Value( i )=='\'' )
03091           nb1 += 1;
03092         else if ( myString.Value( i )=='"' )
03093           nb2 += 1;
03094       }
03095       // if number of ' or " is not divisible by 2,
03096       // then get an object at the start of the command
03097       if ( nb1 % 2 != 0 || nb2 % 2 != 0 )
03098         begPos = 1;
03099     }
03100     myObj = GetWord( myString, begPos, true );
03101     // check if object is complex,
03102     // so far consider case like "smesh.smesh.Method()"
03103     if ( int bracketPos = myString.Location( "(", begPos, Length() )) {
03104       //if ( bracketPos==0 ) bracketPos = Length();
03105       int dotPos = begPos+myObj.Length();
03106       while ( dotPos+1 < bracketPos ) {
03107         if ( int pos = myString.Location( ".", dotPos+1, bracketPos ))
03108           dotPos = pos;
03109         else
03110           break;
03111       }
03112       if ( dotPos > begPos+myObj.Length() )
03113         myObj = myString.SubString( begPos, dotPos-1 );
03114     }
03115     // 1st word after '=' is an object
03116     // else // no method -> no object
03117     // {
03118     //   myObj.Clear();
03119     //   begPos = EMPTY;
03120     // }
03121     // store
03122     SetBegPos( OBJECT_IND, begPos );
03123   }
03124   //SCRUTE(myObj);
03125   return myObj;
03126 }
03127 
03128 //================================================================================
03133 //================================================================================
03134 
03135 const TCollection_AsciiString & _pyCommand::GetMethod()
03136 {
03137   if ( GetBegPos( METHOD_IND ) == UNKNOWN )
03138   {
03139     // beginning
03140     int begPos = GetBegPos( OBJECT_IND ) + myObj.Length();
03141     bool forward = true;
03142     if ( begPos < 1 ) {
03143       begPos = myString.Location( "(", 1, Length() ) - 1;
03144       forward = false;
03145     }
03146     // store
03147     myMeth = GetWord( myString, begPos, forward );
03148     SetBegPos( METHOD_IND, begPos );
03149   }
03150   //SCRUTE(myMeth);
03151   return myMeth;
03152 }
03153 
03154 //================================================================================
03159 //================================================================================
03160 
03161 const TCollection_AsciiString & _pyCommand::GetArg( int index )
03162 {
03163   if ( GetBegPos( ARG1_IND ) == UNKNOWN )
03164   {
03165     // Find all args
03166 
03167     int pos = GetBegPos( METHOD_IND ) + myMeth.Length();
03168     if ( pos < 1 )
03169       pos = myString.Location( "(", 1, Length() );
03170     else
03171       --pos;
03172 
03173     // we are at or before '(', skip it if present
03174     if ( pos > 0 ) {
03175       while ( pos <= Length() && myString.Value( pos ) != '(' ) ++pos;
03176       if ( pos > Length() )
03177         pos = 0;
03178     }
03179     if ( pos < 1 ) {
03180       SetBegPos( ARG1_IND, 0 ); // even no '('
03181       return theEmptyString;
03182     }
03183     ++pos;
03184 
03185     list< TCollection_AsciiString > separatorStack( 1, ",)");
03186     bool ignoreNesting = false;
03187     int prevPos = pos;
03188     while ( pos <= Length() )
03189     {
03190       const char chr = myString.Value( pos );
03191 
03192       if ( separatorStack.back().Location( chr, 1, separatorStack.back().Length()))
03193       {
03194         if ( separatorStack.size() == 1 ) // a comma dividing args or a terminal ')' found
03195         {
03196           while ( pos-1 >= prevPos && isspace( myString.Value( prevPos )))
03197             ++prevPos;
03198           TCollection_AsciiString arg;
03199           if ( pos-1 >= prevPos ) {
03200             arg = myString.SubString( prevPos, pos-1 );
03201             arg.RightAdjust(); // remove spaces
03202             arg.LeftAdjust();
03203           }
03204           if ( !arg.IsEmpty() || chr == ',' )
03205           {
03206             SetBegPos( ARG1_IND + myArgs.Length(), prevPos );
03207             myArgs.Append( arg );
03208           }
03209           if ( chr == ')' )
03210             break;
03211           prevPos = pos+1;
03212         }
03213         else // end of nesting args found
03214         {
03215           separatorStack.pop_back();
03216           ignoreNesting = false;
03217         }
03218       }
03219       else if ( !ignoreNesting )
03220       {
03221         switch ( chr ) {
03222         case '(' : separatorStack.push_back(")"); break;
03223         case '[' : separatorStack.push_back("]"); break;
03224         case '\'': separatorStack.push_back("'");  ignoreNesting=true; break;
03225         case '"' : separatorStack.push_back("\""); ignoreNesting=true; break;
03226         default:;
03227         }
03228       }
03229       ++pos;
03230     }
03231   }
03232   if ( myArgs.Length() < index )
03233     return theEmptyString;
03234   return myArgs( index );
03235 }
03236 
03237 //================================================================================
03243 //================================================================================
03244 
03245 static inline bool isWord(const char c, const bool dotIsWord)
03246 {
03247   return
03248     !isspace(c) && c != ',' && c != '=' && c != ')' && c != '(' && ( dotIsWord || c != '.');
03249 }
03250 
03251 //================================================================================
03259 //================================================================================
03260 
03261 TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString,
03262                                             int &      theStartPos,
03263                                             const bool theForward,
03264                                             const bool dotIsWord )
03265 {
03266   int beg = theStartPos, end = theStartPos;
03267   theStartPos = EMPTY;
03268   if ( beg < 1 || beg > theString.Length() )
03269     return theEmptyString;
03270 
03271   if ( theForward ) { // search forward
03272     // beg
03273     while ( beg <= theString.Length() && !isWord( theString.Value( beg ), dotIsWord))
03274       ++beg;
03275     if ( beg > theString.Length() )
03276       return theEmptyString; // no word found
03277     // end
03278     end = beg + 1;
03279     char begChar = theString.Value( beg );
03280     if ( begChar == '"' || begChar == '\'' || begChar == '[') {
03281       char endChar = ( begChar == '[' ) ? ']' : begChar;
03282       // end is at the corresponding quoting mark or bracket
03283       while ( end < theString.Length() &&
03284               ( theString.Value( end ) != endChar || theString.Value( end-1 ) == '\\'))
03285         ++end;
03286     }
03287     else {
03288       while ( end <= theString.Length() && isWord( theString.Value( end ), dotIsWord))
03289         ++end;
03290       --end;
03291     }
03292   }
03293   else {  // search backward
03294     // end
03295     while ( end > 0 && !isWord( theString.Value( end ), dotIsWord))
03296       --end;
03297     if ( end == 0 )
03298       return theEmptyString; // no word found
03299     beg = end - 1;
03300     char endChar = theString.Value( end );
03301     if ( endChar == '"' || endChar == '\'' || endChar == ']') {
03302       char begChar = ( endChar == ']' ) ? '[' : endChar;
03303       // beg is at the corresponding quoting mark
03304       while ( beg > 1 &&
03305               ( theString.Value( beg ) != begChar || theString.Value( beg-1 ) == '\\'))
03306         --beg;
03307     }
03308     else {
03309       while ( beg > 0 && isWord( theString.Value( beg ), dotIsWord))
03310         --beg;
03311       ++beg;
03312     }
03313   }
03314   theStartPos = beg;
03315   //cout << theString << " ---- " << beg << " - " << end << endl;
03316   return theString.SubString( beg, end );
03317 }
03318 
03319 //================================================================================
03323 //================================================================================
03324 
03325 bool _pyCommand::IsStudyEntry( const TCollection_AsciiString& str )
03326 {
03327   if ( str.Length() < 5 ) return false;
03328 
03329   int nbColons = 0, isColon;
03330   for ( int i = 1; i <= str.Length(); ++i )
03331   {
03332     char c = str.Value(i);
03333     if (!( isColon = (c == ':')) && ( c < '0' || c > '9' ))
03334       return false;
03335     nbColons += isColon;
03336   }
03337   return nbColons > 2 && str.Length()-nbColons > 2;
03338 }
03339 
03340 //================================================================================
03344 //================================================================================
03345 
03346 std::list< _pyID > _pyCommand::GetStudyEntries( const TCollection_AsciiString& str )
03347 {
03348   std::list< _pyID > resList;
03349   int pos = 0;
03350   while ( ++pos <= str.Length() )
03351   {
03352     if ( !isdigit( str.Value( pos ))) continue;
03353     if ( pos != 1 && ( isalpha( str.Value( pos-1 ) || str.Value( pos-1 ) == ':'))) continue;
03354 
03355     int end = pos;
03356     while ( ++end <= str.Length() && ( isdigit( str.Value( end )) || str.Value( end ) == ':' ));
03357     _pyID entry = str.SubString( pos, end-1 );
03358     pos = end;
03359     if ( IsStudyEntry( entry ))
03360       resList.push_back( entry );
03361   }
03362   return resList;
03363 }
03364 
03365 //================================================================================
03372 //================================================================================
03373 
03374 bool _pyCommand::SkipSpaces( const TCollection_AsciiString & theString, int & thePos )
03375 {
03376   if ( thePos < 1 || thePos > theString.Length() )
03377     return false;
03378 
03379   while ( thePos <= theString.Length() && isspace( theString.Value( thePos )))
03380     ++thePos;
03381 
03382   return thePos <= theString.Length();
03383 }
03384 
03385 //================================================================================
03392 //================================================================================
03393 
03394 void _pyCommand::SetPart(int thePartIndex, const TCollection_AsciiString& thePart,
03395                         TCollection_AsciiString& theOldPart)
03396 {
03397   int pos = GetBegPos( thePartIndex );
03398   if ( pos <= Length() && theOldPart != thePart)
03399   {
03400     TCollection_AsciiString seperator;
03401     if ( pos < 1 ) {
03402       pos = GetBegPos( thePartIndex + 1 );
03403       if ( pos < 1 ) return;
03404       switch ( thePartIndex ) {
03405       case RESULT_IND: seperator = " = "; break;
03406       case OBJECT_IND: seperator = "."; break;
03407       case METHOD_IND: seperator = "()"; break;
03408       default:;
03409       }
03410     }
03411     myString.Remove( pos, theOldPart.Length() );
03412     if ( !seperator.IsEmpty() )
03413       myString.Insert( pos , seperator );
03414     myString.Insert( pos, thePart );
03415     // update starting positions of the following parts
03416     int posDelta = thePart.Length() + seperator.Length() - theOldPart.Length();
03417     for ( int i = thePartIndex + 1; i <= myBegPos.Length(); ++i ) {
03418       if ( myBegPos( i ) > 0 )
03419         myBegPos( i ) += posDelta;
03420     }
03421     theOldPart = thePart;
03422   }
03423 }
03424 
03425 //================================================================================
03431 //================================================================================
03432 
03433 void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg)
03434 {
03435   FindAllArgs();
03436   int argInd = ARG1_IND + index - 1;
03437   int pos = GetBegPos( argInd );
03438   if ( pos < 1 ) // no index-th arg exist, append inexistent args
03439   {
03440     // find a closing parenthesis
03441     if ( GetNbArgs() != 0 && index <= GetNbArgs() ) {
03442       int lastArgInd = GetNbArgs();
03443       pos = GetBegPos( ARG1_IND + lastArgInd  - 1 ) + GetArg( lastArgInd ).Length();
03444       while ( pos > 0 && pos <= Length() && myString.Value( pos ) != ')' )
03445         ++pos;
03446     }
03447     else {
03448       pos = Length();
03449       while ( pos > 0 && myString.Value( pos ) != ')' )
03450         --pos;
03451     }
03452     if ( pos < 1 || myString.Value( pos ) != ')' ) { // no parentheses at all
03453       myString += "()";
03454       pos = Length();
03455     }
03456     while ( myArgs.Length() < index ) {
03457       if ( myArgs.Length() )
03458         myString.Insert( pos++, "," );
03459       myArgs.Append("None");
03460       myString.Insert( pos, myArgs.Last() );
03461       SetBegPos( ARG1_IND + myArgs.Length() - 1, pos );
03462       pos += myArgs.Last().Length();
03463     }
03464   }
03465   SetPart( argInd, theArg, myArgs( index ));
03466 }
03467 
03468 //================================================================================
03472 //================================================================================
03473 
03474 void _pyCommand::RemoveArgs()
03475 {
03476   if ( int pos = myString.Location( '(', 1, Length() ))
03477     myString.Trunc( pos );
03478   myString += ")";
03479   myArgs.Clear();
03480   if ( myBegPos.Length() >= ARG1_IND )
03481     myBegPos.Remove( ARG1_IND, myBegPos.Length() );
03482 }
03483 
03484 //================================================================================
03488 //================================================================================
03489 
03490 void _pyCommand::Comment()
03491 {
03492   if ( IsEmpty() ) return;
03493 
03494   int i = 1;
03495   while ( i <= Length() && isspace( myString.Value(i) )) ++i;
03496   if ( i <= Length() )
03497   {
03498     myString.Insert( i, "#" );
03499     for ( int iPart = 0; iPart < myBegPos.Length(); ++iPart )
03500     {
03501       int begPos = GetBegPos( iPart );
03502       if ( begPos != UNKNOWN )
03503         SetBegPos( iPart, begPos + 1 );
03504     }
03505   }
03506 }
03507 
03508 //================================================================================
03512 //================================================================================
03513 
03514 bool _pyCommand::SetDependentCmdsAfter() const
03515 {
03516   bool orderChanged = false;
03517   list< Handle(_pyCommand)>::const_reverse_iterator cmd = myDependentCmds.rbegin();
03518   for ( ; cmd != myDependentCmds.rend(); ++cmd ) {
03519     if ( (*cmd)->GetOrderNb() < GetOrderNb() ) {
03520       orderChanged = true;
03521       theGen->SetCommandAfter( *cmd, this );
03522       (*cmd)->SetDependentCmdsAfter();
03523     }
03524   }
03525   return orderChanged;
03526 }
03527 //================================================================================
03534 //================================================================================
03535 
03536 bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod )
03537 {
03538   if ( !theAcsMethod )
03539     return false;
03540   // start object search from the object, i.e. ignore result
03541   GetObject();
03542   int beg = GetBegPos( OBJECT_IND );
03543   if ( beg < 1 || beg > Length() )
03544     return false;
03545   bool added = false;
03546   while (( beg = myString.Location( theObjectID, beg, Length() )))
03547   {
03548     // check that theObjectID is not just a part of a longer ID
03549     int afterEnd = beg + theObjectID.Length();
03550     Standard_Character c = myString.Value( afterEnd );
03551     if ( !isalnum( c ) && c != ':' ) {
03552       // check if accessor method already present
03553       if ( c != '.' ||
03554            myString.Location( (char*) theAcsMethod, afterEnd, Length() ) != afterEnd+1) {
03555         // insertion
03556         int oldLen = Length();
03557         myString.Insert( afterEnd, (char*) theAcsMethod );
03558         myString.Insert( afterEnd, "." );
03559         // update starting positions of the parts following the modified one
03560         int posDelta = Length() - oldLen;
03561         for ( int i = 1; i <= myBegPos.Length(); ++i ) {
03562           if ( myBegPos( i ) > afterEnd )
03563             myBegPos( i ) += posDelta;
03564         }
03565         added = true;
03566       }
03567     }
03568     beg = afterEnd; // is a part - next search
03569   }
03570   return added;
03571 }
03572 
03573 //================================================================================
03577 //================================================================================
03578 
03579 _pyObject::_pyObject(const Handle(_pyCommand)& theCreationCmd, const _pyID& theID)
03580   : myID(theID), myCreationCmd(theCreationCmd), myIsPublished(false)
03581 {
03582   setID( theID );
03583 }
03584 
03585 //================================================================================
03589 //================================================================================
03590 
03591 void _pyObject::setID(const _pyID& theID)
03592 {
03593   myID = theID;
03594   myIsPublished = !theGen->IsNotPublished( GetID() );
03595 }
03596 
03597 //================================================================================
03601 //================================================================================
03602 
03603 void _pyObject::ClearCommands()
03604 {
03605   if ( !CanClear() )
03606     return;
03607 
03608   if ( !myCreationCmd.IsNull() )
03609     myCreationCmd->Clear();
03610 
03611   list< Handle(_pyCommand) >::iterator cmd = myProcessedCmds.begin();
03612   for ( ; cmd != myProcessedCmds.end(); ++cmd )
03613     (*cmd)->Clear();
03614 }
03615 
03616 //================================================================================
03621 //================================================================================
03622 
03623 const char* _pyObject::AccessorMethod() const
03624 {
03625   return 0;
03626 }
03627 //================================================================================
03631 //================================================================================
03632 
03633 _pyID _pyObject::FatherID(const _pyID & childID)
03634 {
03635   int colPos = childID.SearchFromEnd(':');
03636   if ( colPos > 0 )
03637     return childID.SubString( 1, colPos-1 );
03638   return "";
03639 }
03640 
03641 //================================================================================
03645 //================================================================================
03646 
03647 void _pySelfEraser::Flush()
03648 {
03649   if ( GetNbCalls() == 0 )
03650     GetCreationCmd()->Clear();
03651 }
03652 
03653 //================================================================================
03657 //================================================================================
03658 
03659 _pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd):
03660   _pyObject(theCreationCmd)
03661 {
03662   myMesh = ObjectToMesh( theGen->FindObject( theCreationCmd->GetObject() ));
03663 }
03664 
03665 //================================================================================
03669 //================================================================================
03670 
03671 void _pySubMesh::Process( const Handle(_pyCommand)& theCommand )
03672 {
03673   _pyObject::Process(theCommand); // count calls of Process()
03674   GetCreationCmd()->AddDependantCmd( theCommand );
03675 }
03676 
03677 //================================================================================
03681 //================================================================================
03682 
03683 void _pySubMesh::Flush()
03684 {
03685   if ( GetNbCalls() == 0 ) // move to the end of all commands
03686     theGen->GetLastCommand()->AddDependantCmd( GetCreationCmd() );
03687   else if ( !myCreator.IsNull() )
03688     // move to be just after creator
03689     myCreator->GetCreationCmd()->AddDependantCmd( GetCreationCmd() );
03690 }
03691 
03692 //================================================================================
03696 //================================================================================
03697 
03698 _pyGroup::_pyGroup(const Handle(_pyCommand)& theCreationCmd, const _pyID & id)
03699   :_pySubMesh(theCreationCmd)
03700 {
03701   if ( !id.IsEmpty() )
03702     setID( id );
03703 
03704   myCanClearCreationCmd = true;
03705 
03706   const _AString& method = theCreationCmd->GetMethod();
03707   if ( method == "CreateGroup" ) // CreateGroup() --> CreateEmptyGroup()
03708   {
03709     theCreationCmd->SetMethod( "CreateEmptyGroup" );
03710   }
03711   // ----------------------------------------------------------------------
03712   else if ( method == "CreateGroupFromGEOM" ) // (type, name, grp)
03713   {
03714     _pyID geom = theCreationCmd->GetArg( 3 );
03715     // VSR 24/12/2010. PAL21106: always use GroupOnGeom() function on dump
03716     // next if(){...} section is commented
03717     //if ( sameGroupType( geom, theCreationCmd->GetArg( 1 )) ) { // --> Group(geom)
03718     //  theCreationCmd->SetMethod( "Group" );
03719     //  theCreationCmd->RemoveArgs();
03720     //  theCreationCmd->SetArg( 1, geom );
03721     //}
03722     //else {
03723     // ------------------------->>>>> GroupOnGeom( geom, name, typ )
03724       _pyID type = theCreationCmd->GetArg( 1 );
03725       _pyID name = theCreationCmd->GetArg( 2 );
03726       theCreationCmd->SetMethod( "GroupOnGeom" );
03727       theCreationCmd->RemoveArgs();
03728       theCreationCmd->SetArg( 1, geom );
03729       theCreationCmd->SetArg( 2, name );
03730       theCreationCmd->SetArg( 3, type );
03731     //}
03732   }
03733   else if ( method == "CreateGroupFromFilter" )
03734   {
03735     // -> GroupOnFilter(typ, name, aFilter0x4743dc0 -> aFilter_1)
03736     theCreationCmd->SetMethod( "GroupOnFilter" );
03737 
03738     _pyID filterID = theCreationCmd->GetArg(3);
03739     Handle(_pyFilter) filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID ));
03740     if ( !filter.IsNull())
03741     {
03742       if ( !filter->GetNewID().IsEmpty() )
03743         theCreationCmd->SetArg( 3, filter->GetNewID() );
03744       filter->AddUser( this );
03745     }
03746     myFilter = filter;
03747   }
03748   else
03749   {
03750     // theCreationCmd does something else apart from creation of this group
03751     // and thus it can't be cleared if this group is removed
03752     myCanClearCreationCmd = false;
03753   }
03754 }
03755 
03756 //================================================================================
03760 //================================================================================
03761 
03762 void _pyGroup::Process( const Handle(_pyCommand)& theCommand)
03763 {
03764   // Convert the following set of commands into mesh.MakeGroupByFilter(groupName, theFilter)
03765   // group = mesh.CreateEmptyGroup( elemType, groupName )
03766   // aFilter.SetMesh(mesh)
03767   // nbAdd = group.AddFrom( aFilter )
03768   Handle(_pyFilter) filter;
03769   if ( theCommand->GetMethod() == "AddFrom" )
03770   {
03771     _pyID idSource = theCommand->GetArg(1);
03772     // check if idSource is a filter
03773     filter = Handle(_pyFilter)::DownCast( theGen->FindObject( idSource ));
03774     if ( !filter.IsNull() )
03775     {
03776       // find aFilter.SetMesh(mesh) to clear it, it should be just before theCommand
03777       list< Handle(_pyCommand) >::reverse_iterator cmdIt = theGen->GetCommands().rbegin();
03778       while ( *cmdIt != theCommand ) ++cmdIt;
03779       while ( (*cmdIt)->GetOrderNb() != 1 )
03780       {
03781         const Handle(_pyCommand)& setMeshCmd = *(++cmdIt);
03782         if ((setMeshCmd->GetObject() == idSource ||
03783              setMeshCmd->GetObject() == filter->GetNewID() )
03784             &&
03785             setMeshCmd->GetMethod() == "SetMesh")
03786         {
03787           setMeshCmd->Clear();
03788           break;
03789         }
03790       }
03791       // replace 3 commands by one
03792       theCommand->Clear();
03793       const Handle(_pyCommand)& makeGroupCmd = GetCreationCmd();
03794       TCollection_AsciiString name = makeGroupCmd->GetArg( 2 );
03795       if ( !filter->GetNewID().IsEmpty() )
03796         idSource = filter->GetNewID();
03797       makeGroupCmd->SetMethod( "MakeGroupByFilter" );
03798       makeGroupCmd->SetArg( 1, name );
03799       makeGroupCmd->SetArg( 2, idSource );
03800     }
03801   }
03802   else if ( theCommand->GetMethod() == "SetFilter" )
03803   {
03804     // set new name of a filter or clear the command if the same filter is set
03805     _pyID filterID = theCommand->GetArg(1);
03806     filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID ));
03807     if ( !myFilter.IsNull() && filter == myFilter )
03808       theCommand->Clear();
03809     else if ( !filter.IsNull() && !filter->GetNewID().IsEmpty() )
03810       theCommand->SetArg( 1, filter->GetNewID() );
03811     myFilter = filter;
03812   }
03813   else if ( theCommand->GetMethod() == "GetFilter" )
03814   {
03815     // GetFilter() returns a filter with other ID, make myFilter process
03816     // calls of the returned filter
03817     if ( !myFilter.IsNull() )
03818     {
03819       theGen->SetProxyObject( theCommand->GetResultValue(), myFilter );
03820       theCommand->Clear();
03821     }
03822   }
03823 
03824   if ( !filter.IsNull() )
03825     filter->AddUser( this );
03826 
03827   theGen->AddMeshAccessorMethod( theCommand );
03828 }
03829 
03830 //================================================================================
03836 //================================================================================
03837 
03838 void _pyGroup::Flush()
03839 {
03840   if ( !theGen->IsToKeepAllCommands() &&
03841        myCreationCmd && !myCanClearCreationCmd )
03842   {
03843     myCreationCmd.Nullify(); // this way myCreationCmd won't be cleared
03844   }
03845 }
03846 
03847 //================================================================================
03851 //================================================================================
03852 
03853 _pyFilter::_pyFilter(const Handle(_pyCommand)& theCreationCmd, const _pyID& newID/*=""*/)
03854   :_pyObject(theCreationCmd), myNewID( newID )
03855 {
03856 }
03857 
03858 //================================================================================
03863 //================================================================================
03864 
03865 void _pyFilter::Process( const Handle(_pyCommand)& theCommand)
03866 {
03867   if ( theCommand->GetObject() == GetID() )
03868     _pyObject::Process(theCommand); // count commands
03869 
03870   if ( !myNewID.IsEmpty() )
03871     theCommand->SetObject( myNewID );
03872     
03873   // Convert the following set of commands into smesh.GetFilterFromCriteria(criteria)
03874   // aFilter0x2aaab0487080 = aFilterManager.CreateFilter()
03875   // aFilter0x2aaab0487080.SetCriteria(aCriteria)
03876   if ( GetNbCalls() == 1 && // none method was called before this SetCriteria() call
03877        theCommand->GetMethod() == "SetCriteria")
03878   {
03879     // aFilter.SetCriteria(aCriteria) ->
03880     // aFilter = smesh.GetFilterFromCriteria(criteria)
03881     if ( myNewID.IsEmpty() )
03882       theCommand->SetResultValue( GetID() );
03883     else
03884       theCommand->SetResultValue( myNewID );
03885     theCommand->SetObject( SMESH_2smeshpy::GenName() );
03886     theCommand->SetMethod( "GetFilterFromCriteria" );
03887 
03888     // Clear aFilterManager.CreateFilter()
03889     GetCreationCmd()->Clear();
03890   }
03891   else if ( theCommand->GetMethod() == "SetMesh" )
03892   {
03893     if ( myMesh == theCommand->GetArg( 1 ))
03894       theCommand->Clear();
03895     else
03896       myMesh = theCommand->GetArg( 1 );
03897     theGen->AddMeshAccessorMethod( theCommand );
03898   }
03899 }
03900 
03901 //================================================================================
03905 //================================================================================
03906 
03907 void _pyFilter::Flush()
03908 {
03909   if ( !myNewID.IsEmpty() && !GetCreationCmd()->IsEmpty() )
03910     GetCreationCmd()->SetResultValue( myNewID );
03911 }
03912 
03913 //================================================================================
03917 //================================================================================
03918 
03919 bool _pyFilter::CanClear()
03920 {
03921   list< Handle(_pyObject) >::iterator obj = myUsers.begin();
03922   for ( ; obj != myUsers.end(); ++obj )
03923     if ( !(*obj)->CanClear() )
03924       return false;
03925 
03926   return true;
03927 }
03928 
03929 //================================================================================
03933 //================================================================================
03934 
03935 _pyHypothesisReader::_pyHypothesisReader()
03936 {
03937   // Get paths to xml files of plugins
03938   vector< string > xmlPaths;
03939   string sep;
03940   if ( const char* meshersList = getenv("SMESH_MeshersList") )
03941   {
03942     string meshers = meshersList, plugin;
03943     string::size_type from = 0, pos;
03944     while ( from < meshers.size() )
03945     {
03946       // cut off plugin name
03947       pos = meshers.find( ':', from );
03948       if ( pos != string::npos )
03949         plugin = meshers.substr( from, pos-from );
03950       else
03951         plugin = meshers.substr( from ), pos = meshers.size();
03952       from = pos + 1;
03953 
03954       // get PLUGIN_ROOT_DIR path
03955       string rootDirVar, pluginSubDir = plugin;
03956       if ( plugin == "StdMeshers" )
03957         rootDirVar = "SMESH", pluginSubDir = "smesh";
03958       else
03959         for ( pos = 0; pos < plugin.size(); ++pos )
03960           rootDirVar += toupper( plugin[pos] );
03961       rootDirVar += "_ROOT_DIR";
03962 
03963       const char* rootDir = getenv( rootDirVar.c_str() );
03964       if ( !rootDir || strlen(rootDir) == 0 )
03965       {
03966         rootDirVar = plugin + "_ROOT_DIR"; // HexoticPLUGIN_ROOT_DIR
03967         rootDir = getenv( rootDirVar.c_str() );
03968         if ( !rootDir || strlen(rootDir) == 0 ) continue;
03969       }
03970 
03971       // get a separator from rootDir
03972       for ( pos = strlen( rootDir )-1; pos >= 0 && sep.empty(); --pos )
03973         if ( rootDir[pos] == '/' || rootDir[pos] == '\\' )
03974         {
03975           sep = rootDir[pos];
03976           break;
03977         }
03978 #ifdef WNT
03979       if (sep.empty() ) sep = "\\";
03980 #else
03981       if (sep.empty() ) sep = "/";
03982 #endif
03983 
03984       // get a path to resource file
03985       string xmlPath = rootDir;
03986       if ( xmlPath[ xmlPath.size()-1 ] != sep[0] )
03987         xmlPath += sep;
03988       xmlPath += "share" + sep + "salome" + sep + "resources" + sep;
03989       for ( pos = 0; pos < pluginSubDir.size(); ++pos )
03990         xmlPath += tolower( pluginSubDir[pos] );
03991       xmlPath += sep + plugin + ".xml";
03992       bool fileOK;
03993 #ifdef WNT
03994       fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES);
03995 #else
03996       fileOK = (access(xmlPath.c_str(), F_OK) == 0);
03997 #endif
03998       if ( fileOK )
03999         xmlPaths.push_back( xmlPath );
04000     }
04001   }
04002 
04003   // Read xml files
04004   LDOMParser xmlParser;
04005   for ( size_t i = 0; i < xmlPaths.size(); ++i )
04006   {
04007     bool error = xmlParser.parse( xmlPaths[i].c_str() );
04008     if ( error )
04009     {
04010       _AString data;
04011       INFOS( xmlParser.GetError(data) );
04012       continue;
04013     }
04014     // <algorithm type="Regular_1D"
04015     //            label-id="Wire discretisation"
04016     //            ...>
04017     //   <python-wrap>
04018     //     <algo>Regular_1D=Segment()</algo>
04019     //     <hypo>LocalLength=LocalLength(SetLength(1),,SetPrecision(1))</hypo>
04020     //
04021     LDOM_Document xmlDoc = xmlParser.getDocument();
04022     LDOM_NodeList algoNodeList = xmlDoc.getElementsByTagName( "algorithm" );
04023     for ( int i = 0; i < algoNodeList.getLength(); ++i )
04024     {
04025       LDOM_Node algoNode = algoNodeList.item( i );
04026       LDOM_Element& algoElem = (LDOM_Element&) algoNode;
04027       LDOM_NodeList pyAlgoNodeList = algoElem.getElementsByTagName( "algo" );
04028       if ( pyAlgoNodeList.getLength() < 1 ) continue;
04029 
04030       _AString text, algoType, method, arg;
04031       for ( int iA = 0; iA < pyAlgoNodeList.getLength(); ++iA )
04032       {
04033         LDOM_Node pyAlgoNode = pyAlgoNodeList.item( iA );
04034         LDOM_Node textNode   = pyAlgoNode.getFirstChild();
04035         text = textNode.getNodeValue();
04036         Handle(_pyCommand) algoCmd = new _pyCommand( text );
04037         algoType = algoCmd->GetResultValue();
04038         method   = algoCmd->GetMethod();
04039         arg      = algoCmd->GetArg(1);
04040         if ( !algoType.IsEmpty() && !method.IsEmpty() )
04041         {
04042           Handle(_pyAlgorithm) algo = new _pyAlgorithm( algoCmd );
04043           algo->SetConvMethodAndType( method, algoType );
04044           if ( !arg.IsEmpty() )
04045             algo->setCreationArg( 1, arg );
04046 
04047           myType2Hyp[ algoType ] = algo;
04048           break;
04049         }
04050       }
04051       if ( algoType.IsEmpty() ) continue;
04052 
04053       LDOM_NodeList pyHypoNodeList = algoElem.getElementsByTagName( "hypo" );
04054       _AString hypType;
04055       Handle( _pyHypothesis ) hyp;
04056       for ( int iH = 0; iH < pyHypoNodeList.getLength(); ++iH )
04057       {
04058         LDOM_Node pyHypoNode = pyHypoNodeList.item( iH );
04059         LDOM_Node textNode   = pyHypoNode.getFirstChild();
04060         text = textNode.getNodeValue();
04061         Handle(_pyCommand) hypoCmd = new _pyCommand( text );
04062         hypType = hypoCmd->GetResultValue();
04063         method  = hypoCmd->GetMethod();
04064         if ( !hypType.IsEmpty() && !method.IsEmpty() )
04065         {
04066           map<_AString, Handle(_pyHypothesis)>::iterator type2hyp = myType2Hyp.find( hypType );
04067           if ( type2hyp == myType2Hyp.end() )
04068             hyp = new _pyHypothesis( hypoCmd );
04069           else
04070             hyp = type2hyp->second;
04071           hyp->SetConvMethodAndType( method, algoType );
04072           for ( int iArg = 1; iArg <= hypoCmd->GetNbArgs(); ++iArg )
04073           {
04074             _pyCommand argCmd( hypoCmd->GetArg( iArg ));
04075             _AString argMethod = argCmd.GetMethod();
04076             _AString argNbText = argCmd.GetArg( 1 );
04077             if ( argMethod.IsEmpty() && !argCmd.IsEmpty() )
04078               hyp->setCreationArg( 1, argCmd.GetString() ); // e.g. Parameters(smesh.SIMPLE)
04079             else
04080               hyp->AddArgMethod( argMethod,
04081                                  argNbText.IsIntegerValue() ? argNbText.IntegerValue() : 1 );
04082           }
04083           myType2Hyp[ hypType ] = hyp;
04084         }
04085       }
04086     }
04087   }
04088 }
04089 
04090 //================================================================================
04094 //================================================================================
04095 
04096 Handle(_pyHypothesis)
04097 _pyHypothesisReader::GetHypothesis(const _AString&           hypType,
04098                                    const Handle(_pyCommand)& creationCmd) const
04099 {
04100   Handle(_pyHypothesis) resHyp, sampleHyp;
04101 
04102   map<_AString, Handle(_pyHypothesis)>::const_iterator type2hyp = myType2Hyp.find( hypType );
04103   if ( type2hyp != myType2Hyp.end() )
04104     sampleHyp = type2hyp->second;
04105 
04106   if ( sampleHyp.IsNull() )
04107   {
04108     resHyp = new _pyHypothesis(creationCmd);
04109   }
04110   else
04111   {
04112     if ( sampleHyp->IsAlgo() )
04113       resHyp = new _pyAlgorithm( creationCmd );
04114     else
04115       resHyp = new _pyHypothesis(creationCmd);
04116     resHyp->Assign( sampleHyp, _pyID() );
04117   }
04118   return resHyp;
04119 }