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