Salome HOME
0021308: Remove hard-coded dependency of the external mesh plugins from the SMESH...
[modules/smesh.git] / src / SMESH_I / SMESH_2smeshpy.cxx
1 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
24 // File      : SMESH_2smeshpy.cxx
25 // Created   : Fri Nov 18 13:20:10 2005
26 // Author    : Edward AGAPOV (eap)
27 //
28 #include "SMESH_2smeshpy.hxx"
29
30 #include "utilities.h"
31 #include "SMESH_PythonDump.hxx"
32 #include "SMESH_NoteBook.hxx"
33 #include "SMESH_Filter_i.hxx"
34
35 #include <Resource_DataMapOfAsciiStringAsciiString.hxx>
36 #include <Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString.hxx>
37
38 #include "SMESH_Gen_i.hxx"
39 /* SALOME headers that include CORBA headers that include windows.h
40  * that defines GetObject symbol as GetObjectA should stand before SALOME headers
41  * that declare methods named GetObject - to apply the same rules of GetObject renaming
42  * and thus to avoid mess with GetObject symbol on Windows */
43
44 #include <LDOMParser.hxx>
45
46 #ifdef WNT
47 #include <windows.h>
48 #else
49 #include <unistd.h>
50 #endif
51
52
53 IMPLEMENT_STANDARD_HANDLE (_pyObject          ,Standard_Transient);
54 IMPLEMENT_STANDARD_HANDLE (_pyCommand         ,Standard_Transient);
55 IMPLEMENT_STANDARD_HANDLE (_pyHypothesisReader,Standard_Transient);
56 IMPLEMENT_STANDARD_HANDLE (_pyGen             ,_pyObject);
57 IMPLEMENT_STANDARD_HANDLE (_pyMesh            ,_pyObject);
58 IMPLEMENT_STANDARD_HANDLE (_pySubMesh         ,_pyObject);
59 IMPLEMENT_STANDARD_HANDLE (_pyMeshEditor      ,_pyObject);
60 IMPLEMENT_STANDARD_HANDLE (_pyHypothesis      ,_pyObject);
61 IMPLEMENT_STANDARD_HANDLE (_pySelfEraser      ,_pyObject);
62 IMPLEMENT_STANDARD_HANDLE (_pyGroup           ,_pyObject);
63 IMPLEMENT_STANDARD_HANDLE (_pyFilter          ,_pyObject);
64 IMPLEMENT_STANDARD_HANDLE (_pyAlgorithm       ,_pyHypothesis);
65 IMPLEMENT_STANDARD_HANDLE (_pyComplexParamHypo,_pyHypothesis);
66 IMPLEMENT_STANDARD_HANDLE (_pyNumberOfSegmentsHyp,_pyHypothesis);
67
68 IMPLEMENT_STANDARD_RTTIEXT(_pyObject          ,Standard_Transient);
69 IMPLEMENT_STANDARD_RTTIEXT(_pyCommand         ,Standard_Transient);
70 IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesisReader,Standard_Transient);
71 IMPLEMENT_STANDARD_RTTIEXT(_pyGen             ,_pyObject);
72 IMPLEMENT_STANDARD_RTTIEXT(_pyMesh            ,_pyObject);
73 IMPLEMENT_STANDARD_RTTIEXT(_pySubMesh         ,_pyObject);
74 IMPLEMENT_STANDARD_RTTIEXT(_pyMeshEditor      ,_pyObject);
75 IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis      ,_pyObject);
76 IMPLEMENT_STANDARD_RTTIEXT(_pySelfEraser      ,_pyObject);
77 IMPLEMENT_STANDARD_RTTIEXT(_pyGroup           ,_pyObject);
78 IMPLEMENT_STANDARD_RTTIEXT(_pyFilter          ,_pyObject);
79 IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm       ,_pyHypothesis);
80 IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis);
81 IMPLEMENT_STANDARD_RTTIEXT(_pyNumberOfSegmentsHyp,_pyHypothesis);
82 IMPLEMENT_STANDARD_RTTIEXT(_pyLayerDistributionHypo,_pyHypothesis);
83 IMPLEMENT_STANDARD_RTTIEXT(_pySegmentLengthAroundVertexHyp,_pyHypothesis);
84
85 using namespace std;
86 using SMESH::TPythonDump;
87
88 /*!
89  * \brief Container of commands into which the initial script is split.
90  *        It also contains data coresponding to SMESH_Gen contents
91  */
92 static Handle(_pyGen) theGen;
93
94 static TCollection_AsciiString theEmptyString;
95
96 //#define DUMP_CONVERSION
97
98 #if !defined(_DEBUG_) && defined(DUMP_CONVERSION)
99 #undef DUMP_CONVERSION
100 #endif
101
102
103 namespace {
104
105   //================================================================================
106   /*!
107    * \brief Set of TCollection_AsciiString initialized by C array of C strings
108    */
109   //================================================================================
110
111   struct TStringSet: public set<TCollection_AsciiString>
112   {
113     /*!
114      * \brief Filling. The last string must be ""
115      */
116     void Insert(const char* names[]) {
117       for ( int i = 0; names[i][0] ; ++i )
118         insert( (char*) names[i] );
119     }
120     /*!
121      * \brief Check if a string is in
122      */
123     bool Contains(const TCollection_AsciiString& name ) {
124       return find( name ) != end();
125     }
126   };
127
128   //================================================================================
129   /*!
130    * \brief Returns a mesh by object
131    */
132   //================================================================================
133
134   Handle(_pyMesh) ObjectToMesh( const Handle( _pyObject )& obj )
135   {
136     if ( !obj.IsNull() )
137     {
138       if ( obj->IsKind( STANDARD_TYPE( _pyMesh )))
139         return Handle(_pyMesh)::DownCast( obj );
140       else if ( obj->IsKind( STANDARD_TYPE( _pySubMesh )))
141         return Handle(_pySubMesh)::DownCast( obj )->GetMesh();
142       else if ( obj->IsKind( STANDARD_TYPE( _pyGroup )))
143         return Handle(_pyGroup)::DownCast( obj )->GetMesh();
144     }
145     return Handle(_pyMesh)();
146   }
147
148   //================================================================================
149   /*!
150    * \brief Check if objects used as args have been created by previous commands
151    */
152   //================================================================================
153
154   void CheckObjectPresence( const Handle(_pyCommand)& cmd, set<_pyID> & presentObjects)
155   {
156     for ( int iArg = cmd->GetNbArgs(); iArg; --iArg )
157     {
158       const _pyID& arg = cmd->GetArg( iArg );
159       if ( arg.IsEmpty() || arg.Value( 1 ) == '"' || arg.Value( 1 ) == '\'' )
160         continue;
161       list< _pyID > idList = cmd->GetStudyEntries( arg );
162       list< _pyID >::iterator id = idList.begin();
163       for ( ; id != idList.end(); ++id )
164         if ( !theGen->IsGeomObject( *id ) && !presentObjects.count( *id ))
165         {
166           cmd->Comment();
167           cmd->GetString() += " ### " ;
168           cmd->GetString() += *id + " has not been yet created";
169           return;
170         }
171     }
172     const _pyID& obj = cmd->GetObject();
173     if ( !obj.IsEmpty() && cmd->IsStudyEntry( obj ) && !presentObjects.count( obj ))
174     {
175       cmd->Comment();
176       cmd->GetString() += " ### not created object" ;
177     }
178     const _pyID& result = cmd->GetResultValue();
179     if ( result.IsEmpty() || result.Value( 1 ) == '"' || result.Value( 1 ) == '\'' )
180       return;
181     list< _pyID > idList = cmd->GetStudyEntries( result );
182     list< _pyID >::iterator id = idList.begin();
183     for ( ; id != idList.end(); ++id )
184       presentObjects.insert( *id );
185   }
186 }
187
188 //================================================================================
189 /*!
190  * \brief Convert python script using commands of smesh.py
191   * \param theScript - Input script
192   * \retval TCollection_AsciiString - Convertion result
193   * \param theToKeepAllCommands - to keep all commands or
194   *        to exclude commands relating to objects removed from study
195   *
196   * Class SMESH_2smeshpy declared in SMESH_PythonDump.hxx
197  */
198 //================================================================================
199
200 TCollection_AsciiString
201 SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString&            theScript,
202                               Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
203                               Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
204                               SALOMEDS::Study_ptr&                      theStudy,
205                               const bool                                theToKeepAllCommands)
206 {
207   theGen = new _pyGen( theEntry2AccessorMethod, theObjectNames, theStudy, theToKeepAllCommands );
208
209   // split theScript into separate commands
210
211   SMESH_NoteBook * aNoteBook = new SMESH_NoteBook();
212
213   int from = 1, end = theScript.Length(), to;
214   while ( from < end && ( to = theScript.Location( "\n", from, end )))
215   {
216     if ( to != from )
217         // cut out and store a command
218         aNoteBook->AddCommand( theScript.SubString( from, to - 1 ));
219       from = to + 1;
220   }
221
222   aNoteBook->ReplaceVariables();
223
224   TCollection_AsciiString aNoteScript = aNoteBook->GetResultScript();
225   delete aNoteBook;
226   aNoteBook = 0;
227
228   // split theScript into separate commands
229   from = 1, end = aNoteScript.Length();
230   while ( from < end && ( to = aNoteScript.Location( "\n", from, end )))
231   {
232     if ( to != from )
233       // cut out and store a command
234       theGen->AddCommand( aNoteScript.SubString( from, to - 1 ));
235     from = to + 1;
236   }
237
238   // finish conversion
239   theGen->Flush();
240 #ifdef DUMP_CONVERSION
241   MESSAGE_BEGIN ( std::endl << " ######## RESULT ######## " << std::endl<< std::endl );
242 #endif
243
244   // clean commmands of removed objects depending on myIsPublished flag
245   theGen->ClearCommands();
246
247   // reorder commands after conversion
248   list< Handle(_pyCommand) >::iterator cmd;
249   bool orderChanges;
250   do {
251     orderChanges = false;
252     for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
253       if ( (*cmd)->SetDependentCmdsAfter() )
254         orderChanges = true;
255   } while ( orderChanges );
256
257   // concat commands back into a script
258   TCollection_AsciiString aScript, aPrevCmd;
259   set<_pyID> createdObjects;
260   for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
261   {
262 #ifdef DUMP_CONVERSION
263     MESSAGE_ADD ( "## COM " << (*cmd)->GetOrderNb() << ": "<< (*cmd)->GetString() << std::endl );
264 #endif
265     if ( !(*cmd)->IsEmpty() && aPrevCmd != (*cmd)->GetString()) {
266       CheckObjectPresence( *cmd, createdObjects );
267       aPrevCmd = (*cmd)->GetString();
268       aScript += "\n";
269       aScript += aPrevCmd;
270     }
271   }
272   aScript += "\n";
273
274   theGen->Free();
275   theGen.Nullify();
276
277   return aScript;
278 }
279
280 //================================================================================
281 /*!
282  * \brief _pyGen constructor
283  */
284 //================================================================================
285
286 _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod,
287                Resource_DataMapOfAsciiStringAsciiString& theObjectNames,
288                SALOMEDS::Study_ptr&                      theStudy,
289                const bool                                theToKeepAllCommands)
290   : _pyObject( new _pyCommand( "", 0 )),
291     myNbCommands( 0 ),
292     myID2AccessorMethod( theEntry2AccessorMethod ),
293     myObjectNames( theObjectNames ),
294     myNbFilters( 0 ),
295     myToKeepAllCommands( theToKeepAllCommands ),
296     myStudy( SALOMEDS::Study::_duplicate( theStudy )),
297     myGeomIDNb(0), myGeomIDIndex(-1)
298 {
299   // make that GetID() to return TPythonDump::SMESHGenName()
300   GetCreationCmd()->Clear();
301   GetCreationCmd()->GetString() = TPythonDump::SMESHGenName();
302   GetCreationCmd()->GetString() += "=";
303
304   // Find 1st digit of study entry by which a GEOM object differs from a SMESH object
305   if ( !theObjectNames.IsEmpty() && !CORBA::is_nil( theStudy ))
306   {
307     // find a GEOM entry
308     _pyID geomID;
309     SALOMEDS::SComponent_var geomComp = theStudy->FindComponent("GEOM");
310     if ( geomComp->_is_nil() ) return;
311     CORBA::String_var entry = geomComp->GetID();
312     geomID = entry.in();
313
314     // find a SMESH entry
315     _pyID smeshID;
316     Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString e2n( theObjectNames );
317     for ( ; e2n.More() && smeshID.IsEmpty(); e2n.Next() )
318       if ( _pyCommand::IsStudyEntry( e2n.Key() ))
319         smeshID = e2n.Key();
320
321     // find 1st difference between smeshID and geomID
322     if ( !geomID.IsEmpty() && !smeshID.IsEmpty() )
323       for ( int i = 1; i <= geomID.Length() && i <= smeshID.Length(); ++i )
324         if ( geomID.Value( i ) != smeshID.Value( i ))
325         {
326           myGeomIDNb = geomID.Value( i );
327           myGeomIDIndex = i;
328         }
329   }
330 }
331
332 //================================================================================
333 /*!
334  * \brief name of SMESH_Gen in smesh.py
335  */
336 //================================================================================
337
338 const char* _pyGen::AccessorMethod() const
339 {
340   return SMESH_2smeshpy::GenName();
341 }
342
343 //================================================================================
344 /*!
345  * \brief Convert a command using a specific converter
346   * \param theCommand - the command to convert
347  */
348 //================================================================================
349
350 Handle(_pyCommand) _pyGen::AddCommand( const TCollection_AsciiString& theCommand)
351 {
352   // store theCommand in the sequence
353   myCommands.push_back( new _pyCommand( theCommand, ++myNbCommands ));
354
355   Handle(_pyCommand) aCommand = myCommands.back();
356 #ifdef DUMP_CONVERSION
357   MESSAGE ( "## COM " << myNbCommands << ": "<< aCommand->GetString() );
358 #endif
359
360   const _pyID& objID = aCommand->GetObject();
361
362   if ( objID.IsEmpty() )
363     return aCommand;
364
365   // Find an object to process theCommand
366
367   // SMESH_Gen method?
368   if ( objID == this->GetID() || objID == SMESH_2smeshpy::GenName())
369   {
370     this->Process( aCommand );
371     return aCommand;
372   }
373
374   // SMESH_Mesh method?
375   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( objID );
376   if ( id_mesh != myMeshes.end() )
377   {
378     //id_mesh->second->AddProcessedCmd( aCommand );
379
380     // check for mesh editor object
381     if ( aCommand->GetMethod() == "GetMeshEditor" ) { // MeshEditor creation
382       _pyID editorID = aCommand->GetResultValue();
383       Handle(_pyMeshEditor) editor = new _pyMeshEditor( aCommand );
384       myMeshEditors.insert( make_pair( editorID, editor ));
385       return aCommand;
386     }
387     // check for SubMesh objects
388     else if ( aCommand->GetMethod() == "GetSubMesh" ) { // SubMesh creation
389       _pyID subMeshID = aCommand->GetResultValue();
390       Handle(_pySubMesh) subMesh = new _pySubMesh( aCommand );
391       myObjects.insert( make_pair( subMeshID, subMesh ));
392     }
393
394     id_mesh->second->Process( aCommand );
395     id_mesh->second->AddProcessedCmd( aCommand );
396     return aCommand;
397   }
398
399   // SMESH_MeshEditor method?
400   map< _pyID, Handle(_pyMeshEditor) >::iterator id_editor = myMeshEditors.find( objID );
401   if ( id_editor != myMeshEditors.end() )
402   {
403     const TCollection_AsciiString& method = aCommand->GetMethod();
404
405     // some commands of SMESH_MeshEditor create meshes and groups
406     _pyID meshID, groups;
407     if ( method.Search("MakeMesh") != -1 )
408       meshID = aCommand->GetResultValue();
409     else if ( method == "MakeBoundaryMesh")
410       meshID = aCommand->GetResultValue(1);
411     else if ( method == "MakeBoundaryElements")
412       meshID = aCommand->GetResultValue(2);
413
414     if ( method.Search("MakeGroups") != -1  ||
415          method == "ExtrusionAlongPathX"    ||
416          method == "ExtrusionAlongPathObjX" ||
417          method == "DoubleNodeGroupNew"     ||
418          method == "DoubleNodeGroupsNew"    ||
419          method == "DoubleNodeElemGroupNew" ||
420          method == "DoubleNodeElemGroupsNew" )
421       groups = aCommand->GetResultValue();
422     else if ( method == "MakeBoundaryMesh" )
423       groups = aCommand->GetResultValue(2);
424     else if ( method == "MakeBoundaryElements")
425       groups = aCommand->GetResultValue(3);
426
427     id_editor->second->Process( aCommand );
428     id_editor->second->AddProcessedCmd( aCommand );
429
430     if ( !meshID.IsEmpty() &&
431          !myMeshes.count( meshID ) &&
432          aCommand->IsStudyEntry( meshID ))
433     {
434       TCollection_AsciiString processedCommand = aCommand->GetString();
435       Handle(_pyMesh) mesh = new _pyMesh( aCommand, meshID );
436       myMeshes.insert( make_pair( meshID, mesh ));
437       aCommand->Clear();
438       aCommand->GetString() = processedCommand; // discard changes made by _pyMesh
439     }
440     if ( !groups.IsEmpty() )
441     {
442       if ( !aCommand->IsStudyEntry( meshID ))
443         meshID = id_editor->second->GetMesh();
444       Handle(_pyMesh) mesh = myMeshes[ meshID ];
445
446       list< _pyID > idList = aCommand->GetStudyEntries( groups );
447       list< _pyID >::iterator grID = idList.begin();
448       for ( ; grID != idList.end(); ++grID )
449         if ( !myObjects.count( *grID ))
450         {
451           Handle(_pyGroup) group = new _pyGroup( aCommand, *grID );
452           AddObject( group );
453           if ( !mesh.IsNull() ) mesh->AddGroup( group );
454         }
455     }
456     return aCommand;
457   } // SMESH_MeshEditor methods
458
459   // SMESH_Hypothesis method?
460   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
461   for ( ; hyp != myHypos.end(); ++hyp )
462     if ( !(*hyp)->IsAlgo() && objID == (*hyp)->GetID() ) {
463       (*hyp)->Process( aCommand );
464       (*hyp)->AddProcessedCmd( aCommand );
465       return aCommand;
466     }
467
468   // aFilterManager.CreateFilter() ?
469   if ( aCommand->GetMethod() == "CreateFilter" )
470   {
471     // Set a more human readable name to a filter
472     // aFilter0x7fbf6c71cfb0 -> aFilter_nb
473     _pyID newID, filterID = aCommand->GetResultValue();
474     int pos = filterID.Search( "0x" );
475     if ( pos > 1 )
476       newID = (filterID.SubString(1,pos-1) + "_") + _pyID( ++myNbFilters );
477
478     Handle(_pyObject) filter( new _pyFilter( aCommand, newID ));
479     AddObject( filter );
480   }
481
482   // other object method?
483   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.find( objID );
484   if ( id_obj != myObjects.end() ) {
485     id_obj->second->Process( aCommand );
486     id_obj->second->AddProcessedCmd( aCommand );
487     return aCommand;
488   }
489
490   // Add access to a wrapped mesh
491   AddMeshAccessorMethod( aCommand );
492
493   // Add access to a wrapped algorithm
494   //  AddAlgoAccessorMethod( aCommand ); // ??? what if algo won't be wrapped at all ???
495
496   // PAL12227. PythonDump was not updated at proper time; result is
497   //     aCriteria.append(SMESH.Filter.Criterion(17,26,0,'L1',26,25,1e-07,SMESH.EDGE,-1))
498   // TypeError: __init__() takes exactly 11 arguments (10 given)
499   const char wrongCommand[] = "SMESH.Filter.Criterion(";
500   if ( int beg = theCommand.Location( wrongCommand, 1, theCommand.Length() ))
501   {
502     _pyCommand tmpCmd( theCommand.SubString( beg, theCommand.Length() ), -1);
503     // there must be 10 arguments, 5-th arg ThresholdID is missing,
504     const int wrongNbArgs = 9, missingArg = 5;
505     if ( tmpCmd.GetNbArgs() == wrongNbArgs )
506     {
507       for ( int i = wrongNbArgs; i > missingArg; --i )
508         tmpCmd.SetArg( i + 1, tmpCmd.GetArg( i ));
509       tmpCmd.SetArg(  missingArg, "''");
510       aCommand->GetString().Trunc( beg - 1 );
511       aCommand->GetString() += tmpCmd.GetString();
512     }
513     // IMP issue 0021014
514     // set GetCriterion(elementType,CritType,Compare,Treshold,UnaryOp,BinaryOp,Tolerance)
515     //                  1           2        3       4        5       6        7
516     // instead of "SMESH.Filter.Criterion(
517     // Type,Compare,Threshold,ThresholdStr,ThresholdID,UnaryOp,BinaryOp,Tolerance,TypeOfElement,Precision)
518     // 1    2       3         4            5           6       7        8         9             10
519     // in order to avoid the problem of type mismatch of long and FunctorType
520     const TCollection_AsciiString
521       SMESH("SMESH."), dfltFunctor = "SMESH.FT_Undefined", dftlTol = "1e-07", dftlPreci = "-1";
522     TCollection_AsciiString
523       Type          = aCommand->GetArg(1),  // long
524       Compare       = aCommand->GetArg(2),  // long
525       Threshold     = aCommand->GetArg(3),  // double
526       ThresholdStr  = aCommand->GetArg(4),  // string
527       ThresholdID   = aCommand->GetArg(5),  // string
528       UnaryOp       = aCommand->GetArg(6),  // long
529       BinaryOp      = aCommand->GetArg(7),  // long
530       Tolerance     = aCommand->GetArg(8),  // double
531       TypeOfElement = aCommand->GetArg(9),  // ElementType
532       Precision     = aCommand->GetArg(10); // long
533     Type     = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( Type.IntegerValue() ));
534     Compare  = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( Compare.IntegerValue() ));
535     UnaryOp  = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( UnaryOp.IntegerValue() ));
536     BinaryOp = SMESH + SMESH::FunctorTypeToString( SMESH::FunctorType( BinaryOp.IntegerValue() ));
537
538     aCommand->RemoveArgs();
539     aCommand->SetObject( SMESH_2smeshpy::GenName() );
540     aCommand->SetMethod( "GetCriterion" );
541
542     aCommand->SetArg( 1, TypeOfElement );
543     aCommand->SetArg( 2, Type );
544     aCommand->SetArg( 3, Compare );
545
546     if ( Type == "SMESH.FT_ElemGeomType" && Threshold.IsIntegerValue() )
547     {
548       // set SMESH.GeometryType instead of a numerical Threshold
549       const char* types[SMESH::Geom_POLYHEDRA+1] = {
550         "Geom_POINT", "Geom_EDGE", "Geom_TRIANGLE", "Geom_QUADRANGLE", "Geom_POLYGON",
551         "Geom_TETRA", "Geom_PYRAMID", "Geom_HEXA", "Geom_PENTA", "Geom_HEXAGONAL_PRISM",
552         "Geom_POLYHEDRA"
553       };
554       int iGeom = Threshold.IntegerValue();
555       if ( -1 < iGeom && iGeom < SMESH::Geom_POLYHEDRA+1 )
556         Threshold = SMESH + types[ iGeom ];
557     }
558     if ( ThresholdID.Length() != 2 && ThresholdStr.Length() != 2) // not '' or ""
559       aCommand->SetArg( 4, ThresholdID.SubString( 2, ThresholdID.Length()-1 )); // shape entry
560     else if ( ThresholdStr.Length() != 2 )
561       aCommand->SetArg( 4, ThresholdStr );
562     else if ( ThresholdID.Length() != 2 )
563       aCommand->SetArg( 4, ThresholdID );
564     else
565       aCommand->SetArg( 4, Threshold );
566     // find the last not default arg
567     int lastDefault = 8;
568     if ( Tolerance == dftlTol ) {
569       lastDefault = 7;
570       if ( BinaryOp == dfltFunctor ) {
571         lastDefault = 6;
572         if ( UnaryOp == dfltFunctor )
573           lastDefault = 5;
574       }
575     }
576     if ( 5 < lastDefault ) aCommand->SetArg( 5, UnaryOp );
577     if ( 6 < lastDefault ) aCommand->SetArg( 6, BinaryOp );
578     if ( 7 < lastDefault ) aCommand->SetArg( 7, Tolerance );
579     if ( Precision != dftlPreci )
580     {
581       TCollection_AsciiString crit = aCommand->GetResultValue();
582       aCommand->GetString() += "; ";
583       aCommand->GetString() += crit + ".Precision = " + Precision;
584     }
585   }
586   return aCommand;
587 }
588
589 //================================================================================
590 /*!
591  * \brief Convert the command or remember it for later conversion
592   * \param theCommand - The python command calling a method of SMESH_Gen
593  */
594 //================================================================================
595
596 void _pyGen::Process( const Handle(_pyCommand)& theCommand )
597 {
598   // there are methods to convert:
599   // CreateMesh( shape )
600   // Concatenate( [mesh1, ...], ... )
601   // CreateHypothesis( theHypType, theLibName )
602   // Compute( mesh, geom )
603   // Evaluate( mesh, geom )
604   // mesh creation
605   TCollection_AsciiString method = theCommand->GetMethod();
606
607   if ( method == "CreateMesh" || method == "CreateEmptyMesh")
608   {
609     Handle(_pyMesh) mesh = new _pyMesh( theCommand );
610     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
611     return;
612   }
613   if ( method == "CreateMeshesFromUNV" ||
614        method == "CreateMeshesFromSTL" ||
615        method == "CreateMeshesFromCGNS" ||
616        method == "CopyMesh" )
617   {
618     Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
619     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
620     return;
621   }
622   if( method == "CreateMeshesFromMED" || method == "CreateMeshesFromSAUV")
623   {
624     for(int ind = 0;ind<theCommand->GetNbResultValues();ind++)
625     {
626       const _pyID& meshID = theCommand->GetResultValue(ind+1);
627       if ( !theCommand->IsStudyEntry( meshID ) ) continue;
628       Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue(ind+1));
629       myMeshes.insert( make_pair( mesh->GetID(), mesh ));
630     }
631   }
632
633   // CreateHypothesis()
634   if ( method == "CreateHypothesis" )
635   {
636     // issue 199929, remove standard library name (default parameter)
637     const TCollection_AsciiString & aLibName = theCommand->GetArg( 2 );
638     if ( aLibName.Search( "StdMeshersEngine" ) != -1 ) {
639       // keep first argument
640       TCollection_AsciiString arg = theCommand->GetArg( 1 );
641       theCommand->RemoveArgs();
642       theCommand->SetArg( 1, arg );
643     }
644
645     myHypos.push_back( _pyHypothesis::NewHypothesis( theCommand ));
646     return;
647   }
648
649   // smeshgen.Compute( mesh, geom ) --> mesh.Compute()
650   if ( method == "Compute" )
651   {
652     const _pyID& meshID = theCommand->GetArg( 1 );
653     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
654     if ( id_mesh != myMeshes.end() ) {
655       theCommand->SetObject( meshID );
656       theCommand->RemoveArgs();
657       id_mesh->second->Process( theCommand );
658       id_mesh->second->AddProcessedCmd( theCommand );
659       return;
660     }
661   }
662
663   // smeshgen.Evaluate( mesh, geom ) --> mesh.Evaluate(geom)
664   if ( method == "Evaluate" )
665   {
666     const _pyID& meshID = theCommand->GetArg( 1 );
667     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
668     if ( id_mesh != myMeshes.end() ) {
669       theCommand->SetObject( meshID );
670       _pyID geom = theCommand->GetArg( 2 );
671       theCommand->RemoveArgs();
672       theCommand->SetArg( 1, geom );
673       id_mesh->second->AddProcessedCmd( theCommand );
674       return;
675     }
676   }
677
678   // objects erasing creation command if no more it's commands invoked:
679   // SMESH_Pattern, FilterManager
680   if ( method == "GetPattern" ||
681        method == "CreateFilterManager" ||
682        method == "CreateMeasurements" ) {
683     Handle(_pyObject) obj = new _pySelfEraser( theCommand );
684     if ( !myObjects.insert( make_pair( obj->GetID(), obj )).second )
685       theCommand->Clear(); // already created
686   }
687   // Concatenate( [mesh1, ...], ... )
688   else if ( method == "Concatenate" || method == "ConcatenateWithGroups")
689   {
690     if ( method == "ConcatenateWithGroups" ) {
691       theCommand->SetMethod( "Concatenate" );
692       theCommand->SetArg( theCommand->GetNbArgs() + 1, "True" );
693     }
694     Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
695     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
696     AddMeshAccessorMethod( theCommand );
697   }
698   else if ( method == "SetName" ) // SetName(obj,name)
699   {
700     // store theCommand as one of object commands to erase it along with the object
701     const _pyID& objID = theCommand->GetArg( 1 );
702     Handle(_pyObject) obj = FindObject( objID );
703     if ( !obj.IsNull() )
704       obj->AddProcessedCmd( theCommand );
705   }
706
707   // Replace name of SMESH_Gen
708
709   // names of SMESH_Gen methods fully equal to methods defined in smesh.py
710   static TStringSet smeshpyMethods;
711   if ( smeshpyMethods.empty() ) {
712     const char * names[] =
713       { "SetEmbeddedMode","IsEmbeddedMode","SetCurrentStudy","GetCurrentStudy",
714         "GetPattern","GetSubShapesId",
715         "" }; // <- mark of array end
716     smeshpyMethods.Insert( names );
717   }
718   if ( smeshpyMethods.Contains( theCommand->GetMethod() ))
719     // smeshgen.Method() --> smesh.Method()
720     theCommand->SetObject( SMESH_2smeshpy::SmeshpyName() );
721   else
722     // smeshgen.Method() --> smesh.smesh.Method()
723     theCommand->SetObject( SMESH_2smeshpy::GenName() );
724 }
725
726 //================================================================================
727 /*!
728  * \brief Convert the remembered commands
729  */
730 //================================================================================
731
732 void _pyGen::Flush()
733 {
734   // create an empty command
735   myLastCommand = new _pyCommand();
736
737   map< _pyID, Handle(_pyMesh) >::iterator id_mesh;
738   map< _pyID, Handle(_pyObject) >::iterator id_obj;
739   list< Handle(_pyHypothesis) >::iterator hyp;
740
741   if ( IsToKeepAllCommands() ) // historical dump
742   {
743     // set myIsPublished = true to all objects
744     for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
745       id_mesh->second->SetRemovedFromStudy( false );
746     for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
747       (*hyp)->SetRemovedFromStudy( false );
748     for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj )
749       id_obj->second->SetRemovedFromStudy( false );
750   }
751   else
752   {
753     // let hypotheses find referred objects in order to prevent clearing
754     // not published referred hyps (it's needed for hyps like "LayerDistribution")
755     list< Handle(_pyMesh) > fatherMeshes;
756     for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
757       if ( !hyp->IsNull() )
758         (*hyp)->GetReferredMeshesAndGeom( fatherMeshes );
759   }
760   // set myIsPublished = false to all objects depending on
761   // meshes built on a removed geometry
762   for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
763     if ( id_mesh->second->IsNotGeomPublished() )
764       id_mesh->second->SetRemovedFromStudy( true );
765
766   // Flush meshes
767   for ( id_mesh = myMeshes.begin(); id_mesh != myMeshes.end(); ++id_mesh )
768     if ( ! id_mesh->second.IsNull() )
769       id_mesh->second->Flush();
770
771   // Flush hyps
772   for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
773     if ( !hyp->IsNull() ) {
774       (*hyp)->Flush();
775       // smeshgen.CreateHypothesis() --> smesh.smesh.CreateHypothesis()
776       if ( !(*hyp)->IsWrapped() )
777         (*hyp)->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() );
778     }
779
780   // Flush other objects
781   for ( id_obj = myObjects.begin(); id_obj != myObjects.end(); ++id_obj )
782     if ( ! id_obj->second.IsNull() )
783       id_obj->second->Flush();
784
785   myLastCommand->SetOrderNb( ++myNbCommands );
786   myCommands.push_back( myLastCommand );
787 }
788
789 //================================================================================
790 /*!
791  * \brief Clean commmands of removed objects depending on myIsPublished flag
792  */
793 //================================================================================
794
795 void _pyGen::ClearCommands()
796 {
797   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
798   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
799     id_mesh->second->ClearCommands();
800
801   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
802   for ( ; hyp != myHypos.end(); ++hyp )
803     if ( !hyp->IsNull() )
804       (*hyp)->ClearCommands();
805
806   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin();
807   for ( ; id_obj != myObjects.end(); ++id_obj )
808     id_obj->second->ClearCommands();
809 }
810
811 //================================================================================
812 /*!
813  * \brief Release mutual handles of objects
814  */
815 //================================================================================
816
817 void _pyGen::Free()
818 {
819   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
820   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
821     id_mesh->second->Free();
822   myMeshes.clear();
823
824   map< _pyID, Handle(_pyMeshEditor) >::iterator id_ed = myMeshEditors.begin();
825   for ( ; id_ed != myMeshEditors.end(); ++id_ed )
826     id_ed->second->Free();
827   myMeshEditors.clear();
828
829   map< _pyID, Handle(_pyObject) >::iterator id_obj = myObjects.begin();
830   for ( ; id_obj != myObjects.end(); ++id_obj )
831     id_obj->second->Free();
832   myObjects.clear();
833
834   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
835   for ( ; hyp != myHypos.end(); ++hyp )
836     if ( !hyp->IsNull() )
837       (*hyp)->Free();
838   myHypos.clear();
839
840   myFile2ExportedMesh.clear();
841 }
842
843 //================================================================================
844 /*!
845  * \brief Add access method to mesh that is an argument
846   * \param theCmd - command to add access method
847   * \retval bool - true if added
848  */
849 //================================================================================
850
851 bool _pyGen::AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const
852 {
853   bool added = false;
854   map< _pyID, Handle(_pyMesh) >::const_iterator id_mesh = myMeshes.begin();
855   for ( ; id_mesh != myMeshes.end(); ++id_mesh ) {
856     if ( theCmd->AddAccessorMethod( id_mesh->first, id_mesh->second->AccessorMethod() ))
857       added = true;
858   }
859   return added;
860 }
861
862 //================================================================================
863 /*!
864  * \brief Add access method to algo that is an object or an argument
865   * \param theCmd - command to add access method
866   * \retval bool - true if added
867  */
868 //================================================================================
869
870 bool _pyGen::AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const
871 {
872   bool added = false;
873   list< Handle(_pyHypothesis) >::const_iterator hyp = myHypos.begin();
874   for ( ; hyp != myHypos.end(); ++hyp ) {
875     if ( (*hyp)->IsAlgo() && /*(*hyp)->IsWrapped() &&*/
876          theCmd->AddAccessorMethod( (*hyp)->GetID(), (*hyp)->AccessorMethod() ))
877       added = true;
878   }
879   return added;
880 }
881
882 //================================================================================
883 /*!
884  * \brief Find hypothesis by ID (entry)
885   * \param theHypID - The hypothesis ID
886   * \retval Handle(_pyHypothesis) - The found hypothesis
887  */
888 //================================================================================
889
890 Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID )
891 {
892   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
893   for ( ; hyp != myHypos.end(); ++hyp )
894     if ( !hyp->IsNull() && theHypID == (*hyp)->GetID() )
895       return *hyp;
896   return Handle(_pyHypothesis)();
897 }
898
899 //================================================================================
900 /*!
901  * \brief Find algorithm the created algorithm
902   * \param theGeom - The shape ID the algorithm was created on
903   * \param theMesh - The mesh ID that created the algorithm
904   * \param dim - The algo dimension
905   * \retval Handle(_pyHypothesis) - The found algo
906  */
907 //================================================================================
908
909 Handle(_pyHypothesis) _pyGen::FindAlgo( const _pyID& theGeom, const _pyID& theMesh,
910                                         const Handle(_pyHypothesis)& theHypothesis )
911 {
912   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
913   for ( ; hyp != myHypos.end(); ++hyp )
914     if ( !hyp->IsNull() &&
915          (*hyp)->IsAlgo() &&
916          theHypothesis->CanBeCreatedBy( (*hyp)->GetAlgoType() ) &&
917          (*hyp)->GetGeom() == theGeom &&
918          (*hyp)->GetMesh() == theMesh )
919       return *hyp;
920   return 0;
921 }
922
923 //================================================================================
924 /*!
925  * \brief Find subMesh by ID (entry)
926   * \param theSubMeshID - The subMesh ID
927   * \retval Handle(_pySubMesh) - The found subMesh
928  */
929 //================================================================================
930
931 Handle(_pySubMesh) _pyGen::FindSubMesh( const _pyID& theSubMeshID )
932 {
933   map< _pyID, Handle(_pyObject) >::iterator id_subMesh = myObjects.find(theSubMeshID);
934   if ( id_subMesh != myObjects.end() )
935     return Handle(_pySubMesh)::DownCast( id_subMesh->second );
936   return Handle(_pySubMesh)();
937 }
938
939
940 //================================================================================
941 /*!
942  * \brief Change order of commands in the script
943   * \param theCmd1 - One command
944   * \param theCmd2 - Another command
945  */
946 //================================================================================
947
948 void _pyGen::ExchangeCommands( Handle(_pyCommand) theCmd1, Handle(_pyCommand) theCmd2 )
949 {
950   list< Handle(_pyCommand) >::iterator pos1, pos2;
951   pos1 = find( myCommands.begin(), myCommands.end(), theCmd1 );
952   pos2 = find( myCommands.begin(), myCommands.end(), theCmd2 );
953   myCommands.insert( pos1, theCmd2 );
954   myCommands.insert( pos2, theCmd1 );
955   myCommands.erase( pos1 );
956   myCommands.erase( pos2 );
957
958   int nb1 = theCmd1->GetOrderNb();
959   theCmd1->SetOrderNb( theCmd2->GetOrderNb() );
960   theCmd2->SetOrderNb( nb1 );
961 //   cout << "BECOME " << theCmd1->GetOrderNb() << "\t" << theCmd1->GetString() << endl
962 //        << "BECOME " << theCmd2->GetOrderNb() << "\t" << theCmd2->GetString() << endl << endl;
963 }
964
965 //================================================================================
966 /*!
967  * \brief Set one command after the other
968   * \param theCmd - Command to move
969   * \param theAfterCmd - Command ater which to insert the first one
970  */
971 //================================================================================
972
973 void _pyGen::SetCommandAfter( Handle(_pyCommand) theCmd, Handle(_pyCommand) theAfterCmd )
974 {
975   setNeighbourCommand( theCmd, theAfterCmd, true );
976 }
977
978 //================================================================================
979 /*!
980  * \brief Set one command before the other
981   * \param theCmd - Command to move
982   * \param theBeforeCmd - Command before which to insert the first one
983  */
984 //================================================================================
985
986 void _pyGen::SetCommandBefore( Handle(_pyCommand) theCmd, Handle(_pyCommand) theBeforeCmd )
987 {
988   setNeighbourCommand( theCmd, theBeforeCmd, false );
989 }
990
991 //================================================================================
992 /*!
993  * \brief Set one command before or after the other
994   * \param theCmd - Command to move
995   * \param theOtherCmd - Command ater or before which to insert the first one
996  */
997 //================================================================================
998
999 void _pyGen::setNeighbourCommand( Handle(_pyCommand)& theCmd,
1000                                   Handle(_pyCommand)& theOtherCmd,
1001                                   const bool theIsAfter )
1002 {
1003   list< Handle(_pyCommand) >::iterator pos;
1004   pos = find( myCommands.begin(), myCommands.end(), theCmd );
1005   myCommands.erase( pos );
1006   pos = find( myCommands.begin(), myCommands.end(), theOtherCmd );
1007   myCommands.insert( (theIsAfter ? ++pos : pos), theCmd );
1008
1009   int i = 1;
1010   for ( pos = myCommands.begin(); pos != myCommands.end(); ++pos)
1011     (*pos)->SetOrderNb( i++ );
1012 }
1013
1014 //================================================================================
1015 /*!
1016  * \brief Set command be last in list of commands
1017   * \param theCmd - Command to be last
1018  */
1019 //================================================================================
1020
1021 Handle(_pyCommand)& _pyGen::GetLastCommand()
1022 {
1023   return myLastCommand;
1024 }
1025
1026 //================================================================================
1027 /*!
1028  * \brief Set method to access to object wrapped with python class
1029   * \param theID - The wrapped object entry
1030   * \param theMethod - The accessor method
1031  */
1032 //================================================================================
1033
1034 void _pyGen::SetAccessorMethod(const _pyID& theID, const char* theMethod )
1035 {
1036   myID2AccessorMethod.Bind( theID, (char*) theMethod );
1037 }
1038
1039 //================================================================================
1040 /*!
1041  * \brief Generated new ID for object and assign with existing name
1042   * \param theID - ID of existing object
1043  */
1044 //================================================================================
1045
1046 _pyID _pyGen::GenerateNewID( const _pyID& theID )
1047 {
1048   int index = 1;
1049   _pyID aNewID;
1050   do {
1051     aNewID = theID + _pyID( ":" ) + _pyID( index++ );
1052   }
1053   while ( myObjectNames.IsBound( aNewID ) );
1054
1055   myObjectNames.Bind( aNewID, myObjectNames.IsBound( theID )
1056                       ? (myObjectNames.Find( theID ) + _pyID( "_" ) + _pyID( index-1 ))
1057                       : _pyID( "A" ) + aNewID );
1058   return aNewID;
1059 }
1060
1061 //================================================================================
1062 /*!
1063  * \brief Stores theObj in myObjects
1064  */
1065 //================================================================================
1066
1067 void _pyGen::AddObject( Handle(_pyObject)& theObj )
1068 {
1069   if ( theObj.IsNull() ) return;
1070
1071   if ( theObj->IsKind( STANDARD_TYPE( _pyMesh )))
1072     myMeshes.insert( make_pair( theObj->GetID(), Handle(_pyMesh)::DownCast( theObj )));
1073
1074   else if ( theObj->IsKind( STANDARD_TYPE( _pyMeshEditor )))
1075     myMeshEditors.insert( make_pair( theObj->GetID(), Handle(_pyMeshEditor)::DownCast( theObj )));
1076
1077   else
1078     myObjects.insert( make_pair( theObj->GetID(), theObj ));
1079 }
1080
1081 //================================================================================
1082 /*!
1083  * \brief Finds a _pyObject by ID
1084  */
1085 //================================================================================
1086
1087 Handle(_pyObject) _pyGen::FindObject( const _pyID& theObjID )  const
1088 {
1089   {
1090     map< _pyID, Handle(_pyObject) >::const_iterator id_obj = myObjects.find( theObjID );
1091     if ( id_obj != myObjects.end() )
1092       return id_obj->second;
1093   }
1094   {
1095     map< _pyID, Handle(_pyMesh) >::const_iterator id_obj = myMeshes.find( theObjID );
1096     if ( id_obj != myMeshes.end() )
1097       return id_obj->second;
1098   }
1099   // {
1100   //   map< _pyID, Handle(_pyMeshEditor) >::const_iterator id_obj = myMeshEditors.find( theObjID );
1101   //   if ( id_obj != myMeshEditors.end() )
1102   //     return id_obj->second;
1103   // }
1104   return Handle(_pyObject)();
1105 }
1106
1107 //================================================================================
1108 /*!
1109  * \brief Check if a study entry is under GEOM component
1110  */
1111 //================================================================================
1112
1113 bool _pyGen::IsGeomObject(const _pyID& theObjID) const
1114 {
1115   if ( myGeomIDNb )
1116   {
1117     return ( myGeomIDIndex <= theObjID.Length() &&
1118              int( theObjID.Value( myGeomIDIndex )) == myGeomIDNb);
1119   }
1120   return false;
1121 }
1122
1123 //================================================================================
1124 /*!
1125  * \brief Returns true if an object is not present in a study
1126  */
1127 //================================================================================
1128
1129 bool _pyGen::IsNotPublished(const _pyID& theObjID) const
1130 {
1131   if ( theObjID.IsEmpty() ) return false;
1132
1133   if ( myObjectNames.IsBound( theObjID ))
1134     return false; // SMESH object is in study
1135
1136   // either the SMESH object is not in study or it is a GEOM object
1137   if ( IsGeomObject( theObjID ))
1138   {
1139     SALOMEDS::SObject_var so = myStudy->FindObjectID( theObjID.ToCString() );
1140     if ( so->_is_nil() ) return true;
1141     CORBA::Object_var obj = so->GetObject();
1142     return CORBA::is_nil( obj );
1143   }
1144   return true; // SMESH object not in study
1145 }
1146
1147 //================================================================================
1148 /*!
1149  * \brief Return reader of  hypotheses of plugins
1150  */
1151 //================================================================================
1152
1153 Handle( _pyHypothesisReader ) _pyGen::GetHypothesisReader() const
1154 {
1155   if (myHypReader.IsNull() )
1156     ((_pyGen*) this)->myHypReader = new _pyHypothesisReader;
1157
1158   return myHypReader;
1159 }
1160
1161
1162 //================================================================================
1163 /*!
1164  * \brief Mesh created by SMESH_Gen
1165  */
1166 //================================================================================
1167
1168 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd)
1169   : _pyObject( theCreationCmd ), myGeomNotInStudy( false )
1170 {
1171   if ( theCreationCmd->GetMethod() == "CreateMesh" && theGen->IsNotPublished( GetGeom() ))
1172     myGeomNotInStudy = true;
1173
1174   // convert my creation command --> smeshpy.Mesh(...)
1175   Handle(_pyCommand) creationCmd = GetCreationCmd();
1176   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
1177   creationCmd->SetMethod( "Mesh" );
1178   theGen->SetAccessorMethod( GetID(), _pyMesh::AccessorMethod() );
1179 }
1180
1181 //================================================================================
1182 /*!
1183  * \brief Mesh created by SMESH_MeshEditor
1184  */
1185 //================================================================================
1186
1187 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd, const _pyID& meshId):
1188   _pyObject(theCreationCmd,meshId), myGeomNotInStudy(false )
1189 {
1190   if ( theCreationCmd->MethodStartsFrom( "CreateMeshesFrom" ))
1191   {
1192     // this mesh depends on the exported mesh
1193     const TCollection_AsciiString& file = theCreationCmd->GetArg( 1 );
1194     if ( !file.IsEmpty() )
1195     {
1196       ExportedMeshData& exportData = theGen->FindExportedMesh( file );
1197       addFatherMesh( exportData.myMesh );
1198       if ( !exportData.myLastComputeCmd.IsNull() )
1199       {
1200         // restore cleared Compute() by which the exported mesh was generated
1201         exportData.myLastComputeCmd->GetString() = exportData.myLastComputeCmdString;
1202         // protect that Compute() cmd from clearing
1203         if ( exportData.myMesh->myLastComputeCmd == exportData.myLastComputeCmd )
1204           exportData.myMesh->myLastComputeCmd.Nullify();
1205       }
1206     }
1207   }
1208   else if ( theCreationCmd->MethodStartsFrom( "Concatenate" ))
1209   {
1210     // this mesh depends on concatenated meshes
1211     const TCollection_AsciiString& meshIDs = theCreationCmd->GetArg( 1 );
1212     list< _pyID > idList = theCreationCmd->GetStudyEntries( meshIDs );
1213     list< _pyID >::iterator meshID = idList.begin();
1214     for ( ; meshID != idList.end(); ++meshID )
1215       addFatherMesh( *meshID );
1216   }
1217   else if ( theCreationCmd->GetMethod() == "CopyMesh" )
1218   {
1219     // this mesh depends on a copied IdSource
1220     const _pyID& objID = theCreationCmd->GetArg( 1 );
1221     addFatherMesh( objID );
1222   }
1223   else if ( theCreationCmd->GetMethod().Search("MakeMesh") != -1 ||
1224             theCreationCmd->GetMethod() == "MakeBoundaryMesh" ||
1225             theCreationCmd->GetMethod() == "MakeBoundaryElements" )
1226   {
1227     // this mesh depends on a source mesh
1228     // (theCreationCmd is already Process()ed by _pyMeshEditor)
1229     const _pyID& meshID = theCreationCmd->GetObject();
1230     addFatherMesh( meshID );
1231   }
1232     
1233   // convert my creation command
1234   Handle(_pyCommand) creationCmd = GetCreationCmd();
1235   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
1236   theGen->SetAccessorMethod( meshId, _pyMesh::AccessorMethod() );
1237 }
1238
1239 //================================================================================
1240 /*!
1241  * \brief Convert an IDL API command of SMESH::SMESH_Mesh to a method call of python Mesh
1242   * \param theCommand - Engine method called for this mesh
1243  */
1244 //================================================================================
1245
1246 void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
1247 {
1248   // some methods of SMESH_Mesh interface needs special conversion
1249   // to methods of Mesh python class
1250   //
1251   // 1. GetSubMesh(geom, name) + AddHypothesis(geom, algo)
1252   //     --> in Mesh_Algorithm.Create(mesh, geom, hypo, so)
1253   // 2. AddHypothesis(geom, hyp)
1254   //     --> in Mesh_Algorithm.Hypothesis(hyp, args, so)
1255   // 3. CreateGroupFromGEOM(type, name, grp)
1256   //     --> in Mesh.Group(grp, name="")
1257   // 4. ExportToMED(f, auto_groups, version)
1258   //     --> in Mesh.ExportMED( f, auto_groups, version )
1259   // 5. etc
1260
1261   const TCollection_AsciiString& method = theCommand->GetMethod();
1262   // ----------------------------------------------------------------------
1263   if ( method == "Compute" ) // in snapshot mode, clear the previous Compute()
1264   {
1265     if ( !theGen->IsToKeepAllCommands() ) // !historical
1266     {
1267       list< Handle(_pyHypothesis) >::iterator hyp;
1268       if ( !myLastComputeCmd.IsNull() )
1269       {
1270         for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
1271           (*hyp)->ComputeDiscarded( myLastComputeCmd );
1272
1273         myLastComputeCmd->Clear();
1274       }
1275       myLastComputeCmd = theCommand;
1276
1277       for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
1278         (*hyp)->MeshComputed( myLastComputeCmd );
1279     }
1280     Flush();
1281   }
1282   // ----------------------------------------------------------------------
1283   else if ( method == "Clear" ) // in snapshot mode, clear all previous commands
1284   {
1285     if ( !theGen->IsToKeepAllCommands() ) // !historical
1286     {
1287       int untilCmdNb =
1288         myChildMeshes.empty() ? 0 : myChildMeshes.back()->GetCreationCmd()->GetOrderNb();
1289       // list< Handle(_pyCommand) >::reverse_iterator cmd = myProcessedCmds.rbegin();
1290       // for ( ; cmd != myProcessedCmds.rend() && (*cmd)->GetOrderNb() > untilCmdNb; ++cmd )
1291       //   (*cmd)->Clear();
1292       if ( !myLastComputeCmd.IsNull() )
1293       {
1294         list< Handle(_pyHypothesis) >::iterator hyp;
1295         for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
1296           (*hyp)->ComputeDiscarded( myLastComputeCmd );
1297
1298         myLastComputeCmd->Clear();
1299       }
1300
1301       list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
1302       for ( ; e != myEditors.end(); ++e )
1303       {
1304         list< Handle(_pyCommand)>& cmds = (*e)->GetProcessedCmds();
1305         list< Handle(_pyCommand) >::reverse_iterator cmd = cmds.rbegin();
1306         for ( ; cmd != cmds.rend() && (*cmd)->GetOrderNb() > untilCmdNb; ++cmd )
1307           if ( !(*cmd)->IsEmpty() )
1308           {
1309             if ( (*cmd)->GetStudyEntries( (*cmd)->GetResultValue() ).empty() ) // no object created
1310               (*cmd)->Clear();
1311           }
1312       }
1313       myLastComputeCmd = theCommand; // to clear Clear() the same way as Compute()
1314     }
1315   }
1316   // ----------------------------------------------------------------------
1317   else if ( method == "GetSubMesh" ) { // collect submeshes of the mesh
1318     Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetResultValue() );
1319     if ( !subMesh.IsNull() ) {
1320       subMesh->SetCreator( this );
1321       mySubmeshes.push_back( subMesh );
1322     }
1323   }
1324   else if ( method == "RemoveSubMesh" ) { // move submesh creation before its removal
1325     Handle(_pySubMesh) subMesh = theGen->FindSubMesh( theCommand->GetArg(1) );
1326     if ( !subMesh.IsNull() )
1327       subMesh->Process( theCommand );
1328     AddMeshAccess( theCommand );
1329   }
1330   // ----------------------------------------------------------------------
1331   else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO )
1332     myAddHypCmds.push_back( theCommand );
1333     // set mesh to hypo
1334     const _pyID& hypID = theCommand->GetArg( 2 );
1335     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
1336     if ( !hyp.IsNull() ) {
1337       myHypos.push_back( hyp );
1338       if ( hyp->GetMesh().IsEmpty() )
1339         hyp->SetMesh( this->GetID() );
1340     }
1341   }
1342   // ----------------------------------------------------------------------
1343   else if ( method == "CreateGroup" ) // CreateGroup() --> CreateEmptyGroup()
1344   {
1345     theCommand->SetMethod( "CreateEmptyGroup" );
1346     Handle(_pyGroup) group = new _pyGroup( theCommand );
1347     myGroups.push_back( group );
1348     theGen->AddObject( group );
1349   }
1350   // ----------------------------------------------------------------------
1351   else if ( method == "CreateGroupFromGEOM" ) {// (type, name, grp)
1352     _pyID grp = theCommand->GetArg( 3 );
1353     // VSR 24/12/2010. PAL21106: always use GroupOnGeom() function on dump
1354     // next if(){...} section is commented
1355     //if ( sameGroupType( grp, theCommand->GetArg( 1 )) ) { // --> Group(grp)
1356     //  theCommand->SetMethod( "Group" );
1357     //  theCommand->RemoveArgs();
1358     //  theCommand->SetArg( 1, grp );
1359     //}
1360     //else {
1361     // ------------------------->>>>> GroupOnGeom( grp, name, typ )
1362       _pyID type = theCommand->GetArg( 1 );
1363       _pyID name = theCommand->GetArg( 2 );
1364       theCommand->SetMethod( "GroupOnGeom" );
1365       theCommand->RemoveArgs();
1366       theCommand->SetArg( 1, grp );
1367       theCommand->SetArg( 2, name );
1368       theCommand->SetArg( 3, type );
1369     //}
1370     Handle(_pyGroup) group = new _pyGroup( theCommand );
1371     myGroups.push_back( group );
1372     theGen->AddObject( group );
1373   }
1374   // ----------------------------------------------------------------------
1375   else if ( method == "CreateGroupFromFilter" ) // --> GroupOnFilter()
1376   {
1377     theCommand->SetMethod( "GroupOnFilter" );
1378     Handle(_pyGroup) group = new _pyGroup( theCommand );
1379     myGroups.push_back( group );
1380     theGen->AddObject( group );
1381
1382     // GroupOnFilter(typ, name, aFilter0x4743dc0 -> aFilter_1)
1383     _pyID filterID = theCommand->GetArg(3);
1384     Handle(_pyFilter) filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID ));
1385     if ( !filter.IsNull())
1386     {
1387       filter->Process( theCommand );
1388       filter->AddUser( group );
1389     }
1390   }
1391   // ----------------------------------------------------------------------
1392   else if ( theCommand->MethodStartsFrom( "Export" ))
1393   {
1394     if ( method == "ExportToMED" ||   // ExportToMED()  --> ExportMED()
1395          method == "ExportToMEDX" ) { // ExportToMEDX() --> ExportMED()
1396       theCommand->SetMethod( "ExportMED" );
1397     }
1398     else if ( method == "ExportCGNS" )
1399     { // ExportCGNS(part, ...) -> ExportCGNS(..., part)
1400       _pyID partID = theCommand->GetArg( 1 );
1401       int nbArgs = theCommand->GetNbArgs();
1402       for ( int i = 2; i <= nbArgs; ++i )
1403         theCommand->SetArg( i-1, theCommand->GetArg( i ));
1404       theCommand->SetArg( nbArgs, partID );
1405     }
1406     else if ( theCommand->MethodStartsFrom( "ExportPartTo" ))
1407     { // ExportPartTo*(part, ...) -> Export*(..., part)
1408       //
1409       // remove "PartTo" from the method
1410       TCollection_AsciiString newMethod = method;
1411       newMethod.Remove( 7, 6 );
1412       theCommand->SetMethod( newMethod );
1413       // make the 1st arg be the last one
1414       _pyID partID = theCommand->GetArg( 1 );
1415       int nbArgs = theCommand->GetNbArgs();
1416       for ( int i = 2; i <= nbArgs; ++i )
1417         theCommand->SetArg( i-1, theCommand->GetArg( i ));
1418       theCommand->SetArg( nbArgs, partID );
1419     }
1420     // remember file name
1421     theGen->AddExportedMesh( theCommand->GetArg( 1 ),
1422                              ExportedMeshData( this, myLastComputeCmd ));
1423   }
1424   // ----------------------------------------------------------------------
1425   else if ( method == "RemoveHypothesis" ) // (geom, hyp)
1426   {
1427     _pyID hypID = theCommand->GetArg( 2 );
1428
1429     // check if this mesh still has corresponding addition command
1430     bool hasAddCmd = false;
1431     list< Handle(_pyCommand) >::iterator cmd = myAddHypCmds.begin();
1432     while ( cmd != myAddHypCmds.end() )
1433     {
1434       // AddHypothesis(geom, hyp)
1435       if ( hypID == (*cmd)->GetArg( 2 )) { // erase both (add and remove) commands
1436         theCommand->Clear();
1437         (*cmd)->Clear();
1438         cmd = myAddHypCmds.erase( cmd );
1439         hasAddCmd = true;
1440       }
1441       else {
1442         ++cmd;
1443       }
1444     }
1445     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
1446     if ( ! hasAddCmd && hypID.Length() != 0 ) { // hypo addition already wrapped
1447       // RemoveHypothesis(geom, hyp) --> RemoveHypothesis( hyp, geom=0 )
1448       _pyID geom = theCommand->GetArg( 1 );
1449       theCommand->RemoveArgs();
1450       theCommand->SetArg( 1, hypID );
1451       if ( geom != GetGeom() )
1452         theCommand->SetArg( 2, geom );
1453     }
1454     // remove hyp from myHypos
1455     myHypos.remove( hyp );
1456   }
1457   // check for SubMesh order commands
1458   else if ( method == "GetMeshOrder" || method == "SetMeshOrder" )
1459   {
1460     // make commands GetSubMesh() returning sub-meshes be before using sub-meshes
1461     // by GetMeshOrder() and SetMeshOrder(), since by defalut GetSubMesh()
1462     // commands are moved at the end of the script
1463     TCollection_AsciiString subIDs =
1464       ( method == "SetMeshOrder" ) ? theCommand->GetArg(1) : theCommand->GetResultValue();
1465     list< _pyID > idList = theCommand->GetStudyEntries( subIDs );
1466     list< _pyID >::iterator subID = idList.begin();
1467     for ( ; subID != idList.end(); ++subID )
1468     {
1469       Handle(_pySubMesh) subMesh = theGen->FindSubMesh( *subID );
1470       if ( !subMesh.IsNull() )
1471         subMesh->Process( theCommand ); // it moves GetSubMesh() before theCommand
1472     }
1473   }
1474   // update list of groups
1475   else if ( method == "GetGroups" )
1476   {
1477     TCollection_AsciiString grIDs = theCommand->GetResultValue();
1478     list< _pyID > idList = theCommand->GetStudyEntries( grIDs );
1479     list< _pyID >::iterator grID = idList.begin();
1480     for ( ; grID != idList.end(); ++grID )
1481     {
1482       Handle(_pyObject) obj = theGen->FindObject( *grID );
1483       if ( obj.IsNull() )
1484       {
1485         Handle(_pyGroup) group = new _pyGroup( theCommand, *grID );
1486         theGen->AddObject( group );
1487         myGroups.push_back( group );
1488       }
1489     }
1490   }
1491   // add accessor method if necessary
1492   else
1493   {
1494     if ( NeedMeshAccess( theCommand ))
1495       // apply theCommand to the mesh wrapped by smeshpy mesh
1496       AddMeshAccess( theCommand );
1497   }
1498 }
1499
1500 //================================================================================
1501 /*!
1502  * \brief Return True if addition of accesor method is needed
1503  */
1504 //================================================================================
1505
1506 bool _pyMesh::NeedMeshAccess( const Handle(_pyCommand)& theCommand )
1507 {
1508   // names of SMESH_Mesh methods fully equal to methods of python class Mesh,
1509   // so no conversion is needed for them at all:
1510   static TStringSet sameMethods;
1511   if ( sameMethods.empty() ) {
1512     const char * names[] =
1513       { "ExportDAT","ExportUNV","ExportSTL","ExportSAUV", "RemoveGroup","RemoveGroupWithContents",
1514         "GetGroups","UnionGroups","IntersectGroups","CutGroups","GetLog","GetId","ClearLog",
1515         "GetStudyId","HasDuplicatedGroupNamesMED","GetMEDMesh","NbNodes","NbElements",
1516         "NbEdges","NbEdgesOfOrder","NbFaces","NbFacesOfOrder","NbTriangles",
1517         "NbTrianglesOfOrder","NbQuadrangles","NbQuadranglesOfOrder","NbPolygons","NbVolumes",
1518         "NbVolumesOfOrder","NbTetras","NbTetrasOfOrder","NbHexas","NbHexasOfOrder",
1519         "NbPyramids","NbPyramidsOfOrder","NbPrisms","NbPrismsOfOrder","NbPolyhedrons",
1520         "NbSubMesh","GetElementsId","GetElementsByType","GetNodesId","GetElementType",
1521         "GetSubMeshElementsId","GetSubMeshNodesId","GetSubMeshElementType","Dump","GetNodeXYZ",
1522         "GetNodeInverseElements","GetShapeID","GetShapeIDForElem","GetElemNbNodes",
1523         "GetElemNode","IsMediumNode","IsMediumNodeOfAnyElem","ElemNbEdges","ElemNbFaces",
1524         "IsPoly","IsQuadratic","BaryCenter","GetHypothesisList", "SetAutoColor", "GetAutoColor",
1525         "Clear", "ConvertToStandalone", "GetMeshOrder", "SetMeshOrder"
1526         ,"" }; // <- mark of end
1527     sameMethods.Insert( names );
1528   }
1529
1530   return !sameMethods.Contains( theCommand->GetMethod() );
1531 }
1532
1533 //================================================================================
1534 /*!
1535  * \brief Convert creation and addition of all algos and hypos
1536  */
1537 //================================================================================
1538
1539 void _pyMesh::Flush()
1540 {
1541   {
1542     // get the meshes this mesh depends on via hypotheses
1543     list< Handle(_pyMesh) > fatherMeshes;
1544     list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
1545     for ( ; hyp != myHypos.end(); ++hyp )
1546       if ( ! (*hyp)->GetReferredMeshesAndGeom( fatherMeshes ))
1547         myGeomNotInStudy = true;
1548
1549     list< Handle(_pyMesh) >::iterator m = fatherMeshes.begin();
1550     for ( ; m != fatherMeshes.end(); ++m )
1551       addFatherMesh( *m );
1552     // if ( removedGeom )
1553     //     SetRemovedFromStudy(); // as reffered geometry not in study
1554   }
1555   if ( myGeomNotInStudy )
1556     return;
1557
1558   list < Handle(_pyCommand) >::iterator cmd;
1559
1560   // try to convert algo addition like this:
1561   // mesh.AddHypothesis(geom, ALGO ) --> ALGO = mesh.Algo()
1562   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
1563   {
1564     Handle(_pyCommand) addCmd = *cmd;
1565
1566     _pyID algoID = addCmd->GetArg( 2 );
1567     Handle(_pyHypothesis) algo = theGen->FindHyp( algoID );
1568     if ( algo.IsNull() || !algo->IsAlgo() )
1569       continue;
1570
1571     // check and create new algorithm instance if it is already wrapped
1572     if ( algo->IsWrapped() ) {
1573       _pyID localAlgoID = theGen->GenerateNewID( algoID );
1574       TCollection_AsciiString aNewCmdStr = addCmd->GetIndentation() + localAlgoID +
1575         TCollection_AsciiString( " = " ) + theGen->GetID() +
1576         TCollection_AsciiString( ".CreateHypothesis( \"" ) + algo->GetAlgoType() +
1577         TCollection_AsciiString( "\" )" );
1578
1579       Handle(_pyCommand) newCmd = theGen->AddCommand( aNewCmdStr );
1580       Handle(_pyAlgorithm) newAlgo = Handle(_pyAlgorithm)::DownCast(theGen->FindHyp( localAlgoID ));
1581       if ( !newAlgo.IsNull() ) {
1582         newAlgo->Assign( algo, this->GetID() );
1583         newAlgo->SetCreationCmd( newCmd );
1584         algo = newAlgo;
1585         // set algorithm creation
1586         theGen->SetCommandBefore( newCmd, addCmd );
1587         myHypos.push_back( newAlgo );
1588         if ( !myLastComputeCmd.IsNull() &&
1589              newCmd->GetOrderNb() == myLastComputeCmd->GetOrderNb() + 1)
1590           newAlgo->MeshComputed( myLastComputeCmd );
1591       }
1592       else
1593         newCmd->Clear();
1594     }
1595     _pyID geom = addCmd->GetArg( 1 );
1596     bool isLocalAlgo = ( geom != GetGeom() );
1597
1598     // try to convert
1599     if ( algo->Addition2Creation( addCmd, this->GetID() )) // OK
1600     {
1601       // wrapped algo is created after mesh creation
1602       GetCreationCmd()->AddDependantCmd( addCmd );
1603
1604       if ( isLocalAlgo ) {
1605         // mesh.AddHypothesis(geom, ALGO ) --> mesh.AlgoMethod(geom)
1606         addCmd->SetArg( addCmd->GetNbArgs() + 1,
1607                         TCollection_AsciiString( "geom=" ) + geom );
1608         // sm = mesh.GetSubMesh(geom, name) --> sm = ALGO.GetSubMesh()
1609         list < Handle(_pySubMesh) >::iterator smIt;
1610         for ( smIt = mySubmeshes.begin(); smIt != mySubmeshes.end(); ++smIt ) {
1611           Handle(_pySubMesh) subMesh = *smIt;
1612           Handle(_pyCommand) subCmd = subMesh->GetCreationCmd();
1613           if ( geom == subCmd->GetArg( 1 )) {
1614             subCmd->SetObject( algo->GetID() );
1615             subCmd->RemoveArgs();
1616             subMesh->SetCreator( algo );
1617           }
1618         }
1619       }
1620     }
1621     else // KO - ALGO was already created
1622     {
1623       // mesh.AddHypothesis(geom, ALGO) --> mesh.AddHypothesis(ALGO, geom=0)
1624       addCmd->RemoveArgs();
1625       addCmd->SetArg( 1, algoID );
1626       if ( isLocalAlgo )
1627         addCmd->SetArg( 2, geom );
1628     }
1629   }
1630
1631   // try to convert hypo addition like this:
1632   // mesh.AddHypothesis(geom, HYPO ) --> HYPO = algo.Hypo()
1633   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
1634   {
1635     Handle(_pyCommand) addCmd = *cmd;
1636     _pyID hypID = addCmd->GetArg( 2 );
1637     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
1638     if ( hyp.IsNull() || hyp->IsAlgo() )
1639       continue;
1640     bool converted = hyp->Addition2Creation( addCmd, this->GetID() );
1641     if ( !converted ) {
1642       // mesh.AddHypothesis(geom, HYP) --> mesh.AddHypothesis(HYP, geom=0)
1643       _pyID geom = addCmd->GetArg( 1 );
1644       addCmd->RemoveArgs();
1645       addCmd->SetArg( 1, hypID );
1646       if ( geom != GetGeom() )
1647         addCmd->SetArg( 2, geom );
1648     }
1649   }
1650
1651   myAddHypCmds.clear();
1652   mySubmeshes.clear();
1653
1654   // flush hypotheses
1655   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
1656   for ( hyp = myHypos.begin(); hyp != myHypos.end(); ++hyp )
1657     (*hyp)->Flush();
1658 }
1659
1660 //================================================================================
1661 /*!
1662  * \brief Sets myIsPublished of me and of all objects depending on me.
1663  */
1664 //================================================================================
1665
1666 void _pyMesh::SetRemovedFromStudy(const bool isRemoved)
1667 {
1668   _pyObject::SetRemovedFromStudy(isRemoved);
1669
1670   list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin();
1671   for ( ; sm != mySubmeshes.end(); ++sm )
1672     (*sm)->SetRemovedFromStudy(isRemoved);
1673
1674   list< Handle(_pyGroup) >::iterator gr = myGroups.begin();
1675   for ( ; gr != myGroups.end(); ++gr )
1676     (*gr)->SetRemovedFromStudy(isRemoved);
1677
1678   list< Handle(_pyMesh) >::iterator m = myChildMeshes.begin();
1679   for ( ; m != myChildMeshes.end(); ++m )
1680     (*m)->SetRemovedFromStudy(isRemoved);
1681
1682   list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
1683   for ( ; e != myEditors.end(); ++e )
1684     (*e)->SetRemovedFromStudy(isRemoved);
1685 }
1686
1687 //================================================================================
1688 /*!
1689  * \brief Return true if none of myChildMeshes is in study
1690  */
1691 //================================================================================
1692
1693 bool _pyMesh::CanClear()
1694 {
1695   if ( IsInStudy() )
1696     return false;
1697
1698   list< Handle(_pyMesh) >::iterator m = myChildMeshes.begin();
1699   for ( ; m != myChildMeshes.end(); ++m )
1700     if ( !(*m)->CanClear() )
1701       return false;
1702
1703   return true;
1704 }
1705
1706 //================================================================================
1707 /*!
1708  * \brief Clear my commands and commands of mesh editor
1709  */
1710 //================================================================================
1711
1712 void _pyMesh::ClearCommands()
1713 {
1714   if ( !CanClear() )
1715   {
1716     if ( !IsInStudy() )
1717     {
1718       // mark all sub-objects as not removed, except child meshes
1719       list< Handle(_pyMesh) > children;
1720       children.swap( myChildMeshes );
1721       SetRemovedFromStudy( false );
1722       children.swap( myChildMeshes );
1723     }
1724     return;
1725   }
1726   _pyObject::ClearCommands();
1727
1728   list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin();
1729   for ( ; sm != mySubmeshes.end(); ++sm )
1730     (*sm)->ClearCommands();
1731   
1732   list< Handle(_pyGroup) >::iterator gr = myGroups.begin();
1733   for ( ; gr != myGroups.end(); ++gr )
1734     (*gr)->ClearCommands();
1735
1736   list< Handle(_pyMeshEditor)>::iterator e = myEditors.begin();
1737   for ( ; e != myEditors.end(); ++e )
1738     (*e)->ClearCommands();
1739 }
1740
1741 //================================================================================
1742 /*!
1743  * \brief Add a father mesh by ID
1744  */
1745 //================================================================================
1746
1747 void _pyMesh::addFatherMesh( const _pyID& meshID )
1748 {
1749   if ( !meshID.IsEmpty() )
1750     addFatherMesh( Handle(_pyMesh)::DownCast( theGen->FindObject( meshID )));
1751 }
1752
1753 //================================================================================
1754 /*!
1755  * \brief Add a father mesh
1756  */
1757 //================================================================================
1758
1759 void _pyMesh::addFatherMesh( const Handle(_pyMesh)& mesh )
1760 {
1761   if ( !mesh.IsNull() )
1762   {
1763     //myFatherMeshes.push_back( mesh );
1764     mesh->myChildMeshes.push_back( this );
1765
1766     // protect last Compute() from clearing by the next Compute()
1767     mesh->myLastComputeCmd.Nullify();
1768   }
1769 }
1770
1771 //================================================================================
1772 /*!
1773  * \brief MeshEditor convert its commands to ones of mesh
1774  */
1775 //================================================================================
1776
1777 _pyMeshEditor::_pyMeshEditor(const Handle(_pyCommand)& theCreationCmd):
1778   _pyObject( theCreationCmd )
1779 {
1780   myMesh = theCreationCmd->GetObject();
1781   myCreationCmdStr = theCreationCmd->GetString();
1782   theCreationCmd->Clear();
1783
1784   Handle(_pyMesh) mesh = ObjectToMesh( theGen->FindObject( myMesh ));
1785   if ( !mesh.IsNull() )
1786     mesh->AddEditor( this );
1787 }
1788
1789 //================================================================================
1790 /*!
1791  * \brief convert its commands to ones of mesh
1792  */
1793 //================================================================================
1794
1795 void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand)
1796 {
1797   // names of SMESH_MeshEditor methods fully equal to methods of python class Mesh, so
1798   // commands calling this methods are converted to calls of methods of Mesh
1799   static TStringSet sameMethods;
1800   if ( sameMethods.empty() ) {
1801     const char * names[] = {
1802       "RemoveElements","RemoveNodes","RemoveOrphanNodes","AddNode","Add0DElement","AddEdge","AddFace","AddPolygonalFace",
1803       "AddVolume","AddPolyhedralVolume","AddPolyhedralVolumeByFaces","MoveNode", "MoveClosestNodeToPoint",
1804       "InverseDiag","DeleteDiag","Reorient","ReorientObject","TriToQuad","SplitQuad","SplitQuadObject",
1805       "BestSplit","Smooth","SmoothObject","SmoothParametric","SmoothParametricObject",
1806       "ConvertToQuadratic","ConvertFromQuadratic","RenumberNodes","RenumberElements",
1807       "RotationSweep","RotationSweepObject","RotationSweepObject1D","RotationSweepObject2D",
1808       "ExtrusionSweep","AdvancedExtrusion","ExtrusionSweepObject","ExtrusionSweepObject1D","ExtrusionSweepObject2D",
1809       "ExtrusionAlongPath","ExtrusionAlongPathObject","ExtrusionAlongPathX",
1810       "ExtrusionAlongPathObject1D","ExtrusionAlongPathObject2D",
1811       "Mirror","MirrorObject","Translate","TranslateObject","Rotate","RotateObject",
1812       "FindCoincidentNodes",/*"FindCoincidentNodesOnPart",*/"MergeNodes","FindEqualElements",
1813       "MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders",
1814       "SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes",
1815       "GetLastCreatedElems",
1816       "MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh",
1817       "TranslateObjectMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh",
1818       "MakeBoundaryElements"
1819       ,"" }; // <- mark of the end
1820     sameMethods.Insert( names );
1821   }
1822
1823   // names of SMESH_MeshEditor methods which differ from methods of class Mesh
1824   // only by last two arguments
1825   static TStringSet diffLastTwoArgsMethods;
1826   if (diffLastTwoArgsMethods.empty() ) {
1827     const char * names[] = {
1828       "MirrorMakeGroups","MirrorObjectMakeGroups",
1829       "TranslateMakeGroups","TranslateObjectMakeGroups",
1830       "RotateMakeGroups","RotateObjectMakeGroups",
1831       ""};// <- mark of the end
1832     diffLastTwoArgsMethods.Insert( names );
1833   }
1834
1835   const TCollection_AsciiString & method = theCommand->GetMethod();
1836   bool isPyMeshMethod = sameMethods.Contains( method );
1837   if ( !isPyMeshMethod )
1838   {
1839     //Replace SMESH_MeshEditor "MakeGroups" functions by the Mesh
1840     //functions with the flag "theMakeGroups = True" like:
1841     //SMESH_MeshEditor.CmdMakeGroups => Mesh.Cmd(...,True)
1842     int pos = method.Search("MakeGroups");
1843     if( pos != -1)
1844     {
1845       isPyMeshMethod = true;
1846       bool is0DmethId  = ( method == "ExtrusionSweepMakeGroups0D" );
1847       bool is0DmethObj = ( method == "ExtrusionSweepObject0DMakeGroups");
1848
1849       // 1. Remove "MakeGroups" from the Command
1850       TCollection_AsciiString aMethod = theCommand->GetMethod();
1851       int nbArgsToAdd = diffLastTwoArgsMethods.Contains(aMethod) ? 2 : 1;
1852       
1853       if(is0DmethObj)
1854         pos = pos-2;  //Remove "0D" from the Command too
1855       aMethod.Trunc(pos-1);
1856       theCommand->SetMethod(aMethod);
1857
1858       // 2. And add last "True" argument(s)
1859       while(nbArgsToAdd--)
1860         theCommand->SetArg(theCommand->GetNbArgs()+1,"True");
1861       if( is0DmethId || is0DmethObj )
1862         theCommand->SetArg(theCommand->GetNbArgs()+1,"True");
1863     }
1864   }
1865
1866   // ExtrusionSweep0D() -> ExtrusionSweep()
1867   // ExtrusionSweepObject0D() -> ExtrusionSweepObject()
1868   if ( !isPyMeshMethod && ( method == "ExtrusionSweep0D"  ||
1869                             method == "ExtrusionSweepObject0D" ))
1870   {
1871     isPyMeshMethod=true;
1872     theCommand->SetMethod( method.SubString( 1, method.Length()-2));
1873     theCommand->SetArg(theCommand->GetNbArgs()+1,"False");  //sets flag "MakeGroups = False"
1874     theCommand->SetArg(theCommand->GetNbArgs()+1,"True");  //sets flag "IsNode = True"
1875   }
1876   // set "ExtrusionAlongPathX()" instead of "ExtrusionAlongPathObjX()"
1877   if ( !isPyMeshMethod && method == "ExtrusionAlongPathObjX")
1878   {
1879     isPyMeshMethod=true;
1880     theCommand->SetMethod("ExtrusionAlongPathX");
1881   }
1882
1883   // set "FindCoincidentNodesOnPart()" instead of "FindCoincidentNodesOnPartBut()"
1884   if ( !isPyMeshMethod && method == "FindCoincidentNodesOnPartBut")
1885   {
1886     isPyMeshMethod=true;
1887     theCommand->SetMethod("FindCoincidentNodesOnPart");
1888   }
1889   // DoubleNodeElemGroupNew() -> DoubleNodeElemGroup()
1890   // DoubleNodeGroupNew() -> DoubleNodeGroup()
1891   // DoubleNodeGroupsNew() -> DoubleNodeGroups()
1892   // DoubleNodeElemGroupsNew() -> DoubleNodeElemGroups()
1893   if ( !isPyMeshMethod && ( method == "DoubleNodeElemGroupNew"  ||
1894                             method == "DoubleNodeElemGroupsNew" ||
1895                             method == "DoubleNodeGroupNew"      ||
1896                             method == "DoubleNodeGroupsNew"))
1897   {
1898     isPyMeshMethod=true;
1899     theCommand->SetMethod( method.SubString( 1, method.Length()-3));
1900     theCommand->SetArg(theCommand->GetNbArgs()+1,"True");
1901   }
1902   // ConvertToQuadraticObject(bool,obj) -> ConvertToQuadratic(bool,obj)
1903   // ConvertFromQuadraticObject(obj) -> ConvertFromQuadratic(obj)
1904   if ( !isPyMeshMethod && ( method == "ConvertToQuadraticObject" ||
1905                             method == "ConvertFromQuadraticObject" ))
1906   {
1907     isPyMeshMethod=true;
1908     theCommand->SetMethod( method.SubString( 1, method.Length()-6));
1909     // prevent moving creation of the converted sub-mesh to the end of the script
1910     bool isFromQua = ( method.Value( 8 ) == 'F' );
1911     Handle(_pySubMesh) sm = theGen->FindSubMesh( theCommand->GetArg( isFromQua ? 1 : 2 ));
1912     if ( !sm.IsNull() )
1913       sm->Process( theCommand );
1914   }
1915   // FindAmongElementsByPoint(meshPart, x, y, z, elementType) ->
1916   // FindElementsByPoint(x, y, z, elementType, meshPart)
1917   if ( !isPyMeshMethod && method == "FindAmongElementsByPoint" )
1918   {
1919     isPyMeshMethod=true;
1920     theCommand->SetMethod( "FindElementsByPoint" );
1921     // make the 1st arg be the last one
1922     _pyID partID = theCommand->GetArg( 1 );
1923     int nbArgs = theCommand->GetNbArgs();
1924     for ( int i = 2; i <= nbArgs; ++i )
1925       theCommand->SetArg( i-1, theCommand->GetArg( i ));
1926     theCommand->SetArg( nbArgs, partID );
1927   }
1928
1929   // meshes made by *MakeMesh() methods are not wrapped by _pyMesh,
1930   // so let _pyMesh care of it (TMP?)
1931   //     if ( theCommand->GetMethod().Search("MakeMesh") != -1 )
1932   //       _pyMesh( new _pyCommand( theCommand->GetString(), 0 )); // for theGen->SetAccessorMethod()
1933   if ( isPyMeshMethod )
1934   {
1935     theCommand->SetObject( myMesh );
1936   }
1937   else
1938   {
1939     // editor creation command is needed only if any editor function is called
1940     theGen->AddMeshAccessorMethod( theCommand ); // for *Object()
1941     if ( !myCreationCmdStr.IsEmpty() ) {
1942       GetCreationCmd()->GetString() = myCreationCmdStr;
1943       myCreationCmdStr.Clear();
1944     }
1945   }
1946 }
1947
1948 //================================================================================
1949 /*!
1950  * \brief Return true if my mesh can be removed
1951  */
1952 //================================================================================
1953
1954 bool _pyMeshEditor::CanClear()
1955 {
1956   Handle(_pyMesh) mesh = ObjectToMesh( theGen->FindObject( myMesh ));
1957   return mesh.IsNull() ? true : mesh->CanClear();
1958 }
1959
1960 //================================================================================
1961 /*!
1962  * \brief _pyHypothesis constructor
1963   * \param theCreationCmd -
1964  */
1965 //================================================================================
1966
1967 _pyHypothesis::_pyHypothesis(const Handle(_pyCommand)& theCreationCmd):
1968   _pyObject( theCreationCmd ), myCurCrMethod(0)
1969 {
1970   myIsAlgo = myIsWrapped = /*myIsConverted = myIsLocal = myDim = */false;
1971 }
1972
1973 //================================================================================
1974 /*!
1975  * \brief Creates algorithm or hypothesis
1976   * \param theCreationCmd - The engine command creating a hypothesis
1977   * \retval Handle(_pyHypothesis) - Result _pyHypothesis
1978  */
1979 //================================================================================
1980
1981 Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& theCreationCmd)
1982 {
1983   // theCreationCmd: CreateHypothesis( "theHypType", "theLibName" )
1984   ASSERT (( theCreationCmd->GetMethod() == "CreateHypothesis"));
1985
1986   Handle(_pyHypothesis) hyp, algo;
1987
1988   // "theHypType"
1989   const TCollection_AsciiString & hypTypeQuoted = theCreationCmd->GetArg( 1 );
1990   if ( hypTypeQuoted.IsEmpty() )
1991     return hyp;
1992   // theHypType
1993   TCollection_AsciiString  hypType =
1994     hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
1995
1996   algo = new _pyAlgorithm( theCreationCmd );
1997   hyp  = new _pyHypothesis( theCreationCmd );
1998
1999   if ( hypType == "NumberOfSegments" ) {
2000     hyp = new _pyNumberOfSegmentsHyp( theCreationCmd );
2001     hyp->SetConvMethodAndType( "NumberOfSegments", "Regular_1D");
2002     // arg of SetNumberOfSegments() will become the 1-st arg of hyp creation command
2003     hyp->AddArgMethod( "SetNumberOfSegments" );
2004     // arg of SetScaleFactor() will become the 2-nd arg of hyp creation command
2005     hyp->AddArgMethod( "SetScaleFactor" );
2006     hyp->AddArgMethod( "SetReversedEdges" );
2007     // same for ""CompositeSegment_1D:
2008     hyp->SetConvMethodAndType( "NumberOfSegments", "CompositeSegment_1D");
2009     hyp->AddArgMethod( "SetNumberOfSegments" );
2010     hyp->AddArgMethod( "SetScaleFactor" );
2011     hyp->AddArgMethod( "SetReversedEdges" );
2012   }
2013   else if ( hypType == "SegmentLengthAroundVertex" ) {
2014     hyp = new _pySegmentLengthAroundVertexHyp( theCreationCmd );
2015     hyp->SetConvMethodAndType( "LengthNearVertex", "Regular_1D" );
2016     hyp->AddArgMethod( "SetLength" );
2017     // same for ""CompositeSegment_1D:
2018     hyp->SetConvMethodAndType( "LengthNearVertex", "CompositeSegment_1D");
2019     hyp->AddArgMethod( "SetLength" );
2020   }
2021   else if ( hypType == "LayerDistribution2D" ) {
2022     hyp = new _pyLayerDistributionHypo( theCreationCmd, "Get2DHypothesis" );
2023     hyp->SetConvMethodAndType( "LayerDistribution", "RadialQuadrangle_1D2D");
2024   }
2025   else if ( hypType == "LayerDistribution" ) {
2026     hyp = new _pyLayerDistributionHypo( theCreationCmd, "Get3DHypothesis" );
2027     hyp->SetConvMethodAndType( "LayerDistribution", "RadialPrism_3D");
2028   }
2029   else if ( hypType == "CartesianParameters3D" ) {
2030     hyp = new _pyComplexParamHypo( theCreationCmd );
2031     hyp->SetConvMethodAndType( "SetGrid", "Cartesian_3D");
2032     for ( int iArg = 0; iArg < 4; ++iArg )
2033       hyp->setCreationArg( iArg+1, "[]");
2034   }
2035   else
2036   {
2037     hyp = theGen->GetHypothesisReader()->GetHypothesis( hypType, theCreationCmd );
2038   }
2039
2040   return algo->IsValid() ? algo : hyp;
2041 }
2042
2043 //================================================================================
2044 /*!
2045  * \brief Returns true if addition of this hypothesis to a given mesh can be
2046  *        wrapped into hypothesis creation
2047  */
2048 //================================================================================
2049
2050 bool _pyHypothesis::IsWrappable(const _pyID& theMesh) const
2051 {
2052   if ( !myIsWrapped && myMesh == theMesh && IsInStudy() )
2053   {
2054     Handle(_pyObject) pyMesh = theGen->FindObject( myMesh );
2055     if ( !pyMesh.IsNull() && pyMesh->IsInStudy() )
2056       return true;
2057   }
2058   return false;
2059 }
2060
2061 //================================================================================
2062 /*!
2063  * \brief Convert the command adding a hypothesis to mesh into a smesh command
2064   * \param theCmd - The command like mesh.AddHypothesis( geom, hypo )
2065   * \param theAlgo - The algo that can create this hypo
2066   * \retval bool - false if the command cant be converted
2067  */
2068 //================================================================================
2069
2070 bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd,
2071                                        const _pyID&              theMesh)
2072 {
2073   ASSERT(( theCmd->GetMethod() == "AddHypothesis" ));
2074
2075   if ( !IsWrappable( theMesh ))
2076     return false;
2077
2078   myGeom = theCmd->GetArg( 1 );
2079
2080   Handle(_pyHypothesis) algo;
2081   if ( !IsAlgo() ) {
2082     // find algo created on myGeom in theMesh
2083     algo = theGen->FindAlgo( myGeom, theMesh, this );
2084     if ( algo.IsNull() )
2085       return false;
2086     // attach hypothesis creation command to be after algo creation command
2087     // because it can be new created instance of algorithm
2088     algo->GetCreationCmd()->AddDependantCmd( theCmd );
2089   }
2090   myIsWrapped = true;
2091
2092   // mesh.AddHypothesis(geom,hyp) --> hyp = <theMesh or algo>.myCreationMethod(args)
2093   theCmd->SetResultValue( GetID() );
2094   theCmd->SetObject( IsAlgo() ? theMesh : algo->GetID());
2095   theCmd->SetMethod( IsAlgo() ? GetAlgoCreationMethod() : GetCreationMethod( algo->GetAlgoType() ));
2096   // set args (geom will be set by _pyMesh calling this method)
2097   theCmd->RemoveArgs();
2098   for ( size_t i = 0; i < myCurCrMethod->myArgs.size(); ++i ) {
2099     if ( !myCurCrMethod->myArgs[ i ].IsEmpty() )
2100       theCmd->SetArg( i+1, myCurCrMethod->myArgs[ i ]);
2101     else
2102       theCmd->SetArg( i+1, "[]");
2103   }
2104   // set a new creation command
2105   GetCreationCmd()->Clear();
2106   // replace creation command by wrapped instance
2107   // please note, that hypothesis attaches to algo creation command (see upper)
2108   SetCreationCmd( theCmd );
2109
2110
2111   // clear commands setting arg values
2112   list < Handle(_pyCommand) >::iterator argCmd = myArgCommands.begin();
2113   for ( ; argCmd != myArgCommands.end(); ++argCmd )
2114     (*argCmd)->Clear();
2115
2116   // set unknown arg commands after hypo creation
2117   Handle(_pyCommand) afterCmd = myIsWrapped ? theCmd : GetCreationCmd();
2118   list<Handle(_pyCommand)>::iterator cmd = myUnusedCommands.begin();
2119   for ( ; cmd != myUnusedCommands.end(); ++cmd ) {
2120     afterCmd->AddDependantCmd( *cmd );
2121   }
2122
2123   return myIsWrapped;
2124 }
2125
2126 //================================================================================
2127 /*!
2128  * \brief Remember hypothesis parameter values
2129  * \param theCommand - The called hypothesis method
2130  */
2131 //================================================================================
2132
2133 void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand)
2134 {
2135   ASSERT( !myIsAlgo );
2136   if ( !theGen->IsToKeepAllCommands() )
2137     rememberCmdOfParameter( theCommand );
2138   // set args
2139   bool usedCommand = false;
2140   TType2CrMethod::iterator type2meth = myAlgoType2CreationMethod.begin();
2141   for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth )
2142   {
2143     CreationMethod& crMethod = type2meth->second;
2144     for ( size_t i = 0; i < crMethod.myArgMethods.size(); ++i ) {
2145       if ( crMethod.myArgMethods[ i ] == theCommand->GetMethod() ) {
2146         if ( !usedCommand )
2147           myArgCommands.push_back( theCommand );
2148         usedCommand = true;
2149         while ( crMethod.myArgs.size() < i+1 )
2150           crMethod.myArgs.push_back( "[]" );
2151         crMethod.myArgs[ i ] = theCommand->GetArg( crMethod.myArgNb[i] );
2152       }
2153     }
2154   }
2155   if ( !usedCommand )
2156     myUnusedCommands.push_back( theCommand );
2157 }
2158
2159 //================================================================================
2160 /*!
2161  * \brief Finish conversion
2162  */
2163 //================================================================================
2164
2165 void _pyHypothesis::Flush()
2166 {
2167   if ( !IsAlgo() )
2168   {
2169     list < Handle(_pyCommand) >::iterator cmd = myArgCommands.begin();
2170     for ( ; cmd != myArgCommands.end(); ++cmd ) {
2171       // Add access to a wrapped mesh
2172       theGen->AddMeshAccessorMethod( *cmd );
2173       // Add access to a wrapped algorithm
2174       theGen->AddAlgoAccessorMethod( *cmd );
2175     }
2176     cmd = myUnusedCommands.begin();
2177     for ( ; cmd != myUnusedCommands.end(); ++cmd ) {
2178       // Add access to a wrapped mesh
2179       theGen->AddMeshAccessorMethod( *cmd );
2180       // Add access to a wrapped algorithm
2181       theGen->AddAlgoAccessorMethod( *cmd );
2182     }
2183   }
2184   // forget previous hypothesis modifications
2185   myArgCommands.clear();
2186   myUnusedCommands.clear();
2187 }
2188
2189 //================================================================================
2190 /*!
2191  * \brief clear creation, arg and unkown commands
2192  */
2193 //================================================================================
2194
2195 void _pyHypothesis::ClearAllCommands()
2196 {
2197   GetCreationCmd()->Clear();
2198   list<Handle(_pyCommand)>::iterator cmd = myArgCommands.begin();
2199   for ( ; cmd != myArgCommands.end(); ++cmd )
2200     ( *cmd )->Clear();
2201   cmd = myUnusedCommands.begin();
2202   for ( ; cmd != myUnusedCommands.end(); ++cmd )
2203     ( *cmd )->Clear();
2204 }
2205
2206
2207 //================================================================================
2208 /*!
2209  * \brief Assign fields of theOther to me except myIsWrapped
2210  */
2211 //================================================================================
2212
2213 void _pyHypothesis::Assign( const Handle(_pyHypothesis)& theOther,
2214                             const _pyID&                 theMesh )
2215 {
2216   // myCreationCmd = theOther->myCreationCmd;
2217   myIsAlgo                  = theOther->myIsAlgo;
2218   myIsWrapped               = false;
2219   myGeom                    = theOther->myGeom;
2220   myMesh                    = theMesh;
2221   myAlgoType2CreationMethod = theOther->myAlgoType2CreationMethod;
2222   //myArgCommands             = theOther->myArgCommands;
2223   //myUnusedCommands          = theOther->myUnusedCommands;
2224   // init myCurCrMethod
2225   GetCreationMethod( theOther->GetAlgoType() );
2226 }
2227
2228 //================================================================================
2229 /*!
2230  * \brief Analyze my erasability depending on myReferredObjs
2231  */
2232 //================================================================================
2233
2234 bool _pyHypothesis::CanClear()
2235 {
2236   if ( IsInStudy() )
2237   {
2238     list< Handle(_pyObject) >::iterator obj = myReferredObjs.begin();
2239     for ( ; obj != myReferredObjs.end(); ++obj )
2240       if ( (*obj)->CanClear() )
2241         return true;
2242     return false;
2243   }
2244   return true;
2245 }
2246
2247 //================================================================================
2248 /*!
2249  * \brief Clear my commands depending on usage by meshes
2250  */
2251 //================================================================================
2252
2253 void _pyHypothesis::ClearCommands()
2254 {
2255   // if ( !theGen->IsToKeepAllCommands() )
2256   // {
2257   //   bool isUsed = false;
2258   //   int lastComputeOrder = 0;
2259   //   list<Handle(_pyCommand) >::iterator cmd = myComputeCmds.begin();
2260   //   for ( ; cmd != myComputeCmds.end(); ++cmd )
2261   //     if ( ! (*cmd)->IsEmpty() )
2262   //     {
2263   //       isUsed = true;
2264   //       if ( (*cmd)->GetOrderNb() > lastComputeOrder )
2265   //         lastComputeOrder = (*cmd)->GetOrderNb();
2266   //     }
2267   //   if ( !isUsed )
2268   //   {
2269   //     SetRemovedFromStudy( true );
2270   //   }
2271   //   else
2272   //   {
2273   //     // clear my commands invoked after lastComputeOrder
2274   //     // map<TCollection_AsciiString, list< Handle(_pyCommand) > >::iterator m2c;
2275   //     // for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c )
2276   //     // {
2277   //     //   list< Handle(_pyCommand)> & cmds = m2c->second;
2278   //     //   if ( !cmds.empty() && cmds.back()->GetOrderNb() > lastComputeOrder )
2279   //     //     cmds.back()->Clear();
2280   //     // }
2281   //   }
2282   // }
2283   _pyObject::ClearCommands();
2284 }
2285
2286 //================================================================================
2287 /*!
2288  * \brief Find arguments that are objects like mesh, group, geometry
2289  *  \param meshes - referred meshes (directly or indirrectly)
2290  *  \retval bool - false if a referred geometry is not in the study
2291  */
2292 //================================================================================
2293
2294 bool _pyHypothesis::GetReferredMeshesAndGeom( list< Handle(_pyMesh) >& meshes )
2295 {
2296   if ( IsAlgo() ) return true;
2297
2298   bool geomPublished = true;
2299   vector< _AString > args;
2300   TType2CrMethod::iterator type2meth = myAlgoType2CreationMethod.begin();
2301   for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth )
2302   {
2303     CreationMethod& crMethod = type2meth->second;
2304     args.insert( args.end(), crMethod.myArgs.begin(), crMethod.myArgs.end());
2305   }
2306   list<Handle(_pyCommand)>::iterator cmd = myUnusedCommands.begin();
2307   for ( ; cmd != myUnusedCommands.end(); ++cmd ) {
2308     for ( int nb = (*cmd)->GetNbArgs(); nb; --nb )
2309       args.push_back( (*cmd)->GetArg( nb ));
2310   }
2311
2312   for ( size_t i = 0; i < args.size(); ++i )
2313   {
2314     list< _pyID > idList = _pyCommand::GetStudyEntries( args[ i ]);
2315     if ( idList.empty() && !args[ i ].IsEmpty() )
2316       idList.push_back( args[ i ]);
2317     list< _pyID >::iterator id = idList.begin();
2318     for ( ; id != idList.end(); ++id )
2319     {
2320       Handle(_pyObject)   obj = theGen->FindObject( *id );
2321       if ( obj.IsNull() ) obj = theGen->FindHyp( *id );
2322       if ( obj.IsNull() )
2323       {
2324         if ( theGen->IsGeomObject( *id ) && theGen->IsNotPublished( *id ))
2325           geomPublished = false;
2326       }
2327       else
2328       {
2329         myReferredObjs.push_back( obj );
2330         Handle(_pyMesh) mesh = ObjectToMesh( obj );
2331         if ( !mesh.IsNull() )
2332           meshes.push_back( mesh );
2333         // prevent clearing not published hyps referred e.g. by "LayerDistribution"
2334         else if ( obj->IsKind( STANDARD_TYPE( _pyHypothesis )) && this->IsInStudy() )
2335           obj->SetRemovedFromStudy( false );
2336       }
2337     }
2338   }
2339   return geomPublished;
2340 }
2341
2342 //================================================================================
2343 /*!
2344  * \brief Remember theCommand setting a parameter
2345  */
2346 //================================================================================
2347
2348 void _pyHypothesis::rememberCmdOfParameter( const Handle(_pyCommand) & theCommand )
2349 {
2350   // parameters are discriminated by method name
2351   TCollection_AsciiString method = theCommand->GetMethod();
2352
2353   // discriminate commands setting different parameters via one method
2354   // by passing parameter names like e.g. SetOption("size", "0.2")
2355   if ( theCommand->GetString().FirstLocationInSet( "'\"", 1, theCommand->Length() ) &&
2356        theCommand->GetNbArgs() > 1 )
2357   {
2358     // mangle method by appending a 1st textual arg
2359     for ( int iArg = 1; iArg <= theCommand->GetNbArgs(); ++iArg )
2360     {
2361       const TCollection_AsciiString& arg = theCommand->GetArg( iArg );
2362       if ( arg.Value(1) != '\"' && arg.Value(1) != '\'' ) continue;
2363       if ( !isalpha( arg.Value(2))) continue;
2364       method += arg;
2365       break;
2366     }
2367   }
2368   // parameters are discriminated by method name
2369   list< Handle(_pyCommand)>& cmds = myMeth2Commands[ theCommand->GetMethod() ];
2370   if ( !cmds.empty() && !isCmdUsedForCompute( cmds.back() ))
2371   {
2372     cmds.back()->Clear(); // previous parameter value has not been used
2373     cmds.back() = theCommand;
2374   }
2375   else
2376   {
2377     cmds.push_back( theCommand );
2378   }
2379 }
2380
2381 //================================================================================
2382 /*!
2383  * \brief Return true if a setting parameter command ha been used to compute mesh
2384  */
2385 //================================================================================
2386
2387 bool _pyHypothesis::isCmdUsedForCompute( const Handle(_pyCommand) & cmd,
2388                                          _pyCommand::TAddr          avoidComputeAddr ) const
2389 {
2390   bool isUsed = false;
2391   map< _pyCommand::TAddr, list<Handle(_pyCommand) > >::const_iterator addr2cmds =
2392     myComputeAddr2Cmds.begin();
2393   for ( ; addr2cmds != myComputeAddr2Cmds.end() && !isUsed; ++addr2cmds )
2394   {
2395     if ( addr2cmds->first == avoidComputeAddr ) continue;
2396     const list<Handle(_pyCommand)> & cmds = addr2cmds->second;
2397     isUsed = ( std::find( cmds.begin(), cmds.end(), cmd ) != cmds.end() );
2398   }
2399   return isUsed;
2400 }
2401
2402 //================================================================================
2403 /*!
2404  * \brief Save commands setting parameters as they are used for a mesh computation
2405  */
2406 //================================================================================
2407
2408 void _pyHypothesis::MeshComputed( const Handle(_pyCommand)& theComputeCmd )
2409 {
2410   myComputeCmds.push_back( theComputeCmd );
2411   list<Handle(_pyCommand)>& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ];
2412
2413   map<TCollection_AsciiString, list< Handle(_pyCommand) > >::iterator m2c;
2414   for ( m2c = myMeth2Commands.begin(); m2c != myMeth2Commands.end(); ++m2c )
2415     savedCmds.push_back( m2c->second.back() );
2416 }
2417
2418 //================================================================================
2419 /*!
2420  * \brief Clear commands setting parameters as a mesh computed using them is cleared
2421  */
2422 //================================================================================
2423
2424 void _pyHypothesis::ComputeDiscarded( const Handle(_pyCommand)& theComputeCmd )
2425 {
2426   list<Handle(_pyCommand)>& savedCmds = myComputeAddr2Cmds[ theComputeCmd->GetAddress() ];
2427
2428   list<Handle(_pyCommand)>::iterator cmd = savedCmds.begin();
2429   for ( ; cmd != savedCmds.end(); ++cmd )
2430   {
2431     // check if a cmd has been used to compute another mesh
2432     if ( isCmdUsedForCompute( *cmd, theComputeCmd->GetAddress() ))
2433       continue;
2434     // check if a cmd is a sole command setting its parameter;
2435     // don't use method name for search as it can change
2436     map<TCollection_AsciiString, list<Handle(_pyCommand)> >::iterator
2437       m2cmds = myMeth2Commands.begin();
2438     for ( ; m2cmds != myMeth2Commands.end(); ++m2cmds )
2439     {
2440       list< Handle(_pyCommand)>& cmds = m2cmds->second;
2441       list< Handle(_pyCommand)>::iterator cmdIt = std::find( cmds.begin(), cmds.end(), *cmd );
2442       if ( cmdIt != cmds.end() )
2443       {
2444         if ( cmds.back() != *cmd )
2445         {
2446           cmds.erase( cmdIt );
2447           (*cmd)->Clear();
2448         }
2449         break;
2450       }
2451     }
2452   }
2453   myComputeAddr2Cmds.erase( theComputeCmd->GetAddress() );
2454 }
2455
2456 //================================================================================
2457 /*!
2458  * \brief Sets an argNb-th argument of current creation command
2459  *  \param argNb - argument index countered from 1
2460  */
2461 //================================================================================
2462
2463 void _pyHypothesis::setCreationArg( const int argNb, const _AString& arg )
2464 {
2465   if ( myCurCrMethod )
2466   {
2467     while ( myCurCrMethod->myArgs.size() < argNb )
2468       myCurCrMethod->myArgs.push_back( "None" );
2469     if ( arg.IsEmpty() )
2470       myCurCrMethod->myArgs[ argNb-1 ] = "None";
2471     else
2472       myCurCrMethod->myArgs[ argNb-1 ] = arg;
2473   }
2474 }
2475
2476
2477 //================================================================================
2478 /*!
2479  * \brief Remember hypothesis parameter values
2480  * \param theCommand - The called hypothesis method
2481  */
2482 //================================================================================
2483
2484 void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
2485 {
2486   if ( GetAlgoType() == "Cartesian_3D" )
2487   {
2488     // CartesianParameters3D hyp
2489
2490     if ( theCommand->GetMethod() == "SetSizeThreshold" )
2491     {
2492       setCreationArg( 4, theCommand->GetArg( 1 ));
2493       myArgCommands.push_back( theCommand );
2494       return;
2495     }
2496     if ( theCommand->GetMethod() == "SetGrid" ||
2497          theCommand->GetMethod() == "SetGridSpacing" )
2498     {
2499       TCollection_AsciiString axis = theCommand->GetArg( theCommand->GetNbArgs() );
2500       int iArg = axis.Value(1) - '0';
2501       if ( theCommand->GetMethod() == "SetGrid" )
2502       {
2503         setCreationArg( 1+iArg, theCommand->GetArg( 1 ));
2504       }
2505       else
2506       {
2507         myCurCrMethod->myArgs[ iArg ] = "[ ";
2508         myCurCrMethod->myArgs[ iArg ] += theCommand->GetArg( 1 );
2509         myCurCrMethod->myArgs[ iArg ] += ", ";
2510         myCurCrMethod->myArgs[ iArg ] += theCommand->GetArg( 2 );
2511         myCurCrMethod->myArgs[ iArg ] += "]";
2512       }
2513       myArgCommands.push_back( theCommand );
2514       rememberCmdOfParameter( theCommand );
2515       return;
2516     }
2517   }
2518
2519   if( theCommand->GetMethod() == "SetLength" )
2520   {
2521     // NOW it is OBSOLETE
2522     // ex: hyp.SetLength(start, 1)
2523     //     hyp.SetLength(end,   0)
2524     ASSERT(( theCommand->GetArg( 2 ).IsIntegerValue() ));
2525     int i = 1 - theCommand->GetArg( 2 ).IntegerValue();
2526     TType2CrMethod::iterator type2meth = myAlgoType2CreationMethod.begin();
2527     for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth )
2528     {
2529       CreationMethod& crMethod = type2meth->second;
2530         while ( crMethod.myArgs.size() < i+1 )
2531           crMethod.myArgs.push_back( "[]" );
2532         crMethod.myArgs[ i ] = theCommand->GetArg( 1 ); // arg value
2533     }
2534     myArgCommands.push_back( theCommand );
2535   }
2536   else
2537   {
2538     _pyHypothesis::Process( theCommand );
2539   }
2540 }
2541 //================================================================================
2542 /*!
2543  * \brief Clear SetObjectEntry() as it is called by methods of Mesh_Segment
2544  */
2545 //================================================================================
2546
2547 void _pyComplexParamHypo::Flush()
2548 {
2549   if ( IsWrapped() )
2550   {
2551     list < Handle(_pyCommand) >::iterator cmd = myUnusedCommands.begin();
2552     for ( ; cmd != myUnusedCommands.end(); ++cmd )
2553       if ((*cmd)->GetMethod() == "SetObjectEntry" )
2554         (*cmd)->Clear();
2555   }
2556 }
2557
2558 //================================================================================
2559 /*!
2560  * \brief Convert methods of 1D hypotheses to my own methods
2561   * \param theCommand - The called hypothesis method
2562  */
2563 //================================================================================
2564
2565 void _pyLayerDistributionHypo::Process( const Handle(_pyCommand)& theCommand)
2566 {
2567   if ( theCommand->GetMethod() != "SetLayerDistribution" )
2568     return;
2569
2570   const _pyID& hyp1dID = theCommand->GetArg( 1 );
2571   // Handle(_pyHypothesis) hyp1d = theGen->FindHyp( hyp1dID );
2572   // if ( hyp1d.IsNull() && ! my1dHyp.IsNull()) // apparently hypId changed at study restoration
2573   // {
2574   //   TCollection_AsciiString cmd =
2575   //     my1dHyp->GetCreationCmd()->GetIndentation() + hyp1dID + " = " + my1dHyp->GetID();
2576   //   Handle(_pyCommand) newCmd = theGen->AddCommand( cmd );
2577   //   theGen->SetCommandAfter( newCmd, my1dHyp->GetCreationCmd() );
2578   //   hyp1d = my1dHyp;
2579   // }
2580   // else if ( !my1dHyp.IsNull() && hyp1dID != my1dHyp->GetID() )
2581   // {
2582   //   // 1D hypo is already set, so distribution changes and the old
2583   //   // 1D hypo is thrown away
2584   //   my1dHyp->ClearAllCommands();
2585   // }
2586   // my1dHyp = hyp1d;
2587   // //my1dHyp->SetRemovedFromStudy( false );
2588
2589   // if ( !myArgCommands.empty() )
2590   //   myArgCommands.back()->Clear();
2591   myCurCrMethod->myArgs.push_back( hyp1dID );
2592   myArgCommands.push_back( theCommand );
2593 }
2594
2595 //================================================================================
2596 /*!
2597  * \brief
2598   * \param theAdditionCmd - command to be converted
2599   * \param theMesh - mesh instance
2600   * \retval bool - status
2601  */
2602 //================================================================================
2603
2604 bool _pyLayerDistributionHypo::Addition2Creation( const Handle(_pyCommand)& theAdditionCmd,
2605                                                   const _pyID&              theMesh)
2606 {
2607   myIsWrapped = false;
2608
2609   if ( my1dHyp.IsNull() )
2610     return false;
2611
2612   // set "SetLayerDistribution()" after addition cmd
2613   theAdditionCmd->AddDependantCmd( myArgCommands.front() );
2614
2615   _pyID geom = theAdditionCmd->GetArg( 1 );
2616
2617   Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMesh, this );
2618   if ( !algo.IsNull() )
2619   {
2620     my1dHyp->SetMesh( theMesh );
2621     my1dHyp->SetConvMethodAndType(my1dHyp->GetAlgoCreationMethod().ToCString(),
2622                                   algo->GetAlgoType().ToCString());
2623     if ( !my1dHyp->Addition2Creation( theAdditionCmd, theMesh ))
2624       return false;
2625
2626     // clear "SetLayerDistribution()" cmd
2627     myArgCommands.back()->Clear();
2628
2629     // Convert my creation => me = RadialPrismAlgo.Get3DHypothesis()
2630
2631     // find RadialPrism algo created on <geom> for theMesh
2632     GetCreationCmd()->SetObject( algo->GetID() );
2633     GetCreationCmd()->SetMethod( myAlgoMethod );
2634     GetCreationCmd()->RemoveArgs();
2635     theAdditionCmd->AddDependantCmd( GetCreationCmd() );
2636     myIsWrapped = true;
2637   }
2638   return myIsWrapped;
2639 }
2640
2641 //================================================================================
2642 /*!
2643  * \brief
2644  */
2645 //================================================================================
2646
2647 void _pyLayerDistributionHypo::Flush()
2648 {
2649   // as creation of 1D hyp was written later then it's edition,
2650   // we need to find all it's edition calls and process them
2651   list< Handle(_pyCommand) >::iterator cmd = myArgCommands.begin();
2652   _pyID prevNewName;
2653   for ( cmd = myArgCommands.begin(); cmd != myArgCommands.end(); ++cmd )
2654   {    
2655     const _pyID& hyp1dID = (*cmd)->GetArg( 1 );
2656     if ( hyp1dID.IsEmpty() ) continue;
2657
2658     Handle(_pyHypothesis) hyp1d = theGen->FindHyp( hyp1dID );
2659
2660     // make a new name for 1D hyp = "HypType" + "_Distribution"
2661     _pyID newName;
2662     if ( hyp1d.IsNull() ) // apparently hypId changed at study restoration
2663     {
2664       if ( prevNewName.IsEmpty() ) continue;
2665       newName = prevNewName;
2666     }
2667     else
2668     {
2669       if ( hyp1d->IsWrapped() ) {
2670         newName = hyp1d->GetCreationCmd()->GetMethod();
2671       }
2672       else {
2673         TCollection_AsciiString hypTypeQuoted = hyp1d->GetCreationCmd()->GetArg(1);
2674         newName = hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
2675       }
2676       newName += "_Distribution";
2677       prevNewName = newName;
2678     
2679       hyp1d->GetCreationCmd()->SetResultValue( newName );
2680     }
2681     list< Handle(_pyCommand) >& cmds = theGen->GetCommands();
2682     list< Handle(_pyCommand) >::iterator cmdIt = cmds.begin();
2683     for ( ; cmdIt != cmds.end(); ++cmdIt ) {
2684       const _pyID& objID = (*cmdIt)->GetObject();
2685       if ( objID == hyp1dID ) {
2686         if ( !hyp1d.IsNull() )
2687         {
2688           hyp1d->Process( *cmdIt );
2689           hyp1d->GetCreationCmd()->AddDependantCmd( *cmdIt );
2690         }
2691         ( *cmdIt )->SetObject( newName );
2692       }
2693     }
2694     // Set new hyp name to SetLayerDistribution(hyp1dID) cmd
2695     (*cmd)->SetArg( 1, newName );
2696   }
2697 }
2698
2699 //================================================================================
2700 /*!
2701  * \brief additionally to Addition2Creation, clears SetDistrType() command
2702   * \param theCmd - AddHypothesis() command
2703   * \param theMesh - mesh to which a hypothesis is added
2704   * \retval bool - convertion result
2705  */
2706 //================================================================================
2707
2708 bool _pyNumberOfSegmentsHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
2709                                                 const _pyID&              theMesh)
2710 {
2711   if ( IsWrappable( theMesh ) && myCurCrMethod->myArgs.size() > 1 ) {
2712     // scale factor (2-nd arg) is provided: clear SetDistrType(1) command
2713     bool scaleDistrType = false;
2714     list<Handle(_pyCommand)>::reverse_iterator cmd = myUnusedCommands.rbegin();
2715     for ( ; cmd != myUnusedCommands.rend(); ++cmd ) {
2716       if ( (*cmd)->GetMethod() == "SetDistrType" ) {
2717         if ( (*cmd)->GetArg( 1 ) == "1" ) {
2718           scaleDistrType = true;
2719           (*cmd)->Clear();
2720         }
2721         else if ( !scaleDistrType ) {
2722           // distribution type changed: remove scale factor from args
2723           TType2CrMethod::iterator type2meth = myAlgoType2CreationMethod.begin();
2724           for ( ; type2meth != myAlgoType2CreationMethod.end(); ++type2meth )
2725           {
2726             CreationMethod& crMethod = type2meth->second;
2727             if ( crMethod.myArgs.size() == 2 )
2728               crMethod.myArgs.pop_back();
2729           }
2730           break;
2731         }
2732       }
2733     }
2734   }
2735   return _pyHypothesis::Addition2Creation( theCmd, theMesh );
2736 }
2737
2738 //================================================================================
2739 /*!
2740  * \brief remove repeated commands defining distribution
2741  */
2742 //================================================================================
2743
2744 void _pyNumberOfSegmentsHyp::Flush()
2745 {
2746   // find number of the last SetDistrType() command
2747   list<Handle(_pyCommand)>::reverse_iterator cmd = myUnusedCommands.rbegin();
2748   int distrTypeNb = 0;
2749   for ( ; !distrTypeNb && cmd != myUnusedCommands.rend(); ++cmd )
2750     if ( (*cmd)->GetMethod() == "SetDistrType" )
2751       distrTypeNb = (*cmd)->GetOrderNb();
2752     else if (IsWrapped() && (*cmd)->GetMethod() == "SetObjectEntry" )
2753       (*cmd)->Clear();
2754
2755   // clear commands before the last SetDistrType()
2756   list<Handle(_pyCommand)> * cmds[2] = { &myArgCommands, &myUnusedCommands };
2757   for ( int i = 0; i < 2; ++i ) {
2758     set<TCollection_AsciiString> uniqueMethods;
2759     list<Handle(_pyCommand)> & cmdList = *cmds[i];
2760     for ( cmd = cmdList.rbegin(); cmd != cmdList.rend(); ++cmd )
2761     {
2762       bool clear = ( (*cmd)->GetOrderNb() < distrTypeNb );
2763       const TCollection_AsciiString& method = (*cmd)->GetMethod();
2764       if ( !clear || method == "SetNumberOfSegments" ) {
2765         bool isNewInSet = uniqueMethods.insert( method ).second;
2766         clear = !isNewInSet;
2767       }
2768       if ( clear )
2769         (*cmd)->Clear();
2770     }
2771     cmdList.clear();
2772   }
2773 }
2774
2775 //================================================================================
2776 /*!
2777  * \brief Convert the command adding "SegmentLengthAroundVertex" to mesh
2778  * into regular1D.LengthNearVertex( length, vertex )
2779   * \param theCmd - The command like mesh.AddHypothesis( vertex, SegmentLengthAroundVertex )
2780   * \param theMesh - The mesh needing this hypo
2781   * \retval bool - false if the command cant be converted
2782  */
2783 //================================================================================
2784
2785 bool _pySegmentLengthAroundVertexHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
2786                                                          const _pyID&              theMeshID)
2787 {
2788   if ( IsWrappable( theMeshID )) {
2789
2790     _pyID vertex = theCmd->GetArg( 1 );
2791
2792     // the problem here is that segment algo will not be found
2793     // by pyHypothesis::Addition2Creation() for <vertex>, so we try to find
2794     // geometry where segment algorithm is assigned
2795     Handle(_pyHypothesis) algo;
2796     _pyID geom = vertex;
2797     while ( algo.IsNull() && !geom.IsEmpty()) {
2798       // try to find geom as a father of <vertex>
2799       geom = FatherID( geom );
2800       algo = theGen->FindAlgo( geom, theMeshID, this );
2801     }
2802     if ( algo.IsNull() )
2803       return false; // also possible to find geom as brother of veretex...
2804     // set geom instead of vertex
2805     theCmd->SetArg( 1, geom );
2806
2807     // set vertex as a second arg
2808     if ( myCurCrMethod->myArgs.size() < 1) setCreationArg( 1, "1" ); // :(
2809     setCreationArg( 2, vertex );
2810
2811     // mesh.AddHypothesis(vertex, SegmentLengthAroundVertex) -->
2812     // theMeshID.LengthNearVertex( length, vertex )
2813     return _pyHypothesis::Addition2Creation( theCmd, theMeshID );
2814   }
2815   return false;
2816 }
2817
2818 //================================================================================
2819 /*!
2820  * \brief _pyAlgorithm constructor
2821  * \param theCreationCmd - The command like "algo = smeshgen.CreateHypothesis(type,lib)"
2822  */
2823 //================================================================================
2824
2825 _pyAlgorithm::_pyAlgorithm(const Handle(_pyCommand)& theCreationCmd)
2826   : _pyHypothesis( theCreationCmd )
2827 {
2828   myIsAlgo = true;
2829 }
2830
2831 //================================================================================
2832 /*!
2833  * \brief Convert the command adding an algorithm to mesh
2834   * \param theCmd - The command like mesh.AddHypothesis( geom, algo )
2835   * \param theMesh - The mesh needing this algo
2836   * \retval bool - false if the command cant be converted
2837  */
2838 //================================================================================
2839
2840 bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd,
2841                                       const _pyID&              theMeshID)
2842 {
2843   // mesh.AddHypothesis(geom,algo) --> theMeshID.myCreationMethod()
2844   if ( _pyHypothesis::Addition2Creation( theCmd, theMeshID )) {
2845     theGen->SetAccessorMethod( GetID(), "GetAlgorithm()" );
2846     return true;
2847   }
2848   return false;
2849 }
2850
2851 //================================================================================
2852 /*!
2853  * \brief Return starting position of a part of python command
2854   * \param thePartIndex - The index of command part
2855   * \retval int - Part position
2856  */
2857 //================================================================================
2858
2859 int _pyCommand::GetBegPos( int thePartIndex )
2860 {
2861   if ( IsEmpty() )
2862     return EMPTY;
2863   if ( myBegPos.Length() < thePartIndex )
2864     return UNKNOWN;
2865   return myBegPos( thePartIndex );
2866 }
2867
2868 //================================================================================
2869 /*!
2870  * \brief Store starting position of a part of python command
2871   * \param thePartIndex - The index of command part
2872   * \param thePosition - Part position
2873  */
2874 //================================================================================
2875
2876 void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
2877 {
2878   while ( myBegPos.Length() < thePartIndex )
2879     myBegPos.Append( UNKNOWN );
2880   myBegPos( thePartIndex ) = thePosition;
2881 }
2882
2883 //================================================================================
2884 /*!
2885  * \brief Returns whitespace symbols at the line beginning
2886   * \retval TCollection_AsciiString - result
2887  */
2888 //================================================================================
2889
2890 TCollection_AsciiString _pyCommand::GetIndentation()
2891 {
2892   int end = 1;
2893   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
2894     GetWord( myString, end, true );
2895   else
2896     end = GetBegPos( RESULT_IND );
2897   return myString.SubString( 1, end - 1 );
2898 }
2899
2900 //================================================================================
2901 /*!
2902  * \brief Return substring of python command looking like ResultValue = Obj.Meth()
2903   * \retval const TCollection_AsciiString & - ResultValue substring
2904  */
2905 //================================================================================
2906
2907 const TCollection_AsciiString & _pyCommand::GetResultValue()
2908 {
2909   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
2910   {
2911     SetBegPos( RESULT_IND, EMPTY );
2912     int begPos, endPos = myString.Location( "=", 1, Length() );
2913     if ( endPos )
2914     {
2915       begPos = 1;
2916       while ( begPos < endPos && isspace( myString.Value( begPos ))) ++begPos;
2917       if ( begPos < endPos )
2918       {
2919         SetBegPos( RESULT_IND, begPos );
2920         --endPos;
2921         while ( begPos < endPos && isspace( myString.Value( endPos ))) --endPos;
2922         myRes = myString.SubString( begPos, endPos );
2923       }
2924     }
2925   }
2926   return myRes;
2927 }
2928
2929 //================================================================================
2930 /*!
2931  * \brief Return number of python command result value ResultValue = Obj.Meth()
2932   * \retval const int
2933  */
2934 //================================================================================
2935
2936 const int _pyCommand::GetNbResultValues()
2937 {
2938   int begPos = 1;
2939   int Nb=0;
2940   int endPos = myString.Location( "=", 1, Length() );
2941   TCollection_AsciiString str = "";
2942   while ( begPos < endPos) {
2943     str = GetWord( myString, begPos, true );
2944     begPos = begPos+ str.Length();
2945     Nb++;
2946   }
2947   return (Nb-1);
2948 }
2949
2950
2951 //================================================================================
2952 /*!
2953  * \brief Return substring of python command looking like
2954  *  ResultValue1 , ResultValue1,... = Obj.Meth() with res index
2955  * \retval const TCollection_AsciiString & - ResultValue with res index substring
2956  */
2957 //================================================================================
2958 const TCollection_AsciiString & _pyCommand::GetResultValue(int res)
2959 {
2960   int begPos = 1;
2961   int Nb=0;
2962   int endPos = myString.Location( "=", 1, Length() );
2963   while ( begPos < endPos) {
2964     myRes = GetWord( myString, begPos, true );
2965     begPos = begPos + myRes.Length();
2966     Nb++;
2967     if(res == Nb){
2968       myRes.RemoveAll('[');myRes.RemoveAll(']');
2969       return myRes;
2970     }
2971     if(Nb>res)
2972       break;
2973   }
2974   return theEmptyString;
2975 }
2976
2977 //================================================================================
2978 /*!
2979  * \brief Return substring of python command looking like ResVal = Object.Meth()
2980   * \retval const TCollection_AsciiString & - Object substring
2981  */
2982 //================================================================================
2983
2984 const TCollection_AsciiString & _pyCommand::GetObject()
2985 {
2986   if ( GetBegPos( OBJECT_IND ) == UNKNOWN )
2987   {
2988     // beginning
2989     int begPos = GetBegPos( RESULT_IND ) + myRes.Length();
2990     if ( begPos < 1 ) {
2991       begPos = myString.Location( "=", 1, Length() ) + 1;
2992       // is '=' in the string argument (for example, name) or not
2993       int nb1 = 0; // number of ' character at the left of =
2994       int nb2 = 0; // number of " character at the left of =
2995       for ( int i = 1; i < begPos-1; i++ ) {
2996         if ( myString.Value( i )=='\'' )
2997           nb1 += 1;
2998         else if ( myString.Value( i )=='"' )
2999           nb2 += 1;
3000       }
3001       // if number of ' or " is not divisible by 2,
3002       // then get an object at the start of the command
3003       if ( nb1 % 2 != 0 || nb2 % 2 != 0 )
3004         begPos = 1;
3005     }
3006     myObj = GetWord( myString, begPos, true );
3007     // check if object is complex,
3008     // so far consider case like "smesh.smesh.Method()"
3009     if ( int bracketPos = myString.Location( "(", begPos, Length() )) {
3010       //if ( bracketPos==0 ) bracketPos = Length();
3011       int dotPos = begPos+myObj.Length();
3012       while ( dotPos+1 < bracketPos ) {
3013         if ( int pos = myString.Location( ".", dotPos+1, bracketPos ))
3014           dotPos = pos;
3015         else
3016           break;
3017       }
3018       if ( dotPos > begPos+myObj.Length() )
3019         myObj = myString.SubString( begPos, dotPos-1 );
3020     }
3021     // 1st word after '=' is an object
3022     // else // no method -> no object
3023     // {
3024     //   myObj.Clear();
3025     //   begPos = EMPTY;
3026     // }
3027     // store
3028     SetBegPos( OBJECT_IND, begPos );
3029   }
3030   //SCRUTE(myObj);
3031   return myObj;
3032 }
3033
3034 //================================================================================
3035 /*!
3036  * \brief Return substring of python command looking like ResVal = Obj.Method()
3037   * \retval const TCollection_AsciiString & - Method substring
3038  */
3039 //================================================================================
3040
3041 const TCollection_AsciiString & _pyCommand::GetMethod()
3042 {
3043   if ( GetBegPos( METHOD_IND ) == UNKNOWN )
3044   {
3045     // beginning
3046     int begPos = GetBegPos( OBJECT_IND ) + myObj.Length();
3047     bool forward = true;
3048     if ( begPos < 1 ) {
3049       begPos = myString.Location( "(", 1, Length() ) - 1;
3050       forward = false;
3051     }
3052     // store
3053     myMeth = GetWord( myString, begPos, forward );
3054     SetBegPos( METHOD_IND, begPos );
3055   }
3056   //SCRUTE(myMeth);
3057   return myMeth;
3058 }
3059
3060 //================================================================================
3061 /*!
3062  * \brief Return substring of python command looking like ResVal = Obj.Meth(Arg1,...)
3063   * \retval const TCollection_AsciiString & - Arg<index> substring
3064  */
3065 //================================================================================
3066
3067 const TCollection_AsciiString & _pyCommand::GetArg( int index )
3068 {
3069   if ( GetBegPos( ARG1_IND ) == UNKNOWN )
3070   {
3071     // Find all args
3072
3073     int pos = GetBegPos( METHOD_IND ) + myMeth.Length();
3074     if ( pos < 1 )
3075       pos = myString.Location( "(", 1, Length() );
3076     else
3077       --pos;
3078
3079     // we are at or before '(', skip it if present
3080     if ( pos > 0 ) {
3081       while ( pos <= Length() && myString.Value( pos ) != '(' ) ++pos;
3082       if ( pos > Length() )
3083         pos = 0;
3084     }
3085     if ( pos < 1 ) {
3086       SetBegPos( ARG1_IND, 0 ); // even no '('
3087       return theEmptyString;
3088     }
3089     ++pos;
3090
3091     list< TCollection_AsciiString > separatorStack( 1, ",)");
3092     bool ignoreNesting = false;
3093     int prevPos = pos;
3094     while ( pos <= Length() )
3095     {
3096       const char chr = myString.Value( pos );
3097
3098       if ( separatorStack.back().Location( chr, 1, separatorStack.back().Length()))
3099       {
3100         if ( separatorStack.size() == 1 ) // ',' dividing args or a terminal ')' found
3101         {
3102           while ( pos-1 >= prevPos && isspace( myString.Value( prevPos )))
3103             ++prevPos;
3104           TCollection_AsciiString arg;
3105           if ( pos-1 >= prevPos ) {
3106             arg = myString.SubString( prevPos, pos-1 );
3107             arg.RightAdjust(); // remove spaces
3108             arg.LeftAdjust();
3109           }
3110           SetBegPos( ARG1_IND + myArgs.Length(), prevPos );
3111           myArgs.Append( arg );
3112           if ( chr == ')' )
3113             break;
3114           prevPos = pos+1;
3115         }
3116         else // end of nesting args found
3117         {
3118           separatorStack.pop_back();
3119           ignoreNesting = false;
3120         }
3121       }
3122       else if ( !ignoreNesting )
3123       {
3124         switch ( chr ) {
3125         case '(' : separatorStack.push_back(")"); break;
3126         case '[' : separatorStack.push_back("]"); break;
3127         case '\'': separatorStack.push_back("'");  ignoreNesting=true; break;
3128         case '"' : separatorStack.push_back("\""); ignoreNesting=true; break;
3129         default:;
3130         }
3131       }
3132       ++pos;
3133     }
3134   }
3135   if ( myArgs.Length() < index )
3136     return theEmptyString;
3137   return myArgs( index );
3138 }
3139
3140 //================================================================================
3141 /*!
3142  * \brief Check if char is a word part
3143   * \param c - The character to check
3144   * \retval bool - The check result
3145  */
3146 //================================================================================
3147
3148 static inline bool isWord(const char c, const bool dotIsWord)
3149 {
3150   return
3151     !isspace(c) && c != ',' && c != '=' && c != ')' && c != '(' && ( dotIsWord || c != '.');
3152 }
3153
3154 //================================================================================
3155 /*!
3156  * \brief Looks for a word in the string and returns word's beginning
3157   * \param theString - The input string
3158   * \param theStartPos - The position to start the search, returning word's beginning
3159   * \param theForward - The search direction
3160   * \retval TCollection_AsciiString - The found word
3161  */
3162 //================================================================================
3163
3164 TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString,
3165                                             int &      theStartPos,
3166                                             const bool theForward,
3167                                             const bool dotIsWord )
3168 {
3169   int beg = theStartPos, end = theStartPos;
3170   theStartPos = EMPTY;
3171   if ( beg < 1 || beg > theString.Length() )
3172     return theEmptyString;
3173
3174   if ( theForward ) { // search forward
3175     // beg
3176     while ( beg <= theString.Length() && !isWord( theString.Value( beg ), dotIsWord))
3177       ++beg;
3178     if ( beg > theString.Length() )
3179       return theEmptyString; // no word found
3180     // end
3181     end = beg + 1;
3182     char begChar = theString.Value( beg );
3183     if ( begChar == '"' || begChar == '\'' || begChar == '[') {
3184       char endChar = ( begChar == '[' ) ? ']' : begChar;
3185       // end is at the corresponding quoting mark or bracket
3186       while ( end < theString.Length() &&
3187               ( theString.Value( end ) != endChar || theString.Value( end-1 ) == '\\'))
3188         ++end;
3189     }
3190     else {
3191       while ( end <= theString.Length() && isWord( theString.Value( end ), dotIsWord))
3192         ++end;
3193       --end;
3194     }
3195   }
3196   else {  // search backward
3197     // end
3198     while ( end > 0 && !isWord( theString.Value( end ), dotIsWord))
3199       --end;
3200     if ( end == 0 )
3201       return theEmptyString; // no word found
3202     beg = end - 1;
3203     char endChar = theString.Value( end );
3204     if ( endChar == '"' || endChar == '\'' || endChar == ']') {
3205       char begChar = ( endChar == ']' ) ? '[' : endChar;
3206       // beg is at the corresponding quoting mark
3207       while ( beg > 1 &&
3208               ( theString.Value( beg ) != begChar || theString.Value( beg-1 ) == '\\'))
3209         --beg;
3210     }
3211     else {
3212       while ( beg > 0 && isWord( theString.Value( beg ), dotIsWord))
3213         --beg;
3214       ++beg;
3215     }
3216   }
3217   theStartPos = beg;
3218   //cout << theString << " ---- " << beg << " - " << end << endl;
3219   return theString.SubString( beg, end );
3220 }
3221
3222 //================================================================================
3223 /*!
3224  * \brief Returns true if the string looks like a study entry
3225  */
3226 //================================================================================
3227
3228 bool _pyCommand::IsStudyEntry( const TCollection_AsciiString& str )
3229 {
3230   if ( str.Length() < 5 ) return false;
3231
3232   int nbColons = 0, isColon;
3233   for ( int i = 1; i <= str.Length(); ++i )
3234   {
3235     char c = str.Value(i);
3236     if (!( isColon = (c == ':')) && ( c < '0' || c > '9' ))
3237       return false;
3238     nbColons += isColon;
3239   }
3240   return nbColons > 2 && str.Length()-nbColons > 2;
3241 }
3242
3243 //================================================================================
3244 /*!
3245  * \brief Finds entries in a sting
3246  */
3247 //================================================================================
3248
3249 std::list< _pyID > _pyCommand::GetStudyEntries( const TCollection_AsciiString& str )
3250 {
3251   std::list< _pyID > resList;
3252   int pos = 0;
3253   while ( ++pos <= str.Length() )
3254   {
3255     if ( !isdigit( str.Value( pos ))) continue;
3256     if ( pos != 1 && ( isalpha( str.Value( pos-1 ) || str.Value( pos-1 ) == ':'))) continue;
3257
3258     int end = pos;
3259     while ( ++end <= str.Length() && ( isdigit( str.Value( end )) || str.Value( end ) == ':' ));
3260     _pyID entry = str.SubString( pos, end-1 );
3261     pos = end;
3262     if ( IsStudyEntry( entry ))
3263       resList.push_back( entry );
3264   }
3265   return resList;
3266 }
3267
3268 //================================================================================
3269 /*!
3270  * \brief Look for position where not space char is
3271   * \param theString - The string
3272   * \param thePos - The position to search from and which returns result
3273   * \retval bool - false if there are only space after thePos in theString
3274  *
3275  *
3276  */
3277 //================================================================================
3278
3279 bool _pyCommand::SkipSpaces( const TCollection_AsciiString & theString, int & thePos )
3280 {
3281   if ( thePos < 1 || thePos > theString.Length() )
3282     return false;
3283
3284   while ( thePos <= theString.Length() && isspace( theString.Value( thePos )))
3285     ++thePos;
3286
3287   return thePos <= theString.Length();
3288 }
3289
3290 //================================================================================
3291 /*!
3292  * \brief Modify a part of the command
3293   * \param thePartIndex - The index of the part
3294   * \param thePart - The new part string
3295   * \param theOldPart - The old part
3296  */
3297 //================================================================================
3298
3299 void _pyCommand::SetPart(int thePartIndex, const TCollection_AsciiString& thePart,
3300                         TCollection_AsciiString& theOldPart)
3301 {
3302   int pos = GetBegPos( thePartIndex );
3303   if ( pos <= Length() && theOldPart != thePart)
3304   {
3305     TCollection_AsciiString seperator;
3306     if ( pos < 1 ) {
3307       pos = GetBegPos( thePartIndex + 1 );
3308       if ( pos < 1 ) return;
3309       switch ( thePartIndex ) {
3310       case RESULT_IND: seperator = " = "; break;
3311       case OBJECT_IND: seperator = "."; break;
3312       case METHOD_IND: seperator = "()"; break;
3313       default:;
3314       }
3315     }
3316     myString.Remove( pos, theOldPart.Length() );
3317     if ( !seperator.IsEmpty() )
3318       myString.Insert( pos , seperator );
3319     myString.Insert( pos, thePart );
3320     // update starting positions of the following parts
3321     int posDelta = thePart.Length() + seperator.Length() - theOldPart.Length();
3322     for ( int i = thePartIndex + 1; i <= myBegPos.Length(); ++i ) {
3323       if ( myBegPos( i ) > 0 )
3324         myBegPos( i ) += posDelta;
3325     }
3326     theOldPart = thePart;
3327   }
3328 }
3329
3330 //================================================================================
3331 /*!
3332  * \brief Set agrument
3333   * \param index - The argument index, it counts from 1
3334   * \param theArg - The argument string
3335  */
3336 //================================================================================
3337
3338 void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg)
3339 {
3340   FindAllArgs();
3341   int argInd = ARG1_IND + index - 1;
3342   int pos = GetBegPos( argInd );
3343   if ( pos < 1 ) // no index-th arg exist, append inexistent args
3344   {
3345     // find a closing parenthesis
3346     if ( GetNbArgs() != 0 && index <= GetNbArgs() ) {
3347       int lastArgInd = GetNbArgs();
3348       pos = GetBegPos( ARG1_IND + lastArgInd  - 1 ) + GetArg( lastArgInd ).Length();
3349       while ( pos > 0 && pos <= Length() && myString.Value( pos ) != ')' )
3350         ++pos;
3351     }
3352     else {
3353       pos = Length();
3354       while ( pos > 0 && myString.Value( pos ) != ')' )
3355         --pos;
3356     }
3357     if ( pos < 1 || myString.Value( pos ) != ')' ) { // no parentheses at all
3358       myString += "()";
3359       pos = Length();
3360     }
3361     while ( myArgs.Length() < index ) {
3362       if ( myArgs.Length() )
3363         myString.Insert( pos++, "," );
3364       myArgs.Append("None");
3365       myString.Insert( pos, myArgs.Last() );
3366       SetBegPos( ARG1_IND + myArgs.Length() - 1, pos );
3367       pos += myArgs.Last().Length();
3368     }
3369   }
3370   SetPart( argInd, theArg, myArgs( index ));
3371 }
3372
3373 //================================================================================
3374 /*!
3375  * \brief Empty arg list
3376  */
3377 //================================================================================
3378
3379 void _pyCommand::RemoveArgs()
3380 {
3381   if ( int pos = myString.Location( '(', 1, Length() ))
3382     myString.Trunc( pos );
3383   myString += ")";
3384   myArgs.Clear();
3385   if ( myBegPos.Length() >= ARG1_IND )
3386     myBegPos.Remove( ARG1_IND, myBegPos.Length() );
3387 }
3388
3389 //================================================================================
3390 /*!
3391  * \brief Comment a python command
3392  */
3393 //================================================================================
3394
3395 void _pyCommand::Comment()
3396 {
3397   if ( IsEmpty() ) return;
3398
3399   int i = 1;
3400   while ( i <= Length() && isspace( myString.Value(i) )) ++i;
3401   if ( i <= Length() )
3402   {
3403     myString.Insert( i, "#" );
3404     for ( int iPart = 0; iPart < myBegPos.Length(); ++iPart )
3405     {
3406       int begPos = GetBegPos( iPart );
3407       if ( begPos != UNKNOWN )
3408         SetBegPos( iPart, begPos + 1 );
3409     }
3410   }
3411 }
3412
3413 //================================================================================
3414 /*!
3415  * \brief Set dependent commands after this one
3416  */
3417 //================================================================================
3418
3419 bool _pyCommand::SetDependentCmdsAfter() const
3420 {
3421   bool orderChanged = false;
3422   list< Handle(_pyCommand)>::const_reverse_iterator cmd = myDependentCmds.rbegin();
3423   for ( ; cmd != myDependentCmds.rend(); ++cmd ) {
3424     if ( (*cmd)->GetOrderNb() < GetOrderNb() ) {
3425       orderChanged = true;
3426       theGen->SetCommandAfter( *cmd, this );
3427       (*cmd)->SetDependentCmdsAfter();
3428     }
3429   }
3430   return orderChanged;
3431 }
3432 //================================================================================
3433 /*!
3434  * \brief Insert accessor method after theObjectID
3435   * \param theObjectID - id of the accessed object
3436   * \param theAcsMethod - name of the method giving access to the object
3437   * \retval bool - false if theObjectID is not found in the command string
3438  */
3439 //================================================================================
3440
3441 bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod )
3442 {
3443   if ( !theAcsMethod )
3444     return false;
3445   // start object search from the object, i.e. ignore result
3446   GetObject();
3447   int beg = GetBegPos( OBJECT_IND );
3448   if ( beg < 1 || beg > Length() )
3449     return false;
3450   bool added = false;
3451   while (( beg = myString.Location( theObjectID, beg, Length() )))
3452   {
3453     // check that theObjectID is not just a part of a longer ID
3454     int afterEnd = beg + theObjectID.Length();
3455     Standard_Character c = myString.Value( afterEnd );
3456     if ( !isalnum( c ) && c != ':' ) {
3457       // check if accessor method already present
3458       if ( c != '.' ||
3459            myString.Location( (char*) theAcsMethod, afterEnd, Length() ) != afterEnd+1) {
3460         // insertion
3461         int oldLen = Length();
3462         myString.Insert( afterEnd, (char*) theAcsMethod );
3463         myString.Insert( afterEnd, "." );
3464         // update starting positions of the parts following the modified one
3465         int posDelta = Length() - oldLen;
3466         for ( int i = 1; i <= myBegPos.Length(); ++i ) {
3467           if ( myBegPos( i ) > afterEnd )
3468             myBegPos( i ) += posDelta;
3469         }
3470         added = true;
3471       }
3472     }
3473     beg = afterEnd; // is a part - next search
3474   }
3475   return added;
3476 }
3477
3478 //================================================================================
3479 /*!
3480  * \brief Creates pyObject
3481  */
3482 //================================================================================
3483
3484 _pyObject::_pyObject(const Handle(_pyCommand)& theCreationCmd, const _pyID& theID)
3485   : myID(theID), myCreationCmd(theCreationCmd), myIsPublished(false)
3486 {
3487   setID( theID );
3488 }
3489
3490 //================================================================================
3491 /*!
3492  * \brief Set up myID and myIsPublished
3493  */
3494 //================================================================================
3495
3496 void _pyObject::setID(const _pyID& theID)
3497 {
3498   myID = theID;
3499   myIsPublished = !theGen->IsNotPublished( GetID() );
3500 }
3501
3502 //================================================================================
3503 /*!
3504  * \brief Clear myCreationCmd and myProcessedCmds
3505  */
3506 //================================================================================
3507
3508 void _pyObject::ClearCommands()
3509 {
3510   if ( !CanClear() )
3511     return;
3512
3513   if ( !myCreationCmd.IsNull() )
3514     myCreationCmd->Clear();
3515
3516   list< Handle(_pyCommand) >::iterator cmd = myProcessedCmds.begin();
3517   for ( ; cmd != myProcessedCmds.end(); ++cmd )
3518     (*cmd)->Clear();
3519 }
3520
3521 //================================================================================
3522 /*!
3523  * \brief Return method name giving access to an interaface object wrapped by python class
3524   * \retval const char* - method name
3525  */
3526 //================================================================================
3527
3528 const char* _pyObject::AccessorMethod() const
3529 {
3530   return 0;
3531 }
3532 //================================================================================
3533 /*!
3534  * \brief Return ID of a father
3535  */
3536 //================================================================================
3537
3538 _pyID _pyObject::FatherID(const _pyID & childID)
3539 {
3540   int colPos = childID.SearchFromEnd(':');
3541   if ( colPos > 0 )
3542     return childID.SubString( 1, colPos-1 );
3543   return "";
3544 }
3545
3546 //================================================================================
3547 /*!
3548  * \brief SelfEraser erases creation command if no more it's commands invoked
3549  */
3550 //================================================================================
3551
3552 void _pySelfEraser::Flush()
3553 {
3554   if ( GetNbCalls() == 0 )
3555     GetCreationCmd()->Clear();
3556 }
3557
3558 //================================================================================
3559 /*!
3560  * \brief _pySubMesh constructor
3561  */
3562 //================================================================================
3563
3564 _pySubMesh::_pySubMesh(const Handle(_pyCommand)& theCreationCmd):
3565   _pyObject(theCreationCmd)
3566 {
3567   myMesh = ObjectToMesh( theGen->FindObject( theCreationCmd->GetObject() ));
3568 }
3569
3570 //================================================================================
3571 /*!
3572  * \brief count invoked commands
3573  */
3574 //================================================================================
3575
3576 void _pySubMesh::Process( const Handle(_pyCommand)& theCommand )
3577 {
3578   _pyObject::Process(theCommand); // count calls of Process()
3579   GetCreationCmd()->AddDependantCmd( theCommand );
3580 }
3581
3582 //================================================================================
3583 /*!
3584  * \brief Move creation command depending on invoked commands
3585  */
3586 //================================================================================
3587
3588 void _pySubMesh::Flush()
3589 {
3590   if ( GetNbCalls() == 0 ) // move to the end of all commands
3591     theGen->GetLastCommand()->AddDependantCmd( GetCreationCmd() );
3592   else if ( !myCreator.IsNull() )
3593     // move to be just after creator
3594     myCreator->GetCreationCmd()->AddDependantCmd( GetCreationCmd() );
3595 }
3596
3597 //================================================================================
3598 /*!
3599  * \brief To convert creation of a group by filter
3600  */
3601 //================================================================================
3602
3603 void _pyGroup::Process( const Handle(_pyCommand)& theCommand)
3604 {
3605   // Convert the following set of commands into mesh.MakeGroupByFilter(groupName, theFilter)
3606   // group = mesh.CreateEmptyGroup( elemType, groupName )
3607   // aFilter.SetMesh(mesh)
3608   // nbAdd = group.AddFrom( aFilter )
3609   Handle(_pyFilter) filter;
3610   if ( theCommand->GetMethod() == "AddFrom" )
3611   {
3612     _pyID idSource = theCommand->GetArg(1);
3613     // check if idSource is a filter
3614     filter = Handle(_pyFilter)::DownCast( theGen->FindObject( idSource ));
3615     if ( filter.IsNull() )
3616       return;
3617     // find aFilter.SetMesh(mesh) to clear it, it should be just before theCommand
3618     list< Handle(_pyCommand) >::reverse_iterator cmdIt = theGen->GetCommands().rbegin();
3619     while ( *cmdIt != theCommand ) ++cmdIt;
3620     while ( (*cmdIt)->GetOrderNb() != 1 )
3621     {
3622       const Handle(_pyCommand)& setMeshCmd = *(++cmdIt);
3623       if ((setMeshCmd->GetObject() == idSource ||
3624            setMeshCmd->GetObject() == filter->GetNewID() )
3625           &&
3626           setMeshCmd->GetMethod() == "SetMesh")
3627       {
3628         setMeshCmd->Clear();
3629         break;
3630       }
3631     }
3632     // replace 3 commands by one
3633     theCommand->Clear();
3634     const Handle(_pyCommand)& makeGroupCmd = GetCreationCmd();
3635     TCollection_AsciiString name = makeGroupCmd->GetArg( 2 );
3636     makeGroupCmd->SetMethod( "MakeGroupByFilter" );
3637     makeGroupCmd->SetArg( 1, name );
3638     makeGroupCmd->SetArg( 2, idSource );
3639     // set new name of a filter
3640     filter->Process( makeGroupCmd );
3641   }
3642   else if ( theCommand->GetMethod() == "SetFilter" )
3643   {
3644     // set new name of a filter
3645     _pyID filterID = theCommand->GetArg(1);
3646     filter = Handle(_pyFilter)::DownCast( theGen->FindObject( filterID ));
3647     if ( !filter.IsNull() )
3648       filter->Process( theCommand );
3649   }
3650
3651   if ( !filter.IsNull() )
3652     filter->AddUser( this );
3653 }
3654
3655 //================================================================================
3656 /*!
3657  * \brief Constructor of _pyFilter
3658  */
3659 //================================================================================
3660
3661 _pyFilter::_pyFilter(const Handle(_pyCommand)& theCreationCmd, const _pyID& newID/*=""*/)
3662   :_pyObject(theCreationCmd), myNewID( newID )
3663 {
3664 }
3665
3666 //================================================================================
3667 /*!
3668  * \brief To convert creation of a filter by criteria and
3669  * to replace an old name by a new one
3670  */
3671 //================================================================================
3672
3673 void _pyFilter::Process( const Handle(_pyCommand)& theCommand)
3674 {
3675   if ( theCommand->GetObject() == GetID() )
3676     _pyObject::Process(theCommand); // count commands
3677
3678   if ( !myNewID.IsEmpty() )
3679   {
3680     if ( theCommand->GetObject() == GetID() )
3681       theCommand->SetObject( myNewID );
3682     else if ( theCommand->GetResultValue() == GetID() )
3683       theCommand->SetResultValue( myNewID );
3684     else
3685       for ( int i = 1, nb = theCommand->GetNbArgs(); i <= nb; ++i )
3686         if ( theCommand->GetArg( i ) == GetID() )
3687         {
3688           theCommand->SetArg( i, myNewID );
3689           break;
3690         }
3691   }
3692
3693   // Convert the following set of commands into smesh.GetFilterFromCriteria(criteria)
3694   // aFilter0x2aaab0487080 = aFilterManager.CreateFilter()
3695   // aFilter0x2aaab0487080.SetCriteria(aCriteria)
3696   if ( GetNbCalls() == 1 && // none method was called before this SetCriteria() call
3697        theCommand->GetMethod() == "SetCriteria")
3698   {
3699     // aFilter.SetCriteria(aCriteria) ->
3700     // aFilter = smesh.GetFilterFromCriteria(criteria)
3701     if ( myNewID.IsEmpty() )
3702       theCommand->SetResultValue( GetID() );
3703     else
3704       theCommand->SetResultValue( myNewID );
3705     theCommand->SetObject( SMESH_2smeshpy::GenName() );
3706     theCommand->SetMethod( "GetFilterFromCriteria" );
3707
3708     // Clear aFilterManager.CreateFilter()
3709     GetCreationCmd()->Clear();
3710   }
3711   else if ( theCommand->GetMethod() == "SetMesh")
3712   {
3713     theGen->AddMeshAccessorMethod( theCommand );
3714   }
3715 }
3716
3717 //================================================================================
3718 /*!
3719  * \brief Set new filter name to the creation command
3720  */
3721 //================================================================================
3722
3723 void _pyFilter::Flush()
3724 {
3725   if ( !myNewID.IsEmpty() && !GetCreationCmd()->IsEmpty() )
3726     GetCreationCmd()->SetResultValue( myNewID );
3727 }
3728
3729 //================================================================================
3730 /*!
3731  * \brief Return true if all my users can be cleared
3732  */
3733 //================================================================================
3734
3735 bool _pyFilter::CanClear()
3736 {
3737   list< Handle(_pyObject) >::iterator obj = myUsers.begin();
3738   for ( ; obj != myUsers.end(); ++obj )
3739     if ( !(*obj)->CanClear() )
3740       return false;
3741
3742   return true;
3743 }
3744
3745 //================================================================================
3746 /*!
3747  * \brief Reads _pyHypothesis'es from resource files of mesher Plugins
3748  */
3749 //================================================================================
3750
3751 _pyHypothesisReader::_pyHypothesisReader()
3752 {
3753   // Get paths to xml files of plugins
3754   vector< string > xmlPaths;
3755   string sep;
3756   if ( const char* meshersList = getenv("SMESH_MeshersList") )
3757   {
3758     string meshers = meshersList, plugin;
3759     string::size_type from = 0, pos;
3760     while ( from < meshers.size() )
3761     {
3762       // cut off plugin name
3763       pos = meshers.find( ':', from );
3764       if ( pos != string::npos )
3765         plugin = meshers.substr( from, pos-from );
3766       else
3767         plugin = meshers.substr( from ), pos = meshers.size();
3768       from = pos + 1;
3769
3770       // get PLUGIN_ROOT_DIR path
3771       string rootDirVar, pluginSubDir = plugin;
3772       if ( plugin == "StdMeshers" )
3773         rootDirVar = "SMESH", pluginSubDir = "smesh";
3774       else
3775         for ( pos = 0; pos < plugin.size(); ++pos )
3776           rootDirVar += toupper( plugin[pos] );
3777       rootDirVar += "_ROOT_DIR";
3778
3779       const char* rootDir = getenv( rootDirVar.c_str() );
3780       if ( !rootDir || strlen(rootDir) == 0 ) continue;
3781
3782       // get a separator from rootDir
3783       for ( pos = strlen( rootDir )-1; pos >= 0 && sep.empty(); --pos )
3784         if ( rootDir[pos] == '/' || rootDir[pos] == '\\' )
3785         {
3786           sep = rootDir[pos];
3787           break;
3788         }
3789       if (sep.empty() ) sep = "/";
3790
3791       // get a path to resource file
3792       string xmlPath = rootDir;
3793       if ( xmlPath[ xmlPath.size()-1 ] != sep[0] )
3794         xmlPath += sep;
3795       xmlPath += "share" + sep + "salome" + sep + "resources" + sep;
3796       for ( pos = 0; pos < pluginSubDir.size(); ++pos )
3797         xmlPath += tolower( pluginSubDir[pos] );
3798       xmlPath += sep + plugin + ".xml";
3799       bool fileOK;
3800 #ifdef WNT
3801       fileOK = (GetFileAttributes(xmlPath.c_str()) != INVALID_FILE_ATTRIBUTES);
3802 #else
3803       fileOK = (access(xmlPath.c_str(), F_OK) == 0);
3804 #endif
3805       if ( fileOK )
3806         xmlPaths.push_back( xmlPath );
3807     }
3808   }
3809
3810   // Read xml files
3811   LDOMParser xmlParser;
3812   for ( size_t i = 0; i < xmlPaths.size(); ++i )
3813   {
3814     bool error = xmlParser.parse( xmlPaths[i].c_str() );
3815     if ( error )
3816     {
3817       _AString data;
3818       INFOS( xmlParser.GetError(data) );
3819       continue;
3820     }
3821     // <algorithm type="Regular_1D"
3822     //            label-id="Wire discretisation"
3823     //            ...>
3824     //   <python-wrap>
3825     //     <algo>Regular_1D=Segment()</algo>
3826     //     <hypo>LocalLength=LocalLength(SetLength(1),,SetPrecision(1))</hypo>
3827     //
3828     LDOM_Document xmlDoc = xmlParser.getDocument();
3829     LDOM_NodeList algoNodeList = xmlDoc.getElementsByTagName( "algorithm" );
3830     for ( int i = 0; i < algoNodeList.getLength(); ++i )
3831     {
3832       LDOM_Node algoNode = algoNodeList.item( i );
3833       LDOM_Element& algoElem = (LDOM_Element&) algoNode;
3834       LDOM_NodeList pyAlgoNodeList = algoElem.getElementsByTagName( "algo" );
3835       if ( pyAlgoNodeList.getLength() < 1 ) continue;
3836
3837       _AString text, algoType, method, arg;
3838       for ( int iA = 0; iA < pyAlgoNodeList.getLength(); ++iA )
3839       {
3840         LDOM_Node pyAlgoNode = pyAlgoNodeList.item( iA );
3841         LDOM_Node textNode   = pyAlgoNode.getFirstChild();
3842         text = textNode.getNodeValue();
3843         Handle(_pyCommand) algoCmd = new _pyCommand( text );
3844         algoType = algoCmd->GetResultValue();
3845         method   = algoCmd->GetMethod();
3846         arg      = algoCmd->GetArg(1);
3847         if ( !algoType.IsEmpty() && !method.IsEmpty() )
3848         {
3849           Handle(_pyAlgorithm) algo = new _pyAlgorithm( algoCmd );
3850           algo->SetConvMethodAndType( method, algoType );
3851           if ( !arg.IsEmpty() )
3852             algo->setCreationArg( 1, arg );
3853
3854           myType2Hyp[ algoType ] = algo;
3855           break;
3856         }
3857       }
3858       if ( algoType.IsEmpty() ) continue;
3859
3860       LDOM_NodeList pyHypoNodeList = algoElem.getElementsByTagName( "hypo" );
3861       _AString hypType;
3862       Handle( _pyHypothesis ) hyp;
3863       for ( int iH = 0; iH < pyHypoNodeList.getLength(); ++iH )
3864       {
3865         LDOM_Node pyHypoNode = pyHypoNodeList.item( iH );
3866         LDOM_Node textNode   = pyHypoNode.getFirstChild();
3867         text = textNode.getNodeValue();
3868         Handle(_pyCommand) hypoCmd = new _pyCommand( text );
3869         hypType = hypoCmd->GetResultValue();
3870         method  = hypoCmd->GetMethod();
3871         if ( !hypType.IsEmpty() && !method.IsEmpty() )
3872         {
3873           map<_AString, Handle(_pyHypothesis)>::iterator type2hyp = myType2Hyp.find( hypType );
3874           if ( type2hyp == myType2Hyp.end() )
3875             hyp = new _pyHypothesis( hypoCmd );
3876           else
3877             hyp = type2hyp->second;
3878           hyp->SetConvMethodAndType( method, algoType );
3879           for ( int iArg = 1; iArg <= hypoCmd->GetNbArgs(); ++iArg )
3880           {
3881             _pyCommand argCmd( hypoCmd->GetArg( iArg ));
3882             _AString argMethod = argCmd.GetMethod();
3883             _AString argNbText = argCmd.GetArg( 1 );
3884             if ( argMethod.IsEmpty() && !argCmd.IsEmpty() )
3885               hyp->setCreationArg( 1, argCmd.GetString() ); // e.g. Parameters(smesh.SIMPLE)
3886             else
3887               hyp->AddArgMethod( argMethod,
3888                                  argNbText.IsIntegerValue() ? argNbText.IntegerValue() : 1 );
3889           }
3890           myType2Hyp[ hypType ] = hyp;
3891         }
3892       }
3893     }
3894   }
3895 }
3896
3897 //================================================================================
3898 /*!
3899  * \brief Returns a new hypothesis initialized according to the read information
3900  */
3901 //================================================================================
3902
3903 Handle(_pyHypothesis)
3904 _pyHypothesisReader::GetHypothesis(const _AString&           hypType,
3905                                    const Handle(_pyCommand)& creationCmd) const
3906 {
3907   Handle(_pyHypothesis) resHyp, sampleHyp;
3908
3909   map<_AString, Handle(_pyHypothesis)>::const_iterator type2hyp = myType2Hyp.find( hypType );
3910   if ( type2hyp != myType2Hyp.end() )
3911     sampleHyp = type2hyp->second;
3912
3913   if ( sampleHyp.IsNull() )
3914   {
3915     resHyp = new _pyHypothesis(creationCmd);
3916   }
3917   else
3918   {
3919     if ( sampleHyp->IsAlgo() )
3920       resHyp = new _pyAlgorithm( creationCmd );
3921     else
3922       resHyp = new _pyHypothesis(creationCmd);
3923     resHyp->Assign( sampleHyp, _pyID() );
3924   }
3925   return resHyp;
3926 }