Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / SMESH_I / SMESH_2smeshpy.cxx
1 //  Copyright (C) 2007-2008  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 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
23 //
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 "Resource_DataMapOfAsciiStringAsciiString.hxx"
34
35 #include "SMESH_Gen_i.hxx"
36 /* SALOME headers that include CORBA headers that include windows.h 
37  * that defines GetObject symbol as GetObjectA should stand before SALOME headers
38  * that declare methods named GetObject - to apply the same rules of GetObject renaming
39  * and thus to avoid mess with GetObject symbol on Windows */
40
41 IMPLEMENT_STANDARD_HANDLE (_pyObject          ,Standard_Transient);
42 IMPLEMENT_STANDARD_HANDLE (_pyCommand         ,Standard_Transient);
43 IMPLEMENT_STANDARD_HANDLE (_pyGen             ,_pyObject);
44 IMPLEMENT_STANDARD_HANDLE (_pyMesh            ,_pyObject);
45 IMPLEMENT_STANDARD_HANDLE (_pySubMesh         ,_pyObject);
46 IMPLEMENT_STANDARD_HANDLE (_pyMeshEditor      ,_pyObject);
47 IMPLEMENT_STANDARD_HANDLE (_pyHypothesis      ,_pyObject);
48 IMPLEMENT_STANDARD_HANDLE (_pyFilterManager   ,_pyObject);
49 IMPLEMENT_STANDARD_HANDLE (_pyAlgorithm       ,_pyHypothesis);
50 IMPLEMENT_STANDARD_HANDLE (_pyComplexParamHypo,_pyHypothesis);
51 IMPLEMENT_STANDARD_HANDLE (_pyNumberOfSegmentsHyp,_pyHypothesis);
52
53 IMPLEMENT_STANDARD_RTTIEXT(_pyObject          ,Standard_Transient);
54 IMPLEMENT_STANDARD_RTTIEXT(_pyCommand         ,Standard_Transient);
55 IMPLEMENT_STANDARD_RTTIEXT(_pyGen             ,_pyObject);
56 IMPLEMENT_STANDARD_RTTIEXT(_pyMesh            ,_pyObject);
57 IMPLEMENT_STANDARD_RTTIEXT(_pySubMesh         ,_pyObject);
58 IMPLEMENT_STANDARD_RTTIEXT(_pyMeshEditor      ,_pyObject);
59 IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis      ,_pyObject);
60 IMPLEMENT_STANDARD_RTTIEXT(_pyFilterManager   ,_pyObject);
61 IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm       ,_pyHypothesis);
62 IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis);
63 IMPLEMENT_STANDARD_RTTIEXT(_pyNumberOfSegmentsHyp,_pyHypothesis);
64 IMPLEMENT_STANDARD_RTTIEXT(_pyLayerDistributionHypo,_pyHypothesis);
65 IMPLEMENT_STANDARD_RTTIEXT(_pySegmentLengthAroundVertexHyp,_pyHypothesis);
66
67 using namespace std;
68 using SMESH::TPythonDump;
69
70 /*!
71  * \brief Container of commands into which the initial script is split.
72  *        It also contains data coresponding to SMESH_Gen contents
73  */
74 static Handle(_pyGen) theGen;
75
76 static TCollection_AsciiString theEmptyString;
77
78 //#define DUMP_CONVERSION
79
80 #if !defined(_DEBUG_) && defined(DUMP_CONVERSION)
81 #undef DUMP_CONVERSION
82 #endif
83
84
85 namespace {
86
87   //================================================================================
88   /*!
89    * \brief Set of TCollection_AsciiString initialized by C array of C strings
90    */
91   //================================================================================
92
93   struct TStringSet: public set<TCollection_AsciiString>
94   {
95     /*!
96      * \brief Filling. The last string must be ""
97      */
98     void Insert(const char* names[]) {
99       for ( int i = 0; names[i][0] ; ++i )
100         insert( (char*) names[i] );
101     }
102     /*!
103      * \brief Check if a string is in
104      */
105     bool Contains(const TCollection_AsciiString& name ) {
106       return find( name ) != end();
107     }
108   };
109 }
110
111 //================================================================================
112 /*!
113  * \brief Convert python script using commands of smesh.py
114   * \param theScript - Input script
115   * \retval TCollection_AsciiString - Convertion result
116   *
117   * Class SMESH_2smeshpy declared in SMESH_PythonDump.hxx
118  */
119 //================================================================================
120
121 TCollection_AsciiString
122 SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript,
123                               Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
124                               Resource_DataMapOfAsciiStringAsciiString& theObjectNames)
125 {
126   theGen = new _pyGen( theEntry2AccessorMethod, theObjectNames );
127
128   // split theScript into separate commands
129
130   SMESH_NoteBook * aNoteBook = new SMESH_NoteBook();
131   
132   int from = 1, end = theScript.Length(), to;
133   while ( from < end && ( to = theScript.Location( "\n", from, end )))
134   {
135     if ( to != from )
136         // cut out and store a command
137         aNoteBook->AddCommand( theScript.SubString( from, to - 1 ));
138       from = to + 1;
139   }
140   
141   aNoteBook->ReplaceVariables();
142
143   TCollection_AsciiString aNoteScript = aNoteBook->GetResultScript();
144   delete aNoteBook;
145   aNoteBook = 0;
146   
147   // split theScript into separate commands
148   from = 1, end = aNoteScript.Length();
149   while ( from < end && ( to = aNoteScript.Location( "\n", from, end )))
150   {
151     if ( to != from )
152       // cut out and store a command
153       theGen->AddCommand( aNoteScript.SubString( from, to - 1 ));
154     from = to + 1;
155   }
156
157   // finish conversion
158   theGen->Flush();
159 #ifdef DUMP_CONVERSION
160   MESSAGE_BEGIN ( std::endl << " ######## RESULT ######## " << std::endl<< std::endl );
161 #endif
162
163   // reorder commands after conversion
164   list< Handle(_pyCommand) >::iterator cmd;
165   bool orderChanges;
166   do {
167     orderChanges = false;
168     for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
169       if ( (*cmd)->SetDependentCmdsAfter() )
170         orderChanges = true;
171   } while ( orderChanges );
172   
173   // concat commands back into a script
174   TCollection_AsciiString aScript;
175   for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
176   {
177 #ifdef DUMP_CONVERSION
178     MESSAGE_ADD ( "## COM " << (*cmd)->GetOrderNb() << ": "<< (*cmd)->GetString() << std::endl );
179 #endif
180     if ( !(*cmd)->IsEmpty() ) {
181       aScript += "\n";
182       aScript += (*cmd)->GetString();
183     }
184   }
185   aScript += "\n";
186
187   theGen.Nullify();
188
189   return aScript;
190 }
191
192 //================================================================================
193 /*!
194  * \brief _pyGen constructor
195  */
196 //================================================================================
197
198 _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
199                Resource_DataMapOfAsciiStringAsciiString& theObjectNames)
200   : _pyObject( new _pyCommand( TPythonDump::SMESHGenName(), 0 )),
201     myID2AccessorMethod( theEntry2AccessorMethod ),
202     myObjectNames( theObjectNames )
203 {
204   myNbCommands = 0;
205   myHasPattern = false;
206   // make that GetID() to return TPythonDump::SMESHGenName()
207   GetCreationCmd()->GetString() += "=";
208 }
209
210 //================================================================================
211 /*!
212  * \brief name of SMESH_Gen in smesh.py
213  */
214 //================================================================================
215
216 const char* _pyGen::AccessorMethod() const
217 {
218   return SMESH_2smeshpy::GenName();
219 }
220
221 //================================================================================
222 /*!
223  * \brief Convert a command using a specific converter
224   * \param theCommand - the command to convert
225  */
226 //================================================================================
227
228 Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand)
229 {
230   // store theCommand in the sequence
231   myCommands.push_back( new _pyCommand( theCommand, ++myNbCommands ));
232
233   Handle(_pyCommand) aCommand = myCommands.back();
234 #ifdef DUMP_CONVERSION
235   MESSAGE ( "## COM " << myNbCommands << ": "<< aCommand->GetString() );
236 #endif
237
238   _pyID objID = aCommand->GetObject();
239
240   if ( objID.IsEmpty() )
241     return aCommand;
242
243   // SMESH_Gen method?
244   if ( objID == this->GetID() ) {
245     this->Process( aCommand );
246     return aCommand;
247   }
248   
249   // SMESH_subMesh method?
250   map< _pyID, Handle(_pySubMesh) >::iterator id_subMesh = mySubMeshes.find( objID );
251   if ( id_subMesh != mySubMeshes.end() ) {
252     id_subMesh->second->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     // check for mesh editor object
260     if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation
261       _pyID editorID = aCommand->GetResultValue();
262       Handle(_pyMeshEditor) editor = new _pyMeshEditor( aCommand );
263       myMeshEditors.insert( make_pair( editorID, editor ));
264       return aCommand;
265     } 
266     // check for SubMesh objects
267     else if ( aCommand->GetMethod() == "GetSubMesh" ) { // SubMesh creation
268       _pyID subMeshID = aCommand->GetResultValue();
269       Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand );
270       mySubMeshes.insert( make_pair( subMeshID, subMesh ));
271     }
272     id_mesh->second->Process( aCommand );
273     return aCommand;
274   }
275
276   //SMESH_FilterManager method?
277   if ( theCommand.Search( "aFilterManager" ) != -1 ) {
278     if ( theCommand.Search( "CreateFilterManager" ) != -1 )
279       myFilterManager = new _pyFilterManager( aCommand );
280     else if ( !myFilterManager.IsNull() )
281       myFilterManager->Process( aCommand );
282     return aCommand;
283   }
284
285   // SMESH_MeshEditor method?
286   map< _pyID, Handle(_pyMeshEditor) >::iterator id_editor = myMeshEditors.find( objID );
287   if ( id_editor != myMeshEditors.end() ) {
288     id_editor->second->Process( aCommand );
289     TCollection_AsciiString processedCommand = aCommand->GetString();
290     // some commands of SMESH_MeshEditor create meshes
291     if ( aCommand->GetMethod().Search("MakeMesh") != -1 ) {
292       Handle(_pyMesh) mesh = new _pyMesh( aCommand, aCommand->GetResultValue() );
293       aCommand->GetString() = processedCommand; // discard changes made by _pyMesh
294       myMeshes.insert( make_pair( mesh->GetID(), mesh ));
295     }
296     return aCommand;
297   }
298   // SMESH_Hypothesis method?
299   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
300   for ( ; hyp != myHypos.end(); ++hyp )
301     if ( !(*hyp)->IsAlgo() && objID == (*hyp)->GetID() ) {
302       (*hyp)->Process( aCommand );
303       return aCommand;
304     }
305
306   // Add access to a wrapped mesh
307   AddMeshAccessorMethod( aCommand );
308
309   // Add access to a wrapped algorithm
310   //  AddAlgoAccessorMethod( aCommand ); // ??? what if algo won't be wrapped at all ???
311
312   // PAL12227. PythonDump was not updated at proper time; result is
313   //     aCriteria.append(SMESH.Filter.Criterion(17,26,0,'L1',26,25,1e-07,SMESH.EDGE,-1))
314   // TypeError: __init__() takes exactly 11 arguments (10 given)
315   char wrongCommand[] = "SMESH.Filter.Criterion(";
316   if ( int beg = theCommand.Location( wrongCommand, 1, theCommand.Length() ))
317   {
318     _pyCommand tmpCmd( theCommand.SubString( beg, theCommand.Length() ), -1);
319     // there must be 10 arguments, 5-th arg ThresholdID is missing,
320     const int wrongNbArgs = 9, missingArg = 5;
321     if ( tmpCmd.GetNbArgs() == wrongNbArgs )
322     {
323       for ( int i = wrongNbArgs; i > missingArg; --i )
324         tmpCmd.SetArg( i + 1, tmpCmd.GetArg( i ));
325       tmpCmd.SetArg(  missingArg, "''");
326       aCommand->GetString().Trunc( beg - 1 );
327       aCommand->GetString() += tmpCmd.GetString();
328     }
329   }
330   return aCommand;
331 }
332
333 //================================================================================
334 /*!
335  * \brief Convert the command or remember it for later conversion 
336   * \param theCommand - The python command calling a method of SMESH_Gen
337  */
338 //================================================================================
339
340 void _pyGen::Process( const Handle(_pyCommand)& theCommand )
341 {
342   // there are methods to convert:
343   // CreateMesh( shape )
344   // Concatenate( [mesh1, ...], ... )
345   // CreateHypothesis( theHypType, theLibName )
346   // Compute( mesh, geom )
347   // mesh creation
348   TCollection_AsciiString method = theCommand->GetMethod();
349
350   if ( method == "CreateMesh" || method == "CreateEmptyMesh")
351   {
352     Handle(_pyMesh) mesh = new _pyMesh( theCommand );
353     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
354     return;
355   }
356   if ( method == "CreateMeshesFromUNV" || method == "CreateMeshesFromSTL")
357   {
358     Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
359     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
360     return;
361   }
362   if( method == "CreateMeshesFromMED")
363   {
364     for(int ind = 0;ind<theCommand->GetNbResultValues();ind++)
365     {
366       Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue(ind));
367       myMeshes.insert( make_pair( theCommand->GetResultValue(ind), mesh ));     
368     }
369   }
370
371   // CreateHypothesis()
372   if ( method == "CreateHypothesis" )
373   {
374     // issue 199929, remove standard library name (default parameter)
375     const TCollection_AsciiString & aLibName = theCommand->GetArg( 2 );
376     if ( aLibName.Search( "StdMeshersEngine" ) != -1 ) {
377       // keep first argument
378       TCollection_AsciiString arg = theCommand->GetArg( 1 );
379       theCommand->RemoveArgs();
380       theCommand->SetArg( 1, arg );
381     }
382
383     myHypos.push_back( _pyHypothesis::NewHypothesis( theCommand ));
384     return;
385   }
386
387   // smeshgen.Compute( mesh, geom ) --> mesh.Compute()
388   if ( method == "Compute" )
389   {
390     const _pyID& meshID = theCommand->GetArg( 1 );
391     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
392     if ( id_mesh != myMeshes.end() ) {
393       theCommand->SetObject( meshID );
394       theCommand->RemoveArgs();
395       id_mesh->second->Flush();
396       return;
397     }
398   }
399
400   // leave only one smeshgen.GetPattern() in the script
401   if ( method == "GetPattern" ) {
402     if ( myHasPattern ) {
403       theCommand->Clear();
404       return;
405     }
406     myHasPattern = true;
407   }
408
409   // Concatenate( [mesh1, ...], ... )
410   if ( method == "Concatenate" || method == "ConcatenateWithGroups")
411   {
412     if ( method == "ConcatenateWithGroups" ) {
413       theCommand->SetMethod( "Concatenate" );
414       theCommand->SetArg( theCommand->GetNbArgs() + 1, "True" );
415     }
416     Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
417     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
418     AddMeshAccessorMethod( theCommand );
419   }
420
421   // Replace name of SMESH_Gen
422
423   // names of SMESH_Gen methods fully equal to methods defined in smesh.py
424   static TStringSet smeshpyMethods;
425   if ( smeshpyMethods.empty() ) {
426     const char * names[] =
427       { "SetEmbeddedMode","IsEmbeddedMode","SetCurrentStudy","GetCurrentStudy",
428         "GetPattern","GetSubShapesId",
429         "" }; // <- mark of array end
430     smeshpyMethods.Insert( names );
431   }
432   if ( smeshpyMethods.Contains( theCommand->GetMethod() ))
433     // smeshgen.Method() --> smesh.Method()
434     theCommand->SetObject( SMESH_2smeshpy::SmeshpyName() );
435   else
436     // smeshgen.Method() --> smesh.smesh.Method()
437     theCommand->SetObject( SMESH_2smeshpy::GenName() );
438 }
439
440 //================================================================================
441 /*!
442  * \brief Convert the remembered commands
443  */
444 //================================================================================
445
446 void _pyGen::Flush()
447 {
448   // create empty command
449   myLastCommand = new _pyCommand();
450
451   if ( !myFilterManager.IsNull() )
452     myFilterManager->Flush();
453
454   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
455   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
456     if ( ! id_mesh->second.IsNull() )
457       id_mesh->second->Flush();
458
459   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
460   for ( ; hyp != myHypos.end(); ++hyp )
461     if ( !hyp->IsNull() ) {
462       (*hyp)->Flush();
463       // smeshgen.CreateHypothesis() --> smesh.smesh.CreateHypothesis()
464       if ( !(*hyp)->IsWrapped() )
465         (*hyp)->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() );
466     }
467
468   map< _pyID, Handle(_pySubMesh) >::iterator id_subMesh = mySubMeshes.begin();
469   for ( ; id_subMesh != mySubMeshes.end(); ++id_subMesh )
470     if ( ! id_subMesh->second.IsNull() )
471       id_subMesh->second->Flush();
472
473   myLastCommand->SetOrderNb( ++myNbCommands );
474   myCommands.push_back( myLastCommand );
475 }
476
477 //================================================================================
478 /*!
479  * \brief Add access method to mesh that is an argument
480   * \param theCmd - command to add access method
481   * \retval bool - true if added
482  */
483 //================================================================================
484
485 bool _pyGen::AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const
486 {
487   bool added = false;
488   map< _pyID, Handle(_pyMesh) >::const_iterator id_mesh = myMeshes.begin();
489   for ( ; id_mesh != myMeshes.end(); ++id_mesh ) {
490     if ( theCmd->AddAccessorMethod( id_mesh->first, id_mesh->second->AccessorMethod() ))
491       added = true;
492   }
493   return added;
494 }
495
496 //================================================================================
497 /*!
498  * \brief Add access method to algo that is an object or an argument
499   * \param theCmd - command to add access method
500   * \retval bool - true if added
501  */
502 //================================================================================
503
504 bool _pyGen::AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const
505 {
506   bool added = false;
507   list< Handle(_pyHypothesis) >::const_iterator hyp = myHypos.begin();
508   for ( ; hyp != myHypos.end(); ++hyp ) {
509     if ( (*hyp)->IsAlgo() && /*(*hyp)->IsWrapped() &&*/
510          theCmd->AddAccessorMethod( (*hyp)->GetID(), (*hyp)->AccessorMethod() ))
511       added = true;
512   }
513   return added;
514 }
515
516 //================================================================================
517 /*!
518  * \brief Find hypothesis by ID (entry)
519   * \param theHypID - The hypothesis ID
520   * \retval Handle(_pyHypothesis) - The found hypothesis
521  */
522 //================================================================================
523
524 Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID )
525 {
526   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
527   for ( ; hyp != myHypos.end(); ++hyp )
528     if ( !hyp->IsNull() && theHypID == (*hyp)->GetID() )
529       return *hyp;
530   return Handle(_pyHypothesis)();
531 }
532
533 //================================================================================
534 /*!
535  * \brief Find algorithm the created algorithm
536   * \param theGeom - The shape ID the algorithm was created on
537   * \param theMesh - The mesh ID that created the algorithm
538   * \param dim - The algo dimension
539   * \retval Handle(_pyHypothesis) - The found algo
540  */
541 //================================================================================
542
543 Handle(_pyHypothesis) _pyGen::FindAlgo( const _pyID& theGeom, const _pyID& theMesh,
544                                         const Handle(_pyHypothesis)& theHypothesis )
545 {
546   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
547   for ( ; hyp != myHypos.end(); ++hyp )
548     if ( !hyp->IsNull() &&
549          (*hyp)->IsAlgo() &&
550          theHypothesis->CanBeCreatedBy( (*hyp)->GetAlgoType() ) &&
551          (*hyp)->GetGeom() == theGeom &&
552          (*hyp)->GetMesh() == theMesh )
553       return *hyp;
554   return 0;
555 }
556
557 //================================================================================
558 /*!
559  * \brief Find subMesh by ID (entry)
560   * \param theSubMeshID - The subMesh ID
561   * \retval Handle(_pySubMesh) - The found subMesh
562  */
563 //================================================================================
564
565 Handle(_pySubMesh) _pyGen::FindSubMesh( const _pyID& theSubMeshID )
566 {
567   map< _pyID, Handle(_pySubMesh) >::iterator id_subMesh = mySubMeshes.begin();
568   for ( ; id_subMesh != mySubMeshes.end(); ++id_subMesh ) {
569     Handle(_pySubMesh) sm = id_subMesh->second;
570     if ( !id_subMesh->second.IsNull() && theSubMeshID == id_subMesh->second->GetID() )
571       return sm;
572   }
573   return Handle(_pySubMesh)();
574 }
575
576
577 //================================================================================
578 /*!
579  * \brief Change order of commands in the script
580   * \param theCmd1 - One command
581   * \param theCmd2 - Another command
582  */
583 //================================================================================
584
585 void _pyGen::ExchangeCommands( Handle(_pyCommand) theCmd1, Handle(_pyCommand) theCmd2 )
586 {
587   list< Handle(_pyCommand) >::iterator pos1, pos2;
588   pos1 = find( myCommands.begin(), myCommands.end(), theCmd1 );
589   pos2 = find( myCommands.begin(), myCommands.end(), theCmd2 );
590   myCommands.insert( pos1, theCmd2 );
591   myCommands.insert( pos2, theCmd1 );
592   myCommands.erase( pos1 );
593   myCommands.erase( pos2 );
594
595   int nb1 = theCmd1->GetOrderNb();
596   theCmd1->SetOrderNb( theCmd2->GetOrderNb() );
597   theCmd2->SetOrderNb( nb1 );
598 //   cout << "BECOME " << theCmd1->GetOrderNb() << "\t" << theCmd1->GetString() << endl
599 //        << "BECOME " << theCmd2->GetOrderNb() << "\t" << theCmd2->GetString() << endl << endl;
600 }
601
602 //================================================================================
603 /*!
604  * \brief Set one command after the other
605   * \param theCmd - Command to move
606   * \param theAfterCmd - Command ater which to insert the first one
607  */
608 //================================================================================
609
610 void _pyGen::SetCommandAfter( Handle(_pyCommand) theCmd, Handle(_pyCommand) theAfterCmd )
611 {
612   setNeighbourCommand( theCmd, theAfterCmd, true );
613 }
614
615 //================================================================================
616 /*!
617  * \brief Set one command before the other
618   * \param theCmd - Command to move
619   * \param theBeforeCmd - Command before which to insert the first one
620  */
621 //================================================================================
622
623 void _pyGen::SetCommandBefore( Handle(_pyCommand) theCmd, Handle(_pyCommand) theBeforeCmd )
624 {
625   setNeighbourCommand( theCmd, theBeforeCmd, false );
626 }
627
628 //================================================================================
629 /*!
630  * \brief Set one command before or after the other
631   * \param theCmd - Command to move
632   * \param theOtherCmd - Command ater or before which to insert the first one
633  */
634 //================================================================================
635
636 void _pyGen::setNeighbourCommand( Handle(_pyCommand)& theCmd,
637                                   Handle(_pyCommand)& theOtherCmd,
638                                   const bool theIsAfter )
639 {
640   list< Handle(_pyCommand) >::iterator pos;
641   pos = find( myCommands.begin(), myCommands.end(), theCmd );
642   myCommands.erase( pos );
643   pos = find( myCommands.begin(), myCommands.end(), theOtherCmd );
644   myCommands.insert( (theIsAfter ? ++pos : pos), theCmd );
645
646   int i = 1;
647   for ( pos = myCommands.begin(); pos != myCommands.end(); ++pos)
648     (*pos)->SetOrderNb( i++ );
649 }
650
651 //================================================================================
652 /*!
653  * \brief Set command be last in list of commands
654   * \param theCmd - Command to be last
655  */
656 //================================================================================
657
658 Handle(_pyCommand)& _pyGen::GetLastCommand()
659 {
660   return myLastCommand;
661 }
662
663 //================================================================================
664 /*!
665  * \brief Set method to access to object wrapped with python class
666   * \param theID - The wrapped object entry
667   * \param theMethod - The accessor method
668  */
669 //================================================================================
670
671 void _pyGen::SetAccessorMethod(const _pyID& theID, const char* theMethod )
672 {
673   myID2AccessorMethod.Bind( theID, (char*) theMethod );
674 }
675
676 //================================================================================
677 /*!
678  * \brief Generated new ID for object and assign with existing name
679   * \param theID - ID of existing object
680  */
681 //================================================================================
682
683 _pyID _pyGen::GenerateNewID( const _pyID& theID )
684 {
685   int index = 1;
686   _pyID aNewID;
687   do {
688     aNewID = theID + _pyID( ":" ) + _pyID( index++ );
689   }
690   while ( myObjectNames.IsBound( aNewID ) );
691     
692   myObjectNames.Bind( aNewID, myObjectNames.IsBound( theID ) 
693                       ? (myObjectNames.Find( theID ) + _pyID( "_" ) + _pyID( index-1 ))
694                       : _pyID( "A" ) + aNewID );
695   return aNewID;
696 }
697
698 //================================================================================
699 /*!
700  * \brief Find out type of geom group
701   * \param grpID - The geom group entry
702   * \retval int - The type
703  */
704 //================================================================================
705
706 static bool sameGroupType( const _pyID&                   grpID,
707                            const TCollection_AsciiString& theType)
708 {
709   // define group type as smesh.Mesh.Group() does
710   int type = -1;
711   SALOMEDS::Study_var study = SMESH_Gen_i::GetSMESHGen()->GetCurrentStudy();
712   SALOMEDS::SObject_var aSObj = study->FindObjectID( grpID.ToCString() );
713   if ( !aSObj->_is_nil() ) {
714     GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow( aSObj->GetObject() );
715     if ( !aGeomObj->_is_nil() ) {
716       switch ( aGeomObj->GetShapeType() ) {
717       case GEOM::VERTEX: type = SMESH::NODE; break;
718       case GEOM::EDGE:   type = SMESH::EDGE; break;
719       case GEOM::FACE:   type = SMESH::FACE; break;
720       case GEOM::SOLID:
721       case GEOM::SHELL:  type = SMESH::VOLUME; break;
722       case GEOM::COMPOUND: {
723         GEOM::GEOM_Gen_ptr aGeomGen = SMESH_Gen_i::GetSMESHGen()->GetGeomEngine();
724         if ( !aGeomGen->_is_nil() ) {
725           GEOM::GEOM_IGroupOperations_var aGrpOp =
726             aGeomGen->GetIGroupOperations( study->StudyId() );
727           if ( !aGrpOp->_is_nil() ) {
728             switch ( aGrpOp->GetType( aGeomObj )) {
729             case TopAbs_VERTEX: type = SMESH::NODE; break;
730             case TopAbs_EDGE:   type = SMESH::EDGE; break;
731             case TopAbs_FACE:   type = SMESH::FACE; break;
732             case TopAbs_SOLID:  type = SMESH::VOLUME; break;
733             default:;
734             }
735           }
736         }
737       }
738       default:;
739       }
740     }
741   }
742   if ( type < 0 ) {
743     MESSAGE("Type of the group " << grpID << " not found");
744     return false;
745   }
746   if ( theType.IsIntegerValue() )
747     return type == theType.IntegerValue();
748
749   switch ( type ) {
750   case SMESH::NODE:   return theType.Location( "NODE", 1, theType.Length() );
751   case SMESH::EDGE:   return theType.Location( "EDGE", 1, theType.Length() );
752   case SMESH::FACE:   return theType.Location( "FACE", 1, theType.Length() );
753   case SMESH::VOLUME: return theType.Location( "VOLUME", 1, theType.Length() );
754   default:;
755   }
756   return false;
757 }
758
759 //================================================================================
760 /*!
761  * \brief 
762   * \param theCreationCmd - 
763  */
764 //================================================================================
765
766 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd)
767   : _pyObject(theCreationCmd), myHasEditor(false)
768 {
769   // convert my creation command
770   Handle(_pyCommand) creationCmd = GetCreationCmd();
771   //TCollection_AsciiString str = creationCmd->GetMethod();
772 //   if(str != "CreateMeshesFromUNV" &&
773 //      str != "CreateMeshesFromMED" &&
774 //      str != "CreateMeshesFromSTL")
775   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() ); 
776   creationCmd->SetMethod( "Mesh" );
777
778   theGen->SetAccessorMethod( GetID(), "GetMesh()" );
779 }
780
781 //================================================================================
782 /*!
783  * \brief 
784   * \param theCreationCmd - 
785  */
786 //================================================================================
787 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd, const TCollection_AsciiString& id):
788   _pyObject(theCreationCmd), myHasEditor(false)
789 {
790   // convert my creation command
791   Handle(_pyCommand) creationCmd = GetCreationCmd();
792   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() ); 
793   theGen->SetAccessorMethod( id, "GetMesh()" );
794 }
795
796 //================================================================================
797 /*!
798  * \brief Convert a IDL API command of SMESH::Mesh to a method call of python Mesh
799   * \param theCommand - Engine method called for this mesh
800  */
801 //================================================================================
802
803 void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
804 {
805   // some methods of SMESH_Mesh interface needs special conversion
806   // to methods of Mesh python class
807   //
808   // 1. GetSubMesh(geom, name) + AddHypothesis(geom, algo)
809   //     --> in Mesh_Algorithm.Create(mesh, geom, hypo, so)
810   // 2. AddHypothesis(geom, hyp)
811   //     --> in Mesh_Algorithm.Hypothesis(hyp, args, so)
812   // 3. CreateGroupFromGEOM(type, name, grp)
813   //     --> in Mesh.Group(grp, name="")
814   // 4. ExportToMED(f, auto_groups, version)
815   //     --> in Mesh.ExportMED( f, auto_groups, version )
816   // 5. etc
817
818   const TCollection_AsciiString method = theCommand->GetMethod();
819   // ----------------------------------------------------------------------
820   if ( method == "GetSubMesh" ) {
821     Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetResultValue() );
822     if ( !subMesh.IsNull() ) {
823       subMesh->SetCreator( this );
824       mySubmeshes.push_back( subMesh );
825     }
826   }
827   // ----------------------------------------------------------------------
828   else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO )
829     myAddHypCmds.push_back( theCommand );
830     // set mesh to hypo
831     const _pyID& hypID = theCommand->GetArg( 2 );
832     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
833     if ( !hyp.IsNull() ) {
834       myHypos.push_back( hyp );
835       if ( hyp->GetMesh().IsEmpty() )
836         hyp->SetMesh( this->GetID() );
837     }
838   }
839   // ----------------------------------------------------------------------
840   else if ( method == "CreateGroupFromGEOM" ) {// (type, name, grp)
841     _pyID grp = theCommand->GetArg( 3 );
842     if ( sameGroupType( grp, theCommand->GetArg( 1 )) ) { // --> Group(grp)
843       theCommand->SetMethod( "Group" );
844       theCommand->RemoveArgs();
845       theCommand->SetArg( 1, grp );
846     }
847     else {
848       _pyID type = theCommand->GetArg( 1 );
849       _pyID name = theCommand->GetArg( 2 );
850       theCommand->SetMethod( "GroupOnGeom" );
851       theCommand->RemoveArgs();
852       theCommand->SetArg( 1, grp );
853       theCommand->SetArg( 2, name );
854       theCommand->SetArg( 3, type );
855     }
856   }
857   // ----------------------------------------------------------------------
858   else if ( method == "ExportToMED" ) { // ExportToMED() --> ExportMED()
859     theCommand->SetMethod( "ExportMED" );
860   }
861   // ----------------------------------------------------------------------
862   else if ( method == "CreateGroup" ) { // CreateGroup() --> CreateEmptyGroup()
863     theCommand->SetMethod( "CreateEmptyGroup" );
864   }
865   // ----------------------------------------------------------------------
866   else if ( method == "RemoveHypothesis" ) // (geom, hyp)
867   {
868     _pyID hypID = theCommand->GetArg( 2 );
869
870     // check if this mesh still has corresponding addition command
871     bool hasAddCmd = false;
872     list< Handle(_pyCommand) >::iterator cmd = myAddHypCmds.begin();
873     while ( cmd != myAddHypCmds.end() )
874     {
875       // AddHypothesis(geom, hyp)
876       if ( hypID == (*cmd)->GetArg( 2 )) { // erase both (add and remove) commands
877         theCommand->Clear();
878         (*cmd)->Clear();
879         cmd = myAddHypCmds.erase( cmd );
880         hasAddCmd = true;
881       }
882       else {
883         ++cmd;
884       }
885     }
886     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
887     if ( ! hasAddCmd && hypID.Length() != 0 ) { // hypo addition already wrapped
888       // RemoveHypothesis(geom, hyp) --> RemoveHypothesis( hyp, geom=0 )
889       _pyID geom = theCommand->GetArg( 1 );
890       theCommand->RemoveArgs();
891       theCommand->SetArg( 1, hypID );
892       if ( geom != GetGeom() )
893         theCommand->SetArg( 2, geom );
894     }
895     // remove hyp from myHypos
896     myHypos.remove( hyp );
897   }
898   // add accessor method if necessary
899   else
900   {
901     if ( NeedMeshAccess( theCommand ))
902       // apply theCommand to the mesh wrapped by smeshpy mesh
903       AddMeshAccess( theCommand );
904   }
905 }
906
907 //================================================================================
908 /*!
909  * \brief Return True if addition of accesor method is needed
910  */
911 //================================================================================
912
913 bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand )
914 {
915   // names of SMESH_Mesh methods fully equal to methods of class Mesh, so
916   // no conversion is needed for them at all:
917   static TStringSet sameMethods;
918   if ( sameMethods.empty() ) {
919     const char * names[] =
920       { "ExportDAT","ExportUNV","ExportSTL", "RemoveGroup","RemoveGroupWithContents",
921         "GetGroups","UnionGroups","IntersectGroups","CutGroups","GetLog","GetId","ClearLog",
922         "GetStudyId","HasDuplicatedGroupNamesMED","GetMEDMesh","NbNodes","NbElements",
923         "NbEdges","NbEdgesOfOrder","NbFaces","NbFacesOfOrder","NbTriangles",
924         "NbTrianglesOfOrder","NbQuadrangles","NbQuadranglesOfOrder","NbPolygons","NbVolumes",
925         "NbVolumesOfOrder","NbTetras","NbTetrasOfOrder","NbHexas","NbHexasOfOrder",
926         "NbPyramids","NbPyramidsOfOrder","NbPrisms","NbPrismsOfOrder","NbPolyhedrons",
927         "NbSubMesh","GetElementsId","GetElementsByType","GetNodesId","GetElementType",
928         "GetSubMeshElementsId","GetSubMeshNodesId","GetSubMeshElementType","Dump","GetNodeXYZ",
929         "GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes",
930         "GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces",
931         "IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", "SetAutoColor", "GetAutoColor",
932         "Clear", "ConvertToStandalone"
933         ,"" }; // <- mark of end
934     sameMethods.Insert( names );
935   }
936
937   return !sameMethods.Contains( theCommand->GetMethod() );
938 }
939
940 //================================================================================
941 /*!
942  * \brief Convert creation and addition of all algos and hypos
943  */
944 //================================================================================
945
946 void _pyMesh::Flush()
947 {
948   list < Handle(_pyCommand) >::iterator cmd;
949
950   // try to convert algo addition like this:
951   // mesh.AddHypothesis(geom, ALGO ) --> ALGO = mesh.Algo()
952   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
953   {
954     Handle(_pyCommand) addCmd = *cmd;
955
956     _pyID algoID = addCmd->GetArg( 2 );
957     Handle(_pyHypothesis) algo = theGen->FindHyp( algoID );
958     if ( algo.IsNull() || !algo->IsAlgo() )
959       continue;
960
961     // check and create new algorithm instance if it is already wrapped
962     if ( algo->IsWrapped() ) {
963       _pyID localAlgoID = theGen->GenerateNewID( algoID );
964       TCollection_AsciiString aNewCmdStr = localAlgoID +
965         TCollection_AsciiString( " = " ) + theGen->GetID() +
966         TCollection_AsciiString( ".CreateHypothesis( \"" ) + algo->GetAlgoType() +
967         TCollection_AsciiString( "\" )" );
968       
969       Handle(_pyCommand) newCmd = theGen->AddCommand( aNewCmdStr );
970       Handle(_pyAlgorithm) newAlgo = Handle(_pyAlgorithm)::DownCast(theGen->FindHyp( localAlgoID ));
971       if ( !newAlgo.IsNull() ) {
972         newAlgo->Assign( algo, this->GetID() );
973         newAlgo->SetCreationCmd( newCmd );
974         algo = newAlgo;
975         // set algorithm creation
976         theGen->SetCommandBefore( newCmd, addCmd );
977       }
978       else
979         newCmd->Clear();
980     }
981     _pyID geom = addCmd->GetArg( 1 );
982     bool isLocalAlgo = ( geom != GetGeom() );
983     
984     // try to convert
985     if ( algo->Addition2Creation( addCmd, this->GetID() )) // OK
986     {
987       // wrapped algo is created atfer mesh creation
988       GetCreationCmd()->AddDependantCmd( addCmd );
989
990       if ( isLocalAlgo ) {
991         // mesh.AddHypothesis(geom, ALGO ) --> mesh.AlgoMethod(geom)
992         addCmd->SetArg( addCmd->GetNbArgs() + 1,
993                         TCollection_AsciiString( "geom=" ) + geom );
994         // sm = mesh.GetSubMesh(geom, name) --> sm = ALGO.GetSubMesh()
995         list < Handle(_pySubMesh) >::iterator smIt;
996         for ( smIt = mySubmeshes.begin(); smIt != mySubmeshes.end(); ++smIt ) {
997           Handle(_pySubMesh) subMesh = *smIt;
998           Handle(_pyCommand) subCmd = subMesh->GetCreationCmd();
999           if ( geom == subCmd->GetArg( 1 )) {
1000             subCmd->SetObject( algo->GetID() );
1001             subCmd->RemoveArgs();
1002             subMesh->SetCreator( algo );
1003           }
1004         }
1005       }
1006     }
1007     else // KO - ALGO was already created
1008     {
1009       // mesh.AddHypothesis(geom, ALGO) --> mesh.AddHypothesis(ALGO, geom=0)
1010       addCmd->RemoveArgs();
1011       addCmd->SetArg( 1, algoID );
1012       if ( isLocalAlgo )
1013         addCmd->SetArg( 2, geom );
1014     }
1015   }
1016
1017   // try to convert hypo addition like this:
1018   // mesh.AddHypothesis(geom, HYPO ) --> HYPO = algo.Hypo()
1019   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
1020   {
1021     Handle(_pyCommand) addCmd = *cmd;
1022     _pyID hypID = addCmd->GetArg( 2 );
1023     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
1024     if ( hyp.IsNull() || hyp->IsAlgo() )
1025       continue;
1026     bool converted = hyp->Addition2Creation( addCmd, this->GetID() );
1027     if ( !converted ) {
1028       // mesh.AddHypothesis(geom, HYP) --> mesh.AddHypothesis(HYP, geom=0)
1029       _pyID geom = addCmd->GetArg( 1 );
1030       addCmd->RemoveArgs();
1031       addCmd->SetArg( 1, hypID );
1032       if ( geom != GetGeom() )
1033         addCmd->SetArg( 2, geom );
1034     }
1035   }
1036
1037   // sm = mesh.GetSubMesh(geom, name) --> sm = mesh.GetMesh().GetSubMesh(geom, name)
1038 //   for ( cmd = mySubmeshes.begin(); cmd != mySubmeshes.end(); ++cmd ) {
1039 //     Handle(_pyCommand) subCmd = *cmd;
1040 //     if ( subCmd->GetNbArgs() > 0 )
1041 //       AddMeshAccess( subCmd );
1042 //   }
1043   myAddHypCmds.clear();
1044   mySubmeshes.clear();
1045
1046   // flush hypotheses
1047   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
1048   for ( ; hyp != myHypos.end(); ++hyp )
1049     (*hyp)->Flush();
1050 }
1051
1052 //================================================================================
1053 /*!
1054  * \brief MeshEditor convert its commands to ones of mesh
1055  */
1056 //================================================================================
1057
1058 _pyMeshEditor::_pyMeshEditor(const Handle(_pyCommand)& theCreationCmd):
1059   _pyObject( theCreationCmd )
1060 {
1061   myMesh = theCreationCmd->GetObject();
1062   myCreationCmdStr = theCreationCmd->GetString();
1063   theCreationCmd->Clear();
1064 }
1065
1066 //================================================================================
1067 /*!
1068  * \brief convert its commands to ones of mesh
1069  */
1070 //================================================================================
1071
1072 void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
1073 {
1074   // names of SMESH_MeshEditor methods fully equal to methods of class Mesh, so
1075   // commands calling this methods are converted to calls of methods of Mesh
1076   static TStringSet sameMethods;
1077   if ( sameMethods.empty() ) {
1078     const char * names[] = {
1079       "RemoveElements","RemoveNodes","AddNode","AddEdge","AddFace","AddPolygonalFace",
1080       "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","MoveNode", "MoveClosestNodeToPoint",
1081       "InverseDiag","DeleteDiag","Reorient","ReorientObject","TriToQuad","SplitQuad","SplitQuadObject",
1082       "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject",
1083       "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements",
1084       "RotationSweep","RotationSweepObject","RotationSweepObject1D","RotationSweepObject2D",
1085       "ExtrusionSweep","AdvancedExtrusion","ExtrusionSweepObject","ExtrusionSweepObject1D","ExtrusionSweepObject2D",
1086       "ExtrusionAlongPath","ExtrusionAlongPathObject","ExtrusionAlongPathObject1D","ExtrusionAlongPathObject2D",
1087       "Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject",
1088       "FindCoincidentNodes","FindCoincidentNodesOnPart","MergeNodes","FindEqualElements",
1089       "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders",
1090       "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes",
1091       "GetLastCreatedElems",
1092       "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh",
1093       "TranslateObjectMakeMesh","RotateMakeMesh","RotateObjectMakeMesh"
1094       ,"" }; // <- mark of the end
1095     sameMethods.Insert( names );
1096   }
1097
1098   // names of SMESH_MeshEditor methods which differ from methods of class Mesh
1099   // only last two arguments
1100   static TStringSet diffLastTwoArgsMethods;
1101   if (diffLastTwoArgsMethods.empty() ){
1102     const char * names[] = {
1103       "MirrorMakeGroups","MirrorObjectMakeGroups",
1104       "TranslateMakeGroups","TranslateObjectMakeGroups",
1105       "RotateMakeGroups","RotateObjectMakeGroups",
1106       ""};// <- mark of the end
1107     diffLastTwoArgsMethods.Insert( names );
1108   }
1109
1110   if ( sameMethods.Contains( theCommand->GetMethod() )) {
1111     theCommand->SetObject( myMesh );
1112
1113     // meshes made by *MakeMesh() methods are not wrapped by _pyMesh,
1114     // so let _pyMesh care of it (TMP?)
1115 //     if ( theCommand->GetMethod().Search("MakeMesh") != -1 )
1116 //       _pyMesh( new _pyCommand( theCommand->GetString(), 0 )); // for theGen->SetAccessorMethod()
1117   }
1118   else {
1119     
1120     //Replace SMESH_MeshEditor "MakeGroups" functions on the Mesh 
1121     //functions with the flag "theMakeGroups = True" like:
1122     //SMESH_MeshEditor.CmdMakeGroups => Mesh.Cmd(...,True)
1123     int pos = theCommand->GetMethod().Search("MakeGroups");
1124     if( pos != -1) {  
1125       // 1. Remove "MakeGroups" from the Command
1126       TCollection_AsciiString aMethod = theCommand->GetMethod();
1127       int nbArgsToAdd = diffLastTwoArgsMethods.Contains(aMethod) ? 2 : 1;
1128       aMethod.Trunc(pos-1);
1129       theCommand->SetMethod(aMethod);
1130
1131       // 2. Set Mesh object instead of SMESH_MeshEditor
1132       theCommand->SetObject( myMesh );
1133
1134       // 3. And add last "True" argument
1135       while(nbArgsToAdd--)
1136         theCommand->SetArg(theCommand->GetNbArgs()+1,"True ");
1137     }
1138     else {
1139       // editor creation command is needed only if any editor function is called
1140       theGen->AddMeshAccessorMethod( theCommand ); // for *Object()
1141       if ( !myCreationCmdStr.IsEmpty() ) {
1142         GetCreationCmd()->GetString() = myCreationCmdStr;
1143         myCreationCmdStr.Clear();
1144       }
1145     }
1146   }
1147 }
1148
1149 //================================================================================
1150 /*!
1151  * \brief _pyHypothesis constructor
1152   * \param theCreationCmd - 
1153  */
1154 //================================================================================
1155
1156 _pyHypothesis::_pyHypothesis(const Handle(_pyCommand)& theCreationCmd):
1157   _pyObject( theCreationCmd )
1158 {
1159   myIsAlgo = myIsWrapped = /*myIsConverted = myIsLocal = myDim = */false;
1160 }
1161
1162 //================================================================================
1163 /*!
1164  * \brief Creates algorithm or hypothesis
1165   * \param theCreationCmd - The engine command creating a hypothesis
1166   * \retval Handle(_pyHypothesis) - Result _pyHypothesis
1167  */
1168 //================================================================================
1169
1170 Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& theCreationCmd)
1171 {
1172   // theCreationCmd: CreateHypothesis( "theHypType", "theLibName" )
1173   ASSERT (( theCreationCmd->GetMethod() == "CreateHypothesis"));
1174
1175   Handle(_pyHypothesis) hyp, algo;
1176
1177   // "theHypType"
1178   const TCollection_AsciiString & hypTypeQuoted = theCreationCmd->GetArg( 1 );
1179   if ( hypTypeQuoted.IsEmpty() )
1180     return hyp;
1181   // theHypType
1182   TCollection_AsciiString  hypType =
1183     hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
1184
1185   algo = new _pyAlgorithm( theCreationCmd );
1186   hyp  = new _pyHypothesis( theCreationCmd );
1187
1188   // 1D Regular_1D ----------
1189   if ( hypType == "Regular_1D" ) {
1190     // set mesh's method creating algo,
1191     // i.e. convertion result will be "regular1d = Mesh.Segment()",
1192     // and set hypType by which algo creating a hypothesis is searched for
1193     algo->SetConvMethodAndType("Segment", hypType.ToCString());
1194   }
1195   else if ( hypType == "CompositeSegment_1D" ) {
1196     algo->SetConvMethodAndType("Segment", "Regular_1D");
1197     algo->myArgs.Append( "algo=smesh.COMPOSITE");
1198   }
1199   else if ( hypType == "LocalLength" ) {
1200     // set algo's method creating hyp, and algo type
1201     hyp->SetConvMethodAndType( "LocalLength", "Regular_1D");
1202     // set method whose 1 arg will become the 1-st arg of hyp creation command
1203     // i.e. convertion result will be "locallength = regular1d.LocalLength(<arg of SetLength()>)"
1204     hyp->AddArgMethod( "SetLength" );
1205   }
1206   else if ( hypType == "MaxLength" ) {
1207     // set algo's method creating hyp, and algo type
1208     hyp->SetConvMethodAndType( "MaxSize", "Regular_1D");
1209     // set method whose 1 arg will become the 1-st arg of hyp creation command
1210     // i.e. convertion result will be "maxsize = regular1d.MaxSize(<arg of SetLength()>)"
1211     hyp->AddArgMethod( "SetLength" );
1212   }
1213   else if ( hypType == "NumberOfSegments" ) {
1214     hyp = new _pyNumberOfSegmentsHyp( theCreationCmd );
1215     hyp->SetConvMethodAndType( "NumberOfSegments", "Regular_1D");
1216     // arg of SetNumberOfSegments() will become the 1-st arg of hyp creation command
1217     hyp->AddArgMethod( "SetNumberOfSegments" );
1218     // arg of SetScaleFactor() will become the 2-nd arg of hyp creation command
1219     hyp->AddArgMethod( "SetScaleFactor" );
1220   }
1221   else if ( hypType == "Arithmetic1D" ) {
1222     hyp = new _pyComplexParamHypo( theCreationCmd );
1223     hyp->SetConvMethodAndType( "Arithmetic1D", "Regular_1D");
1224   }
1225   else if ( hypType == "StartEndLength" ) {
1226     hyp = new _pyComplexParamHypo( theCreationCmd );
1227     hyp->SetConvMethodAndType( "StartEndLength", "Regular_1D");
1228   }
1229   else if ( hypType == "Deflection1D" ) {
1230     hyp->SetConvMethodAndType( "Deflection1D", "Regular_1D");
1231     hyp->AddArgMethod( "SetDeflection" );
1232   }
1233   else if ( hypType == "Propagation" ) {
1234     hyp->SetConvMethodAndType( "Propagation", "Regular_1D");
1235   }
1236   else if ( hypType == "QuadraticMesh" ) {
1237     hyp->SetConvMethodAndType( "QuadraticMesh", "Regular_1D");
1238   }
1239   else if ( hypType == "AutomaticLength" ) {
1240     hyp->SetConvMethodAndType( "AutomaticLength", "Regular_1D");
1241     hyp->AddArgMethod( "SetFineness");
1242   }
1243   else if ( hypType == "SegmentLengthAroundVertex" ) {
1244     hyp = new _pySegmentLengthAroundVertexHyp( theCreationCmd );
1245     hyp->SetConvMethodAndType( "LengthNearVertex", "Regular_1D" );
1246     hyp->AddArgMethod( "SetLength" );
1247   }
1248   // 1D Python_1D ----------
1249   else if ( hypType == "Python_1D" ) {
1250     algo->SetConvMethodAndType( "Segment", hypType.ToCString());
1251     algo->myArgs.Append( "algo=smesh.PYTHON");
1252   }
1253   else if ( hypType == "PythonSplit1D" ) {
1254     hyp->SetConvMethodAndType( "PythonSplit1D", "Python_1D");
1255     hyp->AddArgMethod( "SetNumberOfSegments");
1256     hyp->AddArgMethod( "SetPythonLog10RatioFunction");
1257   }
1258   // MEFISTO_2D ----------
1259   else if ( hypType == "MEFISTO_2D" ) { // MEFISTO_2D
1260     algo->SetConvMethodAndType( "Triangle", hypType.ToCString());
1261   }
1262   else if ( hypType == "MaxElementArea" ) {
1263     hyp->SetConvMethodAndType( "MaxElementArea", "MEFISTO_2D");
1264     hyp->SetConvMethodAndType( "MaxElementArea", "NETGEN_2D_ONLY");
1265     hyp->AddArgMethod( "SetMaxElementArea");
1266   }
1267   else if ( hypType == "LengthFromEdges" ) {
1268     hyp->SetConvMethodAndType( "LengthFromEdges", "MEFISTO_2D");
1269     hyp->SetConvMethodAndType( "LengthFromEdges", "NETGEN_2D_ONLY");
1270   }
1271   // Quadrangle_2D ----------
1272   else if ( hypType == "Quadrangle_2D" ) {
1273     algo->SetConvMethodAndType( "Quadrangle" , hypType.ToCString());
1274   }
1275   else if ( hypType == "QuadranglePreference" ) {
1276     hyp->SetConvMethodAndType( "QuadranglePreference", "Quadrangle_2D");
1277     hyp->SetConvMethodAndType( "QuadranglePreference", "NETGEN_2D_ONLY");
1278   }
1279   else if ( hypType == "TrianglePreference" ) {
1280     hyp->SetConvMethodAndType( "TrianglePreference", "Quadrangle_2D");
1281   }     
1282   // NETGEN ----------
1283 //   else if ( hypType == "NETGEN_2D") { // 1D-2D
1284 //     algo->SetConvMethodAndType( "Triangle" , hypType.ToCString());
1285 //     algo->myArgs.Append( "algo=smesh.NETGEN" );
1286 //   }
1287   else if ( hypType == "NETGEN_2D_ONLY") { // 2D
1288     algo->SetConvMethodAndType( "Triangle" , hypType.ToCString());
1289     algo->myArgs.Append( "algo=smesh.NETGEN_2D" );
1290   }
1291   else if ( hypType == "NETGEN_3D") { // 3D
1292     algo->SetConvMethodAndType( "Tetrahedron" , hypType.ToCString());
1293     algo->myArgs.Append( "algo=smesh.NETGEN" );
1294   }
1295   else if ( hypType == "MaxElementVolume") {
1296     hyp->SetConvMethodAndType( "MaxElementVolume", "NETGEN_3D");
1297     hyp->AddArgMethod( "SetMaxElementVolume" );
1298   }
1299   // GHS3D_3D ----------
1300   else if ( hypType == "GHS3D_3D" ) {
1301     algo->SetConvMethodAndType( "Tetrahedron", hypType.ToCString());
1302     algo->myArgs.Append( "algo=smesh.GHS3D" );
1303   }
1304   // Hexa_3D ---------
1305   else if ( hypType == "Hexa_3D" ) {
1306     algo->SetConvMethodAndType( "Hexahedron", hypType.ToCString());
1307   }
1308   // Repetitive Projection_1D ---------
1309   else if ( hypType == "Projection_1D" ) {
1310     algo->SetConvMethodAndType( "Projection1D", hypType.ToCString());
1311   }
1312   else if ( hypType == "ProjectionSource1D" ) {
1313     hyp->SetConvMethodAndType( "SourceEdge", "Projection_1D");
1314     hyp->AddArgMethod( "SetSourceEdge");
1315     hyp->AddArgMethod( "SetSourceMesh");
1316     // 2 args of SetVertexAssociation() will become the 3-th and 4-th args of hyp creation command
1317     hyp->AddArgMethod( "SetVertexAssociation", 2 );
1318   }
1319   // Projection_2D ---------
1320   else if ( hypType == "Projection_2D" ) {
1321     algo->SetConvMethodAndType( "Projection2D", hypType.ToCString());
1322   }
1323   else if ( hypType == "ProjectionSource2D" ) {
1324     hyp->SetConvMethodAndType( "SourceFace", "Projection_2D");
1325     hyp->AddArgMethod( "SetSourceFace");
1326     hyp->AddArgMethod( "SetSourceMesh");
1327     hyp->AddArgMethod( "SetVertexAssociation", 4 );
1328   }
1329   // Projection_3D ---------
1330   else if ( hypType == "Projection_3D" ) {
1331     algo->SetConvMethodAndType( "Projection3D", hypType.ToCString());
1332   }
1333   else if ( hypType == "ProjectionSource3D" ) {
1334     hyp->SetConvMethodAndType( "SourceShape3D", "Projection_3D");
1335     hyp->AddArgMethod( "SetSource3DShape");
1336     hyp->AddArgMethod( "SetSourceMesh");
1337     hyp->AddArgMethod( "SetVertexAssociation", 4 );
1338   }
1339   // Prism_3D ---------
1340   else if ( hypType == "Prism_3D" ) {
1341     algo->SetConvMethodAndType( "Prism", hypType.ToCString());
1342   }
1343   // RadialPrism_3D ---------
1344   else if ( hypType == "RadialPrism_3D" ) {
1345     algo->SetConvMethodAndType( "Prism", hypType.ToCString());
1346   }
1347   else if ( hypType == "NumberOfLayers" ) {
1348     hyp->SetConvMethodAndType( "NumberOfLayers", "RadialPrism_3D");
1349     hyp->AddArgMethod( "SetNumberOfLayers" );
1350   }
1351   else if ( hypType == "LayerDistribution" ) {
1352     hyp = new _pyLayerDistributionHypo( theCreationCmd );
1353     hyp->SetConvMethodAndType( "LayerDistribution", "RadialPrism_3D");
1354   }
1355
1356   if ( algo->IsValid() ) {
1357     return algo;
1358   }
1359   return hyp;
1360 }
1361
1362 //================================================================================
1363 /*!
1364  * \brief Convert the command adding a hypothesis to mesh into a smesh command
1365   * \param theCmd - The command like mesh.AddHypothesis( geom, hypo )
1366   * \param theAlgo - The algo that can create this hypo
1367   * \retval bool - false if the command cant be converted
1368  */
1369 //================================================================================
1370
1371 bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd,
1372                                        const _pyID&              theMesh)
1373 {
1374   ASSERT(( theCmd->GetMethod() == "AddHypothesis" ));
1375
1376   if ( !IsWrappable( theMesh ))
1377     return false;
1378
1379   myGeom = theCmd->GetArg( 1 );
1380
1381   Handle(_pyHypothesis) algo;
1382   if ( !IsAlgo() ) {
1383     // find algo created on myGeom in theMesh
1384     algo = theGen->FindAlgo( myGeom, theMesh, this );
1385     if ( algo.IsNull() )
1386       return false;
1387     // attach hypothesis creation command to be after algo creation command
1388     // because it can be new created instance of algorithm
1389     algo->GetCreationCmd()->AddDependantCmd( theCmd );
1390   }
1391   myIsWrapped = true;
1392
1393   // mesh.AddHypothesis(geom,hyp) --> hyp = <theMesh or algo>.myCreationMethod(args)
1394   theCmd->SetResultValue( GetID() );
1395   theCmd->SetObject( IsAlgo() ? theMesh : algo->GetID());
1396   theCmd->SetMethod( IsAlgo() ? GetAlgoCreationMethod() : GetCreationMethod( algo->GetAlgoType() ));
1397   // set args
1398   theCmd->RemoveArgs();
1399   for ( int i = 1; i <= myArgs.Length(); ++i ) {
1400     if ( !myArgs( i ).IsEmpty() )
1401       theCmd->SetArg( i, myArgs( i ));
1402     else
1403       theCmd->SetArg( i, "[]");
1404   }
1405   // set a new creation command
1406   GetCreationCmd()->Clear();
1407   // replace creation command by wrapped instance
1408   // please note, that hypothesis attaches to algo creation command (see upper)
1409   SetCreationCmd( theCmd );
1410   
1411
1412   // clear commands setting arg values
1413   list < Handle(_pyCommand) >::iterator argCmd = myArgCommands.begin();
1414   for ( ; argCmd != myArgCommands.end(); ++argCmd )
1415     (*argCmd)->Clear();
1416
1417   // set unknown arg commands after hypo creation
1418   Handle(_pyCommand) afterCmd = myIsWrapped ? theCmd : GetCreationCmd();
1419   list<Handle(_pyCommand)>::iterator cmd = myUnknownCommands.begin();
1420   for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
1421     afterCmd->AddDependantCmd( *cmd );
1422   }
1423
1424   return myIsWrapped;
1425 }
1426
1427 //================================================================================
1428 /*!
1429  * \brief Remember hypothesis parameter values
1430  * \param theCommand - The called hypothesis method
1431  */
1432 //================================================================================
1433
1434 void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand)
1435 {
1436   ASSERT( !myIsAlgo );
1437   // set args
1438   int nbArgs = 0;
1439   for ( int i = 1; i <= myArgMethods.Length(); ++i ) {
1440     if ( myArgMethods( i ) == theCommand->GetMethod() ) {
1441       while ( myArgs.Length() < nbArgs + myNbArgsByMethod( i ))
1442         myArgs.Append( "[]" );
1443       for ( int iArg = 1; iArg <= myNbArgsByMethod( i ); ++iArg )
1444         myArgs( nbArgs + iArg ) = theCommand->GetArg( iArg ); // arg value
1445       myArgCommands.push_back( theCommand );
1446       return;
1447     }
1448     nbArgs += myNbArgsByMethod( i );
1449   }
1450   myUnknownCommands.push_back( theCommand );
1451 }
1452
1453 //================================================================================
1454 /*!
1455  * \brief Finish conversion
1456  */
1457 //================================================================================
1458
1459 void _pyHypothesis::Flush()
1460 {
1461   if ( IsWrapped() ) {
1462   }
1463   else {
1464     list < Handle(_pyCommand) >::iterator cmd = myArgCommands.begin();
1465     for ( ; cmd != myArgCommands.end(); ++cmd ) {
1466       // Add access to a wrapped mesh
1467       theGen->AddMeshAccessorMethod( *cmd );
1468       // Add access to a wrapped algorithm
1469       theGen->AddAlgoAccessorMethod( *cmd );
1470     }
1471     cmd = myUnknownCommands.begin();
1472     for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
1473       // Add access to a wrapped mesh
1474       theGen->AddMeshAccessorMethod( *cmd );
1475       // Add access to a wrapped algorithm
1476       theGen->AddAlgoAccessorMethod( *cmd );
1477     }
1478   }
1479   // forget previous hypothesis modifications
1480   myArgCommands.clear();
1481   myUnknownCommands.clear();
1482 }
1483
1484 //================================================================================
1485 /*!
1486  * \brief clear creation, arg and unkown commands
1487  */
1488 //================================================================================
1489
1490 void _pyHypothesis::ClearAllCommands()
1491 {
1492   GetCreationCmd()->Clear();
1493   list<Handle(_pyCommand)>::iterator cmd = myArgCommands.begin();
1494   for ( ; cmd != myArgCommands.end(); ++cmd )
1495     ( *cmd )->Clear();
1496   cmd = myUnknownCommands.begin();
1497   for ( ; cmd != myUnknownCommands.end(); ++cmd )
1498     ( *cmd )->Clear();
1499 }
1500
1501
1502 //================================================================================
1503 /*!
1504  * \brief Assign fields of theOther to me except myIsWrapped
1505  */
1506 //================================================================================
1507
1508 void _pyHypothesis::Assign( const Handle(_pyHypothesis)& theOther,
1509                             const _pyID&                 theMesh )
1510 {
1511   myIsWrapped = false;
1512   myMesh = theMesh;
1513
1514   // myCreationCmd = theOther->myCreationCmd;
1515   myIsAlgo = theOther->myIsAlgo;
1516   myGeom = theOther->myGeom;
1517   myType2CreationMethod = theOther->myType2CreationMethod;
1518   myArgs = theOther->myArgs;
1519   myArgMethods = theOther->myArgMethods;
1520   myNbArgsByMethod = theOther->myNbArgsByMethod;
1521   myArgCommands = theOther->myArgCommands;
1522   myUnknownCommands = theOther->myUnknownCommands;
1523 }
1524
1525 //================================================================================
1526 /*!
1527  * \brief Remember hypothesis parameter values
1528   * \param theCommand - The called hypothesis method
1529  */
1530 //================================================================================
1531
1532 void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
1533 {
1534   // ex: hyp.SetLength(start, 1)
1535   //     hyp.SetLength(end,   0)
1536   ASSERT(( theCommand->GetMethod() == "SetLength" ));
1537   ASSERT(( theCommand->GetArg( 2 ).IsIntegerValue() ));
1538   int i = 2 - theCommand->GetArg( 2 ).IntegerValue();
1539   while ( myArgs.Length() < i )
1540     myArgs.Append( "[]" );
1541   myArgs( i ) = theCommand->GetArg( 1 ); // arg value
1542   myArgCommands.push_back( theCommand );
1543 }
1544
1545 //================================================================================
1546 /*!
1547  * \brief Convert methods of 1D hypotheses to my own methods
1548   * \param theCommand - The called hypothesis method
1549  */
1550 //================================================================================
1551
1552 void _pyLayerDistributionHypo::Process( const Handle(_pyCommand)& theCommand)
1553 {
1554   if ( theCommand->GetMethod() != "SetLayerDistribution" )
1555     return;
1556
1557   _pyID newName; // name for 1D hyp = "HypType" + "_Distribution"
1558
1559   const _pyID& hyp1dID = theCommand->GetArg( 1 );
1560   Handle(_pyHypothesis) hyp1d = theGen->FindHyp( hyp1dID );
1561   if ( hyp1d.IsNull() ) // apparently hypId changed at study restoration
1562     hyp1d = my1dHyp;
1563   else if ( !my1dHyp.IsNull() && hyp1dID != my1dHyp->GetID() ) {
1564     // 1D hypo is already set, so distribution changes and the old
1565     // 1D hypo is thrown away
1566     my1dHyp->ClearAllCommands();
1567   }
1568   my1dHyp = hyp1d;
1569   if ( my1dHyp.IsNull() )
1570     return; // something wrong :(
1571
1572   // make a new name for 1D hyp = "HypType" + "_Distribution"
1573   if ( my1dHyp->GetCreationCmd()->GetMethod() == "CreateHypothesis" ) {
1574     // not yet converted creation cmd
1575     TCollection_AsciiString hypTypeQuoted = my1dHyp->GetCreationCmd()->GetArg(1);
1576     TCollection_AsciiString hypType = hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
1577     newName = hypType + "_Distribution";
1578     my1dHyp->GetCreationCmd()->SetResultValue( newName );
1579   }
1580   else {
1581     // already converted creation cmd
1582     newName = my1dHyp->GetCreationCmd()->GetResultValue();
1583   }
1584
1585   // as creation of 1D hyp was written later then it's edition,
1586   // we need to find all it's edition calls and process them
1587   list< Handle(_pyCommand) >& cmds = theGen->GetCommands();
1588   list< Handle(_pyCommand) >::iterator cmdIt = cmds.begin();
1589   for ( ; cmdIt != cmds.end(); ++cmdIt ) {
1590     const _pyID& objID = (*cmdIt)->GetObject();
1591     if ( objID == hyp1dID ) {
1592       my1dHyp->Process( *cmdIt );
1593       my1dHyp->GetCreationCmd()->AddDependantCmd( *cmdIt );
1594       ( *cmdIt )->SetObject( newName );
1595     }
1596   }
1597   if ( !myArgCommands.empty() )
1598     myArgCommands.front()->Clear();
1599   theCommand->SetArg( 1, newName );
1600   myArgCommands.push_back( theCommand );
1601   // copy hyp1d's creation method and args
1602 //   myCreationMethod = hyp1d->GetCreationMethod();
1603 //   myArgs           = hyp1d->GetArgs();
1604 //   // make them cleared at conversion
1605 //   myArgCommands = hyp1d->GetArgCommands();
1606
1607 //   // to be cleared at convertion only
1608 //   myArgCommands.push_back( theCommand );
1609 }
1610
1611 //================================================================================
1612 /*!
1613  * \brief 
1614   * \param theAdditionCmd - command to be converted
1615   * \param theMesh - mesh instance
1616   * \retval bool - status
1617  */
1618 //================================================================================
1619
1620 bool _pyLayerDistributionHypo::Addition2Creation( const Handle(_pyCommand)& theAdditionCmd,
1621                                                   const _pyID&              theMesh)
1622 {
1623   myIsWrapped = false;
1624
1625   if ( my1dHyp.IsNull() )
1626     return false;
1627
1628   // set "SetLayerDistribution()" after addition cmd
1629   theAdditionCmd->AddDependantCmd( myArgCommands.front() );
1630
1631   _pyID geom = theAdditionCmd->GetArg( 1 );
1632
1633   my1dHyp->SetMesh( theMesh );
1634   if ( !my1dHyp->Addition2Creation( theAdditionCmd, theMesh ))
1635     return false;
1636
1637   // clear "SetLayerDistribution()" cmd
1638   myArgCommands.front()->Clear();
1639
1640   // Convert my creation => me = RadialPrismAlgo.Get3DHypothesis()
1641
1642   // find RadialPrism algo created on <geom> for theMesh
1643   Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMesh, this );
1644   if ( !algo.IsNull() ) {
1645     GetCreationCmd()->SetObject( algo->GetID() );
1646     GetCreationCmd()->SetMethod( "Get3DHypothesis" );
1647     GetCreationCmd()->RemoveArgs();
1648     theAdditionCmd->AddDependantCmd( GetCreationCmd() );
1649     myIsWrapped = true;
1650   }
1651   return myIsWrapped;
1652 }
1653
1654 //================================================================================
1655 /*!
1656  * \brief 
1657  */
1658 //================================================================================
1659
1660 void _pyLayerDistributionHypo::Flush()
1661 {
1662   //my1dHyp.Nullify();
1663   //_pyHypothesis::Flush();
1664 }
1665
1666 //================================================================================
1667 /*!
1668  * \brief additionally to Addition2Creation, clears SetDistrType() command
1669   * \param theCmd - AddHypothesis() command
1670   * \param theMesh - mesh to which a hypothesis is added
1671   * \retval bool - convertion result
1672  */
1673 //================================================================================
1674
1675 bool _pyNumberOfSegmentsHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
1676                                                 const _pyID&              theMesh)
1677 {
1678   if ( IsWrappable( theMesh ) && myArgs.Length() > 1 ) {
1679     // scale factor (2-nd arg) is provided: clear SetDistrType(1) command
1680     bool scaleDistrType = false;
1681     list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
1682     for ( ; cmd != myUnknownCommands.rend(); ++cmd ) {
1683       if ( (*cmd)->GetMethod() == "SetDistrType" ) {
1684         if ( (*cmd)->GetArg( 1 ) == "1" ) {
1685           scaleDistrType = true;
1686           (*cmd)->Clear();
1687         }
1688         else if ( !scaleDistrType ) {
1689           // distribution type changed: remove scale factor from args
1690           myArgs.Remove( 2, myArgs.Length() );
1691           break;
1692         }
1693       }
1694     }
1695   }
1696   return _pyHypothesis::Addition2Creation( theCmd, theMesh );
1697 }
1698
1699 //================================================================================
1700 /*!
1701  * \brief remove repeated commands defining distribution
1702  */
1703 //================================================================================
1704
1705 void _pyNumberOfSegmentsHyp::Flush()
1706 {
1707   // find number of the last SetDistrType() command
1708   list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
1709   int distrTypeNb = 0;
1710   for ( ; !distrTypeNb && cmd != myUnknownCommands.rend(); ++cmd )
1711     if ( (*cmd)->GetMethod() == "SetDistrType" )
1712       distrTypeNb = (*cmd)->GetOrderNb();
1713
1714   // clear commands before the last SetDistrType()
1715   list<Handle(_pyCommand)> * cmds[2] = { &myArgCommands, &myUnknownCommands };
1716   for ( int i = 0; i < 2; ++i ) {
1717     set<TCollection_AsciiString> uniqueMethods;
1718     list<Handle(_pyCommand)> & cmdList = *cmds[i];
1719     for ( cmd = cmdList.rbegin(); cmd != cmdList.rend(); ++cmd )
1720     {
1721       bool clear = ( (*cmd)->GetOrderNb() < distrTypeNb );
1722       const TCollection_AsciiString& method = (*cmd)->GetMethod();
1723       if ( !clear || method == "SetNumberOfSegments" ) {
1724         bool isNewInSet = uniqueMethods.insert( method ).second;
1725         clear = !isNewInSet;
1726       }
1727       if ( clear )
1728         (*cmd)->Clear();
1729     }
1730     cmdList.clear();
1731   }
1732 }
1733
1734 //================================================================================
1735 /*!
1736  * \brief Convert the command adding "SegmentLengthAroundVertex" to mesh
1737  * into regular1D.LengthNearVertex( length, vertex )
1738   * \param theCmd - The command like mesh.AddHypothesis( vertex, SegmentLengthAroundVertex )
1739   * \param theMesh - The mesh needing this hypo
1740   * \retval bool - false if the command cant be converted
1741  */
1742 //================================================================================
1743   
1744 bool _pySegmentLengthAroundVertexHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
1745                                                          const _pyID&              theMeshID)
1746 {
1747   if ( IsWrappable( theMeshID )) {
1748
1749     _pyID vertex = theCmd->GetArg( 1 );
1750
1751     // the problem here is that segment algo will not be found
1752     // by pyHypothesis::Addition2Creation() for <vertex>, so we try to find
1753     // geometry where segment algorithm is assigned
1754     Handle(_pyHypothesis) algo;
1755     _pyID geom = vertex;
1756     while ( algo.IsNull() && !geom.IsEmpty()) {
1757       // try to find geom as a father of <vertex>
1758       geom = FatherID( geom );
1759       algo = theGen->FindAlgo( geom, theMeshID, this );
1760     }
1761     if ( algo.IsNull() )
1762       return false; // also possible to find geom as brother of veretex...
1763     // set geom instead of vertex
1764     theCmd->SetArg( 1, geom );
1765
1766     // set vertex as a second arg
1767     if ( myArgs.Length() < 1) myArgs.Append( "1" ); // :(
1768     myArgs.Append( vertex );
1769
1770     // mesh.AddHypothesis(vertex, SegmentLengthAroundVertex) -->
1771     // theMeshID.LengthNearVertex( length, vertex )
1772     return _pyHypothesis::Addition2Creation( theCmd, theMeshID );
1773   }
1774   return false;
1775 }
1776
1777 //================================================================================
1778 /*!
1779  * \brief _pyAlgorithm constructor
1780  * \param theCreationCmd - The command like "algo = smeshgen.CreateHypothesis(type,lib)"
1781  */
1782 //================================================================================
1783
1784 _pyAlgorithm::_pyAlgorithm(const Handle(_pyCommand)& theCreationCmd)
1785   : _pyHypothesis( theCreationCmd )
1786 {
1787   myIsAlgo = true;
1788 }
1789
1790 //================================================================================
1791 /*!
1792  * \brief Convert the command adding an algorithm to mesh
1793   * \param theCmd - The command like mesh.AddHypothesis( geom, algo )
1794   * \param theMesh - The mesh needing this algo 
1795   * \retval bool - false if the command cant be converted
1796  */
1797 //================================================================================
1798   
1799 bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd,
1800                                       const _pyID&              theMeshID)
1801 {
1802   // mesh.AddHypothesis(geom,algo) --> theMeshID.myCreationMethod()
1803   if ( _pyHypothesis::Addition2Creation( theCmd, theMeshID )) {
1804     theGen->SetAccessorMethod( GetID(), "GetAlgorithm()" );
1805     return true;
1806   }
1807   return false;
1808 }
1809
1810 //================================================================================
1811 /*!
1812  * \brief Return starting position of a part of python command
1813   * \param thePartIndex - The index of command part
1814   * \retval int - Part position
1815  */
1816 //================================================================================
1817
1818 int _pyCommand::GetBegPos( int thePartIndex )
1819 {
1820   if ( IsEmpty() )
1821     return EMPTY;
1822   if ( myBegPos.Length() < thePartIndex )
1823     return UNKNOWN;
1824   return myBegPos( thePartIndex );
1825 }
1826
1827 //================================================================================
1828 /*!
1829  * \brief Store starting position of a part of python command
1830   * \param thePartIndex - The index of command part
1831   * \param thePosition - Part position
1832  */
1833 //================================================================================
1834
1835 void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
1836 {
1837   while ( myBegPos.Length() < thePartIndex )
1838     myBegPos.Append( UNKNOWN );
1839   myBegPos( thePartIndex ) = thePosition;
1840 }
1841
1842 //================================================================================
1843 /*!
1844  * \brief Returns whitespace symbols at the line beginning
1845   * \retval TCollection_AsciiString - result
1846  */
1847 //================================================================================
1848
1849 TCollection_AsciiString _pyCommand::GetIndentation()
1850 {
1851   int end = 1;
1852   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
1853     GetWord( myString, end, true );
1854   else
1855     end = GetBegPos( RESULT_IND );
1856   return myString.SubString( 1, end - 1 );
1857 }
1858
1859 //================================================================================
1860 /*!
1861  * \brief Return substring of python command looking like ResultValue = Obj.Meth()
1862   * \retval const TCollection_AsciiString & - ResultValue substring
1863  */
1864 //================================================================================
1865
1866 const TCollection_AsciiString & _pyCommand::GetResultValue()
1867 {
1868   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
1869   {
1870     int begPos = myString.Location( "=", 1, Length() );
1871     if ( begPos )
1872       myRes = GetWord( myString, begPos, false );
1873     else
1874       begPos = EMPTY;
1875     SetBegPos( RESULT_IND, begPos );
1876   }
1877   return myRes;
1878 }
1879
1880 //================================================================================
1881 /*!
1882  * \brief Return number of python command result value ResultValue = Obj.Meth()
1883   * \retval const int
1884  */
1885 //================================================================================
1886
1887 const int _pyCommand::GetNbResultValues()
1888 {
1889   int begPos = 1;
1890   int Nb=0;
1891   int endPos = myString.Location( "=", 1, Length() );
1892   TCollection_AsciiString str = "";
1893   while ( begPos < endPos) {
1894     str = GetWord( myString, begPos, true );
1895     begPos = begPos+ str.Length();
1896     Nb++;
1897   }
1898   return (Nb-1);
1899 }
1900
1901
1902 //================================================================================
1903 /*!
1904  * \brief Return substring of python command looking like
1905  *  ResultValue1 , ResultValue1,... = Obj.Meth() with res index
1906  * \retval const TCollection_AsciiString & - ResultValue with res index substring
1907  */
1908 //================================================================================
1909 const TCollection_AsciiString & _pyCommand::GetResultValue(int res)
1910 {
1911   int begPos = 1;
1912   int Nb=0;
1913   int endPos = myString.Location( "=", 1, Length() );
1914   while ( begPos < endPos) {
1915     myRes = GetWord( myString, begPos, true );
1916     begPos = begPos + myRes.Length();
1917     Nb++;
1918     if(res == Nb){
1919       myRes.RemoveAll('[');myRes.RemoveAll(']');
1920       return myRes;
1921     }
1922     if(Nb>res)
1923       break;
1924   }
1925   return theEmptyString;
1926 }
1927
1928 //================================================================================
1929 /*!
1930  * \brief Return substring of python command looking like ResVal = Object.Meth()
1931   * \retval const TCollection_AsciiString & - Object substring
1932  */
1933 //================================================================================
1934
1935 const TCollection_AsciiString & _pyCommand::GetObject()
1936 {
1937   if ( GetBegPos( OBJECT_IND ) == UNKNOWN )
1938   {
1939     // beginning
1940     int begPos = GetBegPos( RESULT_IND ) + myRes.Length();
1941     if ( begPos < 1 ) {
1942       begPos = myString.Location( "=", 1, Length() ) + 1;
1943       // is '=' in the string argument (for example, name) or not
1944       int nb1 = 0; // number of ' character at the left of =
1945       int nb2 = 0; // number of " character at the left of =
1946       for ( int i = 1; i < begPos-1; i++ ) {
1947         if ( IsEqual(myString.Value( i ), "'" ) )
1948           nb1 += 1;
1949         else if ( IsEqual( myString.Value( i ), '"' ) )
1950           nb2 += 1;
1951       }
1952       // if number of ' or " is not divisible by 2,
1953       // then get an object at the start of the command
1954       if ( nb1 % 2 != 0 || nb2 % 2 != 0 )
1955         begPos = 1;
1956     }
1957     // store
1958     myObj = GetWord( myString, begPos, true );
1959     SetBegPos( OBJECT_IND, begPos );
1960   }
1961   //SCRUTE(myObj);
1962   return myObj;
1963 }
1964
1965 //================================================================================
1966 /*!
1967  * \brief Return substring of python command looking like ResVal = Obj.Method()
1968   * \retval const TCollection_AsciiString & - Method substring
1969  */
1970 //================================================================================
1971
1972 const TCollection_AsciiString & _pyCommand::GetMethod()
1973 {
1974   if ( GetBegPos( METHOD_IND ) == UNKNOWN )
1975   {
1976     // beginning
1977     int begPos = GetBegPos( OBJECT_IND ) + myObj.Length();
1978     bool forward = true;
1979     if ( begPos < 1 ) {
1980       begPos = myString.Location( "(", 1, Length() ) - 1;
1981       forward = false;
1982     }
1983     // store
1984     myMeth = GetWord( myString, begPos, forward );
1985     SetBegPos( METHOD_IND, begPos );
1986   }
1987   //SCRUTE(myMeth);
1988   return myMeth;
1989 }
1990
1991 //================================================================================
1992 /*!
1993  * \brief Return substring of python command looking like ResVal = Obj.Meth(Arg1,...)
1994   * \retval const TCollection_AsciiString & - Arg<index> substring
1995  */
1996 //================================================================================
1997
1998 const TCollection_AsciiString & _pyCommand::GetArg( int index )
1999 {
2000   if ( GetBegPos( ARG1_IND ) == UNKNOWN )
2001   {
2002     // find all args
2003     int begPos = GetBegPos( METHOD_IND ) + myMeth.Length();
2004     if ( begPos < 1 )
2005       begPos = myString.Location( "(", 1, Length() ) + 1;
2006
2007     int i = 0, prevLen = 0, nbNestings = 0;
2008     while ( begPos != EMPTY ) {
2009       begPos += prevLen;
2010       if( myString.Value( begPos ) == '(' )
2011         nbNestings++;
2012       // check if we are looking at the closing parenthesis
2013       while ( begPos <= Length() && isspace( myString.Value( begPos )))
2014         ++begPos;
2015       if ( begPos > Length() )
2016         break;
2017       if ( myString.Value( begPos ) == ')' ) {
2018         nbNestings--;
2019         if( nbNestings == 0 )
2020           break;
2021       }
2022       myArgs.Append( GetWord( myString, begPos, true, true ));
2023       SetBegPos( ARG1_IND + i, begPos );
2024       prevLen = myArgs.Last().Length();
2025       if ( prevLen == 0 )
2026         myArgs.Remove( myArgs.Length() ); // no more args
2027       i++;
2028     }
2029   }
2030   if ( myArgs.Length() < index )
2031     return theEmptyString;
2032   return myArgs( index );
2033 }
2034
2035 //================================================================================
2036 /*!
2037  * \brief Check if char is a word part
2038   * \param c - The character to check
2039   * \retval bool - The check result
2040  */
2041 //================================================================================
2042
2043 static inline bool isWord(const char c, const bool dotIsWord)
2044 {
2045   return
2046     !isspace(c) && c != ',' && c != '=' && c != ')' && c != '(' && ( dotIsWord || c != '.');
2047 }
2048
2049 //================================================================================
2050 /*!
2051  * \brief Looks for a word in the string and returns word's beginning
2052   * \param theString - The input string
2053   * \param theStartPos - The position to start the search, returning word's beginning
2054   * \param theForward - The search direction
2055   * \retval TCollection_AsciiString - The found word
2056  */
2057 //================================================================================
2058
2059 TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString,
2060                                             int &      theStartPos,
2061                                             const bool theForward,
2062                                             const bool dotIsWord )
2063 {
2064   int beg = theStartPos, end = theStartPos;
2065   theStartPos = EMPTY;
2066   if ( beg < 1 || beg > theString.Length() )
2067     return theEmptyString;
2068
2069   if ( theForward ) { // search forward
2070     // beg
2071     while ( beg <= theString.Length() && !isWord( theString.Value( beg ), dotIsWord))
2072       ++beg;
2073     if ( beg > theString.Length() )
2074       return theEmptyString; // no word found
2075     // end
2076     end = beg + 1;
2077     while ( end <= theString.Length() && isWord( theString.Value( end ), dotIsWord))
2078       ++end;
2079     --end;
2080   }
2081   else {  // search backward
2082     // end
2083     while ( end > 0 && !isWord( theString.Value( end ), dotIsWord))
2084       --end;
2085     if ( end == 0 )
2086       return theEmptyString; // no word found
2087     beg = end - 1;
2088     while ( beg > 0 && isWord( theString.Value( beg ), dotIsWord))
2089       --beg;
2090     ++beg;
2091   }
2092   theStartPos = beg;
2093   //cout << theString << " ---- " << beg << " - " << end << endl;
2094   return theString.SubString( beg, end );
2095 }
2096
2097 //================================================================================
2098 /*!
2099  * \brief Look for position where not space char is
2100   * \param theString - The string 
2101   * \param thePos - The position to search from and which returns result
2102   * \retval bool - false if there are only space after thePos in theString
2103  * 
2104  * 
2105  */
2106 //================================================================================
2107
2108 bool _pyCommand::SkipSpaces( const TCollection_AsciiString & theString, int & thePos )
2109 {
2110   if ( thePos < 1 || thePos > theString.Length() )
2111     return false;
2112
2113   while ( thePos <= theString.Length() && isspace( theString.Value( thePos )))
2114     ++thePos;
2115
2116   return thePos <= theString.Length();
2117 }
2118
2119 //================================================================================
2120 /*!
2121  * \brief Modify a part of the command
2122   * \param thePartIndex - The index of the part
2123   * \param thePart - The new part string
2124   * \param theOldPart - The old part
2125  */
2126 //================================================================================
2127
2128 void _pyCommand::SetPart(int thePartIndex, const TCollection_AsciiString& thePart,
2129                         TCollection_AsciiString& theOldPart)
2130 {
2131   int pos = GetBegPos( thePartIndex );
2132   if ( pos <= Length() && theOldPart != thePart)
2133   {
2134     TCollection_AsciiString seperator;
2135     if ( pos < 1 ) {
2136       pos = GetBegPos( thePartIndex + 1 );
2137       if ( pos < 1 ) return;
2138       switch ( thePartIndex ) {
2139       case RESULT_IND: seperator = " = "; break;
2140       case OBJECT_IND: seperator = "."; break;
2141       case METHOD_IND: seperator = "()"; break;
2142       default:;
2143       }
2144     }      
2145     myString.Remove( pos, theOldPart.Length() );
2146     if ( !seperator.IsEmpty() )
2147       myString.Insert( pos , seperator );
2148     myString.Insert( pos, thePart );
2149     // update starting positions of the following parts
2150     int posDelta = thePart.Length() + seperator.Length() - theOldPart.Length();
2151     for ( int i = thePartIndex + 1; i <= myBegPos.Length(); ++i ) {
2152       if ( myBegPos( i ) > 0 )
2153         myBegPos( i ) += posDelta;
2154     }
2155     theOldPart = thePart;
2156   }
2157 }
2158
2159 //================================================================================
2160 /*!
2161  * \brief Set agrument
2162   * \param index - The argument index, it counts from 1
2163   * \param theArg - The argument string
2164  */
2165 //================================================================================
2166
2167 void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg)
2168 {
2169   FindAllArgs();
2170   int argInd = ARG1_IND + index - 1;
2171   int pos = GetBegPos( argInd );
2172   if ( pos < 1 ) // no index-th arg exist, append inexistent args
2173   {
2174     // find a closing parenthesis
2175     if ( GetNbArgs() != 0 && index <= GetNbArgs() ) {
2176       int lastArgInd = GetNbArgs();
2177       pos = GetBegPos( ARG1_IND + lastArgInd  - 1 ) + GetArg( lastArgInd ).Length();
2178       while ( pos > 0 && pos <= Length() && myString.Value( pos ) != ')' )
2179         ++pos;
2180     }
2181     else {
2182       pos = Length();
2183       while ( pos > 0 && myString.Value( pos ) != ')' )
2184         --pos;
2185     }
2186     if ( pos < 1 || myString.Value( pos ) != ')' ) { // no parentheses at all
2187       myString += "()";
2188       pos = Length();
2189     }
2190     while ( myArgs.Length() < index ) {
2191       if ( myArgs.Length() )
2192         myString.Insert( pos++, "," );
2193       myArgs.Append("None");
2194       myString.Insert( pos, myArgs.Last() );
2195       SetBegPos( ARG1_IND + myArgs.Length() - 1, pos );
2196       pos += myArgs.Last().Length();
2197     }
2198   }
2199   SetPart( argInd, theArg, myArgs( index ));
2200 }
2201
2202 //================================================================================
2203 /*!
2204  * \brief Empty arg list
2205  */
2206 //================================================================================
2207
2208 void _pyCommand::RemoveArgs()
2209 {
2210   if ( int pos = myString.Location( '(', 1, Length() ))
2211     myString.Trunc( pos );
2212   myString += ")";
2213   myArgs.Clear();
2214   if ( myBegPos.Length() >= ARG1_IND )
2215     myBegPos.Remove( ARG1_IND, myBegPos.Length() );
2216 }
2217
2218 //================================================================================
2219 /*!
2220  * \brief Set dependent commands after this one
2221  */
2222 //================================================================================
2223
2224 bool _pyCommand::SetDependentCmdsAfter() const
2225 {
2226   bool orderChanged = false;
2227   list< Handle(_pyCommand)>::const_reverse_iterator cmd = myDependentCmds.rbegin();
2228   for ( ; cmd != myDependentCmds.rend(); ++cmd ) {
2229     if ( (*cmd)->GetOrderNb() < GetOrderNb() ) {
2230       orderChanged = true;
2231       theGen->SetCommandAfter( *cmd, this );
2232       (*cmd)->SetDependentCmdsAfter();
2233     }
2234   }
2235   return orderChanged;
2236 }
2237 //================================================================================
2238 /*!
2239  * \brief Insert accessor method after theObjectID
2240   * \param theObjectID - id of the accessed object
2241   * \param theAcsMethod - name of the method giving access to the object
2242   * \retval bool - false if theObjectID is not found in the command string
2243  */
2244 //================================================================================
2245
2246 bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod )
2247 {
2248   if ( !theAcsMethod )
2249     return false;
2250   // start object search from the object, i.e. ignore result
2251   GetObject();
2252   int beg = GetBegPos( OBJECT_IND );
2253   if ( beg < 1 || beg > Length() )
2254     return false;
2255   bool added = false;
2256   while (( beg = myString.Location( theObjectID, beg, Length() )))
2257   {
2258     // check that theObjectID is not just a part of a longer ID
2259     int afterEnd = beg + theObjectID.Length();
2260     Standard_Character c = myString.Value( afterEnd );
2261     if ( !isalnum( c ) && c != ':' ) {
2262       // check if accessor method already present
2263       if ( c != '.' ||
2264            myString.Location( (char*) theAcsMethod, afterEnd, Length() ) != afterEnd+1) {
2265         // insertion
2266         int oldLen = Length();
2267         myString.Insert( afterEnd, (char*) theAcsMethod );
2268         myString.Insert( afterEnd, "." );
2269         // update starting positions of the parts following the modified one
2270         int posDelta = Length() - oldLen;
2271         for ( int i = 1; i <= myBegPos.Length(); ++i ) {
2272           if ( myBegPos( i ) > afterEnd )
2273             myBegPos( i ) += posDelta;
2274         }
2275         added = true;
2276       }
2277     }
2278     beg = afterEnd; // is a part - next search
2279   }
2280   return added;
2281 }
2282
2283 //================================================================================
2284 /*!
2285  * \brief Return method name giving access to an interaface object wrapped by python class
2286   * \retval const char* - method name
2287  */
2288 //================================================================================
2289
2290 const char* _pyObject::AccessorMethod() const
2291 {
2292   return 0;
2293 }
2294 //================================================================================
2295 /*!
2296  * \brief Return ID of a father
2297  */
2298 //================================================================================
2299
2300 _pyID _pyObject::FatherID(const _pyID & childID)
2301 {
2302   int colPos = childID.SearchFromEnd(':');
2303   if ( colPos > 0 )
2304     return childID.SubString( 1, colPos-1 );
2305   return "";
2306 }
2307
2308 //================================================================================
2309 /*!
2310  * \brief FilterManager creates only if at least one command invoked
2311  */
2312 //================================================================================
2313
2314 _pyFilterManager::_pyFilterManager(const Handle(_pyCommand)& theCreationCmd):
2315   _pyObject( theCreationCmd ),
2316   myCmdCount( 0 )
2317 {
2318 }
2319
2320 //================================================================================
2321 /*!
2322  * \brief count invoked commands
2323  */
2324 //================================================================================
2325
2326 void _pyFilterManager::Process( const Handle(_pyCommand)& /*theCommand*/)
2327 {
2328   myCmdCount++;
2329 }
2330
2331 //================================================================================
2332 /*!
2333  * \brief Clear creatin command if no commands invoked
2334  */
2335 //================================================================================
2336
2337 void _pyFilterManager::Flush()
2338 {
2339   if ( !myCmdCount )
2340     GetCreationCmd()->Clear();
2341 }
2342
2343
2344 //================================================================================
2345 /*!
2346  * \brief SubMesh creation can be moved to the end of engine commands
2347  */
2348 //================================================================================
2349
2350 _pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd):
2351   _pyObject( theCreationCmd ),
2352   myCmdCount( 0 )
2353 {
2354 }
2355
2356 //================================================================================
2357 /*!
2358  * \brief count invoked commands
2359  */
2360 //================================================================================
2361
2362 void _pySubMesh::Process( const Handle(_pyCommand)& theCommand )
2363 {
2364   myCmdCount++;
2365   GetCreationCmd()->AddDependantCmd( theCommand );
2366 }
2367
2368 //================================================================================
2369 /*!
2370  * \brief Clear creatin command if no commands invoked
2371  */
2372 //================================================================================
2373
2374 void _pySubMesh::Flush()
2375 {
2376   if ( !myCmdCount ) // move to the end of all commands
2377     theGen->GetLastCommand()->AddDependantCmd( GetCreationCmd() );
2378   else if ( !myCreator.IsNull() )
2379     // move to be just after creator
2380     myCreator->GetCreationCmd()->AddDependantCmd( GetCreationCmd() );
2381 }