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