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