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