Salome HOME
ea012abc4192b61600fb051aa6ec5d36b6788d43
[modules/smesh.git] / src / SMESH_I / SMESH_2smeshpy.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
24 // File      : SMESH_2smeshpy.cxx
25 // Created   : Fri Nov 18 13:20:10 2005
26 // Author    : Edward AGAPOV (eap)
27 //
28 #include "SMESH_2smeshpy.hxx"
29
30 #include "utilities.h"
31 #include "SMESH_PythonDump.hxx"
32 #include "SMESH_NoteBook.hxx"
33 #include "SMESH_Filter_i.hxx"
34
35 #include <Resource_DataMapOfAsciiStringAsciiString.hxx>
36 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
37
38 #include "SMESH_Gen_i.hxx"
39 /* SALOME headers that include CORBA headers that include windows.h
40  * that defines GetObject symbol as GetObjectA should stand before SALOME headers
41  * that declare methods named GetObject - to apply the same rules of GetObject renaming
42  * and thus to avoid mess with GetObject symbol on Windows */
43
44 IMPLEMENT_STANDARD_HANDLE (_pyObject          ,Standard_Transient);
45 IMPLEMENT_STANDARD_HANDLE (_pyCommand         ,Standard_Transient);
46 IMPLEMENT_STANDARD_HANDLE (_pyGen             ,_pyObject);
47 IMPLEMENT_STANDARD_HANDLE (_pyMesh            ,_pyObject);
48 IMPLEMENT_STANDARD_HANDLE (_pySubMesh         ,_pyObject);
49 IMPLEMENT_STANDARD_HANDLE (_pyMeshEditor      ,_pyObject);
50 IMPLEMENT_STANDARD_HANDLE (_pyHypothesis      ,_pyObject);
51 IMPLEMENT_STANDARD_HANDLE (_pySelfEraser      ,_pyObject);
52 IMPLEMENT_STANDARD_HANDLE (_pyGroup           ,_pyObject);
53 IMPLEMENT_STANDARD_HANDLE (_pyFilter          ,_pyObject);
54 IMPLEMENT_STANDARD_HANDLE (_pyAlgorithm       ,_pyHypothesis);
55 IMPLEMENT_STANDARD_HANDLE (_pyComplexParamHypo,_pyHypothesis);
56 IMPLEMENT_STANDARD_HANDLE (_pyNumberOfSegmentsHyp,_pyHypothesis);
57
58 IMPLEMENT_STANDARD_RTTIEXT(_pyObject          ,Standard_Transient);
59 IMPLEMENT_STANDARD_RTTIEXT(_pyCommand         ,Standard_Transient);
60 IMPLEMENT_STANDARD_RTTIEXT(_pyGen             ,_pyObject);
61 IMPLEMENT_STANDARD_RTTIEXT(_pyMesh            ,_pyObject);
62 IMPLEMENT_STANDARD_RTTIEXT(_pySubMesh         ,_pyObject);
63 IMPLEMENT_STANDARD_RTTIEXT(_pyMeshEditor      ,_pyObject);
64 IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis      ,_pyObject);
65 IMPLEMENT_STANDARD_RTTIEXT(_pySelfEraser      ,_pyObject);
66 IMPLEMENT_STANDARD_RTTIEXT(_pyGroup           ,_pyObject);
67 IMPLEMENT_STANDARD_RTTIEXT(_pyFilter          ,_pyObject);
68 IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm       ,_pyHypothesis);
69 IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis);
70 IMPLEMENT_STANDARD_RTTIEXT(_pyNumberOfSegmentsHyp,_pyHypothesis);
71 IMPLEMENT_STANDARD_RTTIEXT(_pyLayerDistributionHypo,_pyHypothesis);
72 IMPLEMENT_STANDARD_RTTIEXT(_pySegmentLengthAroundVertexHyp,_pyHypothesis);
73
74 using namespace std;
75 using SMESH::TPythonDump;
76
77 /*!
78  * \brief Container of commands into which the initial script is split.
79  *        It also contains data coresponding to SMESH_Gen contents
80  */
81 static Handle(_pyGen) theGen;
82
83 static TCollection_AsciiString theEmptyString;
84
85 //#define DUMP_CONVERSION
86
87 #if !defined(_DEBUG_) && defined(DUMP_CONVERSION)
88 #undef DUMP_CONVERSION
89 #endif
90
91
92 namespace {
93
94   //================================================================================
95   /*!
96    * \brief Set of TCollection_AsciiString initialized by C array of C strings
97    */
98   //================================================================================
99
100   struct TStringSet: public set<TCollection_AsciiString>
101   {
102     /*!
103      * \brief Filling. The last string must be ""
104      */
105     void Insert(const char* names[]) {
106       for ( int i = 0; names[i][0] ; ++i )
107         insert( (char*) names[i] );
108     }
109     /*!
110      * \brief Check if a string is in
111      */
112     bool Contains(const TCollection_AsciiString& name ) {
113       return find( name ) != end();
114     }
115   };
116
117   //================================================================================
118   /*!
119    * \brief Returns a mesh by object
120    */
121   //================================================================================
122
123   Handle(_pyMesh) ObjectToMesh( const Handle( _pyObject )& obj )
124   {
125     if ( !obj.IsNull() )
126     {
127       if ( obj->IsKind( STANDARD_TYPE( _pyMesh )))
128         return Handle(_pyMesh)::DownCast( obj );
129       else if ( obj->IsKind( STANDARD_TYPE( _pySubMesh )))
130         return Handle(_pySubMesh)::DownCast( obj )->GetMesh();
131       else if ( obj->IsKind( STANDARD_TYPE( _pyGroup )))
132         return Handle(_pyGroup)::DownCast( obj )->GetMesh();
133     }
134     return Handle(_pyMesh)();
135   }
136
137   //================================================================================
138   /*!
139    * \brief Check if objects used as args have been created by previous commands
140    */
141   //================================================================================
142
143   void CheckObjectPresence( const Handle(_pyCommand)& cmd, set<_pyID> & presentObjects)
144   {
145     for ( int iArg = cmd->GetNbArgs(); iArg; --iArg )
146     {
147       const _pyID& arg = cmd->GetArg( iArg );
148       if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' )
149         continue;
150       list< _pyID > idList = cmd->GetStudyEntries( arg );
151       list< _pyID >::iterator id = idList.begin();
152       for ( ; id != idList.end(); ++id )
153         if ( !theGen->IsGeomObject( *id ) && !presentObjects.count( *id ))
154         {
155           cmd->Comment();
156           cmd->GetString() += " ### " ;
157           cmd->GetString() += *id + " has not been yet created";
158           return;
159         }
160     }
161     const _pyID& obj = cmd->GetObject();
162     if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj ))
163     {
164       cmd->Comment();
165       cmd->GetString() += " ### not created object" ;
166     }
167     const _pyID& result = cmd->GetResultValue();
168     if ( result.IsEmpty() || result.Value( 1 ) == '"' || result.Value( 1 ) == '\'' )
169       return;
170     list< _pyID > idList = cmd->GetStudyEntries( result );
171     list< _pyID >::iterator id = idList.begin();
172     for ( ; id != idList.end(); ++id )
173       presentObjects.insert( *id );
174   }
175 }
176
177 //================================================================================
178 /*!
179  * \brief Convert python script using commands of smesh.py
180   * \param theScript - Input script
181   * \retval TCollection_AsciiString - Convertion result
182   * \param theToKeepAllCommands - to keep all commands or
183   *        to exclude commands relating to objects removed from study
184   *
185   * Class SMESH_2smeshpy declared in SMESH_PythonDump.hxx
186  */
187 //================================================================================
188
189 TCollection_AsciiString
190 SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString&            theScript,
191                               Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
192                               Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
193                               SALOMEDS::Study_ptr&                      theStudy,
194                               const bool                                theToKeepAllCommands)
195 {
196   theGen = new _pyGen( theEntry2AccessorMethod, theObjectNames, theStudy, theToKeepAllCommands );
197
198   // split theScript into separate commands
199
200   SMESH_NoteBook * aNoteBook = new SMESH_NoteBook();
201
202   int from = 1, end = theScript.Length(), to;
203   while ( from < end && ( to = theScript.Location( "\n", from, end )))
204   {
205     if ( to != from )
206         // cut out and store a command
207         aNoteBook->AddCommand( theScript.SubString( from, to - 1 ));
208       from = to + 1;
209   }
210
211   aNoteBook->ReplaceVariables();
212
213   TCollection_AsciiString aNoteScript = aNoteBook->GetResultScript();
214   delete aNoteBook;
215   aNoteBook = 0;
216
217   // split theScript into separate commands
218   from = 1, end = aNoteScript.Length();
219   while ( from < end && ( to = aNoteScript.Location( "\n", from, end )))
220   {
221     if ( to != from )
222       // cut out and store a command
223       theGen->AddCommand( aNoteScript.SubString( from, to - 1 ));
224     from = to + 1;
225   }
226
227   // finish conversion
228   theGen->Flush();
229 #ifdef DUMP_CONVERSION
230   MESSAGE_BEGIN ( std::endl << " ######## RESULT ######## " << std::endl<< std::endl );
231 #endif
232
233   // clean commmands of removed objects depending on myIsPublished flag
234   theGen->ClearCommands();
235
236   // reorder commands after conversion
237   list< Handle(_pyCommand) >::iterator cmd;
238   bool orderChanges;
239   do {
240     orderChanges = false;
241     for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
242       if ( (*cmd)->SetDependentCmdsAfter() )
243         orderChanges = true;
244   } while ( orderChanges );
245
246   // concat commands back into a script
247   TCollection_AsciiString aScript, aPrevCmd;
248   set<_pyID> createdObjects;
249   for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
250   {
251 #ifdef DUMP_CONVERSION
252     MESSAGE_ADD ( "## COM " << (*cmd)->GetOrderNb() << ": "<< (*cmd)->GetString() << std::endl );
253 #endif
254     if ( !(*cmd)->IsEmpty() && aPrevCmd != (*cmd)->GetString()) {
255       CheckObjectPresence( *cmd, createdObjects );
256       aPrevCmd = (*cmd)->GetString();
257       aScript += "\n";
258       aScript += aPrevCmd;
259     }
260   }
261   aScript += "\n";
262
263   theGen->Free();
264   theGen.Nullify();
265
266   return aScript;
267 }
268
269 //================================================================================
270 /*!
271  * \brief _pyGen constructor
272  */
273 //================================================================================
274
275 _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
276                Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
277                SALOMEDS::Study_ptr&                      theStudy,
278                const bool                                theToKeepAllCommands)
279   : _pyObject( new _pyCommand( "", 0 )),
280     myNbCommands( 0 ),
281     myID2AccessorMethod( theEntry2AccessorMethod ),
282     myObjectNames( theObjectNames ),
283     myNbFilters( 0 ),
284     myToKeepAllCommands( theToKeepAllCommands ),
285     myStudy( SALOMEDS::Study::_duplicate( theStudy )),
286     myGeomIDNb(0), myGeomIDIndex(-1)
287 {
288   // make that GetID() to return TPythonDump::SMESHGenName()
289   GetCreationCmd()->Clear();
290   GetCreationCmd()->GetString() = TPythonDump::SMESHGenName();
291   GetCreationCmd()->GetString() += "=";
292
293   // Find 1st digit of study entry by which a GEOM object differs from a SMESH object
294   if ( !theObjectNames.IsEmpty() && !CORBA::is_nil( theStudy ))
295   {
296     // find a GEOM entry
297     _pyID geomID;
298     SALOMEDS::SComponent_var geomComp = theStudy->FindComponent("GEOM");
299     if ( geomComp->_is_nil() ) return;
300     CORBA::String_var entry = geomComp->GetID();
301     geomID = entry.in();
302
303     // find a SMESH entry
304     _pyID smeshID;
305     Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString e2n( theObjectNames );
306     for ( ; e2n.More() && smeshID.IsEmpty(); e2n.Next() )
307       if ( _pyCommand::IsStudyEntry( e2n.Key() ))
308         smeshID = e2n.Key();
309
310     // find 1st difference between smeshID and geomID
311     if ( !geomID.IsEmpty() && !smeshID.IsEmpty() )
312       for ( int i = 1; i <= geomID.Length() && i <= smeshID.Length(); ++i )
313         if ( geomID.Value( i ) != smeshID.Value( i ))
314         {
315           myGeomIDNb = geomID.Value( i );
316           myGeomIDIndex = i;
317         }
318   }
319 }
320
321 //================================================================================
322 /*!
323  * \brief name of SMESH_Gen in smesh.py
324  */
325 //================================================================================
326
327 const char* _pyGen::AccessorMethod() const
328 {
329   return SMESH_2smeshpy::GenName();
330 }
331
332 //================================================================================
333 /*!
334  * \brief Convert a command using a specific converter
335   * \param theCommand - the command to convert
336  */
337 //================================================================================
338
339 Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand)
340 {
341   // store theCommand in the sequence
342   myCommands.push_back( new _pyCommand( theCommand, ++myNbCommands ));
343
344   Handle(_pyCommand) aCommand = myCommands.back();
345 #ifdef DUMP_CONVERSION
346   MESSAGE ( "## COM " << myNbCommands << ": "<< aCommand->GetString() );
347 #endif
348
349   const _pyID& objID = aCommand->GetObject();
350
351   if ( objID.IsEmpty() )
352     return aCommand;
353
354   // Find an object to process theCommand
355
356   // SMESH_Gen method?
357   if ( objID == this->GetID() || objID == SMESH_2smeshpy::GenName())
358   {
359     this->Process( aCommand );
360     return aCommand;
361   }
362
363   // SMESH_Mesh method?
364   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( objID );
365   if ( id_mesh != myMeshes.end() )
366   {
367     //id_mesh->second->AddProcessedCmd( aCommand );
368
369     // check for mesh editor object
370     if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation
371       _pyID editorID = aCommand->GetResultValue();
372       Handle(_pyMeshEditor) editor = new _pyMeshEditor( aCommand );
373       myMeshEditors.insert( make_pair( editorID, editor ));
374       return aCommand;
375     }
376     // check for SubMesh objects
377     else if ( aCommand->GetMethod() == "GetSubMesh" ) { // SubMesh creation
378       _pyID subMeshID = aCommand->GetResultValue();
379       Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand );
380       myObjects.insert( make_pair( subMeshID, subMesh ));
381     }
382
383     id_mesh->second->Process( aCommand );
384     id_mesh->second->AddProcessedCmd( aCommand );
385     return aCommand;
386   }
387
388   // SMESH_MeshEditor method?
389   map< _pyID, Handle(_pyMeshEditor) >::iterator id_editor = myMeshEditors.find( objID );
390   if ( id_editor != myMeshEditors.end() )
391   {
392     const TCollection_AsciiString& method = aCommand->GetMethod();
393
394     // some commands of SMESH_MeshEditor create meshes and groups
395     _pyID meshID, groups;
396     if ( method.Search("MakeMesh") != -1 )
397       meshID = aCommand->GetResultValue();
398     else if ( method == "MakeBoundaryMesh")
399       meshID = aCommand->GetResultValue(1);
400     else if ( method == "MakeBoundaryElements")
401       meshID = aCommand->GetResultValue(2);
402
403     if ( method.Search("MakeGroups") != -1  ||
404          method == "ExtrusionAlongPathX"    ||
405          method == "ExtrusionAlongPathObjX" ||
406          method == "DoubleNodeGroupNew"     ||
407          method == "DoubleNodeGroupsNew"    ||
408          method == "DoubleNodeElemGroupNew" ||
409          method == "DoubleNodeElemGroupsNew" )
410       groups = aCommand->GetResultValue();
411     else if ( method == "MakeBoundaryMesh" )
412       groups = aCommand->GetResultValue(2);
413     else if ( method == "MakeBoundaryElements")
414       groups = aCommand->GetResultValue(3);
415
416     id_editor->second->Process( aCommand );
417     id_editor->second->AddProcessedCmd( aCommand );
418
419     if ( !meshID.IsEmpty() &&
420          !myMeshes.count( meshID ) &&
421          aCommand->IsStudyEntry( meshID ))
422     {
423       TCollection_AsciiString processedCommand = aCommand->GetString();
424       Handle(_pyMesh) mesh = new _pyMesh( aCommand, meshID );
425       myMeshes.insert( make_pair( meshID, mesh ));
426       aCommand->Clear();
427       aCommand->GetString() = processedCommand; // discard changes made by _pyMesh
428     }
429     if ( !groups.IsEmpty() )
430     {
431       if ( !aCommand->IsStudyEntry( meshID ))
432         meshID = id_editor->second->GetMesh();
433       Handle(_pyMesh) mesh = myMeshes[ meshID ];
434
435       list< _pyID > idList = aCommand->GetStudyEntries( groups );
436       list< _pyID >::iterator grID = idList.begin();
437       for ( ; grID != idList.end(); ++grID )
438         if ( !myObjects.count( *grID ))
439         {
440           Handle(_pyGroup) group = new _pyGroup( aCommand, *grID );
441           AddObject( group );
442           if ( !mesh.IsNull() ) mesh->AddGroup( group );
443         }
444     }
445     return aCommand;
446   } // SMESH_MeshEditor methods
447
448   // SMESH_Hypothesis method?
449   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
450   for ( ; hyp != myHypos.end(); ++hyp )
451     if ( !(*hyp)->IsAlgo() && objID == (*hyp)->GetID() ) {
452       (*hyp)->Process( aCommand );
453       (*hyp)->AddProcessedCmd( aCommand );
454       return aCommand;
455     }
456
457   // aFilterManager.CreateFilter() ?
458   if ( aCommand->GetMethod() == "CreateFilter" )
459   {
460     // Set a more human readable name to a filter
461     // aFilter0x7fbf6c71cfb0 -> aFilter_nb
462     _pyID newID, filterID = aCommand->GetResultValue();
463     int pos = filterID.Search( "0x" );
464     if ( pos > 1 )
465       newID = (filterID.SubString(1,pos-1) + "_") + _pyID( ++myNbFilters );
466
467     Handle(_pyObject) filter( new _pyFilter( aCommand, newID ));
468     AddObject( filter );
469   }
470
471   // other object method?
472   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.find( objID );
473   if ( id_obj != myObjects.end() ) {
474     id_obj->second->Process( aCommand );
475     id_obj->second->AddProcessedCmd( aCommand );
476     return aCommand;
477   }
478
479   // Add access to a wrapped mesh
480   AddMeshAccessorMethod( aCommand );
481
482   // Add access to a wrapped algorithm
483   //  AddAlgoAccessorMethod( aCommand ); // ??? what if algo won't be wrapped at all ???
484
485   // PAL12227. PythonDump was not updated at proper time; result is
486   //     aCriteria.append(SMESH.Filter.Criterion(17,26,0,'L1',26,25,1e-07,SMESH.EDGE,-1))
487   // TypeError: __init__() takes exactly 11 arguments (10 given)
488   const char wrongCommand[] = "SMESH.Filter.Criterion(";
489   if ( int beg = theCommand.Location( wrongCommand, 1, theCommand.Length() ))
490   {
491     _pyCommand tmpCmd( theCommand.SubString( beg, theCommand.Length() ), -1);
492     // there must be 10 arguments, 5-th arg ThresholdID is missing,
493     const int wrongNbArgs = 9, missingArg = 5;
494     if ( tmpCmd.GetNbArgs() == wrongNbArgs )
495     {
496       for ( int i = wrongNbArgs; i > missingArg; --i )
497         tmpCmd.SetArg( i + 1, tmpCmd.GetArg( i ));
498       tmpCmd.SetArg(  missingArg, "''");
499       aCommand->GetString().Trunc( beg - 1 );
500       aCommand->GetString() += tmpCmd.GetString();
501     }
502     // IMP issue 0021014
503     // set GetCriterion(elementType,CritType,Compare,Treshold,UnaryOp,BinaryOp,Tolerance)
504     //                  1           2        3       4        5       6        7
505     // instead of "SMESH.Filter.Criterion(
506     // Type,Compare,Threshold,ThresholdStr,ThresholdID,UnaryOp,BinaryOp,Tolerance,TypeOfElement,Precision)
507     // 1    2       3         4            5           6       7        8         9             10
508     // in order to avoid the problem of type mismatch of long and FunctorType
509     const TCollection_AsciiString
510       SMESH("SMESH."), dfltFunctor = "SMESH.FT_Undefined", dftlTol = "1e-07", dftlPreci = "-1";
511     TCollection_AsciiString
512       Type          = aCommand->GetArg(1),  // long
513       Compare       = aCommand->GetArg(2),  // long
514       Threshold     = aCommand->GetArg(3),  // double
515       ThresholdStr  = aCommand->GetArg(4),  // string
516       ThresholdID   = aCommand->GetArg(5),  // string
517       UnaryOp       = aCommand->GetArg(6),  // long
518       BinaryOp      = aCommand->GetArg(7),  // long
519       Tolerance     = aCommand->GetArg(8),  // double
520       TypeOfElement = aCommand->GetArg(9),  // ElementType
521       Precision     = aCommand->GetArg(10); // long
522     Type     = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( Type.IntegerValue() ));
523     Compare  = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( Compare.IntegerValue() ));
524     UnaryOp  = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( UnaryOp.IntegerValue() ));
525     BinaryOp = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( BinaryOp.IntegerValue() ));
526
527     aCommand->RemoveArgs();
528     aCommand->SetObject( SMESH_2smeshpy::GenName() );
529     aCommand->SetMethod( "GetCriterion" );
530
531     aCommand->SetArg( 1, TypeOfElement );
532     aCommand->SetArg( 2, Type );
533     aCommand->SetArg( 3, Compare );
534
535     if ( Type == "SMESH.FT_ElemGeomType" && Threshold.IsIntegerValue() )
536     {
537       // set SMESH.GeometryType instead of a numerical Threshold
538       const char* types[SMESH::Geom_POLYHEDRA+1] = {
539         "Geom_POINT", "Geom_EDGE", "Geom_TRIANGLE", "Geom_QUADRANGLE", "Geom_POLYGON",
540         "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_HEXAGONAL_PRISM",
541         "Geom_POLYHEDRA"
542       };
543       int iGeom = Threshold.IntegerValue();
544       if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 )
545         Threshold = SMESH + types[ iGeom ];
546     }
547     if ( ThresholdID.Length() != 2 && ThresholdStr.Length() != 2) // not '' or ""
548       aCommand->SetArg( 4, ThresholdID.SubString( 2, ThresholdID.Length()-1 )); // shape entry
549     else if ( ThresholdStr.Length() != 2 )
550       aCommand->SetArg( 4, ThresholdStr );
551     else if ( ThresholdID.Length() != 2 )
552       aCommand->SetArg( 4, ThresholdID );
553     else
554       aCommand->SetArg( 4, Threshold );
555     // find the last not default arg
556     int lastDefault = 8;
557     if ( Tolerance == dftlTol ) {
558       lastDefault = 7;
559       if ( BinaryOp == dfltFunctor ) {
560         lastDefault = 6;
561         if ( UnaryOp == dfltFunctor )
562           lastDefault = 5;
563       }
564     }
565     if ( 5 < lastDefault ) aCommand->SetArg( 5, UnaryOp );
566     if ( 6 < lastDefault ) aCommand->SetArg( 6, BinaryOp );
567     if ( 7 < lastDefault ) aCommand->SetArg( 7, Tolerance );
568     if ( Precision != dftlPreci )
569     {
570       TCollection_AsciiString crit = aCommand->GetResultValue();
571       aCommand->GetString() += "; ";
572       aCommand->GetString() += crit + ".Precision = " + Precision;
573     }
574   }
575   return aCommand;
576 }
577
578 //================================================================================
579 /*!
580  * \brief Convert the command or remember it for later conversion
581   * \param theCommand - The python command calling a method of SMESH_Gen
582  */
583 //================================================================================
584
585 void _pyGen::Process( const Handle(_pyCommand)& theCommand )
586 {
587   // there are methods to convert:
588   // CreateMesh( shape )
589   // Concatenate( [mesh1, ...], ... )
590   // CreateHypothesis( theHypType, theLibName )
591   // Compute( mesh, geom )
592   // Evaluate( mesh, geom )
593   // mesh creation
594   TCollection_AsciiString method = theCommand->GetMethod();
595
596   if ( method == "CreateMesh" || method == "CreateEmptyMesh")
597   {
598     Handle(_pyMesh) mesh = new _pyMesh( theCommand );
599     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
600     return;
601   }
602   if ( method == "CreateMeshesFromUNV" ||
603        method == "CreateMeshesFromSTL" ||
604        method == "CreateMeshesFromCGNS" ||
605        method == "CopyMesh" )
606   {
607     Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
608     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
609     return;
610   }
611   if( method == "CreateMeshesFromMED" || method == "CreateMeshesFromSAUV")
612   {
613     for(int ind = 0;ind<theCommand->GetNbResultValues();ind++)
614     {
615       const _pyID& meshID = theCommand->GetResultValue(ind+1);
616       if ( !theCommand->IsStudyEntry( meshID ) ) continue;
617       Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue(ind+1));
618       myMeshes.insert( make_pair( mesh->GetID(), mesh ));
619     }
620   }
621
622   // CreateHypothesis()
623   if ( method == "CreateHypothesis" )
624   {
625     // issue 199929, remove standard library name (default parameter)
626     const TCollection_AsciiString & aLibName = theCommand->GetArg( 2 );
627     if ( aLibName.Search( "StdMeshersEngine" ) != -1 ) {
628       // keep first argument
629       TCollection_AsciiString arg = theCommand->GetArg( 1 );
630       theCommand->RemoveArgs();
631       theCommand->SetArg( 1, arg );
632     }
633
634     myHypos.push_back( _pyHypothesis::NewHypothesis( theCommand ));
635     return;
636   }
637
638   // smeshgen.Compute( mesh, geom ) --> mesh.Compute()
639   if ( method == "Compute" )
640   {
641     const _pyID& meshID = theCommand->GetArg( 1 );
642     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
643     if ( id_mesh != myMeshes.end() ) {
644       theCommand->SetObject( meshID );
645       theCommand->RemoveArgs();
646       id_mesh->second->Process( theCommand );
647       id_mesh->second->AddProcessedCmd( theCommand );
648       return;
649     }
650   }
651
652   // smeshgen.Evaluate( mesh, geom ) --> mesh.Evaluate(geom)
653   if ( method == "Evaluate" )
654   {
655     const _pyID& meshID = theCommand->GetArg( 1 );
656     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
657     if ( id_mesh != myMeshes.end() ) {
658       theCommand->SetObject( meshID );
659       _pyID geom = theCommand->GetArg( 2 );
660       theCommand->RemoveArgs();
661       theCommand->SetArg( 1, geom );
662       id_mesh->second->AddProcessedCmd( theCommand );
663       return;
664     }
665   }
666
667   // objects erasing creation command if no more it's commands invoked:
668   // SMESH_Pattern, FilterManager
669   if ( method == "GetPattern" ||
670        method == "CreateFilterManager" ||
671        method == "CreateMeasurements" ) {
672     Handle(_pyObject) obj = new _pySelfEraser( theCommand );
673     if ( !myObjects.insert( make_pair( obj->GetID(), obj )).second )
674       theCommand->Clear(); // already created
675   }
676   // Concatenate( [mesh1, ...], ... )
677   else if ( method == "Concatenate" || method == "ConcatenateWithGroups")
678   {
679     if ( method == "ConcatenateWithGroups" ) {
680       theCommand->SetMethod( "Concatenate" );
681       theCommand->SetArg( theCommand->GetNbArgs() + 1, "True" );
682     }
683     Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
684     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
685     AddMeshAccessorMethod( theCommand );
686   }
687   else if ( method == "SetName" ) // SetName(obj,name)
688   {
689     // store theCommand as one of object commands to erase it along with the object
690     const _pyID& objID = theCommand->GetArg( 1 );
691     Handle(_pyObject) obj = FindObject( objID );
692     if ( !obj.IsNull() )
693       obj->AddProcessedCmd( theCommand );
694   }
695
696   // Replace name of SMESH_Gen
697
698   // names of SMESH_Gen methods fully equal to methods defined in smesh.py
699   static TStringSet smeshpyMethods;
700   if ( smeshpyMethods.empty() ) {
701     const char * names[] =
702       { "SetEmbeddedMode","IsEmbeddedMode","SetCurrentStudy","GetCurrentStudy",
703         "GetPattern","GetSubShapesId",
704         "" }; // <- mark of array end
705     smeshpyMethods.Insert( names );
706   }
707   if ( smeshpyMethods.Contains( theCommand->GetMethod() ))
708     // smeshgen.Method() --> smesh.Method()
709     theCommand->SetObject( SMESH_2smeshpy::SmeshpyName() );
710   else
711     // smeshgen.Method() --> smesh.smesh.Method()
712     theCommand->SetObject( SMESH_2smeshpy::GenName() );
713 }
714
715 //================================================================================
716 /*!
717  * \brief Convert the remembered commands
718  */
719 //================================================================================
720
721 void _pyGen::Flush()
722 {
723   // create an empty command
724   myLastCommand = new _pyCommand();
725
726   map< _pyID, Handle(_pyMesh) >::iterator id_mesh;
727   map< _pyID, Handle(_pyObject) >::iterator id_obj;
728   list< Handle(_pyHypothesis) >::iterator hyp;
729
730   if ( IsToKeepAllCommands() ) // historical dump
731   {
732     // set myIsPublished = true to all objects
733     for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
734       id_mesh->second->SetRemovedFromStudy( false );
735     for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
736       (*hyp)->SetRemovedFromStudy( false );
737     for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj )
738       id_obj->second->SetRemovedFromStudy( false );
739   }
740   // set myIsPublished = false to all objects depending on
741   // meshes built on a removed geometry
742   for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
743     if ( id_mesh->second->IsNotGeomPublished() )
744       id_mesh->second->SetRemovedFromStudy( true );
745
746   // Flush meshes
747   for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
748     if ( ! id_mesh->second.IsNull() )
749       id_mesh->second->Flush();
750
751   // Flush hyps
752   for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
753     if ( !hyp->IsNull() ) {
754       (*hyp)->Flush();
755       // smeshgen.CreateHypothesis() --> smesh.smesh.CreateHypothesis()
756       if ( !(*hyp)->IsWrapped() )
757         (*hyp)->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() );
758     }
759
760   // Flush other objects
761   for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj )
762     if ( ! id_obj->second.IsNull() )
763       id_obj->second->Flush();
764
765   myLastCommand->SetOrderNb( ++myNbCommands );
766   myCommands.push_back( myLastCommand );
767 }
768
769 //================================================================================
770 /*!
771  * \brief Clean commmands of removed objects depending on myIsPublished flag
772  */
773 //================================================================================
774
775 void _pyGen::ClearCommands()
776 {
777   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
778   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
779     id_mesh->second->ClearCommands();
780
781   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
782   for ( ; hyp != myHypos.end(); ++hyp )
783     if ( !hyp->IsNull() )
784       (*hyp)->ClearCommands();
785
786   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin();
787   for ( ; id_obj != myObjects.end(); ++id_obj )
788     id_obj->second->ClearCommands();
789 }
790
791 //================================================================================
792 /*!
793  * \brief Release mutual handles of objects
794  */
795 //================================================================================
796
797 void _pyGen::Free()
798 {
799   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
800   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
801     id_mesh->second->Free();
802   myMeshes.clear();
803
804   map< _pyID, Handle(_pyMeshEditor) >::iterator id_ed = myMeshEditors.begin();
805   for ( ; id_ed != myMeshEditors.end(); ++id_ed )
806     id_ed->second->Free();
807   myMeshEditors.clear();
808
809   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin();
810   for ( ; id_obj != myObjects.end(); ++id_obj )
811     id_obj->second->Free();
812   myObjects.clear();
813
814   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
815   for ( ; hyp != myHypos.end(); ++hyp )
816     if ( !hyp->IsNull() )
817       (*hyp)->Free();
818   myHypos.clear();
819
820   myFile2ExportedMesh.clear();
821 }
822
823 //================================================================================
824 /*!
825  * \brief Add access method to mesh that is an argument
826   * \param theCmd - command to add access method
827   * \retval bool - true if added
828  */
829 //================================================================================
830
831 bool _pyGen::AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const
832 {
833   bool added = false;
834   map< _pyID, Handle(_pyMesh) >::const_iterator id_mesh = myMeshes.begin();
835   for ( ; id_mesh != myMeshes.end(); ++id_mesh ) {
836     if ( theCmd->AddAccessorMethod( id_mesh->first, id_mesh->second->AccessorMethod() ))
837       added = true;
838   }
839   return added;
840 }
841
842 //================================================================================
843 /*!
844  * \brief Add access method to algo that is an object or an argument
845   * \param theCmd - command to add access method
846   * \retval bool - true if added
847  */
848 //================================================================================
849
850 bool _pyGen::AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const
851 {
852   bool added = false;
853   list< Handle(_pyHypothesis) >::const_iterator hyp = myHypos.begin();
854   for ( ; hyp != myHypos.end(); ++hyp ) {
855     if ( (*hyp)->IsAlgo() && /*(*hyp)->IsWrapped() &&*/
856          theCmd->AddAccessorMethod( (*hyp)->GetID(), (*hyp)->AccessorMethod() ))
857       added = true;
858   }
859   return added;
860 }
861
862 //================================================================================
863 /*!
864  * \brief Find hypothesis by ID (entry)
865   * \param theHypID - The hypothesis ID
866   * \retval Handle(_pyHypothesis) - The found hypothesis
867  */
868 //================================================================================
869
870 Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID )
871 {
872   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
873   for ( ; hyp != myHypos.end(); ++hyp )
874     if ( !hyp->IsNull() && theHypID == (*hyp)->GetID() )
875       return *hyp;
876   return Handle(_pyHypothesis)();
877 }
878
879 //================================================================================
880 /*!
881  * \brief Find algorithm the created algorithm
882   * \param theGeom - The shape ID the algorithm was created on
883   * \param theMesh - The mesh ID that created the algorithm
884   * \param dim - The algo dimension
885   * \retval Handle(_pyHypothesis) - The found algo
886  */
887 //================================================================================
888
889 Handle(_pyHypothesis) _pyGen::FindAlgo( const _pyID& theGeom, const _pyID& theMesh,
890                                         const Handle(_pyHypothesis)& theHypothesis )
891 {
892   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
893   for ( ; hyp != myHypos.end(); ++hyp )
894     if ( !hyp->IsNull() &&
895          (*hyp)->IsAlgo() &&
896          theHypothesis->CanBeCreatedBy( (*hyp)->GetAlgoType() ) &&
897          (*hyp)->GetGeom() == theGeom &&
898          (*hyp)->GetMesh() == theMesh )
899       return *hyp;
900   return 0;
901 }
902
903 //================================================================================
904 /*!
905  * \brief Find subMesh by ID (entry)
906   * \param theSubMeshID - The subMesh ID
907   * \retval Handle(_pySubMesh) - The found subMesh
908  */
909 //================================================================================
910
911 Handle(_pySubMesh) _pyGen::FindSubMesh( const _pyID& theSubMeshID )
912 {
913   map< _pyID, Handle(_pyObject) >::iterator id_subMesh = myObjects.find(theSubMeshID);
914   if ( id_subMesh != myObjects.end() )
915     return Handle(_pySubMesh)::DownCast( id_subMesh->second );
916   return Handle(_pySubMesh)();
917 }
918
919
920 //================================================================================
921 /*!
922  * \brief Change order of commands in the script
923   * \param theCmd1 - One command
924   * \param theCmd2 - Another command
925  */
926 //================================================================================
927
928 void _pyGen::ExchangeCommands( Handle(_pyCommand) theCmd1, Handle(_pyCommand) theCmd2 )
929 {
930   list< Handle(_pyCommand) >::iterator pos1, pos2;
931   pos1 = find( myCommands.begin(), myCommands.end(), theCmd1 );
932   pos2 = find( myCommands.begin(), myCommands.end(), theCmd2 );
933   myCommands.insert( pos1, theCmd2 );
934   myCommands.insert( pos2, theCmd1 );
935   myCommands.erase( pos1 );
936   myCommands.erase( pos2 );
937
938   int nb1 = theCmd1->GetOrderNb();
939   theCmd1->SetOrderNb( theCmd2->GetOrderNb() );
940   theCmd2->SetOrderNb( nb1 );
941 //   cout << "BECOME " << theCmd1->GetOrderNb() << "\t" << theCmd1->GetString() << endl
942 //        << "BECOME " << theCmd2->GetOrderNb() << "\t" << theCmd2->GetString() << endl << endl;
943 }
944
945 //================================================================================
946 /*!
947  * \brief Set one command after the other
948   * \param theCmd - Command to move
949   * \param theAfterCmd - Command ater which to insert the first one
950  */
951 //================================================================================
952
953 void _pyGen::SetCommandAfter( Handle(_pyCommand) theCmd, Handle(_pyCommand) theAfterCmd )
954 {
955   setNeighbourCommand( theCmd, theAfterCmd, true );
956 }
957
958 //================================================================================
959 /*!
960  * \brief Set one command before the other
961   * \param theCmd - Command to move
962   * \param theBeforeCmd - Command before which to insert the first one
963  */
964 //================================================================================
965
966 void _pyGen::SetCommandBefore( Handle(_pyCommand) theCmd, Handle(_pyCommand) theBeforeCmd )
967 {
968   setNeighbourCommand( theCmd, theBeforeCmd, false );
969 }
970
971 //================================================================================
972 /*!
973  * \brief Set one command before or after the other
974   * \param theCmd - Command to move
975   * \param theOtherCmd - Command ater or before which to insert the first one
976  */
977 //================================================================================
978
979 void _pyGen::setNeighbourCommand( Handle(_pyCommand)& theCmd,
980                                   Handle(_pyCommand)& theOtherCmd,
981                                   const bool theIsAfter )
982 {
983   list< Handle(_pyCommand) >::iterator pos;
984   pos = find( myCommands.begin(), myCommands.end(), theCmd );
985   myCommands.erase( pos );
986   pos = find( myCommands.begin(), myCommands.end(), theOtherCmd );
987   myCommands.insert( (theIsAfter ? ++pos : pos), theCmd );
988
989   int i = 1;
990   for ( pos = myCommands.begin(); pos != myCommands.end(); ++pos)
991     (*pos)->SetOrderNb( i++ );
992 }
993
994 //================================================================================
995 /*!
996  * \brief Set command be last in list of commands
997   * \param theCmd - Command to be last
998  */
999 //================================================================================
1000
1001 Handle(_pyCommand)& _pyGen::GetLastCommand()
1002 {
1003   return myLastCommand;
1004 }
1005
1006 //================================================================================
1007 /*!
1008  * \brief Set method to access to object wrapped with python class
1009   * \param theID - The wrapped object entry
1010   * \param theMethod - The accessor method
1011  */
1012 //================================================================================
1013
1014 void _pyGen::SetAccessorMethod(const _pyID& theID, const char* theMethod )
1015 {
1016   myID2AccessorMethod.Bind( theID, (char*) theMethod );
1017 }
1018
1019 //================================================================================
1020 /*!
1021  * \brief Generated new ID for object and assign with existing name
1022   * \param theID - ID of existing object
1023  */
1024 //================================================================================
1025
1026 _pyID _pyGen::GenerateNewID( const _pyID& theID )
1027 {
1028   int index = 1;
1029   _pyID aNewID;
1030   do {
1031     aNewID = theID + _pyID( ":" ) + _pyID( index++ );
1032   }
1033   while ( myObjectNames.IsBound( aNewID ) );
1034
1035   myObjectNames.Bind( aNewID, myObjectNames.IsBound( theID )
1036                       ? (myObjectNames.Find( theID ) + _pyID( "_" ) + _pyID( index-1 ))
1037                       : _pyID( "A" ) + aNewID );
1038   return aNewID;
1039 }
1040
1041 //================================================================================
1042 /*!
1043  * \brief Stores theObj in myObjects
1044  */
1045 //================================================================================
1046
1047 void _pyGen::AddObject( Handle(_pyObject)& theObj )
1048 {
1049   if ( theObj.IsNull() ) return;
1050
1051   if ( theObj->IsKind( STANDARD_TYPE( _pyMesh )))
1052     myMeshes.insert( make_pair( theObj->GetID(), Handle(_pyMesh)::DownCast( theObj )));
1053
1054   else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor )))
1055     myMeshEditors.insert( make_pair( theObj->GetID(), Handle(_pyMeshEditor)::DownCast( theObj )));
1056
1057   else
1058     myObjects.insert( make_pair( theObj->GetID(), theObj ));
1059 }
1060
1061 //================================================================================
1062 /*!
1063  * \brief Finds a _pyObject by ID
1064  */
1065 //================================================================================
1066
1067 Handle(_pyObject) _pyGen::FindObject( const _pyID& theObjID )  const
1068 {
1069   {
1070     map< _pyID, Handle(_pyObject) >::const_iterator id_obj = myObjects.find( theObjID );
1071     if ( id_obj != myObjects.end() )
1072       return id_obj->second;
1073   }
1074   {
1075     map< _pyID, Handle(_pyMesh) >::const_iterator id_obj = myMeshes.find( theObjID );
1076     if ( id_obj != myMeshes.end() )
1077       return id_obj->second;
1078   }
1079   // {
1080   //   map< _pyID, Handle(_pyMeshEditor) >::const_iterator id_obj = myMeshEditors.find( theObjID );
1081   //   if ( id_obj != myMeshEditors.end() )
1082   //     return id_obj->second;
1083   // }
1084   return Handle(_pyObject)();
1085 }
1086
1087 //================================================================================
1088 /*!
1089  * \brief Check if a study entry is under GEOM component
1090  */
1091 //================================================================================
1092
1093 bool _pyGen::IsGeomObject(const _pyID& theObjID) const
1094 {
1095   if ( myGeomIDNb )
1096   {
1097     return ( myGeomIDIndex <= theObjID.Length() &&
1098              int( theObjID.Value( myGeomIDIndex )) == myGeomIDNb);
1099   }
1100   return false;
1101 }
1102
1103 //================================================================================
1104 /*!
1105  * \brief Returns true if an object is not present in a study
1106  */
1107 //================================================================================
1108
1109 bool _pyGen::IsNotPublished(const _pyID& theObjID) const
1110 {
1111   if ( theObjID.IsEmpty() ) return false;
1112
1113   if ( myObjectNames.IsBound( theObjID ))
1114     return false; // SMESH object is in study
1115
1116   // either the SMESH object is not in study or it is a GEOM object
1117   if ( IsGeomObject( theObjID ))
1118   {
1119     SALOMEDS::SObject_var so = myStudy->FindObjectID( theObjID.ToCString() );
1120     if ( so->_is_nil() ) return true;
1121     CORBA::Object_var obj = so->GetObject();
1122     return CORBA::is_nil( obj );
1123   }
1124   return true; // SMESH object not in study
1125 }
1126
1127 //================================================================================
1128 /*!
1129  * \brief Mesh created by SMESH_Gen
1130  */
1131 //================================================================================
1132
1133 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd)
1134   : _pyObject( theCreationCmd ), myGeomNotInStudy( false )
1135 {
1136   if ( theCreationCmd->GetMethod() == "CreateMesh" && theGen->IsNotPublished( GetGeom() ))
1137     myGeomNotInStudy = true;
1138
1139   // convert my creation command --> smeshpy.Mesh(...)
1140   Handle(_pyCommand) creationCmd = GetCreationCmd();
1141   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
1142   creationCmd->SetMethod( "Mesh" );
1143   theGen->SetAccessorMethod( GetID(), _pyMesh::AccessorMethod() );
1144 }
1145
1146 //================================================================================
1147 /*!
1148  * \brief Mesh created by SMESH_MeshEditor
1149  */
1150 //================================================================================
1151
1152 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd, const _pyID& meshId):
1153   _pyObject(theCreationCmd,meshId), myGeomNotInStudy(false )
1154 {
1155   if ( theCreationCmd->MethodStartsFrom( "CreateMeshesFrom" ))
1156   {
1157     // this mesh depends on the exported mesh
1158     const TCollection_AsciiString& file = theCreationCmd->GetArg( 1 );
1159     if ( !file.IsEmpty() )
1160     {
1161       ExportedMeshData& exportData = theGen->FindExportedMesh( file );
1162       addFatherMesh( exportData.myMesh );
1163       if ( !exportData.myLastComputeCmd.IsNull() )
1164       {
1165         // restore cleared Compute() by which the exported mesh was generated
1166         exportData.myLastComputeCmd->GetString() = exportData.myLastComputeCmdString;
1167         // protect that Compute() cmd from clearing
1168         if ( exportData.myMesh->myLastComputeCmd == exportData.myLastComputeCmd )
1169           exportData.myMesh->myLastComputeCmd.Nullify();
1170       }
1171     }
1172   }
1173   else if ( theCreationCmd->MethodStartsFrom( "Concatenate" ))
1174   {
1175     // this mesh depends on concatenated meshes
1176     const TCollection_AsciiString& meshIDs = theCreationCmd->GetArg( 1 );
1177     list< _pyID > idList = theCreationCmd->GetStudyEntries( meshIDs );
1178     list< _pyID >::iterator meshID = idList.begin();
1179     for ( ; meshID != idList.end(); ++meshID )
1180       addFatherMesh( *meshID );
1181   }
1182   else if ( theCreationCmd->GetMethod() == "CopyMesh" )
1183   {
1184     // this mesh depends on a copied IdSource
1185     const _pyID& objID = theCreationCmd->GetArg( 1 );
1186     addFatherMesh( objID );
1187   }
1188   else if ( theCreationCmd->GetMethod().Search("MakeMesh") != -1 ||
1189             theCreationCmd->GetMethod() == "MakeBoundaryMesh" ||
1190             theCreationCmd->GetMethod() == "MakeBoundaryElements" )
1191   {
1192     // this mesh depends on a source mesh
1193     // (theCreationCmd is already Process()ed by _pyMeshEditor)
1194     const _pyID& meshID = theCreationCmd->GetObject();
1195     addFatherMesh( meshID );
1196   }
1197     
1198   // convert my creation command
1199   Handle(_pyCommand) creationCmd = GetCreationCmd();
1200   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
1201   theGen->SetAccessorMethod( meshId, _pyMesh::AccessorMethod() );
1202 }
1203
1204 //================================================================================
1205 /*!
1206  * \brief Convert an IDL API command of SMESH::SMESH_Mesh to a method call of python Mesh
1207   * \param theCommand - Engine method called for this mesh
1208  */
1209 //================================================================================
1210
1211 void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
1212 {
1213   // some methods of SMESH_Mesh interface needs special conversion
1214   // to methods of Mesh python class
1215   //
1216   // 1. GetSubMesh(geom, name) + AddHypothesis(geom, algo)
1217   //     --> in Mesh_Algorithm.Create(mesh, geom, hypo, so)
1218   // 2. AddHypothesis(geom, hyp)
1219   //     --> in Mesh_Algorithm.Hypothesis(hyp, args, so)
1220   // 3. CreateGroupFromGEOM(type, name, grp)
1221   //     --> in Mesh.Group(grp, name="")
1222   // 4. ExportToMED(f, auto_groups, version)
1223   //     --> in Mesh.ExportMED( f, auto_groups, version )
1224   // 5. etc
1225
1226   const TCollection_AsciiString& method = theCommand->GetMethod();
1227   // ----------------------------------------------------------------------
1228   if ( method == "Compute" ) // in snapshot mode, clear the previous Compute()
1229   {
1230     if ( !theGen->IsToKeepAllCommands() ) // !historical
1231     {
1232       list< Handle(_pyHypothesis) >::iterator hyp;
1233       if ( !myLastComputeCmd.IsNull() )
1234       {
1235         for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
1236           (*hyp)->ComputeDiscarded( myLastComputeCmd );
1237
1238         myLastComputeCmd->Clear();
1239       }
1240       myLastComputeCmd = theCommand;
1241
1242       for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
1243         (*hyp)->MeshComputed( myLastComputeCmd );
1244     }
1245     Flush();
1246   }
1247   // ----------------------------------------------------------------------
1248   else if ( method == "Clear" ) // in snapshot mode, clear all previous commands
1249   {
1250     if ( !theGen->IsToKeepAllCommands() ) // !historical
1251     {
1252       int untilCmdNb =
1253         myChildMeshes.empty() ? 0 : myChildMeshes.back()->GetCreationCmd()->GetOrderNb();
1254       // list< Handle(_pyCommand) >::reverse_iterator cmd = myProcessedCmds.rbegin();
1255       // for ( ; cmd != myProcessedCmds.rend() && (*cmd)->GetOrderNb() > untilCmdNb; ++cmd )
1256       //   (*cmd)->Clear();
1257       if ( !myLastComputeCmd.IsNull() )
1258       {
1259         list< Handle(_pyHypothesis) >::iterator hyp;
1260         for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
1261           (*hyp)->ComputeDiscarded( myLastComputeCmd );
1262
1263         myLastComputeCmd->Clear();
1264       }
1265
1266       list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
1267       for ( ; e != myEditors.end(); ++e )
1268       {
1269         list< Handle(_pyCommand)>& cmds = (*e)->GetProcessedCmds();
1270         list< Handle(_pyCommand) >::reverse_iterator cmd = cmds.rbegin();
1271         for ( ; cmd != cmds.rend() && (*cmd)->GetOrderNb() > untilCmdNb; ++cmd )
1272           if ( !(*cmd)->IsEmpty() )
1273           {
1274             if ( (*cmd)->GetStudyEntries( (*cmd)->GetResultValue() ).empty() ) // no object created
1275               (*cmd)->Clear();
1276           }
1277       }
1278       myLastComputeCmd = theCommand; // to clear Clear() the same way as Compute()
1279     }
1280   }
1281   // ----------------------------------------------------------------------
1282   else if ( method == "GetSubMesh" ) { // collect submeshes of the mesh
1283     Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetResultValue() );
1284     if ( !subMesh.IsNull() ) {
1285       subMesh->SetCreator( this );
1286       mySubmeshes.push_back( subMesh );
1287     }
1288   }
1289   else if ( method == "RemoveSubMesh" ) { // move submesh creation before its removal
1290     Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetArg(1) );
1291     if ( !subMesh.IsNull() )
1292       subMesh->Process( theCommand );
1293     AddMeshAccess( theCommand );
1294   }
1295   // ----------------------------------------------------------------------
1296   else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO )
1297     myAddHypCmds.push_back( theCommand );
1298     // set mesh to hypo
1299     const _pyID& hypID = theCommand->GetArg( 2 );
1300     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
1301     if ( !hyp.IsNull() ) {
1302       myHypos.push_back( hyp );
1303       if ( hyp->GetMesh().IsEmpty() )
1304         hyp->SetMesh( this->GetID() );
1305     }
1306   }
1307   // ----------------------------------------------------------------------
1308   else if ( method == "CreateGroup" ) // CreateGroup() --> CreateEmptyGroup()
1309   {
1310     theCommand->SetMethod( "CreateEmptyGroup" );
1311     Handle(_pyGroup) group = new _pyGroup( theCommand );
1312     myGroups.push_back( group );
1313     theGen->AddObject( group );
1314   }
1315   // ----------------------------------------------------------------------
1316   else if ( method == "CreateGroupFromGEOM" ) {// (type, name, grp)
1317     _pyID grp = theCommand->GetArg( 3 );
1318     // VSR 24/12/2010. PAL21106: always use GroupOnGeom() function on dump
1319     // next if(){...} section is commented
1320     //if ( sameGroupType( grp, theCommand->GetArg( 1 )) ) { // --> Group(grp)
1321     //  theCommand->SetMethod( "Group" );
1322     //  theCommand->RemoveArgs();
1323     //  theCommand->SetArg( 1, grp );
1324     //}
1325     //else {
1326     // ------------------------->>>>> GroupOnGeom( grp, name, typ )
1327       _pyID type = theCommand->GetArg( 1 );
1328       _pyID name = theCommand->GetArg( 2 );
1329       theCommand->SetMethod( "GroupOnGeom" );
1330       theCommand->RemoveArgs();
1331       theCommand->SetArg( 1, grp );
1332       theCommand->SetArg( 2, name );
1333       theCommand->SetArg( 3, type );
1334     //}
1335     Handle(_pyGroup) group = new _pyGroup( theCommand );
1336     myGroups.push_back( group );
1337     theGen->AddObject( group );
1338   }
1339   // ----------------------------------------------------------------------
1340   else if ( method == "CreateGroupFromFilter" ) // --> GroupOnFilter()
1341   {
1342     theCommand->SetMethod( "GroupOnFilter" );
1343     Handle(_pyGroup) group = new _pyGroup( theCommand );
1344     myGroups.push_back( group );
1345     theGen->AddObject( group );
1346
1347     // GroupOnFilter(typ, name, aFilter0x4743dc0 -> aFilter_1)
1348     _pyID filterID = theCommand->GetArg(3);
1349     Handle(_pyFilter) filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID ));
1350     if ( !filter.IsNull())
1351     {
1352       filter->Process( theCommand );
1353       filter->AddUser( group );
1354     }
1355   }
1356   // ----------------------------------------------------------------------
1357   else if ( theCommand->MethodStartsFrom( "Export" ))
1358   {
1359     if ( method == "ExportToMED" ||   // ExportToMED()  --> ExportMED()
1360          method == "ExportToMEDX" ) { // ExportToMEDX() --> ExportMED()
1361       theCommand->SetMethod( "ExportMED" );
1362     }
1363     else if ( method == "ExportCGNS" )
1364     { // ExportCGNS(part, ...) -> ExportCGNS(..., part)
1365       _pyID partID = theCommand->GetArg( 1 );
1366       int nbArgs = theCommand->GetNbArgs();
1367       for ( int i = 2; i <= nbArgs; ++i )
1368         theCommand->SetArg( i-1, theCommand->GetArg( i ));
1369       theCommand->SetArg( nbArgs, partID );
1370     }
1371     else if ( theCommand->MethodStartsFrom( "ExportPartTo" ))
1372     { // ExportPartTo*(part, ...) -> Export*(..., part)
1373       //
1374       // remove "PartTo" from the method
1375       TCollection_AsciiString newMethod = method;
1376       newMethod.Remove( 7, 6 );
1377       theCommand->SetMethod( newMethod );
1378       // make the 1st arg be the last one
1379       _pyID partID = theCommand->GetArg( 1 );
1380       int nbArgs = theCommand->GetNbArgs();
1381       for ( int i = 2; i <= nbArgs; ++i )
1382         theCommand->SetArg( i-1, theCommand->GetArg( i ));
1383       theCommand->SetArg( nbArgs, partID );
1384     }
1385     // remember file name
1386     theGen->AddExportedMesh( theCommand->GetArg( 1 ),
1387                              ExportedMeshData( this, myLastComputeCmd ));
1388   }
1389   // ----------------------------------------------------------------------
1390   else if ( method == "RemoveHypothesis" ) // (geom, hyp)
1391   {
1392     _pyID hypID = theCommand->GetArg( 2 );
1393
1394     // check if this mesh still has corresponding addition command
1395     bool hasAddCmd = false;
1396     list< Handle(_pyCommand) >::iterator cmd = myAddHypCmds.begin();
1397     while ( cmd != myAddHypCmds.end() )
1398     {
1399       // AddHypothesis(geom, hyp)
1400       if ( hypID == (*cmd)->GetArg( 2 )) { // erase both (add and remove) commands
1401         theCommand->Clear();
1402         (*cmd)->Clear();
1403         cmd = myAddHypCmds.erase( cmd );
1404         hasAddCmd = true;
1405       }
1406       else {
1407         ++cmd;
1408       }
1409     }
1410     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
1411     if ( ! hasAddCmd && hypID.Length() != 0 ) { // hypo addition already wrapped
1412       // RemoveHypothesis(geom, hyp) --> RemoveHypothesis( hyp, geom=0 )
1413       _pyID geom = theCommand->GetArg( 1 );
1414       theCommand->RemoveArgs();
1415       theCommand->SetArg( 1, hypID );
1416       if ( geom != GetGeom() )
1417         theCommand->SetArg( 2, geom );
1418     }
1419     // remove hyp from myHypos
1420     myHypos.remove( hyp );
1421   }
1422   // check for SubMesh order commands
1423   else if ( method == "GetMeshOrder" || method == "SetMeshOrder" )
1424   {
1425     // make commands GetSubMesh() returning sub-meshes be before using sub-meshes
1426     // by GetMeshOrder() and SetMeshOrder(), since by defalut GetSubMesh()
1427     // commands are moved at the end of the script
1428     TCollection_AsciiString subIDs =
1429       ( method == "SetMeshOrder" ) ? theCommand->GetArg(1) : theCommand->GetResultValue();
1430     list< _pyID > idList = theCommand->GetStudyEntries( subIDs );
1431     list< _pyID >::iterator subID = idList.begin();
1432     for ( ; subID != idList.end(); ++subID )
1433     {
1434       Handle(_pySubMesh) subMesh = theGen->FindSubMesh( *subID );
1435       if ( !subMesh.IsNull() )
1436         subMesh->Process( theCommand ); // it moves GetSubMesh() before theCommand
1437     }
1438   }
1439   // update list of groups
1440   else if ( method == "GetGroups" )
1441   {
1442     TCollection_AsciiString grIDs = theCommand->GetResultValue();
1443     list< _pyID > idList = theCommand->GetStudyEntries( grIDs );
1444     list< _pyID >::iterator grID = idList.begin();
1445     for ( ; grID != idList.end(); ++grID )
1446     {
1447       Handle(_pyObject) obj = theGen->FindObject( *grID );
1448       if ( obj.IsNull() )
1449       {
1450         Handle(_pyGroup) group = new _pyGroup( theCommand, *grID );
1451         theGen->AddObject( group );
1452         myGroups.push_back( group );
1453       }
1454     }
1455   }
1456   // add accessor method if necessary
1457   else
1458   {
1459     if ( NeedMeshAccess( theCommand ))
1460       // apply theCommand to the mesh wrapped by smeshpy mesh
1461       AddMeshAccess( theCommand );
1462   }
1463 }
1464
1465 //================================================================================
1466 /*!
1467  * \brief Return True if addition of accesor method is needed
1468  */
1469 //================================================================================
1470
1471 bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand )
1472 {
1473   // names of SMESH_Mesh methods fully equal to methods of python class Mesh,
1474   // so no conversion is needed for them at all:
1475   static TStringSet sameMethods;
1476   if ( sameMethods.empty() ) {
1477     const char * names[] =
1478       { "ExportDAT","ExportUNV","ExportSTL","ExportSAUV", "RemoveGroup","RemoveGroupWithContents",
1479         "GetGroups","UnionGroups","IntersectGroups","CutGroups","GetLog","GetId","ClearLog",
1480         "GetStudyId","HasDuplicatedGroupNamesMED","GetMEDMesh","NbNodes","NbElements",
1481         "NbEdges","NbEdgesOfOrder","NbFaces","NbFacesOfOrder","NbTriangles",
1482         "NbTrianglesOfOrder","NbQuadrangles","NbQuadranglesOfOrder","NbPolygons","NbVolumes",
1483         "NbVolumesOfOrder","NbTetras","NbTetrasOfOrder","NbHexas","NbHexasOfOrder",
1484         "NbPyramids","NbPyramidsOfOrder","NbPrisms","NbPrismsOfOrder","NbPolyhedrons",
1485         "NbSubMesh","GetElementsId","GetElementsByType","GetNodesId","GetElementType",
1486         "GetSubMeshElementsId","GetSubMeshNodesId","GetSubMeshElementType","Dump","GetNodeXYZ",
1487         "GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes",
1488         "GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces",
1489         "IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", "SetAutoColor", "GetAutoColor",
1490         "Clear", "ConvertToStandalone", "GetMeshOrder", "SetMeshOrder"
1491         ,"" }; // <- mark of end
1492     sameMethods.Insert( names );
1493   }
1494
1495   return !sameMethods.Contains( theCommand->GetMethod() );
1496 }
1497
1498 //================================================================================
1499 /*!
1500  * \brief Convert creation and addition of all algos and hypos
1501  */
1502 //================================================================================
1503
1504 void _pyMesh::Flush()
1505 {
1506   {
1507     // get the meshes this mesh depends on via hypotheses
1508     list< Handle(_pyMesh) > fatherMeshes;
1509     list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
1510     for ( ; hyp != myHypos.end(); ++hyp )
1511       if ( ! (*hyp)->GetReferredMeshesAndGeom( fatherMeshes ))
1512         myGeomNotInStudy = true;
1513
1514     list< Handle(_pyMesh) >::iterator m = fatherMeshes.begin();
1515     for ( ; m != fatherMeshes.end(); ++m )
1516       addFatherMesh( *m );
1517     // if ( removedGeom )
1518     //     SetRemovedFromStudy(); // as reffered geometry not in study
1519   }
1520   if ( myGeomNotInStudy )
1521     return;
1522
1523   list < Handle(_pyCommand) >::iterator cmd;
1524
1525   // try to convert algo addition like this:
1526   // mesh.AddHypothesis(geom, ALGO ) --> ALGO = mesh.Algo()
1527   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
1528   {
1529     Handle(_pyCommand) addCmd = *cmd;
1530
1531     _pyID algoID = addCmd->GetArg( 2 );
1532     Handle(_pyHypothesis) algo = theGen->FindHyp( algoID );
1533     if ( algo.IsNull() || !algo->IsAlgo() )
1534       continue;
1535
1536     // check and create new algorithm instance if it is already wrapped
1537     if ( algo->IsWrapped() ) {
1538       _pyID localAlgoID = theGen->GenerateNewID( algoID );
1539       TCollection_AsciiString aNewCmdStr = addCmd->GetIndentation() + localAlgoID +
1540         TCollection_AsciiString( " = " ) + theGen->GetID() +
1541         TCollection_AsciiString( ".CreateHypothesis( \"" ) + algo->GetAlgoType() +
1542         TCollection_AsciiString( "\" )" );
1543
1544       Handle(_pyCommand) newCmd = theGen->AddCommand( aNewCmdStr );
1545       Handle(_pyAlgorithm) newAlgo = Handle(_pyAlgorithm)::DownCast(theGen->FindHyp( localAlgoID ));
1546       if ( !newAlgo.IsNull() ) {
1547         newAlgo->Assign( algo, this->GetID() );
1548         newAlgo->SetCreationCmd( newCmd );
1549         algo = newAlgo;
1550         // set algorithm creation
1551         theGen->SetCommandBefore( newCmd, addCmd );
1552         myHypos.push_back( newAlgo );
1553         if ( !myLastComputeCmd.IsNull() &&
1554              newCmd->GetOrderNb() == myLastComputeCmd->GetOrderNb() + 1)
1555           newAlgo->MeshComputed( myLastComputeCmd );
1556       }
1557       else
1558         newCmd->Clear();
1559     }
1560     _pyID geom = addCmd->GetArg( 1 );
1561     bool isLocalAlgo = ( geom != GetGeom() );
1562
1563     // try to convert
1564     if ( algo->Addition2Creation( addCmd, this->GetID() )) // OK
1565     {
1566       // wrapped algo is created after mesh creation
1567       GetCreationCmd()->AddDependantCmd( addCmd );
1568
1569       if ( isLocalAlgo ) {
1570         // mesh.AddHypothesis(geom, ALGO ) --> mesh.AlgoMethod(geom)
1571         addCmd->SetArg( addCmd->GetNbArgs() + 1,
1572                         TCollection_AsciiString( "geom=" ) + geom );
1573         // sm = mesh.GetSubMesh(geom, name) --> sm = ALGO.GetSubMesh()
1574         list < Handle(_pySubMesh) >::iterator smIt;
1575         for ( smIt = mySubmeshes.begin(); smIt != mySubmeshes.end(); ++smIt ) {
1576           Handle(_pySubMesh) subMesh = *smIt;
1577           Handle(_pyCommand) subCmd = subMesh->GetCreationCmd();
1578           if ( geom == subCmd->GetArg( 1 )) {
1579             subCmd->SetObject( algo->GetID() );
1580             subCmd->RemoveArgs();
1581             subMesh->SetCreator( algo );
1582           }
1583         }
1584       }
1585     }
1586     else // KO - ALGO was already created
1587     {
1588       // mesh.AddHypothesis(geom, ALGO) --> mesh.AddHypothesis(ALGO, geom=0)
1589       addCmd->RemoveArgs();
1590       addCmd->SetArg( 1, algoID );
1591       if ( isLocalAlgo )
1592         addCmd->SetArg( 2, geom );
1593     }
1594   }
1595
1596   // try to convert hypo addition like this:
1597   // mesh.AddHypothesis(geom, HYPO ) --> HYPO = algo.Hypo()
1598   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
1599   {
1600     Handle(_pyCommand) addCmd = *cmd;
1601     _pyID hypID = addCmd->GetArg( 2 );
1602     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
1603     if ( hyp.IsNull() || hyp->IsAlgo() )
1604       continue;
1605     bool converted = hyp->Addition2Creation( addCmd, this->GetID() );
1606     if ( !converted ) {
1607       // mesh.AddHypothesis(geom, HYP) --> mesh.AddHypothesis(HYP, geom=0)
1608       _pyID geom = addCmd->GetArg( 1 );
1609       addCmd->RemoveArgs();
1610       addCmd->SetArg( 1, hypID );
1611       if ( geom != GetGeom() )
1612         addCmd->SetArg( 2, geom );
1613     }
1614   }
1615
1616   myAddHypCmds.clear();
1617   mySubmeshes.clear();
1618
1619   // flush hypotheses
1620   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
1621   for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
1622     (*hyp)->Flush();
1623 }
1624
1625 //================================================================================
1626 /*!
1627  * \brief Sets myIsPublished of me and of all objects depending on me.
1628  */
1629 //================================================================================
1630
1631 void _pyMesh::SetRemovedFromStudy(const bool isRemoved)
1632 {
1633   _pyObject::SetRemovedFromStudy(isRemoved);
1634
1635   list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin();
1636   for ( ; sm != mySubmeshes.end(); ++sm )
1637     (*sm)->SetRemovedFromStudy(isRemoved);
1638
1639   list< Handle(_pyGroup) >::iterator gr = myGroups.begin();
1640   for ( ; gr != myGroups.end(); ++gr )
1641     (*gr)->SetRemovedFromStudy(isRemoved);
1642
1643   list< Handle(_pyMesh) >::iterator m = myChildMeshes.begin();
1644   for ( ; m != myChildMeshes.end(); ++m )
1645     (*m)->SetRemovedFromStudy(isRemoved);
1646
1647   list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
1648   for ( ; e != myEditors.end(); ++e )
1649     (*e)->SetRemovedFromStudy(isRemoved);
1650 }
1651
1652 //================================================================================
1653 /*!
1654  * \brief Return true if none of myChildMeshes is in study
1655  */
1656 //================================================================================
1657
1658 bool _pyMesh::CanClear()
1659 {
1660   if ( IsInStudy() )
1661     return false;
1662
1663   list< Handle(_pyMesh) >::iterator m = myChildMeshes.begin();
1664   for ( ; m != myChildMeshes.end(); ++m )
1665     if ( !(*m)->CanClear() )
1666       return false;
1667
1668   return true;
1669 }
1670
1671 //================================================================================
1672 /*!
1673  * \brief Clear my commands and commands of mesh editor
1674  */
1675 //================================================================================
1676
1677 void _pyMesh::ClearCommands()
1678 {
1679   if ( !CanClear() )
1680   {
1681     if ( !IsInStudy() )
1682     {
1683       // mark all sub-objects as not removed, except child meshes
1684       list< Handle(_pyMesh) > children;
1685       children.swap( myChildMeshes );
1686       SetRemovedFromStudy( false );
1687       children.swap( myChildMeshes );
1688     }
1689     return;
1690   }
1691   _pyObject::ClearCommands();
1692
1693   list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin();
1694   for ( ; sm != mySubmeshes.end(); ++sm )
1695     (*sm)->ClearCommands();
1696   
1697   list< Handle(_pyGroup) >::iterator gr = myGroups.begin();
1698   for ( ; gr != myGroups.end(); ++gr )
1699     (*gr)->ClearCommands();
1700
1701   list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
1702   for ( ; e != myEditors.end(); ++e )
1703     (*e)->ClearCommands();
1704 }
1705
1706 //================================================================================
1707 /*!
1708  * \brief Add a father mesh by ID
1709  */
1710 //================================================================================
1711
1712 void _pyMesh::addFatherMesh( const _pyID& meshID )
1713 {
1714   if ( !meshID.IsEmpty() )
1715     addFatherMesh( Handle(_pyMesh)::DownCast( theGen->FindObject( meshID )));
1716 }
1717
1718 //================================================================================
1719 /*!
1720  * \brief Add a father mesh
1721  */
1722 //================================================================================
1723
1724 void _pyMesh::addFatherMesh( const Handle(_pyMesh)& mesh )
1725 {
1726   if ( !mesh.IsNull() )
1727   {
1728     //myFatherMeshes.push_back( mesh );
1729     mesh->myChildMeshes.push_back( this );
1730
1731     // protect last Compute() from clearing by the next Compute()
1732     mesh->myLastComputeCmd.Nullify();
1733   }
1734 }
1735
1736 //================================================================================
1737 /*!
1738  * \brief MeshEditor convert its commands to ones of mesh
1739  */
1740 //================================================================================
1741
1742 _pyMeshEditor::_pyMeshEditor(const Handle(_pyCommand)& theCreationCmd):
1743   _pyObject( theCreationCmd )
1744 {
1745   myMesh = theCreationCmd->GetObject();
1746   myCreationCmdStr = theCreationCmd->GetString();
1747   theCreationCmd->Clear();
1748
1749   Handle(_pyMesh) mesh = ObjectToMesh( theGen->FindObject( myMesh ));
1750   if ( !mesh.IsNull() )
1751     mesh->AddEditor( this );
1752 }
1753
1754 //================================================================================
1755 /*!
1756  * \brief convert its commands to ones of mesh
1757  */
1758 //================================================================================
1759
1760 void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
1761 {
1762   // names of SMESH_MeshEditor methods fully equal to methods of python class Mesh, so
1763   // commands calling this methods are converted to calls of methods of Mesh
1764   static TStringSet sameMethods;
1765   if ( sameMethods.empty() ) {
1766     const char * names[] = {
1767       "RemoveElements","RemoveNodes","RemoveOrphanNodes","AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace",
1768       "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","MoveNode", "MoveClosestNodeToPoint",
1769       "InverseDiag","DeleteDiag","Reorient","ReorientObject","TriToQuad","SplitQuad","SplitQuadObject",
1770       "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject",
1771       "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements",
1772       "RotationSweep","RotationSweepObject","RotationSweepObject1D","RotationSweepObject2D",
1773       "ExtrusionSweep","AdvancedExtrusion","ExtrusionSweepObject","ExtrusionSweepObject1D","ExtrusionSweepObject2D",
1774       "ExtrusionAlongPath","ExtrusionAlongPathObject","ExtrusionAlongPathX",
1775       "ExtrusionAlongPathObject1D","ExtrusionAlongPathObject2D",
1776       "Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject",
1777       "FindCoincidentNodes",/*"FindCoincidentNodesOnPart",*/"MergeNodes","FindEqualElements",
1778       "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders",
1779       "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes",
1780       "GetLastCreatedElems",
1781       "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh",
1782       "TranslateObjectMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh",
1783       "MakeBoundaryElements"
1784       ,"" }; // <- mark of the end
1785     sameMethods.Insert( names );
1786   }
1787
1788   // names of SMESH_MeshEditor methods which differ from methods of class Mesh
1789   // only by last two arguments
1790   static TStringSet diffLastTwoArgsMethods;
1791   if (diffLastTwoArgsMethods.empty() ) {
1792     const char * names[] = {
1793       "MirrorMakeGroups","MirrorObjectMakeGroups",
1794       "TranslateMakeGroups","TranslateObjectMakeGroups",
1795       "RotateMakeGroups","RotateObjectMakeGroups",
1796       ""};// <- mark of the end
1797     diffLastTwoArgsMethods.Insert( names );
1798   }
1799
1800   const TCollection_AsciiString & method = theCommand->GetMethod();
1801   bool isPyMeshMethod = sameMethods.Contains( method );
1802   if ( !isPyMeshMethod )
1803   {
1804     //Replace SMESH_MeshEditor "MakeGroups" functions by the Mesh
1805     //functions with the flag "theMakeGroups = True" like:
1806     //SMESH_MeshEditor.CmdMakeGroups => Mesh.Cmd(...,True)
1807     int pos = method.Search("MakeGroups");
1808     if( pos != -1)
1809     {
1810       isPyMeshMethod = true;
1811
1812       // 1. Remove "MakeGroups" from the Command
1813       TCollection_AsciiString aMethod = theCommand->GetMethod();
1814       int nbArgsToAdd = diffLastTwoArgsMethods.Contains(aMethod) ? 2 : 1;
1815       aMethod.Trunc(pos-1);
1816       theCommand->SetMethod(aMethod);
1817
1818       // 2. And add last "True" argument(s)
1819       while(nbArgsToAdd--)
1820         theCommand->SetArg(theCommand->GetNbArgs()+1,"True");
1821     }
1822   }
1823
1824   // set "ExtrusionAlongPathX()" instead of "ExtrusionAlongPathObjX()"
1825   if ( !isPyMeshMethod && method == "ExtrusionAlongPathObjX")
1826   {
1827     isPyMeshMethod=true;
1828     theCommand->SetMethod("ExtrusionAlongPathX");
1829   }
1830
1831   // set "FindCoincidentNodesOnPart()" instead of "FindCoincidentNodesOnPartBut()"
1832   if ( !isPyMeshMethod && method == "FindCoincidentNodesOnPartBut")
1833   {
1834     isPyMeshMethod=true;
1835     theCommand->SetMethod("FindCoincidentNodesOnPart");
1836   }
1837   // DoubleNodeElemGroupNew() -> DoubleNodeElemGroup()
1838   // DoubleNodeGroupNew() -> DoubleNodeGroup()
1839   // DoubleNodeGroupsNew() -> DoubleNodeGroups()
1840   // DoubleNodeElemGroupsNew() -> DoubleNodeElemGroups()
1841   if ( !isPyMeshMethod && ( method == "DoubleNodeElemGroupNew"  ||
1842                             method == "DoubleNodeElemGroupsNew" ||
1843                             method == "DoubleNodeGroupNew"      ||
1844                             method == "DoubleNodeGroupsNew"))
1845   {
1846     isPyMeshMethod=true;
1847     theCommand->SetMethod( method.SubString( 1, method.Length()-3));
1848     theCommand->SetArg(theCommand->GetNbArgs()+1,"True");
1849   }
1850   // ConvertToQuadraticObject(bool,obj) -> ConvertToQuadratic(bool,obj)
1851   // ConvertFromQuadraticObject(obj) -> ConvertFromQuadratic(obj)
1852   if ( !isPyMeshMethod && ( method == "ConvertToQuadraticObject" ||
1853                             method == "ConvertFromQuadraticObject" ))
1854   {
1855     isPyMeshMethod=true;
1856     theCommand->SetMethod( method.SubString( 1, method.Length()-6));
1857     // prevent moving creation of the converted sub-mesh to the end of the script
1858     bool isFromQua = ( method.Value( 8 ) == 'F' );
1859     Handle(_pySubMesh) sm = theGen->FindSubMesh( theCommand->GetArg( isFromQua ? 1 : 2 ));
1860     if ( !sm.IsNull() )
1861       sm->Process( theCommand );
1862   }
1863   // FindAmongElementsByPoint(meshPart, x, y, z, elementType) ->
1864   // FindElementsByPoint(x, y, z, elementType, meshPart)
1865   if ( !isPyMeshMethod && method == "FindAmongElementsByPoint" )
1866   {
1867     isPyMeshMethod=true;
1868     theCommand->SetMethod( "FindElementsByPoint" );
1869     // make the 1st arg be the last one
1870     _pyID partID = theCommand->GetArg( 1 );
1871     int nbArgs = theCommand->GetNbArgs();
1872     for ( int i = 2; i <= nbArgs; ++i )
1873       theCommand->SetArg( i-1, theCommand->GetArg( i ));
1874     theCommand->SetArg( nbArgs, partID );
1875   }
1876
1877   // meshes made by *MakeMesh() methods are not wrapped by _pyMesh,
1878   // so let _pyMesh care of it (TMP?)
1879   //     if ( theCommand->GetMethod().Search("MakeMesh") != -1 )
1880   //       _pyMesh( new _pyCommand( theCommand->GetString(), 0 )); // for theGen->SetAccessorMethod()
1881   if ( isPyMeshMethod )
1882   {
1883     theCommand->SetObject( myMesh );
1884   }
1885   else
1886   {
1887     // editor creation command is needed only if any editor function is called
1888     theGen->AddMeshAccessorMethod( theCommand ); // for *Object()
1889     if ( !myCreationCmdStr.IsEmpty() ) {
1890       GetCreationCmd()->GetString() = myCreationCmdStr;
1891       myCreationCmdStr.Clear();
1892     }
1893   }
1894 }
1895
1896 //================================================================================
1897 /*!
1898  * \brief Return true if my mesh can be removed
1899  */
1900 //================================================================================
1901
1902 bool _pyMeshEditor::CanClear()
1903 {
1904   Handle(_pyMesh) mesh = ObjectToMesh( theGen->FindObject( myMesh ));
1905   return mesh.IsNull() ? true : mesh->CanClear();
1906 }
1907
1908 //================================================================================
1909 /*!
1910  * \brief _pyHypothesis constructor
1911   * \param theCreationCmd -
1912  */
1913 //================================================================================
1914
1915 _pyHypothesis::_pyHypothesis(const Handle(_pyCommand)& theCreationCmd):
1916   _pyObject( theCreationCmd )
1917 {
1918   myIsAlgo = myIsWrapped = /*myIsConverted = myIsLocal = myDim = */false;
1919 }
1920
1921 //================================================================================
1922 /*!
1923  * \brief Creates algorithm or hypothesis
1924   * \param theCreationCmd - The engine command creating a hypothesis
1925   * \retval Handle(_pyHypothesis) - Result _pyHypothesis
1926  */
1927 //================================================================================
1928
1929 Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& theCreationCmd)
1930 {
1931   // theCreationCmd: CreateHypothesis( "theHypType", "theLibName" )
1932   ASSERT (( theCreationCmd->GetMethod() == "CreateHypothesis"));
1933
1934   Handle(_pyHypothesis) hyp, algo;
1935
1936   // "theHypType"
1937   const TCollection_AsciiString & hypTypeQuoted = theCreationCmd->GetArg( 1 );
1938   if ( hypTypeQuoted.IsEmpty() )
1939     return hyp;
1940   // theHypType
1941   TCollection_AsciiString  hypType =
1942     hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
1943
1944   algo = new _pyAlgorithm( theCreationCmd );
1945   hyp  = new _pyHypothesis( theCreationCmd );
1946
1947   // 1D Regular_1D ----------
1948   if ( hypType == "Regular_1D" ) {
1949     // set mesh's method creating algo,
1950     // i.e. convertion result will be "regular1d = Mesh.Segment()",
1951     // and set hypType by which algo creating a hypothesis is searched for
1952     algo->SetConvMethodAndType("Segment", hypType.ToCString());
1953   }
1954   else if ( hypType == "CompositeSegment_1D" ) {
1955     algo->SetConvMethodAndType("Segment", "Regular_1D");
1956     algo->myArgs.Append( "algo=smesh.COMPOSITE");
1957   }
1958   else if ( hypType == "LocalLength" ) {
1959     // set algo's method creating hyp, and algo type
1960     hyp->SetConvMethodAndType( "LocalLength", "Regular_1D");
1961     // set method whose 1 arg will become the 1-st arg of hyp creation command
1962     // i.e. convertion result will be "locallength = regular1d.LocalLength(<arg of SetLength()>)"
1963     hyp->AddArgMethod( "SetLength" );
1964   }
1965   else if ( hypType == "MaxLength" ) {
1966     // set algo's method creating hyp, and algo type
1967     hyp->SetConvMethodAndType( "MaxSize", "Regular_1D");
1968     // set method whose 1 arg will become the 1-st arg of hyp creation command
1969     // i.e. convertion result will be "maxsize = regular1d.MaxSize(<arg of SetLength()>)"
1970     hyp->AddArgMethod( "SetLength" );
1971   }
1972   else if ( hypType == "NumberOfSegments" ) {
1973     hyp = new _pyNumberOfSegmentsHyp( theCreationCmd );
1974     hyp->SetConvMethodAndType( "NumberOfSegments", "Regular_1D");
1975     // arg of SetNumberOfSegments() will become the 1-st arg of hyp creation command
1976     hyp->AddArgMethod( "SetNumberOfSegments" );
1977     // arg of SetScaleFactor() will become the 2-nd arg of hyp creation command
1978     hyp->AddArgMethod( "SetScaleFactor" );
1979     hyp->AddArgMethod( "SetReversedEdges" );
1980   }
1981   else if ( hypType == "Arithmetic1D" ) {
1982     hyp = new _pyComplexParamHypo( theCreationCmd );
1983     hyp->SetConvMethodAndType( "Arithmetic1D", "Regular_1D");
1984     hyp->AddArgMethod( "SetStartLength" );
1985     hyp->AddArgMethod( "SetEndLength" );
1986     hyp->AddArgMethod( "SetReversedEdges" );
1987   }
1988   else if ( hypType == "StartEndLength" ) {
1989     hyp = new _pyComplexParamHypo( theCreationCmd );
1990     hyp->SetConvMethodAndType( "StartEndLength", "Regular_1D");
1991     hyp->AddArgMethod( "SetStartLength" );
1992     hyp->AddArgMethod( "SetEndLength" );
1993     hyp->AddArgMethod( "SetReversedEdges" );
1994   }
1995   else if ( hypType == "Deflection1D" ) {
1996     hyp->SetConvMethodAndType( "Deflection1D", "Regular_1D");
1997     hyp->AddArgMethod( "SetDeflection" );
1998   }
1999   else if ( hypType == "Propagation" ) {
2000     hyp->SetConvMethodAndType( "Propagation", "Regular_1D");
2001   }
2002   else if ( hypType == "QuadraticMesh" ) {
2003     hyp->SetConvMethodAndType( "QuadraticMesh", "Regular_1D");
2004   }
2005   else if ( hypType == "AutomaticLength" ) {
2006     hyp->SetConvMethodAndType( "AutomaticLength", "Regular_1D");
2007     hyp->AddArgMethod( "SetFineness");
2008   }
2009   else if ( hypType == "SegmentLengthAroundVertex" ) {
2010     hyp = new _pySegmentLengthAroundVertexHyp( theCreationCmd );
2011     hyp->SetConvMethodAndType( "LengthNearVertex", "Regular_1D" );
2012     hyp->AddArgMethod( "SetLength" );
2013   }
2014   // 1D Python_1D ----------
2015   else if ( hypType == "Python_1D" ) {
2016     algo->SetConvMethodAndType( "Segment", hypType.ToCString());
2017     algo->myArgs.Append( "algo=smesh.PYTHON");
2018   }
2019   else if ( hypType == "PythonSplit1D" ) {
2020     hyp->SetConvMethodAndType( "PythonSplit1D", "Python_1D");
2021     hyp->AddArgMethod( "SetNumberOfSegments");
2022     hyp->AddArgMethod( "SetPythonLog10RatioFunction");
2023   }
2024   // MEFISTO_2D ----------
2025   else if ( hypType == "MEFISTO_2D" ) { // MEFISTO_2D
2026     algo->SetConvMethodAndType( "Triangle", hypType.ToCString());
2027   }
2028   else if ( hypType == "MaxElementArea" ) {
2029     hyp->SetConvMethodAndType( "MaxElementArea", "MEFISTO_2D");
2030     hyp->SetConvMethodAndType( "MaxElementArea", "NETGEN_2D_ONLY");
2031     hyp->AddArgMethod( "SetMaxElementArea");
2032   }
2033   else if ( hypType == "LengthFromEdges" ) {
2034     hyp->SetConvMethodAndType( "LengthFromEdges", "MEFISTO_2D");
2035     hyp->SetConvMethodAndType( "LengthFromEdges", "NETGEN_2D_ONLY");
2036   }
2037   // Quadrangle_2D ----------
2038   else if ( hypType == "Quadrangle_2D" ) {
2039     algo->SetConvMethodAndType( "Quadrangle" , hypType.ToCString());
2040   }
2041   else if ( hypType == "QuadranglePreference" ) {
2042     hyp->SetConvMethodAndType( "QuadranglePreference", "Quadrangle_2D");
2043     hyp->SetConvMethodAndType( "SetQuadAllowed", "NETGEN_2D_ONLY");
2044   }
2045   else if ( hypType == "TrianglePreference" ) {
2046     hyp->SetConvMethodAndType( "TrianglePreference", "Quadrangle_2D");
2047   }
2048   // RadialQuadrangle_1D2D ----------
2049   else if ( hypType == "RadialQuadrangle_1D2D" ) {
2050     algo->SetConvMethodAndType( "Quadrangle" , hypType.ToCString());
2051     algo->myArgs.Append( "algo=smesh.RADIAL_QUAD" );
2052   }
2053   else if ( hypType == "NumberOfLayers2D" ) {
2054     hyp->SetConvMethodAndType( "NumberOfLayers", "RadialQuadrangle_1D2D");
2055     hyp->AddArgMethod( "SetNumberOfLayers" );
2056   }
2057   else if ( hypType == "LayerDistribution2D" ) {
2058     hyp = new _pyLayerDistributionHypo( theCreationCmd, "Get2DHypothesis" );
2059     hyp->SetConvMethodAndType( "LayerDistribution", "RadialQuadrangle_1D2D");
2060   }
2061   // BLSURF ----------
2062   else if ( hypType == "BLSURF" ) {
2063     algo->SetConvMethodAndType( "Triangle", hypType.ToCString());
2064     algo->myArgs.Append( "algo=smesh.BLSURF" );
2065   }
2066   else if ( hypType == "BLSURF_Parameters") {
2067     hyp->SetConvMethodAndType( "Parameters", "BLSURF");
2068   }
2069   // NETGEN ----------
2070   else if ( hypType == "NETGEN_2D") { // 1D-2D
2071     algo->SetConvMethodAndType( "Triangle" , hypType.ToCString());
2072     algo->myArgs.Append( "algo=smesh.NETGEN" );
2073   }
2074   else if ( hypType == "NETGEN_Parameters_2D") {
2075     hyp->SetConvMethodAndType( "Parameters", "NETGEN_2D");
2076   }
2077   else if ( hypType == "NETGEN_SimpleParameters_2D") {
2078     hyp->SetConvMethodAndType( "Parameters", "NETGEN_2D");
2079     hyp->myArgs.Append( "which=smesh.SIMPLE" );
2080   }
2081   else if ( hypType == "NETGEN_2D3D") { // 1D-2D-3D
2082     algo->SetConvMethodAndType( "Tetrahedron" , hypType.ToCString());
2083     algo->myArgs.Append( "algo=smesh.FULL_NETGEN" );
2084   }
2085   else if ( hypType == "NETGEN_Parameters") {
2086     hyp->SetConvMethodAndType( "Parameters", "NETGEN_2D3D");
2087   }
2088   else if ( hypType == "NETGEN_SimpleParameters_3D") {
2089     hyp->SetConvMethodAndType( "Parameters", "NETGEN_2D3D");
2090     hyp->myArgs.Append( "which=smesh.SIMPLE" );
2091   }
2092   else if ( hypType == "NETGEN_2D_ONLY") { // 2D
2093     algo->SetConvMethodAndType( "Triangle" , hypType.ToCString());
2094     algo->myArgs.Append( "algo=smesh.NETGEN_2D" );
2095   }
2096   else if ( hypType == "NETGEN_3D") { // 3D
2097     algo->SetConvMethodAndType( "Tetrahedron" , hypType.ToCString());
2098     algo->myArgs.Append( "algo=smesh.NETGEN" );
2099   }
2100   else if ( hypType == "MaxElementVolume") {
2101     hyp->SetConvMethodAndType( "MaxElementVolume", "NETGEN_3D");
2102     hyp->AddArgMethod( "SetMaxElementVolume" );
2103   }
2104   // GHS3D_3D ----------
2105   else if ( hypType == "GHS3D_3D" ) {
2106     algo->SetConvMethodAndType( "Tetrahedron", hypType.ToCString());
2107     algo->myArgs.Append( "algo=smesh.GHS3D" );
2108   }
2109   else if ( hypType == "GHS3D_Parameters") {
2110     hyp->SetConvMethodAndType( "Parameters", "GHS3D_3D");
2111   }
2112   // Hexa_3D ---------
2113   else if ( hypType == "Hexa_3D" ) {
2114     algo->SetConvMethodAndType( "Hexahedron", hypType.ToCString());
2115   }
2116   // Repetitive Projection_1D ---------
2117   else if ( hypType == "Projection_1D" ) {
2118     algo->SetConvMethodAndType( "Projection1D", hypType.ToCString());
2119   }
2120   else if ( hypType == "ProjectionSource1D" ) {
2121     hyp->SetConvMethodAndType( "SourceEdge", "Projection_1D");
2122     hyp->AddArgMethod( "SetSourceEdge");
2123     hyp->AddArgMethod( "SetSourceMesh");
2124     // 2 args of SetVertexAssociation() will become the 3-th and 4-th args of hyp creation command
2125     hyp->AddArgMethod( "SetVertexAssociation", 2 );
2126   }
2127   // Projection_2D ---------
2128   else if ( hypType == "Projection_2D" ) {
2129     algo->SetConvMethodAndType( "Projection2D", hypType.ToCString());
2130   }
2131   else if ( hypType == "Projection_1D2D" ) {
2132     algo->SetConvMethodAndType( "Projection1D2D", hypType.ToCString());
2133   }
2134   else if ( hypType == "ProjectionSource2D" ) {
2135     hyp->SetConvMethodAndType( "SourceFace", "Projection_2D");
2136     hyp->SetConvMethodAndType( "SourceFace", "Projection_1D2D");
2137     hyp->AddArgMethod( "SetSourceFace");
2138     hyp->AddArgMethod( "SetSourceMesh");
2139     hyp->AddArgMethod( "SetVertexAssociation", 4 );
2140   }
2141   // Projection_3D ---------
2142   else if ( hypType == "Projection_3D" ) {
2143     algo->SetConvMethodAndType( "Projection3D", hypType.ToCString());
2144   }
2145   else if ( hypType == "ProjectionSource3D" ) {
2146     hyp->SetConvMethodAndType( "SourceShape3D", "Projection_3D");
2147     hyp->AddArgMethod( "SetSource3DShape");
2148     hyp->AddArgMethod( "SetSourceMesh");
2149     hyp->AddArgMethod( "SetVertexAssociation", 4 );
2150   }
2151   // Prism_3D ---------
2152   else if ( hypType == "Prism_3D" ) {
2153     algo->SetConvMethodAndType( "Prism", hypType.ToCString());
2154   }
2155   // RadialPrism_3D ---------
2156   else if ( hypType == "RadialPrism_3D" ) {
2157     algo->SetConvMethodAndType( "Prism", hypType.ToCString());
2158   }
2159   else if ( hypType == "NumberOfLayers" ) {
2160     hyp->SetConvMethodAndType( "NumberOfLayers", "RadialPrism_3D");
2161     hyp->AddArgMethod( "SetNumberOfLayers" );
2162   }
2163   else if ( hypType == "LayerDistribution" ) {
2164     hyp = new _pyLayerDistributionHypo( theCreationCmd, "Get3DHypothesis" );
2165     hyp->SetConvMethodAndType( "LayerDistribution", "RadialPrism_3D");
2166   }
2167   // Cartesian 3D ---------
2168   else if ( hypType == "Cartesian_3D" ) {
2169     algo->SetConvMethodAndType( "BodyFitted", hypType.ToCString());
2170   }
2171   else if ( hypType == "CartesianParameters3D" ) {
2172     hyp = new _pyComplexParamHypo( theCreationCmd );
2173     hyp->SetConvMethodAndType( "SetGrid", "Cartesian_3D");
2174     for ( int iArg = 0; iArg < 4; ++iArg )
2175       hyp->myArgs.Append("[]");
2176   }
2177
2178   return algo->IsValid() ? algo : hyp;
2179 }
2180
2181 //================================================================================
2182 /*!
2183  * \brief Returns true if addition of this hypothesis to a given mesh can be
2184  *        wrapped into hypothesis creation
2185  */
2186 //================================================================================
2187
2188 bool _pyHypothesis::IsWrappable(const _pyID& theMesh) const
2189 {
2190   if ( !myIsWrapped && myMesh == theMesh && IsInStudy() )
2191   {
2192     Handle(_pyObject) pyMesh = theGen->FindObject( myMesh );
2193     if ( !pyMesh.IsNull() && pyMesh->IsInStudy() )
2194       return true;
2195   }
2196   return false;
2197 }
2198
2199 //================================================================================
2200 /*!
2201  * \brief Convert the command adding a hypothesis to mesh into a smesh command
2202   * \param theCmd - The command like mesh.AddHypothesis( geom, hypo )
2203   * \param theAlgo - The algo that can create this hypo
2204   * \retval bool - false if the command cant be converted
2205  */
2206 //================================================================================
2207
2208 bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd,
2209                                        const _pyID&              theMesh)
2210 {
2211   ASSERT(( theCmd->GetMethod() == "AddHypothesis" ));
2212
2213   if ( !IsWrappable( theMesh ))
2214     return false;
2215
2216   myGeom = theCmd->GetArg( 1 );
2217
2218   Handle(_pyHypothesis) algo;
2219   if ( !IsAlgo() ) {
2220     // find algo created on myGeom in theMesh
2221     algo = theGen->FindAlgo( myGeom, theMesh, this );
2222     if ( algo.IsNull() )
2223       return false;
2224     // attach hypothesis creation command to be after algo creation command
2225     // because it can be new created instance of algorithm
2226     algo->GetCreationCmd()->AddDependantCmd( theCmd );
2227   }
2228   myIsWrapped = true;
2229
2230   // mesh.AddHypothesis(geom,hyp) --> hyp = <theMesh or algo>.myCreationMethod(args)
2231   theCmd->SetResultValue( GetID() );
2232   theCmd->SetObject( IsAlgo() ? theMesh : algo->GetID());
2233   theCmd->SetMethod( IsAlgo() ? GetAlgoCreationMethod() : GetCreationMethod( algo->GetAlgoType() ));
2234   // set args
2235   theCmd->RemoveArgs();
2236   for ( int i = 1; i <= myArgs.Length(); ++i ) {
2237     if ( !myArgs( i ).IsEmpty() )
2238       theCmd->SetArg( i, myArgs( i ));
2239     else
2240       theCmd->SetArg( i, "[]");
2241   }
2242   // set a new creation command
2243   GetCreationCmd()->Clear();
2244   // replace creation command by wrapped instance
2245   // please note, that hypothesis attaches to algo creation command (see upper)
2246   SetCreationCmd( theCmd );
2247
2248
2249   // clear commands setting arg values
2250   list < Handle(_pyCommand) >::iterator argCmd = myArgCommands.begin();
2251   for ( ; argCmd != myArgCommands.end(); ++argCmd )
2252     (*argCmd)->Clear();
2253
2254   // set unknown arg commands after hypo creation
2255   Handle(_pyCommand) afterCmd = myIsWrapped ? theCmd : GetCreationCmd();
2256   list<Handle(_pyCommand)>::iterator cmd = myUnknownCommands.begin();
2257   for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
2258     afterCmd->AddDependantCmd( *cmd );
2259   }
2260
2261   return myIsWrapped;
2262 }
2263
2264 //================================================================================
2265 /*!
2266  * \brief Remember hypothesis parameter values
2267  * \param theCommand - The called hypothesis method
2268  */
2269 //================================================================================
2270
2271 void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand)
2272 {
2273   ASSERT( !myIsAlgo );
2274   rememberCmdOfParameter( theCommand );
2275   // set args
2276   int nbArgs = 0;
2277   for ( int i = 1; i <= myArgMethods.Length(); ++i ) {
2278     if ( myArgMethods( i ) == theCommand->GetMethod() ) {
2279       while ( myArgs.Length() < nbArgs + myNbArgsByMethod( i ))
2280         myArgs.Append( "[]" );
2281       for ( int iArg = 1; iArg <= myNbArgsByMethod( i ); ++iArg )
2282         myArgs( nbArgs + iArg ) = theCommand->GetArg( iArg ); // arg value
2283       myArgCommands.push_back( theCommand );
2284       return;
2285     }
2286     nbArgs += myNbArgsByMethod( i );
2287   }
2288   myUnknownCommands.push_back( theCommand );
2289 }
2290
2291 //================================================================================
2292 /*!
2293  * \brief Finish conversion
2294  */
2295 //================================================================================
2296
2297 void _pyHypothesis::Flush()
2298 {
2299   if ( IsWrapped() ) {
2300   }
2301   else {
2302     list < Handle(_pyCommand) >::iterator cmd = myArgCommands.begin();
2303     for ( ; cmd != myArgCommands.end(); ++cmd ) {
2304       // Add access to a wrapped mesh
2305       theGen->AddMeshAccessorMethod( *cmd );
2306       // Add access to a wrapped algorithm
2307       theGen->AddAlgoAccessorMethod( *cmd );
2308     }
2309     cmd = myUnknownCommands.begin();
2310     for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
2311       // Add access to a wrapped mesh
2312       theGen->AddMeshAccessorMethod( *cmd );
2313       // Add access to a wrapped algorithm
2314       theGen->AddAlgoAccessorMethod( *cmd );
2315     }
2316   }
2317   // forget previous hypothesis modifications
2318   myArgCommands.clear();
2319   myUnknownCommands.clear();
2320 }
2321
2322 //================================================================================
2323 /*!
2324  * \brief clear creation, arg and unkown commands
2325  */
2326 //================================================================================
2327
2328 void _pyHypothesis::ClearAllCommands()
2329 {
2330   GetCreationCmd()->Clear();
2331   list<Handle(_pyCommand)>::iterator cmd = myArgCommands.begin();
2332   for ( ; cmd != myArgCommands.end(); ++cmd )
2333     ( *cmd )->Clear();
2334   cmd = myUnknownCommands.begin();
2335   for ( ; cmd != myUnknownCommands.end(); ++cmd )
2336     ( *cmd )->Clear();
2337 }
2338
2339
2340 //================================================================================
2341 /*!
2342  * \brief Assign fields of theOther to me except myIsWrapped
2343  */
2344 //================================================================================
2345
2346 void _pyHypothesis::Assign( const Handle(_pyHypothesis)& theOther,
2347                             const _pyID&                 theMesh )
2348 {
2349   myIsWrapped = false;
2350   myMesh = theMesh;
2351
2352   // myCreationCmd = theOther->myCreationCmd;
2353   myIsAlgo = theOther->myIsAlgo;
2354   myGeom = theOther->myGeom;
2355   myType2CreationMethod = theOther->myType2CreationMethod;
2356   myArgs = theOther->myArgs;
2357   myArgMethods = theOther->myArgMethods;
2358   myNbArgsByMethod = theOther->myNbArgsByMethod;
2359   myArgCommands = theOther->myArgCommands;
2360   myUnknownCommands = theOther->myUnknownCommands;
2361 }
2362
2363 //================================================================================
2364 /*!
2365  * \brief Analyze my erasability depending on myReferredObjs
2366  */
2367 //================================================================================
2368
2369 bool _pyHypothesis::CanClear()
2370 {
2371   if ( IsInStudy() )
2372   {
2373     list< Handle(_pyObject) >::iterator obj = myReferredObjs.begin();
2374     for ( ; obj != myReferredObjs.end(); ++obj )
2375       if ( (*obj)->CanClear() )
2376         return true;
2377     return false;
2378   }
2379   return true;
2380 }
2381
2382 //================================================================================
2383 /*!
2384  * \brief Clear my commands depending on usage by meshes
2385  */
2386 //================================================================================
2387
2388 void _pyHypothesis::ClearCommands()
2389 {
2390   if ( !theGen->IsToKeepAllCommands() )
2391   {
2392     bool isUsed = false;
2393     int lastComputeOrder = 0;
2394     list<Handle(_pyCommand) >::iterator cmd = myComputeCmds.begin();
2395     for ( ; cmd != myComputeCmds.end(); ++cmd )
2396       if ( ! (*cmd)->IsEmpty() )
2397       {
2398         isUsed = true;
2399         if ( (*cmd)->GetOrderNb() > lastComputeOrder )
2400           lastComputeOrder = (*cmd)->GetOrderNb();
2401       }
2402     if ( !isUsed )
2403     {
2404       SetRemovedFromStudy( true );
2405     }
2406     else
2407     {
2408       // clear my commands invoked after lastComputeOrder
2409       map<TCollection_AsciiString, list< Handle(_pyCommand) > >::iterator m2c;
2410       for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c )
2411       {
2412         list< Handle(_pyCommand)> & cmds = m2c->second;
2413         if ( !cmds.empty() && cmds.back()->GetOrderNb() > lastComputeOrder )
2414           cmds.back()->Clear();
2415       }
2416     }
2417   }
2418   _pyObject::ClearCommands();
2419 }
2420
2421 //================================================================================
2422 /*!
2423  * \brief Find arguments that are objects like mesh, group, geometry
2424  *  \param meshes - referred meshes (directly or indirrectly)
2425  *  \retval bool - false if a referred geometry is not in the study
2426  */
2427 //================================================================================
2428
2429 bool _pyHypothesis::GetReferredMeshesAndGeom( list< Handle(_pyMesh) >& meshes )
2430 {
2431   if ( IsAlgo() ) return true;
2432
2433   bool geomPublished = true;
2434   TColStd_SequenceOfAsciiString args; args = myArgs;
2435
2436   list<Handle(_pyCommand)>::iterator cmd = myUnknownCommands.begin();
2437   for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
2438     for ( int nb = (*cmd)->GetNbArgs(); nb; --nb )
2439       args.Append( (*cmd)->GetArg( nb ));
2440   }
2441
2442   for ( int i = 1; i <= args.Length(); ++i )
2443   {
2444     list< _pyID > idList = _pyCommand::GetStudyEntries( args( i ));
2445     list< _pyID >::iterator id = idList.begin();
2446     for ( ; id != idList.end(); ++id )
2447     {
2448       Handle(_pyObject) obj = theGen->FindObject( *id );
2449       if ( obj.IsNull() )
2450       {
2451         if ( theGen->IsGeomObject( *id ) && theGen->IsNotPublished( *id ))
2452           geomPublished = false;
2453       }
2454       else
2455       {
2456         myReferredObjs.push_back( obj );
2457         Handle(_pyMesh) mesh = ObjectToMesh( obj );
2458         if ( !mesh.IsNull() )
2459           meshes.push_back( mesh );
2460       }
2461     }
2462   }
2463   return geomPublished;
2464 }
2465
2466 //================================================================================
2467 /*!
2468  * \brief Remember theCommand setting a parameter
2469  */
2470 //================================================================================
2471
2472 void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theCommand )
2473 {
2474   // not to clear commands setting different parameters via one method
2475   // by passing parameter names like e.g. SetOption("size", "0.2")
2476   int quotePos = theCommand->GetString().FirstLocationInSet( "'\"", 1, theCommand->Length() );
2477   if ( !quotePos )
2478   {
2479     // parameters are discriminated by method name
2480     list< Handle(_pyCommand)>& cmds = myMeth2Commands[ theCommand->GetMethod() ];
2481     if ( !cmds.empty() && !isCmdUsedForCompute( cmds.back() ))
2482     {
2483       cmds.back()->Clear(); // previous parameter value has not been used
2484       cmds.back() = theCommand;
2485     }
2486     else
2487     {
2488       cmds.push_back( theCommand );
2489     }
2490   }
2491 }
2492
2493 //================================================================================
2494 /*!
2495  * \brief Return true if a setting parameter command ha been used to compute mesh
2496  */
2497 //================================================================================
2498
2499 bool _pyHypothesis::isCmdUsedForCompute( const Handle(_pyCommand) & cmd,
2500                                          _pyCommand::TAddr          avoidComputeAddr ) const
2501 {
2502   bool isUsed = false;
2503   map< _pyCommand::TAddr, list<Handle(_pyCommand) > >::const_iterator addr2cmds =
2504     myComputeAddr2Cmds.begin();
2505   for ( ; addr2cmds != myComputeAddr2Cmds.end() && !isUsed; ++addr2cmds )
2506   {
2507     if ( addr2cmds->first == avoidComputeAddr ) continue;
2508     const list<Handle(_pyCommand)> & cmds = addr2cmds->second;
2509     isUsed = ( std::find( cmds.begin(), cmds.end(), cmd ) != cmds.end() );
2510   }
2511   return isUsed;
2512 }
2513
2514 //================================================================================
2515 /*!
2516  * \brief Save commands setting parameters as they are used for a mesh computation
2517  */
2518 //================================================================================
2519
2520 void _pyHypothesis::MeshComputed( const Handle(_pyCommand)& theComputeCmd )
2521 {
2522   myComputeCmds.push_back( theComputeCmd );
2523   list<Handle(_pyCommand)>& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ];
2524
2525   map<TCollection_AsciiString, list< Handle(_pyCommand) > >::iterator m2c;
2526   for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c )
2527     savedCmds.push_back( m2c->second.back() );
2528 }
2529
2530 //================================================================================
2531 /*!
2532  * \brief Clear commands setting parameters as a mesh computed using them is cleared
2533  */
2534 //================================================================================
2535
2536 void _pyHypothesis::ComputeDiscarded( const Handle(_pyCommand)& theComputeCmd )
2537 {
2538   list<Handle(_pyCommand)>& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ];
2539
2540   list<Handle(_pyCommand)>::iterator cmd = savedCmds.begin();
2541   for ( ; cmd != savedCmds.end(); ++cmd )
2542   {
2543     // check if a cmd has been used to compute another mesh
2544     if ( isCmdUsedForCompute( *cmd, theComputeCmd->GetAddress() ))
2545       continue;
2546     // check if a cmd is a sole command setting its parameter;
2547     // don't use method name for search as it can change
2548     map<TCollection_AsciiString, list<Handle(_pyCommand)> >::iterator
2549       m2cmds = myMeth2Commands.begin();
2550     for ( ; m2cmds != myMeth2Commands.end(); ++m2cmds )
2551     {
2552       list< Handle(_pyCommand)>& cmds = m2cmds->second;
2553       list< Handle(_pyCommand)>::iterator cmdIt = std::find( cmds.begin(), cmds.end(), *cmd );
2554       if ( cmdIt != cmds.end() )
2555       {
2556         if ( cmds.back() != *cmd )
2557         {
2558           cmds.erase( cmdIt );
2559           (*cmd)->Clear();
2560         }
2561         break;
2562       }
2563     }
2564   }
2565   myComputeAddr2Cmds.erase( theComputeCmd->GetAddress() );
2566 }
2567 // void _pyHypothesis::ComputeSaved( const Handle(_pyCommand)& theComputeCommand )
2568 // {
2569 // }
2570
2571
2572 //================================================================================
2573 /*!
2574  * \brief Remember hypothesis parameter values
2575  * \param theCommand - The called hypothesis method
2576  */
2577 //================================================================================
2578
2579 void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
2580 {
2581   if ( GetAlgoType() == "Cartesian_3D" )
2582   {
2583     // CartesianParameters3D hyp
2584
2585     if ( theCommand->GetMethod() == "SetSizeThreshold" )
2586     {
2587       myArgs( 4 ) = theCommand->GetArg( 1 );
2588       myArgCommands.push_back( theCommand );
2589       return;
2590     }
2591     if ( theCommand->GetMethod() == "SetGrid" ||
2592          theCommand->GetMethod() == "SetGridSpacing" )
2593     {
2594       TCollection_AsciiString axis = theCommand->GetArg( theCommand->GetNbArgs() );
2595       int iArg = 1 + ( axis.Value(1) - '0' );
2596       if ( theCommand->GetMethod() == "SetGrid" )
2597       {
2598         myArgs( iArg ) = theCommand->GetArg( 1 );
2599       }
2600       else
2601       {
2602         myArgs( iArg ) = "[ ";
2603         myArgs( iArg ) += theCommand->GetArg( 1 );
2604         myArgs( iArg ) += ", ";
2605         myArgs( iArg ) += theCommand->GetArg( 2 );
2606         myArgs( iArg ) += "]";
2607       }
2608       myArgCommands.push_back( theCommand );
2609       rememberCmdOfParameter( theCommand );
2610       return;
2611     }
2612   }
2613
2614   if( theCommand->GetMethod() == "SetLength" )
2615   {
2616     // NOW it is OBSOLETE
2617     // ex: hyp.SetLength(start, 1)
2618     //     hyp.SetLength(end,   0)
2619     ASSERT(( theCommand->GetArg( 2 ).IsIntegerValue() ));
2620     int i = 2 - theCommand->GetArg( 2 ).IntegerValue();
2621     while ( myArgs.Length() < i )
2622       myArgs.Append( "[]" );
2623     myArgs( i ) = theCommand->GetArg( 1 ); // arg value
2624     myArgCommands.push_back( theCommand );
2625   }
2626   else
2627   {
2628     _pyHypothesis::Process( theCommand );
2629   }
2630 }
2631 //================================================================================
2632 /*!
2633  * \brief Clear SetObjectEntry() as it is called by methods of Mesh_Segment
2634  */
2635 //================================================================================
2636
2637 void _pyComplexParamHypo::Flush()
2638 {
2639   if ( IsWrapped() )
2640   {
2641     list < Handle(_pyCommand) >::iterator cmd = myUnknownCommands.begin();
2642     for ( ; cmd != myUnknownCommands.end(); ++cmd )
2643       if ((*cmd)->GetMethod() == "SetObjectEntry" )
2644         (*cmd)->Clear();
2645   }
2646 }
2647
2648 //================================================================================
2649 /*!
2650  * \brief Convert methods of 1D hypotheses to my own methods
2651   * \param theCommand - The called hypothesis method
2652  */
2653 //================================================================================
2654
2655 void _pyLayerDistributionHypo::Process( const Handle(_pyCommand)& theCommand)
2656 {
2657   if ( theCommand->GetMethod() != "SetLayerDistribution" )
2658     return;
2659
2660   _pyID newName; // name for 1D hyp = "HypType" + "_Distribution"
2661
2662   const _pyID& hyp1dID = theCommand->GetArg( 1 );
2663   Handle(_pyHypothesis) hyp1d = theGen->FindHyp( hyp1dID );
2664   if ( hyp1d.IsNull() ) // apparently hypId changed at study restoration
2665     hyp1d = my1dHyp;
2666   else if ( !my1dHyp.IsNull() && hyp1dID != my1dHyp->GetID() ) {
2667     // 1D hypo is already set, so distribution changes and the old
2668     // 1D hypo is thrown away
2669     my1dHyp->ClearAllCommands();
2670   }
2671   my1dHyp = hyp1d;
2672
2673   if ( !myArgCommands.empty() )
2674     myArgCommands.front()->Clear();
2675   myArgCommands.push_back( theCommand );
2676 }
2677
2678 //================================================================================
2679 /*!
2680  * \brief
2681   * \param theAdditionCmd - command to be converted
2682   * \param theMesh - mesh instance
2683   * \retval bool - status
2684  */
2685 //================================================================================
2686
2687 bool _pyLayerDistributionHypo::Addition2Creation( const Handle(_pyCommand)& theAdditionCmd,
2688                                                   const _pyID&              theMesh)
2689 {
2690   myIsWrapped = false;
2691
2692   if ( my1dHyp.IsNull() )
2693     return false;
2694
2695   // set "SetLayerDistribution()" after addition cmd
2696   theAdditionCmd->AddDependantCmd( myArgCommands.front() );
2697
2698   _pyID geom = theAdditionCmd->GetArg( 1 );
2699
2700   Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMesh, this );
2701   if ( !algo.IsNull() )
2702   {
2703     my1dHyp->SetMesh( theMesh );
2704     my1dHyp->SetConvMethodAndType(my1dHyp->GetAlgoCreationMethod().ToCString(),
2705                                   algo->GetAlgoType().ToCString());
2706     if ( !my1dHyp->Addition2Creation( theAdditionCmd, theMesh ))
2707       return false;
2708
2709     // clear "SetLayerDistribution()" cmd
2710     myArgCommands.back()->Clear();
2711
2712     // Convert my creation => me = RadialPrismAlgo.Get3DHypothesis()
2713
2714     // find RadialPrism algo created on <geom> for theMesh
2715     GetCreationCmd()->SetObject( algo->GetID() );
2716     GetCreationCmd()->SetMethod( myAlgoMethod );
2717     GetCreationCmd()->RemoveArgs();
2718     theAdditionCmd->AddDependantCmd( GetCreationCmd() );
2719     myIsWrapped = true;
2720   }
2721   return myIsWrapped;
2722 }
2723
2724 //================================================================================
2725 /*!
2726  * \brief
2727  */
2728 //================================================================================
2729
2730 void _pyLayerDistributionHypo::Flush()
2731 {
2732   // as creation of 1D hyp was written later then it's edition,
2733   // we need to find all it's edition calls and process them
2734   if ( !my1dHyp.IsNull() )
2735   {
2736     _pyID hyp1dID = my1dHyp->GetCreationCmd()->GetResultValue();
2737
2738     // make a new name for 1D hyp = "HypType" + "_Distribution"
2739     _pyID newName;
2740     if ( my1dHyp->IsWrapped() ) {
2741       newName = my1dHyp->GetCreationCmd()->GetMethod();
2742     }
2743     else {
2744       TCollection_AsciiString hypTypeQuoted = my1dHyp->GetCreationCmd()->GetArg(1);
2745       newName = hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
2746     }
2747     newName += "_Distribution";
2748     my1dHyp->GetCreationCmd()->SetResultValue( newName );
2749
2750     list< Handle(_pyCommand) >& cmds = theGen->GetCommands();
2751     list< Handle(_pyCommand) >::iterator cmdIt = cmds.begin();
2752     for ( ; cmdIt != cmds.end(); ++cmdIt ) {
2753       const _pyID& objID = (*cmdIt)->GetObject();
2754       if ( objID == hyp1dID ) {
2755         my1dHyp->Process( *cmdIt );
2756         my1dHyp->GetCreationCmd()->AddDependantCmd( *cmdIt );
2757         ( *cmdIt )->SetObject( newName );
2758       }
2759     }
2760     // Set new hyp name to SetLayerDistribution() cmd
2761     if ( !myArgCommands.empty() && !myArgCommands.back()->IsEmpty() )
2762       myArgCommands.back()->SetArg( 1, newName );
2763   }
2764 }
2765
2766 //================================================================================
2767 /*!
2768  * \brief additionally to Addition2Creation, clears SetDistrType() command
2769   * \param theCmd - AddHypothesis() command
2770   * \param theMesh - mesh to which a hypothesis is added
2771   * \retval bool - convertion result
2772  */
2773 //================================================================================
2774
2775 bool _pyNumberOfSegmentsHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
2776                                                 const _pyID&              theMesh)
2777 {
2778   if ( IsWrappable( theMesh ) && myArgs.Length() > 1 ) {
2779     // scale factor (2-nd arg) is provided: clear SetDistrType(1) command
2780     bool scaleDistrType = false;
2781     list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
2782     for ( ; cmd != myUnknownCommands.rend(); ++cmd ) {
2783       if ( (*cmd)->GetMethod() == "SetDistrType" ) {
2784         if ( (*cmd)->GetArg( 1 ) == "1" ) {
2785           scaleDistrType = true;
2786           (*cmd)->Clear();
2787         }
2788         else if ( !scaleDistrType ) {
2789           // distribution type changed: remove scale factor from args
2790           myArgs.Remove( 2, myArgs.Length() );
2791           break;
2792         }
2793       }
2794     }
2795   }
2796   return _pyHypothesis::Addition2Creation( theCmd, theMesh );
2797 }
2798
2799 //================================================================================
2800 /*!
2801  * \brief remove repeated commands defining distribution
2802  */
2803 //================================================================================
2804
2805 void _pyNumberOfSegmentsHyp::Flush()
2806 {
2807   // find number of the last SetDistrType() command
2808   list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
2809   int distrTypeNb = 0;
2810   for ( ; !distrTypeNb && cmd != myUnknownCommands.rend(); ++cmd )
2811     if ( (*cmd)->GetMethod() == "SetDistrType" )
2812       distrTypeNb = (*cmd)->GetOrderNb();
2813     else if (IsWrapped() && (*cmd)->GetMethod() == "SetObjectEntry" )
2814       (*cmd)->Clear();
2815
2816   // clear commands before the last SetDistrType()
2817   list<Handle(_pyCommand)> * cmds[2] = { &myArgCommands, &myUnknownCommands };
2818   for ( int i = 0; i < 2; ++i ) {
2819     set<TCollection_AsciiString> uniqueMethods;
2820     list<Handle(_pyCommand)> & cmdList = *cmds[i];
2821     for ( cmd = cmdList.rbegin(); cmd != cmdList.rend(); ++cmd )
2822     {
2823       bool clear = ( (*cmd)->GetOrderNb() < distrTypeNb );
2824       const TCollection_AsciiString& method = (*cmd)->GetMethod();
2825       if ( !clear || method == "SetNumberOfSegments" ) {
2826         bool isNewInSet = uniqueMethods.insert( method ).second;
2827         clear = !isNewInSet;
2828       }
2829       if ( clear )
2830         (*cmd)->Clear();
2831     }
2832     cmdList.clear();
2833   }
2834 }
2835
2836 //================================================================================
2837 /*!
2838  * \brief Convert the command adding "SegmentLengthAroundVertex" to mesh
2839  * into regular1D.LengthNearVertex( length, vertex )
2840   * \param theCmd - The command like mesh.AddHypothesis( vertex, SegmentLengthAroundVertex )
2841   * \param theMesh - The mesh needing this hypo
2842   * \retval bool - false if the command cant be converted
2843  */
2844 //================================================================================
2845
2846 bool _pySegmentLengthAroundVertexHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
2847                                                          const _pyID&              theMeshID)
2848 {
2849   if ( IsWrappable( theMeshID )) {
2850
2851     _pyID vertex = theCmd->GetArg( 1 );
2852
2853     // the problem here is that segment algo will not be found
2854     // by pyHypothesis::Addition2Creation() for <vertex>, so we try to find
2855     // geometry where segment algorithm is assigned
2856     Handle(_pyHypothesis) algo;
2857     _pyID geom = vertex;
2858     while ( algo.IsNull() && !geom.IsEmpty()) {
2859       // try to find geom as a father of <vertex>
2860       geom = FatherID( geom );
2861       algo = theGen->FindAlgo( geom, theMeshID, this );
2862     }
2863     if ( algo.IsNull() )
2864       return false; // also possible to find geom as brother of veretex...
2865     // set geom instead of vertex
2866     theCmd->SetArg( 1, geom );
2867
2868     // set vertex as a second arg
2869     if ( myArgs.Length() < 1) myArgs.Append( "1" ); // :(
2870     myArgs.Append( vertex );
2871
2872     // mesh.AddHypothesis(vertex, SegmentLengthAroundVertex) -->
2873     // theMeshID.LengthNearVertex( length, vertex )
2874     return _pyHypothesis::Addition2Creation( theCmd, theMeshID );
2875   }
2876   return false;
2877 }
2878
2879 //================================================================================
2880 /*!
2881  * \brief _pyAlgorithm constructor
2882  * \param theCreationCmd - The command like "algo = smeshgen.CreateHypothesis(type,lib)"
2883  */
2884 //================================================================================
2885
2886 _pyAlgorithm::_pyAlgorithm(const Handle(_pyCommand)& theCreationCmd)
2887   : _pyHypothesis( theCreationCmd )
2888 {
2889   myIsAlgo = true;
2890 }
2891
2892 //================================================================================
2893 /*!
2894  * \brief Convert the command adding an algorithm to mesh
2895   * \param theCmd - The command like mesh.AddHypothesis( geom, algo )
2896   * \param theMesh - The mesh needing this algo
2897   * \retval bool - false if the command cant be converted
2898  */
2899 //================================================================================
2900
2901 bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd,
2902                                       const _pyID&              theMeshID)
2903 {
2904   // mesh.AddHypothesis(geom,algo) --> theMeshID.myCreationMethod()
2905   if ( _pyHypothesis::Addition2Creation( theCmd, theMeshID )) {
2906     theGen->SetAccessorMethod( GetID(), "GetAlgorithm()" );
2907     return true;
2908   }
2909   return false;
2910 }
2911
2912 //================================================================================
2913 /*!
2914  * \brief Return starting position of a part of python command
2915   * \param thePartIndex - The index of command part
2916   * \retval int - Part position
2917  */
2918 //================================================================================
2919
2920 int _pyCommand::GetBegPos( int thePartIndex )
2921 {
2922   if ( IsEmpty() )
2923     return EMPTY;
2924   if ( myBegPos.Length() < thePartIndex )
2925     return UNKNOWN;
2926   return myBegPos( thePartIndex );
2927 }
2928
2929 //================================================================================
2930 /*!
2931  * \brief Store starting position of a part of python command
2932   * \param thePartIndex - The index of command part
2933   * \param thePosition - Part position
2934  */
2935 //================================================================================
2936
2937 void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
2938 {
2939   while ( myBegPos.Length() < thePartIndex )
2940     myBegPos.Append( UNKNOWN );
2941   myBegPos( thePartIndex ) = thePosition;
2942 }
2943
2944 //================================================================================
2945 /*!
2946  * \brief Returns whitespace symbols at the line beginning
2947   * \retval TCollection_AsciiString - result
2948  */
2949 //================================================================================
2950
2951 TCollection_AsciiString _pyCommand::GetIndentation()
2952 {
2953   int end = 1;
2954   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
2955     GetWord( myString, end, true );
2956   else
2957     end = GetBegPos( RESULT_IND );
2958   return myString.SubString( 1, end - 1 );
2959 }
2960
2961 //================================================================================
2962 /*!
2963  * \brief Return substring of python command looking like ResultValue = Obj.Meth()
2964   * \retval const TCollection_AsciiString & - ResultValue substring
2965  */
2966 //================================================================================
2967
2968 const TCollection_AsciiString & _pyCommand::GetResultValue()
2969 {
2970   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
2971   {
2972     SetBegPos( RESULT_IND, EMPTY );
2973     int begPos, endPos = myString.Location( "=", 1, Length() );
2974     if ( endPos )
2975     {
2976       begPos = 1;
2977       while ( begPos < endPos && isblank( myString.Value( begPos ))) ++begPos;
2978       if ( begPos < endPos )
2979       {
2980         SetBegPos( RESULT_IND, begPos );
2981         --endPos;
2982         while ( begPos < endPos && isblank( myString.Value( endPos ))) --endPos;
2983         myRes = myString.SubString( begPos, endPos );
2984       }
2985     }
2986   }
2987   return myRes;
2988 }
2989
2990 //================================================================================
2991 /*!
2992  * \brief Return number of python command result value ResultValue = Obj.Meth()
2993   * \retval const int
2994  */
2995 //================================================================================
2996
2997 const int _pyCommand::GetNbResultValues()
2998 {
2999   int begPos = 1;
3000   int Nb=0;
3001   int endPos = myString.Location( "=", 1, Length() );
3002   TCollection_AsciiString str = "";
3003   while ( begPos < endPos) {
3004     str = GetWord( myString, begPos, true );
3005     begPos = begPos+ str.Length();
3006     Nb++;
3007   }
3008   return (Nb-1);
3009 }
3010
3011
3012 //================================================================================
3013 /*!
3014  * \brief Return substring of python command looking like
3015  *  ResultValue1 , ResultValue1,... = Obj.Meth() with res index
3016  * \retval const TCollection_AsciiString & - ResultValue with res index substring
3017  */
3018 //================================================================================
3019 const TCollection_AsciiString & _pyCommand::GetResultValue(int res)
3020 {
3021   int begPos = 1;
3022   int Nb=0;
3023   int endPos = myString.Location( "=", 1, Length() );
3024   while ( begPos < endPos) {
3025     myRes = GetWord( myString, begPos, true );
3026     begPos = begPos + myRes.Length();
3027     Nb++;
3028     if(res == Nb){
3029       myRes.RemoveAll('[');myRes.RemoveAll(']');
3030       return myRes;
3031     }
3032     if(Nb>res)
3033       break;
3034   }
3035   return theEmptyString;
3036 }
3037
3038 //================================================================================
3039 /*!
3040  * \brief Return substring of python command looking like ResVal = Object.Meth()
3041   * \retval const TCollection_AsciiString & - Object substring
3042  */
3043 //================================================================================
3044
3045 const TCollection_AsciiString & _pyCommand::GetObject()
3046 {
3047   if ( GetBegPos( OBJECT_IND ) == UNKNOWN )
3048   {
3049     // beginning
3050     int begPos = GetBegPos( RESULT_IND ) + myRes.Length();
3051     if ( begPos < 1 ) {
3052       begPos = myString.Location( "=", 1, Length() ) + 1;
3053       // is '=' in the string argument (for example, name) or not
3054       int nb1 = 0; // number of ' character at the left of =
3055       int nb2 = 0; // number of " character at the left of =
3056       for ( int i = 1; i < begPos-1; i++ ) {
3057         if ( myString.Value( i )=='\'' )
3058           nb1 += 1;
3059         else if ( myString.Value( i )=='"' )
3060           nb2 += 1;
3061       }
3062       // if number of ' or " is not divisible by 2,
3063       // then get an object at the start of the command
3064       if ( nb1 % 2 != 0 || nb2 % 2 != 0 )
3065         begPos = 1;
3066     }
3067     myObj = GetWord( myString, begPos, true );
3068     // check if object is complex,
3069     // so far consider case like "smesh.smesh.Method()"
3070     if ( int bracketPos = myString.Location( "(", begPos, Length() )) {
3071       //if ( bracketPos==0 ) bracketPos = Length();
3072       int dotPos = begPos+myObj.Length();
3073       while ( dotPos+1 < bracketPos ) {
3074         if ( int pos = myString.Location( ".", dotPos+1, bracketPos ))
3075           dotPos = pos;
3076         else
3077           break;
3078       }
3079       if ( dotPos > begPos+myObj.Length() )
3080         myObj = myString.SubString( begPos, dotPos-1 );
3081     }
3082     // store
3083     SetBegPos( OBJECT_IND, begPos );
3084   }
3085   //SCRUTE(myObj);
3086   return myObj;
3087 }
3088
3089 //================================================================================
3090 /*!
3091  * \brief Return substring of python command looking like ResVal = Obj.Method()
3092   * \retval const TCollection_AsciiString & - Method substring
3093  */
3094 //================================================================================
3095
3096 const TCollection_AsciiString & _pyCommand::GetMethod()
3097 {
3098   if ( GetBegPos( METHOD_IND ) == UNKNOWN )
3099   {
3100     // beginning
3101     int begPos = GetBegPos( OBJECT_IND ) + myObj.Length();
3102     bool forward = true;
3103     if ( begPos < 1 ) {
3104       begPos = myString.Location( "(", 1, Length() ) - 1;
3105       forward = false;
3106     }
3107     // store
3108     myMeth = GetWord( myString, begPos, forward );
3109     SetBegPos( METHOD_IND, begPos );
3110   }
3111   //SCRUTE(myMeth);
3112   return myMeth;
3113 }
3114
3115 //================================================================================
3116 /*!
3117  * \brief Return substring of python command looking like ResVal = Obj.Meth(Arg1,...)
3118   * \retval const TCollection_AsciiString & - Arg<index> substring
3119  */
3120 //================================================================================
3121
3122 const TCollection_AsciiString & _pyCommand::GetArg( int index )
3123 {
3124   if ( GetBegPos( ARG1_IND ) == UNKNOWN )
3125   {
3126     // Find all args
3127
3128     int pos = GetBegPos( METHOD_IND ) + myMeth.Length();
3129     if ( pos < 1 )
3130       pos = myString.Location( "(", 1, Length() );
3131     else
3132       --pos;
3133
3134     // we are at or before '(', skip it if present
3135     if ( pos > 0 ) {
3136       while ( pos <= Length() && myString.Value( pos ) != '(' ) ++pos;
3137       if ( pos > Length() )
3138         pos = 0;
3139     }
3140     if ( pos < 1 ) {
3141       SetBegPos( ARG1_IND, 0 ); // even no '('
3142       return theEmptyString;
3143     }
3144     ++pos;
3145
3146     list< TCollection_AsciiString > separatorStack( 1, ",)");
3147     bool ignoreNesting = false;
3148     int prevPos = pos;
3149     while ( pos <= Length() )
3150     {
3151       const char chr = myString.Value( pos );
3152
3153       if ( separatorStack.back().Location( chr, 1, separatorStack.back().Length()))
3154       {
3155         if ( separatorStack.size() == 1 ) // ',' dividing args or a terminal ')' found
3156         {
3157           while ( pos-1 >= prevPos && isspace( myString.Value( prevPos )))
3158             ++prevPos;
3159           if ( pos-1 >= prevPos ) {
3160             TCollection_AsciiString arg = myString.SubString( prevPos, pos-1 );
3161             arg.RightAdjust(); // remove spaces
3162             arg.LeftAdjust();
3163             SetBegPos( ARG1_IND + myArgs.Length(), prevPos );
3164             myArgs.Append( arg );
3165           }
3166           if ( chr == ')' )
3167             break;
3168           prevPos = pos+1;
3169         }
3170         else // end of nesting args found
3171         {
3172           separatorStack.pop_back();
3173           ignoreNesting = false;
3174         }
3175       }
3176       else if ( !ignoreNesting )
3177       {
3178         switch ( chr ) {
3179         case '(' : separatorStack.push_back(")"); break;
3180         case '[' : separatorStack.push_back("]"); break;
3181         case '\'': separatorStack.push_back("'");  ignoreNesting=true; break;
3182         case '"' : separatorStack.push_back("\""); ignoreNesting=true; break;
3183         default:;
3184         }
3185       }
3186       ++pos;
3187     }
3188   }
3189   if ( myArgs.Length() < index )
3190     return theEmptyString;
3191   return myArgs( index );
3192 }
3193
3194 //================================================================================
3195 /*!
3196  * \brief Check if char is a word part
3197   * \param c - The character to check
3198   * \retval bool - The check result
3199  */
3200 //================================================================================
3201
3202 static inline bool isWord(const char c, const bool dotIsWord)
3203 {
3204   return
3205     !isspace(c) && c != ',' && c != '=' && c != ')' && c != '(' && ( dotIsWord || c != '.');
3206 }
3207
3208 //================================================================================
3209 /*!
3210  * \brief Looks for a word in the string and returns word's beginning
3211   * \param theString - The input string
3212   * \param theStartPos - The position to start the search, returning word's beginning
3213   * \param theForward - The search direction
3214   * \retval TCollection_AsciiString - The found word
3215  */
3216 //================================================================================
3217
3218 TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString,
3219                                             int &      theStartPos,
3220                                             const bool theForward,
3221                                             const bool dotIsWord )
3222 {
3223   int beg = theStartPos, end = theStartPos;
3224   theStartPos = EMPTY;
3225   if ( beg < 1 || beg > theString.Length() )
3226     return theEmptyString;
3227
3228   if ( theForward ) { // search forward
3229     // beg
3230     while ( beg <= theString.Length() && !isWord( theString.Value( beg ), dotIsWord))
3231       ++beg;
3232     if ( beg > theString.Length() )
3233       return theEmptyString; // no word found
3234     // end
3235     end = beg + 1;
3236     char begChar = theString.Value( beg );
3237     if ( begChar == '"' || begChar == '\'' || begChar == '[') {
3238       char endChar = ( begChar == '[' ) ? ']' : begChar;
3239       // end is at the corresponding quoting mark or bracket
3240       while ( end < theString.Length() &&
3241               ( theString.Value( end ) != endChar || theString.Value( end-1 ) == '\\'))
3242         ++end;
3243     }
3244     else {
3245       while ( end <= theString.Length() && isWord( theString.Value( end ), dotIsWord))
3246         ++end;
3247       --end;
3248     }
3249   }
3250   else {  // search backward
3251     // end
3252     while ( end > 0 && !isWord( theString.Value( end ), dotIsWord))
3253       --end;
3254     if ( end == 0 )
3255       return theEmptyString; // no word found
3256     beg = end - 1;
3257     char endChar = theString.Value( end );
3258     if ( endChar == '"' || endChar == '\'' || endChar == ']') {
3259       char begChar = ( endChar == ']' ) ? '[' : endChar;
3260       // beg is at the corresponding quoting mark
3261       while ( beg > 1 &&
3262               ( theString.Value( beg ) != begChar || theString.Value( beg-1 ) == '\\'))
3263         --beg;
3264     }
3265     else {
3266       while ( beg > 0 && isWord( theString.Value( beg ), dotIsWord))
3267         --beg;
3268       ++beg;
3269     }
3270   }
3271   theStartPos = beg;
3272   //cout << theString << " ---- " << beg << " - " << end << endl;
3273   return theString.SubString( beg, end );
3274 }
3275
3276 //================================================================================
3277 /*!
3278  * \brief Returns true if the string looks like a study entry
3279  */
3280 //================================================================================
3281
3282 bool _pyCommand::IsStudyEntry( const TCollection_AsciiString& str )
3283 {
3284   if ( str.Length() < 5 ) return false;
3285
3286   int nbColons = 0, isColon;
3287   for ( int i = 1; i <= str.Length(); ++i )
3288   {
3289     char c = str.Value(i);
3290     if (!( isColon = (c == ':')) && ( c < '0' || c > '9' ))
3291       return false;
3292     nbColons += isColon;
3293   }
3294   return nbColons > 2 && str.Length()-nbColons > 2;
3295 }
3296
3297 //================================================================================
3298 /*!
3299  * \brief Finds entries in a sting
3300  */
3301 //================================================================================
3302
3303 std::list< _pyID > _pyCommand::GetStudyEntries( const TCollection_AsciiString& str )
3304 {
3305   std::list< _pyID > resList;
3306   int pos = 0;
3307   while ( ++pos <= str.Length() )
3308   {
3309     if ( !isdigit( str.Value( pos ))) continue;
3310     if ( pos != 1 && ( isalpha( str.Value( pos-1 ) || str.Value( pos-1 ) == ':'))) continue;
3311
3312     int end = pos;
3313     while ( ++end <= str.Length() && ( isdigit( str.Value( end )) || str.Value( end ) == ':' ));
3314     _pyID entry = str.SubString( pos, end-1 );
3315     pos = end;
3316     if ( IsStudyEntry( entry ))
3317       resList.push_back( entry );
3318   }
3319   return resList;
3320 }
3321
3322 //================================================================================
3323 /*!
3324  * \brief Look for position where not space char is
3325   * \param theString - The string
3326   * \param thePos - The position to search from and which returns result
3327   * \retval bool - false if there are only space after thePos in theString
3328  *
3329  *
3330  */
3331 //================================================================================
3332
3333 bool _pyCommand::SkipSpaces( const TCollection_AsciiString & theString, int & thePos )
3334 {
3335   if ( thePos < 1 || thePos > theString.Length() )
3336     return false;
3337
3338   while ( thePos <= theString.Length() && isspace( theString.Value( thePos )))
3339     ++thePos;
3340
3341   return thePos <= theString.Length();
3342 }
3343
3344 //================================================================================
3345 /*!
3346  * \brief Modify a part of the command
3347   * \param thePartIndex - The index of the part
3348   * \param thePart - The new part string
3349   * \param theOldPart - The old part
3350  */
3351 //================================================================================
3352
3353 void _pyCommand::SetPart(int thePartIndex, const TCollection_AsciiString& thePart,
3354                         TCollection_AsciiString& theOldPart)
3355 {
3356   int pos = GetBegPos( thePartIndex );
3357   if ( pos <= Length() && theOldPart != thePart)
3358   {
3359     TCollection_AsciiString seperator;
3360     if ( pos < 1 ) {
3361       pos = GetBegPos( thePartIndex + 1 );
3362       if ( pos < 1 ) return;
3363       switch ( thePartIndex ) {
3364       case RESULT_IND: seperator = " = "; break;
3365       case OBJECT_IND: seperator = "."; break;
3366       case METHOD_IND: seperator = "()"; break;
3367       default:;
3368       }
3369     }
3370     myString.Remove( pos, theOldPart.Length() );
3371     if ( !seperator.IsEmpty() )
3372       myString.Insert( pos , seperator );
3373     myString.Insert( pos, thePart );
3374     // update starting positions of the following parts
3375     int posDelta = thePart.Length() + seperator.Length() - theOldPart.Length();
3376     for ( int i = thePartIndex + 1; i <= myBegPos.Length(); ++i ) {
3377       if ( myBegPos( i ) > 0 )
3378         myBegPos( i ) += posDelta;
3379     }
3380     theOldPart = thePart;
3381   }
3382 }
3383
3384 //================================================================================
3385 /*!
3386  * \brief Set agrument
3387   * \param index - The argument index, it counts from 1
3388   * \param theArg - The argument string
3389  */
3390 //================================================================================
3391
3392 void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg)
3393 {
3394   FindAllArgs();
3395   int argInd = ARG1_IND + index - 1;
3396   int pos = GetBegPos( argInd );
3397   if ( pos < 1 ) // no index-th arg exist, append inexistent args
3398   {
3399     // find a closing parenthesis
3400     if ( GetNbArgs() != 0 && index <= GetNbArgs() ) {
3401       int lastArgInd = GetNbArgs();
3402       pos = GetBegPos( ARG1_IND + lastArgInd  - 1 ) + GetArg( lastArgInd ).Length();
3403       while ( pos > 0 && pos <= Length() && myString.Value( pos ) != ')' )
3404         ++pos;
3405     }
3406     else {
3407       pos = Length();
3408       while ( pos > 0 && myString.Value( pos ) != ')' )
3409         --pos;
3410     }
3411     if ( pos < 1 || myString.Value( pos ) != ')' ) { // no parentheses at all
3412       myString += "()";
3413       pos = Length();
3414     }
3415     while ( myArgs.Length() < index ) {
3416       if ( myArgs.Length() )
3417         myString.Insert( pos++, "," );
3418       myArgs.Append("None");
3419       myString.Insert( pos, myArgs.Last() );
3420       SetBegPos( ARG1_IND + myArgs.Length() - 1, pos );
3421       pos += myArgs.Last().Length();
3422     }
3423   }
3424   SetPart( argInd, theArg, myArgs( index ));
3425 }
3426
3427 //================================================================================
3428 /*!
3429  * \brief Empty arg list
3430  */
3431 //================================================================================
3432
3433 void _pyCommand::RemoveArgs()
3434 {
3435   if ( int pos = myString.Location( '(', 1, Length() ))
3436     myString.Trunc( pos );
3437   myString += ")";
3438   myArgs.Clear();
3439   if ( myBegPos.Length() >= ARG1_IND )
3440     myBegPos.Remove( ARG1_IND, myBegPos.Length() );
3441 }
3442
3443 //================================================================================
3444 /*!
3445  * \brief Comment a python command
3446  */
3447 //================================================================================
3448
3449 void _pyCommand::Comment()
3450 {
3451   if ( IsEmpty() ) return;
3452
3453   int i = 1;
3454   while ( i <= Length() && isblank( myString.Value(i) )) ++i;
3455   if ( i <= Length() )
3456   {
3457     myString.Insert( i, "#" );
3458     for ( int iPart = 0; iPart < myBegPos.Length(); ++iPart )
3459     {
3460       int begPos = GetBegPos( iPart );
3461       if ( begPos != UNKNOWN )
3462         SetBegPos( iPart, begPos + 1 );
3463     }
3464   }
3465 }
3466
3467 //================================================================================
3468 /*!
3469  * \brief Set dependent commands after this one
3470  */
3471 //================================================================================
3472
3473 bool _pyCommand::SetDependentCmdsAfter() const
3474 {
3475   bool orderChanged = false;
3476   list< Handle(_pyCommand)>::const_reverse_iterator cmd = myDependentCmds.rbegin();
3477   for ( ; cmd != myDependentCmds.rend(); ++cmd ) {
3478     if ( (*cmd)->GetOrderNb() < GetOrderNb() ) {
3479       orderChanged = true;
3480       theGen->SetCommandAfter( *cmd, this );
3481       (*cmd)->SetDependentCmdsAfter();
3482     }
3483   }
3484   return orderChanged;
3485 }
3486 //================================================================================
3487 /*!
3488  * \brief Insert accessor method after theObjectID
3489   * \param theObjectID - id of the accessed object
3490   * \param theAcsMethod - name of the method giving access to the object
3491   * \retval bool - false if theObjectID is not found in the command string
3492  */
3493 //================================================================================
3494
3495 bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod )
3496 {
3497   if ( !theAcsMethod )
3498     return false;
3499   // start object search from the object, i.e. ignore result
3500   GetObject();
3501   int beg = GetBegPos( OBJECT_IND );
3502   if ( beg < 1 || beg > Length() )
3503     return false;
3504   bool added = false;
3505   while (( beg = myString.Location( theObjectID, beg, Length() )))
3506   {
3507     // check that theObjectID is not just a part of a longer ID
3508     int afterEnd = beg + theObjectID.Length();
3509     Standard_Character c = myString.Value( afterEnd );
3510     if ( !isalnum( c ) && c != ':' ) {
3511       // check if accessor method already present
3512       if ( c != '.' ||
3513            myString.Location( (char*) theAcsMethod, afterEnd, Length() ) != afterEnd+1) {
3514         // insertion
3515         int oldLen = Length();
3516         myString.Insert( afterEnd, (char*) theAcsMethod );
3517         myString.Insert( afterEnd, "." );
3518         // update starting positions of the parts following the modified one
3519         int posDelta = Length() - oldLen;
3520         for ( int i = 1; i <= myBegPos.Length(); ++i ) {
3521           if ( myBegPos( i ) > afterEnd )
3522             myBegPos( i ) += posDelta;
3523         }
3524         added = true;
3525       }
3526     }
3527     beg = afterEnd; // is a part - next search
3528   }
3529   return added;
3530 }
3531
3532 //================================================================================
3533 /*!
3534  * \brief Creates pyObject
3535  */
3536 //================================================================================
3537
3538 _pyObject::_pyObject(const Handle(_pyCommand)& theCreationCmd, const _pyID& theID)
3539   : myID(theID), myCreationCmd(theCreationCmd), myIsPublished(false)
3540 {
3541   setID( theID );
3542 }
3543
3544 //================================================================================
3545 /*!
3546  * \brief Set up myID and myIsPublished
3547  */
3548 //================================================================================
3549
3550 void _pyObject::setID(const _pyID& theID)
3551 {
3552   myID = theID;
3553   myIsPublished = !theGen->IsNotPublished( GetID() );
3554 }
3555
3556 //================================================================================
3557 /*!
3558  * \brief Clear myCreationCmd and myProcessedCmds
3559  */
3560 //================================================================================
3561
3562 void _pyObject::ClearCommands()
3563 {
3564   if ( !CanClear() )
3565     return;
3566
3567   if ( !myCreationCmd.IsNull() )
3568     myCreationCmd->Clear();
3569
3570   list< Handle(_pyCommand) >::iterator cmd = myProcessedCmds.begin();
3571   for ( ; cmd != myProcessedCmds.end(); ++cmd )
3572     (*cmd)->Clear();
3573 }
3574
3575 //================================================================================
3576 /*!
3577  * \brief Return method name giving access to an interaface object wrapped by python class
3578   * \retval const char* - method name
3579  */
3580 //================================================================================
3581
3582 const char* _pyObject::AccessorMethod() const
3583 {
3584   return 0;
3585 }
3586 //================================================================================
3587 /*!
3588  * \brief Return ID of a father
3589  */
3590 //================================================================================
3591
3592 _pyID _pyObject::FatherID(const _pyID & childID)
3593 {
3594   int colPos = childID.SearchFromEnd(':');
3595   if ( colPos > 0 )
3596     return childID.SubString( 1, colPos-1 );
3597   return "";
3598 }
3599
3600 //================================================================================
3601 /*!
3602  * \brief SelfEraser erases creation command if no more it's commands invoked
3603  */
3604 //================================================================================
3605
3606 void _pySelfEraser::Flush()
3607 {
3608   if ( GetNbCalls() == 0 )
3609     GetCreationCmd()->Clear();
3610 }
3611
3612 //================================================================================
3613 /*!
3614  * \brief _pySubMesh constructor
3615  */
3616 //================================================================================
3617
3618 _pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd):
3619   _pyObject(theCreationCmd)
3620 {
3621   myMesh = ObjectToMesh( theGen->FindObject( theCreationCmd->GetObject() ));
3622 }
3623
3624 //================================================================================
3625 /*!
3626  * \brief count invoked commands
3627  */
3628 //================================================================================
3629
3630 void _pySubMesh::Process( const Handle(_pyCommand)& theCommand )
3631 {
3632   _pyObject::Process(theCommand); // count calls of Process()
3633   GetCreationCmd()->AddDependantCmd( theCommand );
3634 }
3635
3636 //================================================================================
3637 /*!
3638  * \brief Move creation command depending on invoked commands
3639  */
3640 //================================================================================
3641
3642 void _pySubMesh::Flush()
3643 {
3644   if ( GetNbCalls() == 0 ) // move to the end of all commands
3645     theGen->GetLastCommand()->AddDependantCmd( GetCreationCmd() );
3646   else if ( !myCreator.IsNull() )
3647     // move to be just after creator
3648     myCreator->GetCreationCmd()->AddDependantCmd( GetCreationCmd() );
3649 }
3650
3651 //================================================================================
3652 /*!
3653  * \brief To convert creation of a group by filter
3654  */
3655 //================================================================================
3656
3657 void _pyGroup::Process( const Handle(_pyCommand)& theCommand)
3658 {
3659   // Convert the following set of commands into mesh.MakeGroupByFilter(groupName, theFilter)
3660   // group = mesh.CreateEmptyGroup( elemType, groupName )
3661   // aFilter.SetMesh(mesh)
3662   // nbAdd = group.AddFrom( aFilter )
3663   Handle(_pyFilter) filter;
3664   if ( theCommand->GetMethod() == "AddFrom" )
3665   {
3666     _pyID idSource = theCommand->GetArg(1);
3667     // check if idSource is a filter
3668     filter = Handle(_pyFilter)::DownCast( theGen->FindObject( idSource ));
3669     if ( filter.IsNull() )
3670       return;
3671     // find aFilter.SetMesh(mesh) to clear it, it should be just before theCommand
3672     list< Handle(_pyCommand) >::reverse_iterator cmdIt = theGen->GetCommands().rbegin();
3673     while ( *cmdIt != theCommand ) ++cmdIt;
3674     while ( (*cmdIt)->GetOrderNb() != 1 )
3675     {
3676       const Handle(_pyCommand)& setMeshCmd = *(++cmdIt);
3677       if ((setMeshCmd->GetObject() == idSource ||
3678            setMeshCmd->GetObject() == filter->GetNewID() )
3679           &&
3680           setMeshCmd->GetMethod() == "SetMesh")
3681       {
3682         setMeshCmd->Clear();
3683         break;
3684       }
3685     }
3686     // replace 3 commands by one
3687     theCommand->Clear();
3688     const Handle(_pyCommand)& makeGroupCmd = GetCreationCmd();
3689     TCollection_AsciiString name = makeGroupCmd->GetArg( 2 );
3690     makeGroupCmd->SetMethod( "MakeGroupByFilter" );
3691     makeGroupCmd->SetArg( 1, name );
3692     makeGroupCmd->SetArg( 2, idSource );
3693     // set new name of a filter
3694     filter->Process( makeGroupCmd );
3695   }
3696   else if ( theCommand->GetMethod() == "SetFilter" )
3697   {
3698     // set new name of a filter
3699     _pyID filterID = theCommand->GetArg(1);
3700     filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID ));
3701     if ( !filter.IsNull() )
3702       filter->Process( theCommand );
3703   }
3704
3705   if ( !filter.IsNull() )
3706     filter->AddUser( this );
3707 }
3708
3709 //================================================================================
3710 /*!
3711  * \brief Constructor of _pyFilter
3712  */
3713 //================================================================================
3714
3715 _pyFilter::_pyFilter(const Handle(_pyCommand)& theCreationCmd, const _pyID& newID/*=""*/)
3716   :_pyObject(theCreationCmd), myNewID( newID )
3717 {
3718 }
3719
3720 //================================================================================
3721 /*!
3722  * \brief To convert creation of a filter by criteria and
3723  * to replace an old name by a new one
3724  */
3725 //================================================================================
3726
3727 void _pyFilter::Process( const Handle(_pyCommand)& theCommand)
3728 {
3729   if ( theCommand->GetObject() == GetID() )
3730     _pyObject::Process(theCommand); // count commands
3731
3732   if ( !myNewID.IsEmpty() )
3733   {
3734     if ( theCommand->GetObject() == GetID() )
3735       theCommand->SetObject( myNewID );
3736     else if ( theCommand->GetResultValue() == GetID() )
3737       theCommand->SetResultValue( myNewID );
3738     else
3739       for ( int i = 1, nb = theCommand->GetNbArgs(); i <= nb; ++i )
3740         if ( theCommand->GetArg( i ) == GetID() )
3741         {
3742           theCommand->SetArg( i, myNewID );
3743           break;
3744         }
3745   }
3746
3747   // Convert the following set of commands into smesh.GetFilterFromCriteria(criteria)
3748   // aFilter0x2aaab0487080 = aFilterManager.CreateFilter()
3749   // aFilter0x2aaab0487080.SetCriteria(aCriteria)
3750   if ( GetNbCalls() == 1 && // none method was called before this SetCriteria() call
3751        theCommand->GetMethod() == "SetCriteria")
3752   {
3753     // aFilter.SetCriteria(aCriteria) ->
3754     // aFilter = smesh.GetFilterFromCriteria(criteria)
3755     if ( myNewID.IsEmpty() )
3756       theCommand->SetResultValue( GetID() );
3757     else
3758       theCommand->SetResultValue( myNewID );
3759     theCommand->SetObject( SMESH_2smeshpy::GenName() );
3760     theCommand->SetMethod( "GetFilterFromCriteria" );
3761
3762     // Clear aFilterManager.CreateFilter()
3763     GetCreationCmd()->Clear();
3764   }
3765   else if ( theCommand->GetMethod() == "SetMesh")
3766   {
3767     theGen->AddMeshAccessorMethod( theCommand );
3768   }
3769 }
3770
3771 //================================================================================
3772 /*!
3773  * \brief Set new filter name to the creation command
3774  */
3775 //================================================================================
3776
3777 void _pyFilter::Flush()
3778 {
3779   if ( !myNewID.IsEmpty() && !GetCreationCmd()->IsEmpty() )
3780     GetCreationCmd()->SetResultValue( myNewID );
3781 }
3782
3783 //================================================================================
3784 /*!
3785  * \brief Return true if all my users can be cleared
3786  */
3787 //================================================================================
3788
3789 bool _pyFilter::CanClear()
3790 {
3791   list< Handle(_pyObject) >::iterator obj = myUsers.begin();
3792   for ( ; obj != myUsers.end(); ++obj )
3793     if ( !(*obj)->CanClear() )
3794       return false;
3795
3796   return true;
3797 }