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