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