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