Salome HOME
0021374: EDF 1898 SMESH: Extrusion of a node to have an edge
[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 ( !IsAlgo() )
2300   {
2301     list < Handle(_pyCommand) >::iterator cmd = myArgCommands.begin();
2302     for ( ; cmd != myArgCommands.end(); ++cmd ) {
2303       // Add access to a wrapped mesh
2304       theGen->AddMeshAccessorMethod( *cmd );
2305       // Add access to a wrapped algorithm
2306       theGen->AddAlgoAccessorMethod( *cmd );
2307     }
2308     cmd = myUnknownCommands.begin();
2309     for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
2310       // Add access to a wrapped mesh
2311       theGen->AddMeshAccessorMethod( *cmd );
2312       // Add access to a wrapped algorithm
2313       theGen->AddAlgoAccessorMethod( *cmd );
2314     }
2315   }
2316   // forget previous hypothesis modifications
2317   myArgCommands.clear();
2318   myUnknownCommands.clear();
2319 }
2320
2321 //================================================================================
2322 /*!
2323  * \brief clear creation, arg and unkown commands
2324  */
2325 //================================================================================
2326
2327 void _pyHypothesis::ClearAllCommands()
2328 {
2329   GetCreationCmd()->Clear();
2330   list<Handle(_pyCommand)>::iterator cmd = myArgCommands.begin();
2331   for ( ; cmd != myArgCommands.end(); ++cmd )
2332     ( *cmd )->Clear();
2333   cmd = myUnknownCommands.begin();
2334   for ( ; cmd != myUnknownCommands.end(); ++cmd )
2335     ( *cmd )->Clear();
2336 }
2337
2338
2339 //================================================================================
2340 /*!
2341  * \brief Assign fields of theOther to me except myIsWrapped
2342  */
2343 //================================================================================
2344
2345 void _pyHypothesis::Assign( const Handle(_pyHypothesis)& theOther,
2346                             const _pyID&                 theMesh )
2347 {
2348   myIsWrapped = false;
2349   myMesh = theMesh;
2350
2351   // myCreationCmd = theOther->myCreationCmd;
2352   myIsAlgo = theOther->myIsAlgo;
2353   myGeom = theOther->myGeom;
2354   myType2CreationMethod = theOther->myType2CreationMethod;
2355   myArgs = theOther->myArgs;
2356   myArgMethods = theOther->myArgMethods;
2357   myNbArgsByMethod = theOther->myNbArgsByMethod;
2358   myArgCommands = theOther->myArgCommands;
2359   myUnknownCommands = theOther->myUnknownCommands;
2360 }
2361
2362 //================================================================================
2363 /*!
2364  * \brief Analyze my erasability depending on myReferredObjs
2365  */
2366 //================================================================================
2367
2368 bool _pyHypothesis::CanClear()
2369 {
2370   if ( IsInStudy() )
2371   {
2372     list< Handle(_pyObject) >::iterator obj = myReferredObjs.begin();
2373     for ( ; obj != myReferredObjs.end(); ++obj )
2374       if ( (*obj)->CanClear() )
2375         return true;
2376     return false;
2377   }
2378   return true;
2379 }
2380
2381 //================================================================================
2382 /*!
2383  * \brief Clear my commands depending on usage by meshes
2384  */
2385 //================================================================================
2386
2387 void _pyHypothesis::ClearCommands()
2388 {
2389   if ( !theGen->IsToKeepAllCommands() )
2390   {
2391     bool isUsed = false;
2392     int lastComputeOrder = 0;
2393     list<Handle(_pyCommand) >::iterator cmd = myComputeCmds.begin();
2394     for ( ; cmd != myComputeCmds.end(); ++cmd )
2395       if ( ! (*cmd)->IsEmpty() )
2396       {
2397         isUsed = true;
2398         if ( (*cmd)->GetOrderNb() > lastComputeOrder )
2399           lastComputeOrder = (*cmd)->GetOrderNb();
2400       }
2401     if ( !isUsed )
2402     {
2403       SetRemovedFromStudy( true );
2404     }
2405     else
2406     {
2407       // clear my commands invoked after lastComputeOrder
2408       map<TCollection_AsciiString, list< Handle(_pyCommand) > >::iterator m2c;
2409       for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c )
2410       {
2411         list< Handle(_pyCommand)> & cmds = m2c->second;
2412         if ( !cmds.empty() && cmds.back()->GetOrderNb() > lastComputeOrder )
2413           cmds.back()->Clear();
2414       }
2415     }
2416   }
2417   _pyObject::ClearCommands();
2418 }
2419
2420 //================================================================================
2421 /*!
2422  * \brief Find arguments that are objects like mesh, group, geometry
2423  *  \param meshes - referred meshes (directly or indirrectly)
2424  *  \retval bool - false if a referred geometry is not in the study
2425  */
2426 //================================================================================
2427
2428 bool _pyHypothesis::GetReferredMeshesAndGeom( list< Handle(_pyMesh) >& meshes )
2429 {
2430   if ( IsAlgo() ) return true;
2431
2432   bool geomPublished = true;
2433   TColStd_SequenceOfAsciiString args; args = myArgs;
2434
2435   list<Handle(_pyCommand)>::iterator cmd = myUnknownCommands.begin();
2436   for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
2437     for ( int nb = (*cmd)->GetNbArgs(); nb; --nb )
2438       args.Append( (*cmd)->GetArg( nb ));
2439   }
2440
2441   for ( int i = 1; i <= args.Length(); ++i )
2442   {
2443     list< _pyID > idList = _pyCommand::GetStudyEntries( args( i ));
2444     list< _pyID >::iterator id = idList.begin();
2445     for ( ; id != idList.end(); ++id )
2446     {
2447       Handle(_pyObject) obj = theGen->FindObject( *id );
2448       if ( obj.IsNull() )
2449       {
2450         if ( theGen->IsGeomObject( *id ) && theGen->IsNotPublished( *id ))
2451           geomPublished = false;
2452       }
2453       else
2454       {
2455         myReferredObjs.push_back( obj );
2456         Handle(_pyMesh) mesh = ObjectToMesh( obj );
2457         if ( !mesh.IsNull() )
2458           meshes.push_back( mesh );
2459       }
2460     }
2461   }
2462   return geomPublished;
2463 }
2464
2465 //================================================================================
2466 /*!
2467  * \brief Remember theCommand setting a parameter
2468  */
2469 //================================================================================
2470
2471 void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theCommand )
2472 {
2473   // not to clear commands setting different parameters via one method
2474   // by passing parameter names like e.g. SetOption("size", "0.2")
2475   int quotePos = theCommand->GetString().FirstLocationInSet( "'\"", 1, theCommand->Length() );
2476   if ( !quotePos )
2477   {
2478     // parameters are discriminated by method name
2479     list< Handle(_pyCommand)>& cmds = myMeth2Commands[ theCommand->GetMethod() ];
2480     if ( !cmds.empty() && !isCmdUsedForCompute( cmds.back() ))
2481     {
2482       cmds.back()->Clear(); // previous parameter value has not been used
2483       cmds.back() = theCommand;
2484     }
2485     else
2486     {
2487       cmds.push_back( theCommand );
2488     }
2489   }
2490 }
2491
2492 //================================================================================
2493 /*!
2494  * \brief Return true if a setting parameter command ha been used to compute mesh
2495  */
2496 //================================================================================
2497
2498 bool _pyHypothesis::isCmdUsedForCompute( const Handle(_pyCommand) & cmd,
2499                                          _pyCommand::TAddr          avoidComputeAddr ) const
2500 {
2501   bool isUsed = false;
2502   map< _pyCommand::TAddr, list<Handle(_pyCommand) > >::const_iterator addr2cmds =
2503     myComputeAddr2Cmds.begin();
2504   for ( ; addr2cmds != myComputeAddr2Cmds.end() && !isUsed; ++addr2cmds )
2505   {
2506     if ( addr2cmds->first == avoidComputeAddr ) continue;
2507     const list<Handle(_pyCommand)> & cmds = addr2cmds->second;
2508     isUsed = ( std::find( cmds.begin(), cmds.end(), cmd ) != cmds.end() );
2509   }
2510   return isUsed;
2511 }
2512
2513 //================================================================================
2514 /*!
2515  * \brief Save commands setting parameters as they are used for a mesh computation
2516  */
2517 //================================================================================
2518
2519 void _pyHypothesis::MeshComputed( const Handle(_pyCommand)& theComputeCmd )
2520 {
2521   myComputeCmds.push_back( theComputeCmd );
2522   list<Handle(_pyCommand)>& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ];
2523
2524   map<TCollection_AsciiString, list< Handle(_pyCommand) > >::iterator m2c;
2525   for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c )
2526     savedCmds.push_back( m2c->second.back() );
2527 }
2528
2529 //================================================================================
2530 /*!
2531  * \brief Clear commands setting parameters as a mesh computed using them is cleared
2532  */
2533 //================================================================================
2534
2535 void _pyHypothesis::ComputeDiscarded( const Handle(_pyCommand)& theComputeCmd )
2536 {
2537   list<Handle(_pyCommand)>& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ];
2538
2539   list<Handle(_pyCommand)>::iterator cmd = savedCmds.begin();
2540   for ( ; cmd != savedCmds.end(); ++cmd )
2541   {
2542     // check if a cmd has been used to compute another mesh
2543     if ( isCmdUsedForCompute( *cmd, theComputeCmd->GetAddress() ))
2544       continue;
2545     // check if a cmd is a sole command setting its parameter;
2546     // don't use method name for search as it can change
2547     map<TCollection_AsciiString, list<Handle(_pyCommand)> >::iterator
2548       m2cmds = myMeth2Commands.begin();
2549     for ( ; m2cmds != myMeth2Commands.end(); ++m2cmds )
2550     {
2551       list< Handle(_pyCommand)>& cmds = m2cmds->second;
2552       list< Handle(_pyCommand)>::iterator cmdIt = std::find( cmds.begin(), cmds.end(), *cmd );
2553       if ( cmdIt != cmds.end() )
2554       {
2555         if ( cmds.back() != *cmd )
2556         {
2557           cmds.erase( cmdIt );
2558           (*cmd)->Clear();
2559         }
2560         break;
2561       }
2562     }
2563   }
2564   myComputeAddr2Cmds.erase( theComputeCmd->GetAddress() );
2565 }
2566 // void _pyHypothesis::ComputeSaved( const Handle(_pyCommand)& theComputeCommand )
2567 // {
2568 // }
2569
2570
2571 //================================================================================
2572 /*!
2573  * \brief Remember hypothesis parameter values
2574  * \param theCommand - The called hypothesis method
2575  */
2576 //================================================================================
2577
2578 void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
2579 {
2580   if ( GetAlgoType() == "Cartesian_3D" )
2581   {
2582     // CartesianParameters3D hyp
2583
2584     if ( theCommand->GetMethod() == "SetSizeThreshold" )
2585     {
2586       myArgs( 4 ) = theCommand->GetArg( 1 );
2587       myArgCommands.push_back( theCommand );
2588       return;
2589     }
2590     if ( theCommand->GetMethod() == "SetGrid" ||
2591          theCommand->GetMethod() == "SetGridSpacing" )
2592     {
2593       TCollection_AsciiString axis = theCommand->GetArg( theCommand->GetNbArgs() );
2594       int iArg = 1 + ( axis.Value(1) - '0' );
2595       if ( theCommand->GetMethod() == "SetGrid" )
2596       {
2597         myArgs( iArg ) = theCommand->GetArg( 1 );
2598       }
2599       else
2600       {
2601         myArgs( iArg ) = "[ ";
2602         myArgs( iArg ) += theCommand->GetArg( 1 );
2603         myArgs( iArg ) += ", ";
2604         myArgs( iArg ) += theCommand->GetArg( 2 );
2605         myArgs( iArg ) += "]";
2606       }
2607       myArgCommands.push_back( theCommand );
2608       rememberCmdOfParameter( theCommand );
2609       return;
2610     }
2611   }
2612
2613   if( theCommand->GetMethod() == "SetLength" )
2614   {
2615     // NOW it is OBSOLETE
2616     // ex: hyp.SetLength(start, 1)
2617     //     hyp.SetLength(end,   0)
2618     ASSERT(( theCommand->GetArg( 2 ).IsIntegerValue() ));
2619     int i = 2 - theCommand->GetArg( 2 ).IntegerValue();
2620     while ( myArgs.Length() < i )
2621       myArgs.Append( "[]" );
2622     myArgs( i ) = theCommand->GetArg( 1 ); // arg value
2623     myArgCommands.push_back( theCommand );
2624   }
2625   else
2626   {
2627     _pyHypothesis::Process( theCommand );
2628   }
2629 }
2630 //================================================================================
2631 /*!
2632  * \brief Clear SetObjectEntry() as it is called by methods of Mesh_Segment
2633  */
2634 //================================================================================
2635
2636 void _pyComplexParamHypo::Flush()
2637 {
2638   if ( IsWrapped() )
2639   {
2640     list < Handle(_pyCommand) >::iterator cmd = myUnknownCommands.begin();
2641     for ( ; cmd != myUnknownCommands.end(); ++cmd )
2642       if ((*cmd)->GetMethod() == "SetObjectEntry" )
2643         (*cmd)->Clear();
2644   }
2645 }
2646
2647 //================================================================================
2648 /*!
2649  * \brief Convert methods of 1D hypotheses to my own methods
2650   * \param theCommand - The called hypothesis method
2651  */
2652 //================================================================================
2653
2654 void _pyLayerDistributionHypo::Process( const Handle(_pyCommand)& theCommand)
2655 {
2656   if ( theCommand->GetMethod() != "SetLayerDistribution" )
2657     return;
2658
2659   _pyID newName; // name for 1D hyp = "HypType" + "_Distribution"
2660
2661   const _pyID& hyp1dID = theCommand->GetArg( 1 );
2662   Handle(_pyHypothesis) hyp1d = theGen->FindHyp( hyp1dID );
2663   if ( hyp1d.IsNull() ) // apparently hypId changed at study restoration
2664     hyp1d = my1dHyp;
2665   else if ( !my1dHyp.IsNull() && hyp1dID != my1dHyp->GetID() ) {
2666     // 1D hypo is already set, so distribution changes and the old
2667     // 1D hypo is thrown away
2668     my1dHyp->ClearAllCommands();
2669   }
2670   my1dHyp = hyp1d;
2671
2672   if ( !myArgCommands.empty() )
2673     myArgCommands.front()->Clear();
2674   myArgCommands.push_back( theCommand );
2675 }
2676
2677 //================================================================================
2678 /*!
2679  * \brief
2680   * \param theAdditionCmd - command to be converted
2681   * \param theMesh - mesh instance
2682   * \retval bool - status
2683  */
2684 //================================================================================
2685
2686 bool _pyLayerDistributionHypo::Addition2Creation( const Handle(_pyCommand)& theAdditionCmd,
2687                                                   const _pyID&              theMesh)
2688 {
2689   myIsWrapped = false;
2690
2691   if ( my1dHyp.IsNull() )
2692     return false;
2693
2694   // set "SetLayerDistribution()" after addition cmd
2695   theAdditionCmd->AddDependantCmd( myArgCommands.front() );
2696
2697   _pyID geom = theAdditionCmd->GetArg( 1 );
2698
2699   Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMesh, this );
2700   if ( !algo.IsNull() )
2701   {
2702     my1dHyp->SetMesh( theMesh );
2703     my1dHyp->SetConvMethodAndType(my1dHyp->GetAlgoCreationMethod().ToCString(),
2704                                   algo->GetAlgoType().ToCString());
2705     if ( !my1dHyp->Addition2Creation( theAdditionCmd, theMesh ))
2706       return false;
2707
2708     // clear "SetLayerDistribution()" cmd
2709     myArgCommands.back()->Clear();
2710
2711     // Convert my creation => me = RadialPrismAlgo.Get3DHypothesis()
2712
2713     // find RadialPrism algo created on <geom> for theMesh
2714     GetCreationCmd()->SetObject( algo->GetID() );
2715     GetCreationCmd()->SetMethod( myAlgoMethod );
2716     GetCreationCmd()->RemoveArgs();
2717     theAdditionCmd->AddDependantCmd( GetCreationCmd() );
2718     myIsWrapped = true;
2719   }
2720   return myIsWrapped;
2721 }
2722
2723 //================================================================================
2724 /*!
2725  * \brief
2726  */
2727 //================================================================================
2728
2729 void _pyLayerDistributionHypo::Flush()
2730 {
2731   // as creation of 1D hyp was written later then it's edition,
2732   // we need to find all it's edition calls and process them
2733   if ( !my1dHyp.IsNull() )
2734   {
2735     _pyID hyp1dID = my1dHyp->GetCreationCmd()->GetResultValue();
2736
2737     // make a new name for 1D hyp = "HypType" + "_Distribution"
2738     _pyID newName;
2739     if ( my1dHyp->IsWrapped() ) {
2740       newName = my1dHyp->GetCreationCmd()->GetMethod();
2741     }
2742     else {
2743       TCollection_AsciiString hypTypeQuoted = my1dHyp->GetCreationCmd()->GetArg(1);
2744       newName = hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
2745     }
2746     newName += "_Distribution";
2747     my1dHyp->GetCreationCmd()->SetResultValue( newName );
2748
2749     list< Handle(_pyCommand) >& cmds = theGen->GetCommands();
2750     list< Handle(_pyCommand) >::iterator cmdIt = cmds.begin();
2751     for ( ; cmdIt != cmds.end(); ++cmdIt ) {
2752       const _pyID& objID = (*cmdIt)->GetObject();
2753       if ( objID == hyp1dID ) {
2754         my1dHyp->Process( *cmdIt );
2755         my1dHyp->GetCreationCmd()->AddDependantCmd( *cmdIt );
2756         ( *cmdIt )->SetObject( newName );
2757       }
2758     }
2759     // Set new hyp name to SetLayerDistribution() cmd
2760     if ( !myArgCommands.empty() && !myArgCommands.back()->IsEmpty() )
2761       myArgCommands.back()->SetArg( 1, newName );
2762   }
2763 }
2764
2765 //================================================================================
2766 /*!
2767  * \brief additionally to Addition2Creation, clears SetDistrType() command
2768   * \param theCmd - AddHypothesis() command
2769   * \param theMesh - mesh to which a hypothesis is added
2770   * \retval bool - convertion result
2771  */
2772 //================================================================================
2773
2774 bool _pyNumberOfSegmentsHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
2775                                                 const _pyID&              theMesh)
2776 {
2777   if ( IsWrappable( theMesh ) && myArgs.Length() > 1 ) {
2778     // scale factor (2-nd arg) is provided: clear SetDistrType(1) command
2779     bool scaleDistrType = false;
2780     list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
2781     for ( ; cmd != myUnknownCommands.rend(); ++cmd ) {
2782       if ( (*cmd)->GetMethod() == "SetDistrType" ) {
2783         if ( (*cmd)->GetArg( 1 ) == "1" ) {
2784           scaleDistrType = true;
2785           (*cmd)->Clear();
2786         }
2787         else if ( !scaleDistrType ) {
2788           // distribution type changed: remove scale factor from args
2789           myArgs.Remove( 2, myArgs.Length() );
2790           break;
2791         }
2792       }
2793     }
2794   }
2795   return _pyHypothesis::Addition2Creation( theCmd, theMesh );
2796 }
2797
2798 //================================================================================
2799 /*!
2800  * \brief remove repeated commands defining distribution
2801  */
2802 //================================================================================
2803
2804 void _pyNumberOfSegmentsHyp::Flush()
2805 {
2806   // find number of the last SetDistrType() command
2807   list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
2808   int distrTypeNb = 0;
2809   for ( ; !distrTypeNb && cmd != myUnknownCommands.rend(); ++cmd )
2810     if ( (*cmd)->GetMethod() == "SetDistrType" )
2811       distrTypeNb = (*cmd)->GetOrderNb();
2812     else if (IsWrapped() && (*cmd)->GetMethod() == "SetObjectEntry" )
2813       (*cmd)->Clear();
2814
2815   // clear commands before the last SetDistrType()
2816   list<Handle(_pyCommand)> * cmds[2] = { &myArgCommands, &myUnknownCommands };
2817   for ( int i = 0; i < 2; ++i ) {
2818     set<TCollection_AsciiString> uniqueMethods;
2819     list<Handle(_pyCommand)> & cmdList = *cmds[i];
2820     for ( cmd = cmdList.rbegin(); cmd != cmdList.rend(); ++cmd )
2821     {
2822       bool clear = ( (*cmd)->GetOrderNb() < distrTypeNb );
2823       const TCollection_AsciiString& method = (*cmd)->GetMethod();
2824       if ( !clear || method == "SetNumberOfSegments" ) {
2825         bool isNewInSet = uniqueMethods.insert( method ).second;
2826         clear = !isNewInSet;
2827       }
2828       if ( clear )
2829         (*cmd)->Clear();
2830     }
2831     cmdList.clear();
2832   }
2833 }
2834
2835 //================================================================================
2836 /*!
2837  * \brief Convert the command adding "SegmentLengthAroundVertex" to mesh
2838  * into regular1D.LengthNearVertex( length, vertex )
2839   * \param theCmd - The command like mesh.AddHypothesis( vertex, SegmentLengthAroundVertex )
2840   * \param theMesh - The mesh needing this hypo
2841   * \retval bool - false if the command cant be converted
2842  */
2843 //================================================================================
2844
2845 bool _pySegmentLengthAroundVertexHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
2846                                                          const _pyID&              theMeshID)
2847 {
2848   if ( IsWrappable( theMeshID )) {
2849
2850     _pyID vertex = theCmd->GetArg( 1 );
2851
2852     // the problem here is that segment algo will not be found
2853     // by pyHypothesis::Addition2Creation() for <vertex>, so we try to find
2854     // geometry where segment algorithm is assigned
2855     Handle(_pyHypothesis) algo;
2856     _pyID geom = vertex;
2857     while ( algo.IsNull() && !geom.IsEmpty()) {
2858       // try to find geom as a father of <vertex>
2859       geom = FatherID( geom );
2860       algo = theGen->FindAlgo( geom, theMeshID, this );
2861     }
2862     if ( algo.IsNull() )
2863       return false; // also possible to find geom as brother of veretex...
2864     // set geom instead of vertex
2865     theCmd->SetArg( 1, geom );
2866
2867     // set vertex as a second arg
2868     if ( myArgs.Length() < 1) myArgs.Append( "1" ); // :(
2869     myArgs.Append( vertex );
2870
2871     // mesh.AddHypothesis(vertex, SegmentLengthAroundVertex) -->
2872     // theMeshID.LengthNearVertex( length, vertex )
2873     return _pyHypothesis::Addition2Creation( theCmd, theMeshID );
2874   }
2875   return false;
2876 }
2877
2878 //================================================================================
2879 /*!
2880  * \brief _pyAlgorithm constructor
2881  * \param theCreationCmd - The command like "algo = smeshgen.CreateHypothesis(type,lib)"
2882  */
2883 //================================================================================
2884
2885 _pyAlgorithm::_pyAlgorithm(const Handle(_pyCommand)& theCreationCmd)
2886   : _pyHypothesis( theCreationCmd )
2887 {
2888   myIsAlgo = true;
2889 }
2890
2891 //================================================================================
2892 /*!
2893  * \brief Convert the command adding an algorithm to mesh
2894   * \param theCmd - The command like mesh.AddHypothesis( geom, algo )
2895   * \param theMesh - The mesh needing this algo
2896   * \retval bool - false if the command cant be converted
2897  */
2898 //================================================================================
2899
2900 bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd,
2901                                       const _pyID&              theMeshID)
2902 {
2903   // mesh.AddHypothesis(geom,algo) --> theMeshID.myCreationMethod()
2904   if ( _pyHypothesis::Addition2Creation( theCmd, theMeshID )) {
2905     theGen->SetAccessorMethod( GetID(), "GetAlgorithm()" );
2906     return true;
2907   }
2908   return false;
2909 }
2910
2911 //================================================================================
2912 /*!
2913  * \brief Return starting position of a part of python command
2914   * \param thePartIndex - The index of command part
2915   * \retval int - Part position
2916  */
2917 //================================================================================
2918
2919 int _pyCommand::GetBegPos( int thePartIndex )
2920 {
2921   if ( IsEmpty() )
2922     return EMPTY;
2923   if ( myBegPos.Length() < thePartIndex )
2924     return UNKNOWN;
2925   return myBegPos( thePartIndex );
2926 }
2927
2928 //================================================================================
2929 /*!
2930  * \brief Store starting position of a part of python command
2931   * \param thePartIndex - The index of command part
2932   * \param thePosition - Part position
2933  */
2934 //================================================================================
2935
2936 void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
2937 {
2938   while ( myBegPos.Length() < thePartIndex )
2939     myBegPos.Append( UNKNOWN );
2940   myBegPos( thePartIndex ) = thePosition;
2941 }
2942
2943 //================================================================================
2944 /*!
2945  * \brief Returns whitespace symbols at the line beginning
2946   * \retval TCollection_AsciiString - result
2947  */
2948 //================================================================================
2949
2950 TCollection_AsciiString _pyCommand::GetIndentation()
2951 {
2952   int end = 1;
2953   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
2954     GetWord( myString, end, true );
2955   else
2956     end = GetBegPos( RESULT_IND );
2957   return myString.SubString( 1, end - 1 );
2958 }
2959
2960 //================================================================================
2961 /*!
2962  * \brief Return substring of python command looking like ResultValue = Obj.Meth()
2963   * \retval const TCollection_AsciiString & - ResultValue substring
2964  */
2965 //================================================================================
2966
2967 const TCollection_AsciiString & _pyCommand::GetResultValue()
2968 {
2969   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
2970   {
2971     SetBegPos( RESULT_IND, EMPTY );
2972     int begPos, endPos = myString.Location( "=", 1, Length() );
2973     if ( endPos )
2974     {
2975       begPos = 1;
2976       while ( begPos < endPos && isblank( myString.Value( begPos ))) ++begPos;
2977       if ( begPos < endPos )
2978       {
2979         SetBegPos( RESULT_IND, begPos );
2980         --endPos;
2981         while ( begPos < endPos && isblank( myString.Value( endPos ))) --endPos;
2982         myRes = myString.SubString( begPos, endPos );
2983       }
2984     }
2985   }
2986   return myRes;
2987 }
2988
2989 //================================================================================
2990 /*!
2991  * \brief Return number of python command result value ResultValue = Obj.Meth()
2992   * \retval const int
2993  */
2994 //================================================================================
2995
2996 const int _pyCommand::GetNbResultValues()
2997 {
2998   int begPos = 1;
2999   int Nb=0;
3000   int endPos = myString.Location( "=", 1, Length() );
3001   TCollection_AsciiString str = "";
3002   while ( begPos < endPos) {
3003     str = GetWord( myString, begPos, true );
3004     begPos = begPos+ str.Length();
3005     Nb++;
3006   }
3007   return (Nb-1);
3008 }
3009
3010
3011 //================================================================================
3012 /*!
3013  * \brief Return substring of python command looking like
3014  *  ResultValue1 , ResultValue1,... = Obj.Meth() with res index
3015  * \retval const TCollection_AsciiString & - ResultValue with res index substring
3016  */
3017 //================================================================================
3018 const TCollection_AsciiString & _pyCommand::GetResultValue(int res)
3019 {
3020   int begPos = 1;
3021   int Nb=0;
3022   int endPos = myString.Location( "=", 1, Length() );
3023   while ( begPos < endPos) {
3024     myRes = GetWord( myString, begPos, true );
3025     begPos = begPos + myRes.Length();
3026     Nb++;
3027     if(res == Nb){
3028       myRes.RemoveAll('[');myRes.RemoveAll(']');
3029       return myRes;
3030     }
3031     if(Nb>res)
3032       break;
3033   }
3034   return theEmptyString;
3035 }
3036
3037 //================================================================================
3038 /*!
3039  * \brief Return substring of python command looking like ResVal = Object.Meth()
3040   * \retval const TCollection_AsciiString & - Object substring
3041  */
3042 //================================================================================
3043
3044 const TCollection_AsciiString & _pyCommand::GetObject()
3045 {
3046   if ( GetBegPos( OBJECT_IND ) == UNKNOWN )
3047   {
3048     // beginning
3049     int begPos = GetBegPos( RESULT_IND ) + myRes.Length();
3050     if ( begPos < 1 ) {
3051       begPos = myString.Location( "=", 1, Length() ) + 1;
3052       // is '=' in the string argument (for example, name) or not
3053       int nb1 = 0; // number of ' character at the left of =
3054       int nb2 = 0; // number of " character at the left of =
3055       for ( int i = 1; i < begPos-1; i++ ) {
3056         if ( myString.Value( i )=='\'' )
3057           nb1 += 1;
3058         else if ( myString.Value( i )=='"' )
3059           nb2 += 1;
3060       }
3061       // if number of ' or " is not divisible by 2,
3062       // then get an object at the start of the command
3063       if ( nb1 % 2 != 0 || nb2 % 2 != 0 )
3064         begPos = 1;
3065     }
3066     myObj = GetWord( myString, begPos, true );
3067     // check if object is complex,
3068     // so far consider case like "smesh.smesh.Method()"
3069     if ( int bracketPos = myString.Location( "(", begPos, Length() )) {
3070       //if ( bracketPos==0 ) bracketPos = Length();
3071       int dotPos = begPos+myObj.Length();
3072       while ( dotPos+1 < bracketPos ) {
3073         if ( int pos = myString.Location( ".", dotPos+1, bracketPos ))
3074           dotPos = pos;
3075         else
3076           break;
3077       }
3078       if ( dotPos > begPos+myObj.Length() )
3079         myObj = myString.SubString( begPos, dotPos-1 );
3080     }
3081     // store
3082     SetBegPos( OBJECT_IND, begPos );
3083   }
3084   //SCRUTE(myObj);
3085   return myObj;
3086 }
3087
3088 //================================================================================
3089 /*!
3090  * \brief Return substring of python command looking like ResVal = Obj.Method()
3091   * \retval const TCollection_AsciiString & - Method substring
3092  */
3093 //================================================================================
3094
3095 const TCollection_AsciiString & _pyCommand::GetMethod()
3096 {
3097   if ( GetBegPos( METHOD_IND ) == UNKNOWN )
3098   {
3099     // beginning
3100     int begPos = GetBegPos( OBJECT_IND ) + myObj.Length();
3101     bool forward = true;
3102     if ( begPos < 1 ) {
3103       begPos = myString.Location( "(", 1, Length() ) - 1;
3104       forward = false;
3105     }
3106     // store
3107     myMeth = GetWord( myString, begPos, forward );
3108     SetBegPos( METHOD_IND, begPos );
3109   }
3110   //SCRUTE(myMeth);
3111   return myMeth;
3112 }
3113
3114 //================================================================================
3115 /*!
3116  * \brief Return substring of python command looking like ResVal = Obj.Meth(Arg1,...)
3117   * \retval const TCollection_AsciiString & - Arg<index> substring
3118  */
3119 //================================================================================
3120
3121 const TCollection_AsciiString & _pyCommand::GetArg( int index )
3122 {
3123   if ( GetBegPos( ARG1_IND ) == UNKNOWN )
3124   {
3125     // Find all args
3126
3127     int pos = GetBegPos( METHOD_IND ) + myMeth.Length();
3128     if ( pos < 1 )
3129       pos = myString.Location( "(", 1, Length() );
3130     else
3131       --pos;
3132
3133     // we are at or before '(', skip it if present
3134     if ( pos > 0 ) {
3135       while ( pos <= Length() && myString.Value( pos ) != '(' ) ++pos;
3136       if ( pos > Length() )
3137         pos = 0;
3138     }
3139     if ( pos < 1 ) {
3140       SetBegPos( ARG1_IND, 0 ); // even no '('
3141       return theEmptyString;
3142     }
3143     ++pos;
3144
3145     list< TCollection_AsciiString > separatorStack( 1, ",)");
3146     bool ignoreNesting = false;
3147     int prevPos = pos;
3148     while ( pos <= Length() )
3149     {
3150       const char chr = myString.Value( pos );
3151
3152       if ( separatorStack.back().Location( chr, 1, separatorStack.back().Length()))
3153       {
3154         if ( separatorStack.size() == 1 ) // ',' dividing args or a terminal ')' found
3155         {
3156           while ( pos-1 >= prevPos && isspace( myString.Value( prevPos )))
3157             ++prevPos;
3158           if ( pos-1 >= prevPos ) {
3159             TCollection_AsciiString arg = myString.SubString( prevPos, pos-1 );
3160             arg.RightAdjust(); // remove spaces
3161             arg.LeftAdjust();
3162             SetBegPos( ARG1_IND + myArgs.Length(), prevPos );
3163             myArgs.Append( arg );
3164           }
3165           if ( chr == ')' )
3166             break;
3167           prevPos = pos+1;
3168         }
3169         else // end of nesting args found
3170         {
3171           separatorStack.pop_back();
3172           ignoreNesting = false;
3173         }
3174       }
3175       else if ( !ignoreNesting )
3176       {
3177         switch ( chr ) {
3178         case '(' : separatorStack.push_back(")"); break;
3179         case '[' : separatorStack.push_back("]"); break;
3180         case '\'': separatorStack.push_back("'");  ignoreNesting=true; break;
3181         case '"' : separatorStack.push_back("\""); ignoreNesting=true; break;
3182         default:;
3183         }
3184       }
3185       ++pos;
3186     }
3187   }
3188   if ( myArgs.Length() < index )
3189     return theEmptyString;
3190   return myArgs( index );
3191 }
3192
3193 //================================================================================
3194 /*!
3195  * \brief Check if char is a word part
3196   * \param c - The character to check
3197   * \retval bool - The check result
3198  */
3199 //================================================================================
3200
3201 static inline bool isWord(const char c, const bool dotIsWord)
3202 {
3203   return
3204     !isspace(c) && c != ',' && c != '=' && c != ')' && c != '(' && ( dotIsWord || c != '.');
3205 }
3206
3207 //================================================================================
3208 /*!
3209  * \brief Looks for a word in the string and returns word's beginning
3210   * \param theString - The input string
3211   * \param theStartPos - The position to start the search, returning word's beginning
3212   * \param theForward - The search direction
3213   * \retval TCollection_AsciiString - The found word
3214  */
3215 //================================================================================
3216
3217 TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString,
3218                                             int &      theStartPos,
3219                                             const bool theForward,
3220                                             const bool dotIsWord )
3221 {
3222   int beg = theStartPos, end = theStartPos;
3223   theStartPos = EMPTY;
3224   if ( beg < 1 || beg > theString.Length() )
3225     return theEmptyString;
3226
3227   if ( theForward ) { // search forward
3228     // beg
3229     while ( beg <= theString.Length() && !isWord( theString.Value( beg ), dotIsWord))
3230       ++beg;
3231     if ( beg > theString.Length() )
3232       return theEmptyString; // no word found
3233     // end
3234     end = beg + 1;
3235     char begChar = theString.Value( beg );
3236     if ( begChar == '"' || begChar == '\'' || begChar == '[') {
3237       char endChar = ( begChar == '[' ) ? ']' : begChar;
3238       // end is at the corresponding quoting mark or bracket
3239       while ( end < theString.Length() &&
3240               ( theString.Value( end ) != endChar || theString.Value( end-1 ) == '\\'))
3241         ++end;
3242     }
3243     else {
3244       while ( end <= theString.Length() && isWord( theString.Value( end ), dotIsWord))
3245         ++end;
3246       --end;
3247     }
3248   }
3249   else {  // search backward
3250     // end
3251     while ( end > 0 && !isWord( theString.Value( end ), dotIsWord))
3252       --end;
3253     if ( end == 0 )
3254       return theEmptyString; // no word found
3255     beg = end - 1;
3256     char endChar = theString.Value( end );
3257     if ( endChar == '"' || endChar == '\'' || endChar == ']') {
3258       char begChar = ( endChar == ']' ) ? '[' : endChar;
3259       // beg is at the corresponding quoting mark
3260       while ( beg > 1 &&
3261               ( theString.Value( beg ) != begChar || theString.Value( beg-1 ) == '\\'))
3262         --beg;
3263     }
3264     else {
3265       while ( beg > 0 && isWord( theString.Value( beg ), dotIsWord))
3266         --beg;
3267       ++beg;
3268     }
3269   }
3270   theStartPos = beg;
3271   //cout << theString << " ---- " << beg << " - " << end << endl;
3272   return theString.SubString( beg, end );
3273 }
3274
3275 //================================================================================
3276 /*!
3277  * \brief Returns true if the string looks like a study entry
3278  */
3279 //================================================================================
3280
3281 bool _pyCommand::IsStudyEntry( const TCollection_AsciiString& str )
3282 {
3283   if ( str.Length() < 5 ) return false;
3284
3285   int nbColons = 0, isColon;
3286   for ( int i = 1; i <= str.Length(); ++i )
3287   {
3288     char c = str.Value(i);
3289     if (!( isColon = (c == ':')) && ( c < '0' || c > '9' ))
3290       return false;
3291     nbColons += isColon;
3292   }
3293   return nbColons > 2 && str.Length()-nbColons > 2;
3294 }
3295
3296 //================================================================================
3297 /*!
3298  * \brief Finds entries in a sting
3299  */
3300 //================================================================================
3301
3302 std::list< _pyID > _pyCommand::GetStudyEntries( const TCollection_AsciiString& str )
3303 {
3304   std::list< _pyID > resList;
3305   int pos = 0;
3306   while ( ++pos <= str.Length() )
3307   {
3308     if ( !isdigit( str.Value( pos ))) continue;
3309     if ( pos != 1 && ( isalpha( str.Value( pos-1 ) || str.Value( pos-1 ) == ':'))) continue;
3310
3311     int end = pos;
3312     while ( ++end <= str.Length() && ( isdigit( str.Value( end )) || str.Value( end ) == ':' ));
3313     _pyID entry = str.SubString( pos, end-1 );
3314     pos = end;
3315     if ( IsStudyEntry( entry ))
3316       resList.push_back( entry );
3317   }
3318   return resList;
3319 }
3320
3321 //================================================================================
3322 /*!
3323  * \brief Look for position where not space char is
3324   * \param theString - The string
3325   * \param thePos - The position to search from and which returns result
3326   * \retval bool - false if there are only space after thePos in theString
3327  *
3328  *
3329  */
3330 //================================================================================
3331
3332 bool _pyCommand::SkipSpaces( const TCollection_AsciiString & theString, int & thePos )
3333 {
3334   if ( thePos < 1 || thePos > theString.Length() )
3335     return false;
3336
3337   while ( thePos <= theString.Length() && isspace( theString.Value( thePos )))
3338     ++thePos;
3339
3340   return thePos <= theString.Length();
3341 }
3342
3343 //================================================================================
3344 /*!
3345  * \brief Modify a part of the command
3346   * \param thePartIndex - The index of the part
3347   * \param thePart - The new part string
3348   * \param theOldPart - The old part
3349  */
3350 //================================================================================
3351
3352 void _pyCommand::SetPart(int thePartIndex, const TCollection_AsciiString& thePart,
3353                         TCollection_AsciiString& theOldPart)
3354 {
3355   int pos = GetBegPos( thePartIndex );
3356   if ( pos <= Length() && theOldPart != thePart)
3357   {
3358     TCollection_AsciiString seperator;
3359     if ( pos < 1 ) {
3360       pos = GetBegPos( thePartIndex + 1 );
3361       if ( pos < 1 ) return;
3362       switch ( thePartIndex ) {
3363       case RESULT_IND: seperator = " = "; break;
3364       case OBJECT_IND: seperator = "."; break;
3365       case METHOD_IND: seperator = "()"; break;
3366       default:;
3367       }
3368     }
3369     myString.Remove( pos, theOldPart.Length() );
3370     if ( !seperator.IsEmpty() )
3371       myString.Insert( pos , seperator );
3372     myString.Insert( pos, thePart );
3373     // update starting positions of the following parts
3374     int posDelta = thePart.Length() + seperator.Length() - theOldPart.Length();
3375     for ( int i = thePartIndex + 1; i <= myBegPos.Length(); ++i ) {
3376       if ( myBegPos( i ) > 0 )
3377         myBegPos( i ) += posDelta;
3378     }
3379     theOldPart = thePart;
3380   }
3381 }
3382
3383 //================================================================================
3384 /*!
3385  * \brief Set agrument
3386   * \param index - The argument index, it counts from 1
3387   * \param theArg - The argument string
3388  */
3389 //================================================================================
3390
3391 void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg)
3392 {
3393   FindAllArgs();
3394   int argInd = ARG1_IND + index - 1;
3395   int pos = GetBegPos( argInd );
3396   if ( pos < 1 ) // no index-th arg exist, append inexistent args
3397   {
3398     // find a closing parenthesis
3399     if ( GetNbArgs() != 0 && index <= GetNbArgs() ) {
3400       int lastArgInd = GetNbArgs();
3401       pos = GetBegPos( ARG1_IND + lastArgInd  - 1 ) + GetArg( lastArgInd ).Length();
3402       while ( pos > 0 && pos <= Length() && myString.Value( pos ) != ')' )
3403         ++pos;
3404     }
3405     else {
3406       pos = Length();
3407       while ( pos > 0 && myString.Value( pos ) != ')' )
3408         --pos;
3409     }
3410     if ( pos < 1 || myString.Value( pos ) != ')' ) { // no parentheses at all
3411       myString += "()";
3412       pos = Length();
3413     }
3414     while ( myArgs.Length() < index ) {
3415       if ( myArgs.Length() )
3416         myString.Insert( pos++, "," );
3417       myArgs.Append("None");
3418       myString.Insert( pos, myArgs.Last() );
3419       SetBegPos( ARG1_IND + myArgs.Length() - 1, pos );
3420       pos += myArgs.Last().Length();
3421     }
3422   }
3423   SetPart( argInd, theArg, myArgs( index ));
3424 }
3425
3426 //================================================================================
3427 /*!
3428  * \brief Empty arg list
3429  */
3430 //================================================================================
3431
3432 void _pyCommand::RemoveArgs()
3433 {
3434   if ( int pos = myString.Location( '(', 1, Length() ))
3435     myString.Trunc( pos );
3436   myString += ")";
3437   myArgs.Clear();
3438   if ( myBegPos.Length() >= ARG1_IND )
3439     myBegPos.Remove( ARG1_IND, myBegPos.Length() );
3440 }
3441
3442 //================================================================================
3443 /*!
3444  * \brief Comment a python command
3445  */
3446 //================================================================================
3447
3448 void _pyCommand::Comment()
3449 {
3450   if ( IsEmpty() ) return;
3451
3452   int i = 1;
3453   while ( i <= Length() && isblank( myString.Value(i) )) ++i;
3454   if ( i <= Length() )
3455   {
3456     myString.Insert( i, "#" );
3457     for ( int iPart = 0; iPart < myBegPos.Length(); ++iPart )
3458     {
3459       int begPos = GetBegPos( iPart );
3460       if ( begPos != UNKNOWN )
3461         SetBegPos( iPart, begPos + 1 );
3462     }
3463   }
3464 }
3465
3466 //================================================================================
3467 /*!
3468  * \brief Set dependent commands after this one
3469  */
3470 //================================================================================
3471
3472 bool _pyCommand::SetDependentCmdsAfter() const
3473 {
3474   bool orderChanged = false;
3475   list< Handle(_pyCommand)>::const_reverse_iterator cmd = myDependentCmds.rbegin();
3476   for ( ; cmd != myDependentCmds.rend(); ++cmd ) {
3477     if ( (*cmd)->GetOrderNb() < GetOrderNb() ) {
3478       orderChanged = true;
3479       theGen->SetCommandAfter( *cmd, this );
3480       (*cmd)->SetDependentCmdsAfter();
3481     }
3482   }
3483   return orderChanged;
3484 }
3485 //================================================================================
3486 /*!
3487  * \brief Insert accessor method after theObjectID
3488   * \param theObjectID - id of the accessed object
3489   * \param theAcsMethod - name of the method giving access to the object
3490   * \retval bool - false if theObjectID is not found in the command string
3491  */
3492 //================================================================================
3493
3494 bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod )
3495 {
3496   if ( !theAcsMethod )
3497     return false;
3498   // start object search from the object, i.e. ignore result
3499   GetObject();
3500   int beg = GetBegPos( OBJECT_IND );
3501   if ( beg < 1 || beg > Length() )
3502     return false;
3503   bool added = false;
3504   while (( beg = myString.Location( theObjectID, beg, Length() )))
3505   {
3506     // check that theObjectID is not just a part of a longer ID
3507     int afterEnd = beg + theObjectID.Length();
3508     Standard_Character c = myString.Value( afterEnd );
3509     if ( !isalnum( c ) && c != ':' ) {
3510       // check if accessor method already present
3511       if ( c != '.' ||
3512            myString.Location( (char*) theAcsMethod, afterEnd, Length() ) != afterEnd+1) {
3513         // insertion
3514         int oldLen = Length();
3515         myString.Insert( afterEnd, (char*) theAcsMethod );
3516         myString.Insert( afterEnd, "." );
3517         // update starting positions of the parts following the modified one
3518         int posDelta = Length() - oldLen;
3519         for ( int i = 1; i <= myBegPos.Length(); ++i ) {
3520           if ( myBegPos( i ) > afterEnd )
3521             myBegPos( i ) += posDelta;
3522         }
3523         added = true;
3524       }
3525     }
3526     beg = afterEnd; // is a part - next search
3527   }
3528   return added;
3529 }
3530
3531 //================================================================================
3532 /*!
3533  * \brief Creates pyObject
3534  */
3535 //================================================================================
3536
3537 _pyObject::_pyObject(const Handle(_pyCommand)& theCreationCmd, const _pyID& theID)
3538   : myID(theID), myCreationCmd(theCreationCmd), myIsPublished(false)
3539 {
3540   setID( theID );
3541 }
3542
3543 //================================================================================
3544 /*!
3545  * \brief Set up myID and myIsPublished
3546  */
3547 //================================================================================
3548
3549 void _pyObject::setID(const _pyID& theID)
3550 {
3551   myID = theID;
3552   myIsPublished = !theGen->IsNotPublished( GetID() );
3553 }
3554
3555 //================================================================================
3556 /*!
3557  * \brief Clear myCreationCmd and myProcessedCmds
3558  */
3559 //================================================================================
3560
3561 void _pyObject::ClearCommands()
3562 {
3563   if ( !CanClear() )
3564     return;
3565
3566   if ( !myCreationCmd.IsNull() )
3567     myCreationCmd->Clear();
3568
3569   list< Handle(_pyCommand) >::iterator cmd = myProcessedCmds.begin();
3570   for ( ; cmd != myProcessedCmds.end(); ++cmd )
3571     (*cmd)->Clear();
3572 }
3573
3574 //================================================================================
3575 /*!
3576  * \brief Return method name giving access to an interaface object wrapped by python class
3577   * \retval const char* - method name
3578  */
3579 //================================================================================
3580
3581 const char* _pyObject::AccessorMethod() const
3582 {
3583   return 0;
3584 }
3585 //================================================================================
3586 /*!
3587  * \brief Return ID of a father
3588  */
3589 //================================================================================
3590
3591 _pyID _pyObject::FatherID(const _pyID & childID)
3592 {
3593   int colPos = childID.SearchFromEnd(':');
3594   if ( colPos > 0 )
3595     return childID.SubString( 1, colPos-1 );
3596   return "";
3597 }
3598
3599 //================================================================================
3600 /*!
3601  * \brief SelfEraser erases creation command if no more it's commands invoked
3602  */
3603 //================================================================================
3604
3605 void _pySelfEraser::Flush()
3606 {
3607   if ( GetNbCalls() == 0 )
3608     GetCreationCmd()->Clear();
3609 }
3610
3611 //================================================================================
3612 /*!
3613  * \brief _pySubMesh constructor
3614  */
3615 //================================================================================
3616
3617 _pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd):
3618   _pyObject(theCreationCmd)
3619 {
3620   myMesh = ObjectToMesh( theGen->FindObject( theCreationCmd->GetObject() ));
3621 }
3622
3623 //================================================================================
3624 /*!
3625  * \brief count invoked commands
3626  */
3627 //================================================================================
3628
3629 void _pySubMesh::Process( const Handle(_pyCommand)& theCommand )
3630 {
3631   _pyObject::Process(theCommand); // count calls of Process()
3632   GetCreationCmd()->AddDependantCmd( theCommand );
3633 }
3634
3635 //================================================================================
3636 /*!
3637  * \brief Move creation command depending on invoked commands
3638  */
3639 //================================================================================
3640
3641 void _pySubMesh::Flush()
3642 {
3643   if ( GetNbCalls() == 0 ) // move to the end of all commands
3644     theGen->GetLastCommand()->AddDependantCmd( GetCreationCmd() );
3645   else if ( !myCreator.IsNull() )
3646     // move to be just after creator
3647     myCreator->GetCreationCmd()->AddDependantCmd( GetCreationCmd() );
3648 }
3649
3650 //================================================================================
3651 /*!
3652  * \brief To convert creation of a group by filter
3653  */
3654 //================================================================================
3655
3656 void _pyGroup::Process( const Handle(_pyCommand)& theCommand)
3657 {
3658   // Convert the following set of commands into mesh.MakeGroupByFilter(groupName, theFilter)
3659   // group = mesh.CreateEmptyGroup( elemType, groupName )
3660   // aFilter.SetMesh(mesh)
3661   // nbAdd = group.AddFrom( aFilter )
3662   Handle(_pyFilter) filter;
3663   if ( theCommand->GetMethod() == "AddFrom" )
3664   {
3665     _pyID idSource = theCommand->GetArg(1);
3666     // check if idSource is a filter
3667     filter = Handle(_pyFilter)::DownCast( theGen->FindObject( idSource ));
3668     if ( filter.IsNull() )
3669       return;
3670     // find aFilter.SetMesh(mesh) to clear it, it should be just before theCommand
3671     list< Handle(_pyCommand) >::reverse_iterator cmdIt = theGen->GetCommands().rbegin();
3672     while ( *cmdIt != theCommand ) ++cmdIt;
3673     while ( (*cmdIt)->GetOrderNb() != 1 )
3674     {
3675       const Handle(_pyCommand)& setMeshCmd = *(++cmdIt);
3676       if ((setMeshCmd->GetObject() == idSource ||
3677            setMeshCmd->GetObject() == filter->GetNewID() )
3678           &&
3679           setMeshCmd->GetMethod() == "SetMesh")
3680       {
3681         setMeshCmd->Clear();
3682         break;
3683       }
3684     }
3685     // replace 3 commands by one
3686     theCommand->Clear();
3687     const Handle(_pyCommand)& makeGroupCmd = GetCreationCmd();
3688     TCollection_AsciiString name = makeGroupCmd->GetArg( 2 );
3689     makeGroupCmd->SetMethod( "MakeGroupByFilter" );
3690     makeGroupCmd->SetArg( 1, name );
3691     makeGroupCmd->SetArg( 2, idSource );
3692     // set new name of a filter
3693     filter->Process( makeGroupCmd );
3694   }
3695   else if ( theCommand->GetMethod() == "SetFilter" )
3696   {
3697     // set new name of a filter
3698     _pyID filterID = theCommand->GetArg(1);
3699     filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID ));
3700     if ( !filter.IsNull() )
3701       filter->Process( theCommand );
3702   }
3703
3704   if ( !filter.IsNull() )
3705     filter->AddUser( this );
3706 }
3707
3708 //================================================================================
3709 /*!
3710  * \brief Constructor of _pyFilter
3711  */
3712 //================================================================================
3713
3714 _pyFilter::_pyFilter(const Handle(_pyCommand)& theCreationCmd, const _pyID& newID/*=""*/)
3715   :_pyObject(theCreationCmd), myNewID( newID )
3716 {
3717 }
3718
3719 //================================================================================
3720 /*!
3721  * \brief To convert creation of a filter by criteria and
3722  * to replace an old name by a new one
3723  */
3724 //================================================================================
3725
3726 void _pyFilter::Process( const Handle(_pyCommand)& theCommand)
3727 {
3728   if ( theCommand->GetObject() == GetID() )
3729     _pyObject::Process(theCommand); // count commands
3730
3731   if ( !myNewID.IsEmpty() )
3732   {
3733     if ( theCommand->GetObject() == GetID() )
3734       theCommand->SetObject( myNewID );
3735     else if ( theCommand->GetResultValue() == GetID() )
3736       theCommand->SetResultValue( myNewID );
3737     else
3738       for ( int i = 1, nb = theCommand->GetNbArgs(); i <= nb; ++i )
3739         if ( theCommand->GetArg( i ) == GetID() )
3740         {
3741           theCommand->SetArg( i, myNewID );
3742           break;
3743         }
3744   }
3745
3746   // Convert the following set of commands into smesh.GetFilterFromCriteria(criteria)
3747   // aFilter0x2aaab0487080 = aFilterManager.CreateFilter()
3748   // aFilter0x2aaab0487080.SetCriteria(aCriteria)
3749   if ( GetNbCalls() == 1 && // none method was called before this SetCriteria() call
3750        theCommand->GetMethod() == "SetCriteria")
3751   {
3752     // aFilter.SetCriteria(aCriteria) ->
3753     // aFilter = smesh.GetFilterFromCriteria(criteria)
3754     if ( myNewID.IsEmpty() )
3755       theCommand->SetResultValue( GetID() );
3756     else
3757       theCommand->SetResultValue( myNewID );
3758     theCommand->SetObject( SMESH_2smeshpy::GenName() );
3759     theCommand->SetMethod( "GetFilterFromCriteria" );
3760
3761     // Clear aFilterManager.CreateFilter()
3762     GetCreationCmd()->Clear();
3763   }
3764   else if ( theCommand->GetMethod() == "SetMesh")
3765   {
3766     theGen->AddMeshAccessorMethod( theCommand );
3767   }
3768 }
3769
3770 //================================================================================
3771 /*!
3772  * \brief Set new filter name to the creation command
3773  */
3774 //================================================================================
3775
3776 void _pyFilter::Flush()
3777 {
3778   if ( !myNewID.IsEmpty() && !GetCreationCmd()->IsEmpty() )
3779     GetCreationCmd()->SetResultValue( myNewID );
3780 }
3781
3782 //================================================================================
3783 /*!
3784  * \brief Return true if all my users can be cleared
3785  */
3786 //================================================================================
3787
3788 bool _pyFilter::CanClear()
3789 {
3790   list< Handle(_pyObject) >::iterator obj = myUsers.begin();
3791   for ( ; obj != myUsers.end(); ++obj )
3792     if ( !(*obj)->CanClear() )
3793       return false;
3794
3795   return true;
3796 }