Salome HOME
e232506b6b15e6d9f71183066b84909b12d12b8b
[modules/smesh.git] / src / SMESH_I / SMESH_2smeshpy.cxx
1 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
2 //
3 //  Copyright (C) 2003  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 //
24 //  File   : SMESH_2D_Algo_i.hxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 // File      : SMESH_2smeshpy.cxx
30 // Created   : Fri Nov 18 13:20:10 2005
31 // Author    : Edward AGAPOV (eap)
32
33 #include "SMESH_2smeshpy.hxx"
34
35 #include "SMESH_Gen_i.hxx"
36 #include "utilities.h"
37 #include "SMESH_PythonDump.hxx"
38 #include "Resource_DataMapOfAsciiStringAsciiString.hxx"
39
40 IMPLEMENT_STANDARD_HANDLE (_pyObject          ,Standard_Transient);
41 IMPLEMENT_STANDARD_HANDLE (_pyCommand         ,Standard_Transient);
42 IMPLEMENT_STANDARD_HANDLE (_pyGen             ,_pyObject);
43 IMPLEMENT_STANDARD_HANDLE (_pyMesh            ,_pyObject);
44 IMPLEMENT_STANDARD_HANDLE (_pyHypothesis      ,_pyObject);
45 IMPLEMENT_STANDARD_HANDLE (_pyAlgorithm       ,_pyHypothesis);
46 IMPLEMENT_STANDARD_HANDLE (_pyComplexParamHypo,_pyHypothesis);
47 IMPLEMENT_STANDARD_HANDLE (_pyNumberOfSegmentsHyp,_pyHypothesis);
48
49 IMPLEMENT_STANDARD_RTTIEXT(_pyObject          ,Standard_Transient);
50 IMPLEMENT_STANDARD_RTTIEXT(_pyCommand         ,Standard_Transient);
51 IMPLEMENT_STANDARD_RTTIEXT(_pyGen             ,_pyObject);
52 IMPLEMENT_STANDARD_RTTIEXT(_pyMesh            ,_pyObject);
53 IMPLEMENT_STANDARD_RTTIEXT(_pyHypothesis      ,_pyObject);
54 IMPLEMENT_STANDARD_RTTIEXT(_pyAlgorithm       ,_pyHypothesis);
55 IMPLEMENT_STANDARD_RTTIEXT(_pyComplexParamHypo,_pyHypothesis);
56 IMPLEMENT_STANDARD_RTTIEXT(_pyNumberOfSegmentsHyp,_pyHypothesis);
57 IMPLEMENT_STANDARD_RTTIEXT(_pyLayerDistributionHypo,_pyHypothesis);
58
59 using namespace std;
60 using SMESH::TPythonDump;
61
62 /*!
63  * \brief Container of commands into which the initial script is split.
64  *        It also contains data coresponding to SMESH_Gen contents
65  */
66 static Handle(_pyGen) theGen;
67
68 static TCollection_AsciiString theEmptyString;
69
70 //#define DUMP_CONVERSION
71
72 #if !defined(_DEBUG_) && defined(DUMP_CONVERSION)
73 #undef DUMP_CONVERSION
74 #endif
75
76 //================================================================================
77 /*!
78  * \brief Convert python script using commands of smesh.py
79   * \param theScript - Input script
80   * \retval TCollection_AsciiString - Convertion result
81  */
82 //================================================================================
83
84 TCollection_AsciiString
85 SMESH_2smeshpy::ConvertScript(const TCollection_AsciiString& theScript,
86                               Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod)
87 {
88   theGen = new _pyGen( theEntry2AccessorMethod );
89
90   // split theScript into separate commands
91   int from = 1, end = theScript.Length(), to;
92   while ( from < end && ( to = theScript.Location( "\n", from, end )))
93   {
94     if ( to != from )
95       // cut out and store a command
96       theGen->AddCommand( theScript.SubString( from, to - 1 ));
97     from = to + 1;
98   }
99   // finish conversion
100   theGen->Flush();
101 #ifdef DUMP_CONVERSION
102   cout << endl << " ######## RESULT ######## " << endl<< endl;
103 #endif
104   // reorder commands after conversion
105   list< Handle(_pyCommand) >::iterator cmd;
106   bool orderChanges;
107   do {
108     orderChanges = false;
109     for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
110       if ( (*cmd)->SetDependentCmdsAfter() )
111         orderChanges = true;
112   } while ( orderChanges );
113   
114   // concat commands back into a script
115   TCollection_AsciiString aScript;
116   for ( cmd = theGen->GetCommands().begin(); cmd != theGen->GetCommands().end(); ++cmd )
117   {
118 #ifdef DUMP_CONVERSION
119     cout << "## COM " << (*cmd)->GetOrderNb() << ": "<< (*cmd)->GetString() << endl;
120 #endif
121     if ( !(*cmd)->IsEmpty() ) {
122       aScript += "\n";
123       aScript += (*cmd)->GetString();
124     }
125   }
126   aScript += "\n";
127
128   theGen.Nullify();
129
130   return aScript;
131 }
132
133 //================================================================================
134 /*!
135  * \brief _pyGen constructor
136  */
137 //================================================================================
138
139 _pyGen::_pyGen(Resource_DataMapOfAsciiStringAsciiString& theEntry2AccessorMethod)
140   : _pyObject( new _pyCommand( TPythonDump::SMESHGenName(), 0 )),
141     myID2AccessorMethod( theEntry2AccessorMethod )
142 {
143   myNbCommands = 0;
144   myHasPattern = false;
145   // make that GetID() to return TPythonDump::SMESHGenName()
146   GetCreationCmd()->GetString() += "=";
147 }
148
149 //================================================================================
150 /*!
151  * \brief Convert a command using a specific converter
152   * \param theCommand - the command to convert
153  */
154 //================================================================================
155
156 void _pyGen::AddCommand( const TCollection_AsciiString& theCommand)
157 {
158   // store theCommand in the sequence
159   myCommands.push_back( new _pyCommand( theCommand, ++myNbCommands ));
160
161   Handle(_pyCommand) aCommand = myCommands.back();
162 #ifdef DUMP_CONVERSION
163   cout << "## COM " << myNbCommands << ": "<< aCommand->GetString() << endl;
164 #endif
165
166   _pyID objID = aCommand->GetObject();
167
168   if ( objID.IsEmpty() )
169     return;
170
171   // SMESH_Gen method?
172   if ( objID == this->GetID() ) {
173     this->Process( aCommand );
174     return;
175   }
176   // SMESH_Mesh method?
177   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( objID );
178   if ( id_mesh != myMeshes.end() ) {
179     id_mesh->second->Process( aCommand );
180     return;
181   }
182   // SMESH_Hypothesis method?
183   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
184   for ( ; hyp != myHypos.end(); ++hyp )
185     if ( !(*hyp)->IsAlgo() && objID == (*hyp)->GetID() ) {
186       (*hyp)->Process( aCommand );
187       return;
188     }
189
190   // Add access to a wrapped mesh
191   AddMeshAccessorMethod( aCommand );
192
193   // Add access to a wrapped algorithm
194   AddAlgoAccessorMethod( aCommand );
195
196   // PAL12227. PythonDump was not updated at proper time; result is
197   //     aCriteria.append(SMESH.Filter.Criterion(17,26,0,'L1',26,25,1e-07,SMESH.EDGE,-1))
198   // TypeError: __init__() takes exactly 11 arguments (10 given)
199   char wrongCommand[] = "SMESH.Filter.Criterion(";
200   if ( int beg = theCommand.Location( wrongCommand, 1, theCommand.Length() ))
201   {
202     _pyCommand tmpCmd( theCommand.SubString( beg, theCommand.Length() ), -1);
203     // there must be 10 arguments, 5-th arg ThresholdID is missing,
204     const int wrongNbArgs = 9, missingArg = 5;
205     if ( tmpCmd.GetNbArgs() == wrongNbArgs )
206     {
207       for ( int i = wrongNbArgs; i > missingArg; --i )
208         tmpCmd.SetArg( i + 1, tmpCmd.GetArg( i ));
209       tmpCmd.SetArg(  missingArg, "''");
210       aCommand->GetString().Trunc( beg - 1 );
211       aCommand->GetString() += tmpCmd.GetString();
212     }
213   }
214 }
215
216 //================================================================================
217 /*!
218  * \brief Convert the command or remember it for later conversion 
219   * \param theCommand - The python command calling a method of SMESH_Gen
220  */
221 //================================================================================
222
223 void _pyGen::Process( const Handle(_pyCommand)& theCommand )
224 {
225   // there are methods to convert:
226   // CreateMesh( shape )
227   // CreateHypothesis( theHypType, theLibName )
228   // Compute( mesh, geom )
229
230   if ( theCommand->GetMethod() == "CreateMesh" )
231   {
232     Handle(_pyMesh) mesh = new _pyMesh( theCommand );
233     myMeshes.insert( make_pair( mesh->GetID(), mesh ));
234     return;
235   }
236
237   // CreateHypothesis()
238   if ( theCommand->GetMethod() == "CreateHypothesis" )
239   {
240     myHypos.push_back( _pyHypothesis::NewHypothesis( theCommand ));
241     return;
242   }
243
244   // smeshgen.Compute( mesh, geom ) --> mesh.Compute()
245   if ( theCommand->GetMethod() == "Compute" )
246   {
247     const _pyID& meshID = theCommand->GetArg( 1 );
248     map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.find( meshID );
249     if ( id_mesh != myMeshes.end() ) {
250       theCommand->SetObject( meshID );
251       theCommand->RemoveArgs();
252       id_mesh->second->Flush();
253       return;
254     }
255   }
256
257   // leave only one smeshgen.GetPattern() in the script
258   if ( theCommand->GetMethod() == "GetPattern" ) {
259     if ( myHasPattern ) {
260       theCommand->Clear();
261       return;
262     }
263     myHasPattern = true;
264   }
265
266   // smeshgen.Method() --> smesh.smesh.Method()
267   theCommand->SetObject( SMESH_2smeshpy::GenName() );
268 }
269
270 //================================================================================
271 /*!
272  * \brief Convert the remembered commands
273  */
274 //================================================================================
275
276 void _pyGen::Flush()
277 {
278   map< _pyID, Handle(_pyMesh) >::iterator id_mesh = myMeshes.begin();
279   for ( ; id_mesh != myMeshes.end(); ++id_mesh )
280     if ( ! id_mesh->second.IsNull() )
281       id_mesh->second->Flush();
282
283   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
284   for ( ; hyp != myHypos.end(); ++hyp )
285     if ( !hyp->IsNull() ) {
286       (*hyp)->Flush();
287       // smeshgen.CreateHypothesis() --> smesh.smesh.CreateHypothesis()
288       if ( !(*hyp)->IsWrapped() )
289         (*hyp)->GetCreationCmd()->SetObject( SMESH_2smeshpy::GenName() );
290     }
291 }
292
293 //================================================================================
294 /*!
295  * \brief Add access method to mesh that is object or arg
296   * \param theCmd - command to add access method
297   * \retval bool - true if added
298  */
299 //================================================================================
300
301 bool _pyGen::AddMeshAccessorMethod( Handle(_pyCommand) theCmd ) const
302 {
303   map< _pyID, Handle(_pyMesh) >::const_iterator id_mesh = myMeshes.begin();
304   for ( ; id_mesh != myMeshes.end(); ++id_mesh ) {
305     if ( theCmd->AddAccessorMethod( id_mesh->first, id_mesh->second->AccessorMethod() ))
306       return true;
307   }
308   return false;
309 }
310
311 //================================================================================
312 /*!
313  * \brief Add access method to algo that is object or arg
314   * \param theCmd - command to add access method
315   * \retval bool - true if added
316  */
317 //================================================================================
318
319 bool _pyGen::AddAlgoAccessorMethod( Handle(_pyCommand) theCmd ) const
320 {
321   list< Handle(_pyHypothesis) >::const_iterator hyp = myHypos.begin();
322   for ( ; hyp != myHypos.end(); ++hyp ) {
323     if ( (*hyp)->IsAlgo() &&
324          theCmd->AddAccessorMethod( (*hyp)->GetID(), (*hyp)->AccessorMethod() ))
325       return true;
326   }
327   return false;
328 }
329
330 //================================================================================
331 /*!
332  * \brief Find hypothesis by ID (entry)
333   * \param theHypID - The hypothesis ID
334   * \retval Handle(_pyHypothesis) - The found hypothesis
335  */
336 //================================================================================
337
338 Handle(_pyHypothesis) _pyGen::FindHyp( const _pyID& theHypID )
339 {
340   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
341   for ( ; hyp != myHypos.end(); ++hyp )
342     if ( !hyp->IsNull() && theHypID == (*hyp)->GetID() )
343       return *hyp;
344   return Handle(_pyHypothesis)();
345 }
346
347 //================================================================================
348 /*!
349  * \brief Find algorithm the created algorithm
350   * \param theGeom - The shape ID the algorithm was created on
351   * \param theMesh - The mesh ID that created the algorithm
352   * \param dim - The algo dimension
353   * \retval Handle(_pyHypothesis) - The found algo
354  */
355 //================================================================================
356
357 Handle(_pyHypothesis) _pyGen::FindAlgo( const _pyID& theGeom, const _pyID& theMesh,
358                                       const TCollection_AsciiString& theAlgoType )
359 {
360   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
361   for ( ; hyp != myHypos.end(); ++hyp )
362     if ( !hyp->IsNull() &&
363          (*hyp)->IsAlgo() &&
364          (*hyp)->GetType() == theAlgoType &&
365          (*hyp)->GetGeom() == theGeom &&
366          (*hyp)->GetMesh() == theMesh )
367       return *hyp;
368   return 0;
369 }
370
371 //================================================================================
372 /*!
373  * \brief Change order of commands in the script
374   * \param theCmd1 - One command
375   * \param theCmd2 - Another command
376  */
377 //================================================================================
378
379 void _pyGen::ExchangeCommands( Handle(_pyCommand) theCmd1, Handle(_pyCommand) theCmd2 )
380 {
381   list< Handle(_pyCommand) >::iterator pos1, pos2;
382   pos1 = find( myCommands.begin(), myCommands.end(), theCmd1 );
383   pos2 = find( myCommands.begin(), myCommands.end(), theCmd2 );
384   myCommands.insert( pos1, theCmd2 );
385   myCommands.insert( pos2, theCmd1 );
386   myCommands.erase( pos1 );
387   myCommands.erase( pos2 );
388
389   int nb1 = theCmd1->GetOrderNb();
390   theCmd1->SetOrderNb( theCmd2->GetOrderNb() );
391   theCmd2->SetOrderNb( nb1 );
392 //   cout << "BECOME " << theCmd1->GetOrderNb() << "\t" << theCmd1->GetString() << endl
393 //        << "BECOME " << theCmd2->GetOrderNb() << "\t" << theCmd2->GetString() << endl << endl;
394 }
395
396 //================================================================================
397 /*!
398  * \brief Set one command after the other
399   * \param theCmd - Command to move
400   * \param theAfterCmd - Command ater which to insert the first one
401  */
402 //================================================================================
403
404 void _pyGen::SetCommandAfter( Handle(_pyCommand) theCmd, Handle(_pyCommand) theAfterCmd )
405 {
406 //   cout << "SET\t" << theCmd->GetString() << endl << "AFTER\t" << theAfterCmd->GetString() << endl << endl;
407   list< Handle(_pyCommand) >::iterator pos;
408   pos = find( myCommands.begin(), myCommands.end(), theCmd );
409   myCommands.erase( pos );
410   pos = find( myCommands.begin(), myCommands.end(), theAfterCmd );
411   myCommands.insert( ++pos, theCmd );
412
413   int i = 1;
414   for ( pos = myCommands.begin(); pos != myCommands.end(); ++pos)
415     (*pos)->SetOrderNb( i++ );
416 }
417
418 //================================================================================
419 /*!
420  * \brief Set method to access to object wrapped with python class
421   * \param theID - The wrapped object entry
422   * \param theMethod - The accessor method
423  */
424 //================================================================================
425
426 void _pyGen::SetAccessorMethod(const _pyID& theID, const char* theMethod )
427 {
428   myID2AccessorMethod.Bind( theID, (char*) theMethod );
429 }
430
431 //================================================================================
432 /*!
433  * \brief Find out type of geom group
434   * \param grpID - The geom group entry
435   * \retval int - The type
436  */
437 //================================================================================
438
439 static bool sameGroupType( const _pyID&                   grpID,
440                            const TCollection_AsciiString& theType)
441 {
442   // define group type as smesh.Mesh.Group() does
443   int type = -1;
444   SALOMEDS::Study_var study = SMESH_Gen_i::GetSMESHGen()->GetCurrentStudy();
445   SALOMEDS::SObject_var aSObj = study->FindObjectID( grpID.ToCString() );
446   if ( !aSObj->_is_nil() ) {
447     GEOM::GEOM_Object_var aGeomObj = GEOM::GEOM_Object::_narrow( aSObj->GetObject() );
448     if ( !aGeomObj->_is_nil() ) {
449       switch ( aGeomObj->GetShapeType() ) {
450       case GEOM::VERTEX: type = SMESH::NODE; break;
451       case GEOM::EDGE:   type = SMESH::EDGE; break;
452       case GEOM::FACE:   type = SMESH::FACE; break;
453       case GEOM::SOLID:
454       case GEOM::SHELL:  type = SMESH::VOLUME; break;
455       case GEOM::COMPOUND: {
456         GEOM::GEOM_Gen_var aGeomGen = SMESH_Gen_i::GetSMESHGen()->GetGeomEngine();
457         if ( !aGeomGen->_is_nil() ) {
458           GEOM::GEOM_IGroupOperations_var aGrpOp =
459             aGeomGen->GetIGroupOperations( study->StudyId() );
460           if ( !aGrpOp->_is_nil() ) {
461             switch ( aGrpOp->GetType( aGeomObj )) {
462             case TopAbs_VERTEX: type = SMESH::NODE; break;
463             case TopAbs_EDGE:   type = SMESH::EDGE; break;
464             case TopAbs_FACE:   type = SMESH::FACE; break;
465             case TopAbs_SOLID:  type = SMESH::VOLUME; break;
466             default:;
467             }
468           }
469         }
470       }
471       default:;
472       }
473     }
474   }
475   if ( type < 0 ) {
476     MESSAGE("Type of the group " << grpID << " not found");
477     return false;
478   }
479   if ( theType.IsIntegerValue() )
480     return type == theType.IntegerValue();
481
482   switch ( type ) {
483   case SMESH::NODE:   return theType.Location( "NODE", 1, theType.Length() );
484   case SMESH::EDGE:   return theType.Location( "EDGE", 1, theType.Length() );
485   case SMESH::FACE:   return theType.Location( "FACE", 1, theType.Length() );
486   case SMESH::VOLUME: return theType.Location( "VOLUME", 1, theType.Length() );
487   default:;
488   }
489   return false;
490 }
491
492 //================================================================================
493 /*!
494  * \brief 
495   * \param theCreationCmd - 
496  */
497 //================================================================================
498
499 _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd):
500   _pyObject(theCreationCmd), myHasEditor(false)
501 {
502   // convert my creation command
503   Handle(_pyCommand) creationCmd = GetCreationCmd();
504   creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
505   creationCmd->SetMethod( "Mesh" );
506
507   theGen->SetAccessorMethod( GetID(), "GetMesh()" );
508 }
509
510 //================================================================================
511 /*!
512  * \brief Convert a IDL API command of SMESH::Mesh to a method call of python Mesh
513   * \param theCommand - Engine method called for this mesh
514  */
515 //================================================================================
516
517 void _pyMesh::Process( const Handle(_pyCommand)& theCommand )
518 {
519   // smesh.py wraps the following methods:
520   //
521   // 1. GetSubMesh(geom, name) + AddHypothesis(geom, algo)
522   //     --> in Mesh_Algorithm.Create(mesh, geom, hypo, so)
523   // 2. AddHypothesis(geom, hyp)
524   //     --> in Mesh_Algorithm.Hypothesis(hyp, args, so)
525   // 3. CreateGroupFromGEOM(type, name, grp)
526   //     --> in Mesh.Group(grp, name="")
527   // 4. ExportToMED(f, opt, version)
528   //     --> in Mesh.ExportToMED( f, version, opt=0 )
529   // 5. ExportMED(f, opt)
530   //     --> in Mesh.ExportMED( f,opt=0 )
531   // 6. ExportDAT(f)
532   //     --> in Mesh.ExportDAT( f )
533   // 7. ExportUNV(f)
534   //     --> in Mesh.ExportUNV(f)
535   // 8. ExportSTL(f, ascii)
536   //     --> in Mesh.ExportSTL(f, ascii=1)
537
538   const TCollection_AsciiString method = theCommand->GetMethod();
539   if ( method == "GetSubMesh" ) {
540     mySubmeshes.push_back( theCommand );
541   }
542   else if ( method == "AddHypothesis" ) { // mesh.AddHypothesis(geom, HYPO )
543     myAddHypCmds.push_back( theCommand );
544     // set mesh to hypo
545     const _pyID& hypID = theCommand->GetArg( 2 );
546     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
547     if ( !hyp.IsNull() ) {
548       myHypos.push_back( hyp );
549       if ( hyp->GetMesh().IsEmpty() )
550         hyp->SetMesh( this->GetID() );
551     }
552   }
553   else if ( method == "CreateGroupFromGEOM" ) {// (type, name, grp)
554     _pyID grp = theCommand->GetArg( 3 );
555     if ( sameGroupType( grp, theCommand->GetArg( 1 )) ) { // --> Group(grp)
556       theCommand->SetMethod( "Group" );
557       theCommand->RemoveArgs();
558       theCommand->SetArg( 1, grp );
559     }
560     else {
561       AddMeshAccess( theCommand );
562     }
563   }
564   else if ( method == "ExportToMED" ) {//(f, opt, version)
565     // --> (f, version, opt)
566     _pyID opt = theCommand->GetArg( 2 );
567     _pyID ver = theCommand->GetArg( 3 );
568     theCommand->SetArg( 2, ver );
569     theCommand->SetArg( 3, opt );
570   }
571   else if ( method == "RemoveHypothesis" ) // (geom, hyp)
572   {
573     const _pyID & hypID = theCommand->GetArg( 2 );
574
575     // check if this mesh still has corresponding addition command
576     bool hasAddCmd = false;
577     list< Handle(_pyCommand) >::iterator cmd = myAddHypCmds.begin();
578     while ( cmd != myAddHypCmds.end() )
579     {
580       // AddHypothesis(geom, hyp)
581       if ( hypID == (*cmd)->GetArg( 2 )) { // erase both (add and remove) commands
582         theCommand->Clear();
583         (*cmd)->Clear();
584         cmd = myAddHypCmds.erase( cmd );
585         hasAddCmd = true;
586       }
587       else {
588         ++cmd;
589       }
590     }
591     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
592     if ( ! hasAddCmd ) { // hypo addition already wrapped
593       // access to wrapped mesh
594       AddMeshAccess( theCommand );
595       // access to wrapped algo
596       if ( !hyp.IsNull() && hyp->IsAlgo() && hyp->IsWrapped() )
597         theCommand->SetArg( 2, theCommand->GetArg( 2 ) + ".GetAlgorithm()" );
598     }
599     // remove hyp from myHypos
600     myHypos.remove( hyp );
601   }
602
603   // leave only one "  mesh_editor_<nb> = mesh.GetMeshEditor()"
604   else if ( theCommand->GetMethod() == "GetMeshEditor")
605   {
606     if ( myHasEditor )
607       theCommand->Clear();
608     else
609       AddMeshAccess( theCommand );
610     myHasEditor = true;
611   }
612
613   // apply theCommand to the mesh wrapped by smeshpy mesh
614   else
615   {
616     AddMeshAccess( theCommand );
617   }
618 }
619
620 //================================================================================
621 /*!
622  * \brief Convert creation and addition of all algos and hypos
623  */
624 //================================================================================
625
626 void _pyMesh::Flush()
627 {
628   list < Handle(_pyCommand) >::iterator cmd, cmd2;
629
630   // try to convert algo addition like this:
631   // mesh.AddHypothesis(geom, ALGO ) --> ALGO = mesh.Algo()
632   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
633   {
634     Handle(_pyCommand) addCmd = *cmd;
635     const _pyID& algoID = addCmd->GetArg( 2 );
636     Handle(_pyHypothesis) algo = theGen->FindHyp( algoID );
637     if ( algo.IsNull() || !algo->IsAlgo() )
638       continue;
639     // try to convert
640     _pyID geom = addCmd->GetArg( 1 );
641     if ( algo->Addition2Creation( addCmd, this->GetID() )) // OK
642     {
643       // wrapped algo is created atfer mesh creation
644       GetCreationCmd()->AddDependantCmd( addCmd );
645
646       if ( geom != GetGeom() ) // local algo
647       {
648         // mesh.AddHypothesis(geom, ALGO ) --> mesh.AlgoMethod(geom)
649         addCmd->SetArg( addCmd->GetNbArgs() + 1,
650                         TCollection_AsciiString( "geom=" ) + geom );
651         // sm = mesh.GetSubMesh(geom, name) --> sm = ALGO.GetSubMesh()
652         for ( cmd2 = mySubmeshes.begin(); cmd2 != mySubmeshes.end(); ++cmd2 ) {
653           Handle(_pyCommand) subCmd = *cmd2;
654           if ( geom == subCmd->GetArg( 1 )) {
655             subCmd->SetObject( algo->GetID() );
656             subCmd->RemoveArgs();
657             addCmd->AddDependantCmd( subCmd );
658           }
659         }
660       }
661     }
662     else // ALGO was already created
663     {
664       // mesh.AddHypothesis(geom, ALGO ) --> mesh.GetMesh().AddHypothesis(geom, ALGO )
665       AddMeshAccess( addCmd );
666       // mesh.GetMesh().AddHypothesis(geom, ALGO ) ->
667       // mesh.GetMesh().AddHypothesis(geom, ALGO.GetAlgorithm() )
668       addCmd->SetArg( 2, addCmd->GetArg( 2 ) + ".GetAlgorithm()" );
669     }
670   }
671
672   // try to convert hypo addition like this:
673   // mesh.AddHypothesis(geom, HYPO ) --> HYPO = algo.Hypo()
674   for ( cmd = myAddHypCmds.begin(); cmd != myAddHypCmds.end(); ++cmd )
675   {
676     Handle(_pyCommand) addCmd = *cmd;
677     const _pyID& hypID = addCmd->GetArg( 2 );
678     Handle(_pyHypothesis) hyp = theGen->FindHyp( hypID );
679     if ( hyp.IsNull() || hyp->IsAlgo() )
680       continue;
681     const _pyID& geom = addCmd->GetArg( 1 );
682     // find algo created on <geom> for this mesh
683     Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, this->GetID(), hyp->GetType() );
684     //_pyID algoID = algo.IsNull() ? "" : algo->GetID();
685     if ( !algo.IsNull() && hyp->Addition2Creation( addCmd, this->GetID() )) // OK
686     {
687       addCmd->SetObject( algo->GetID() );
688       algo->GetCreationCmd()->AddDependantCmd( addCmd );
689     }
690     else
691     {
692       AddMeshAccess( addCmd );
693     }
694   }
695
696   // sm = mesh.GetSubMesh(geom, name) --> sm = mesh.GetMesh().GetSubMesh(geom, name)
697   for ( cmd = mySubmeshes.begin(); cmd != mySubmeshes.end(); ++cmd ) {
698     Handle(_pyCommand) subCmd = *cmd;
699     if ( subCmd->GetNbArgs() > 0 )
700       AddMeshAccess( subCmd );
701   }
702   myAddHypCmds.clear();
703   mySubmeshes.clear();
704
705   // flush hypotheses
706   list< Handle(_pyHypothesis) >::iterator hyp = myHypos.begin();
707   for ( ; hyp != myHypos.end(); ++hyp )
708     (*hyp)->Flush();
709 }
710
711 //================================================================================
712 /*!
713  * \brief _pyHypothesis constructor
714   * \param theCreationCmd - 
715  */
716 //================================================================================
717
718 _pyHypothesis::_pyHypothesis(const Handle(_pyCommand)& theCreationCmd):
719   _pyObject( theCreationCmd )
720 {
721   myDim = myIsAlgo = /*myIsLocal = */myIsWrapped = myIsConverted = false;
722 }
723
724 //================================================================================
725 /*!
726  * \brief Creates algorithm or hypothesis
727   * \param theCreationCmd - The engine command creating a hypothesis
728   * \retval Handle(_pyHypothesis) - Result _pyHypothesis
729  */
730 //================================================================================
731
732 Handle(_pyHypothesis) _pyHypothesis::NewHypothesis( const Handle(_pyCommand)& theCreationCmd)
733 {
734   // theCreationCmd: CreateHypothesis( "theHypType", "theLibName" )
735   ASSERT (( theCreationCmd->GetMethod() == "CreateHypothesis"));
736
737   Handle(_pyHypothesis) hyp, algo;
738
739   // "theHypType"
740   const TCollection_AsciiString & hypTypeQuoted = theCreationCmd->GetArg( 1 );
741   if ( hypTypeQuoted.IsEmpty() )
742     return hyp;
743   // theHypType
744   TCollection_AsciiString  hypType =
745     hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
746
747   algo = new _pyAlgorithm( theCreationCmd );
748   hyp  = new _pyHypothesis( theCreationCmd );
749
750   // 1D Regular_1D ----------
751   if ( hypType == "Regular_1D" ) {
752     algo->SetDimMethodType( 1, "Segment");
753   }
754   else if ( hypType == "LocalLength" ) {
755     hyp->SetDimMethodType( 1, "LocalLength", "Regular_1D");
756     hyp->AddArgMethod( "SetLength" );
757   }
758   else if ( hypType == "NumberOfSegments" ) {
759     hyp = new _pyNumberOfSegmentsHyp( theCreationCmd );
760     hyp->SetDimMethodType( 1, "NumberOfSegments", "Regular_1D");
761     hyp->AddArgMethod( "SetNumberOfSegments" );
762     hyp->AddArgMethod( "SetScaleFactor" );
763   }
764   else if ( hypType == "Arithmetic1D" ) {
765     hyp = new _pyComplexParamHypo( theCreationCmd );
766     hyp->SetDimMethodType( 1, "Arithmetic1D", "Regular_1D");
767   }
768   else if ( hypType == "StartEndLength" ) {
769     hyp = new _pyComplexParamHypo( theCreationCmd );
770     hyp->SetDimMethodType( 1, "StartEndLength", "Regular_1D");
771   }
772   else if ( hypType == "Deflection1D" ) {
773     hyp->SetDimMethodType( 1, "Deflection1D", "Regular_1D");
774     hyp->AddArgMethod( "SetDeflection" );
775   }
776   else if ( hypType == "Propagation" ) {
777     hyp->SetDimMethodType( 1, "Propagation", "Regular_1D");
778   }
779   else if ( hypType == "QuadraticMesh" ) {
780     hyp->SetDimMethodType( 1, "QuadraticMesh", "Regular_1D");
781   }
782   else if ( hypType == "AutomaticLength" ) {
783     hyp->SetDimMethodType( 1, "AutomaticLength", "Regular_1D");
784     hyp->AddArgMethod( "SetFineness");
785   }
786   // 1D Python_1D ----------
787   else if ( hypType == "Python_1D" ) {
788     algo->SetDimMethodType( 1, "Segment");
789     algo->myArgs.Append( "algo=smesh.PYTHON");
790   }
791   else if ( hypType == "PythonSplit1D" ) {
792     hyp->SetDimMethodType( 1, "PythonSplit1D", "Python_1D");
793     hyp->AddArgMethod( "SetNumberOfSegments");
794     hyp->AddArgMethod( "SetPythonLog10RatioFunction");
795   }
796   // 2D ----------
797   else if ( hypType == "MEFISTO_2D" ) {
798     algo->SetDimMethodType( 2, "Triangle");
799   }
800   else if ( hypType == "MaxElementArea" ) {
801     hyp->SetDimMethodType( 2, "MaxElementArea", "MEFISTO_2D");
802     hyp->AddArgMethod( "SetMaxElementArea");
803   }
804   else if ( hypType == "LengthFromEdges" ) {
805     hyp->SetDimMethodType( 2, "LengthFromEdges", "MEFISTO_2D");
806   }
807   else if ( hypType == "Quadrangle_2D" ) {
808     algo->SetDimMethodType( 2, "Quadrangle" );
809   }
810   else if ( hypType == "QuadranglePreference" ) {
811     hyp->SetDimMethodType( 2, "QuadranglePreference", "Quadrangle_2D");
812   }
813   // 3D ----------
814   else if ( hypType == "NETGEN_3D") {
815     algo->SetDimMethodType( 3, "Tetrahedron" );
816     algo->myArgs.Append( "algo=smesh.NETGEN" );
817   }
818   else if ( hypType == "MaxElementVolume") {
819     hyp->SetDimMethodType( 3, "MaxElementVolume", "NETGEN_3D");
820     hyp->AddArgMethod( "SetMaxElementVolume" );
821   }
822   else if ( hypType == "GHS3D_3D" ) {
823     algo->SetDimMethodType( 3, "Tetrahedron");
824     algo->myArgs.Append( "algo=smesh.GHS3D" );
825   }
826   else if ( hypType == "Hexa_3D" ) {
827     algo->SetDimMethodType( 3, "Hexahedron");
828   }
829   // Repetitive ---------
830   else if ( hypType == "Projection_1D" ) {
831     algo->SetDimMethodType( 1, "Projection1D");
832   }
833   else if ( hypType == "ProjectionSource1D" ) {
834     hyp->SetDimMethodType( 1, "SourceEdge", "Projection_1D");
835     hyp->AddArgMethod( "SetSourceEdge");
836     hyp->AddArgMethod( "SetSourceMesh");
837     hyp->AddArgMethod( "SetVertexAssociation", 2 );
838   }
839   else if ( hypType == "Projection_2D" ) {
840     algo->SetDimMethodType( 2, "Projection2D");
841   }
842   else if ( hypType == "ProjectionSource2D" ) {
843     hyp->SetDimMethodType( 2, "SourceFace", "Projection_2D");
844     hyp->AddArgMethod( "SetSourceFace");
845     hyp->AddArgMethod( "SetSourceMesh");
846     hyp->AddArgMethod( "SetVertexAssociation", 4 );
847   }
848   else if ( hypType == "Projection_3D" ) {
849     algo->SetDimMethodType( 3, "Projection3D");
850   }
851   else if ( hypType == "ProjectionSource3D" ) {
852     hyp->SetDimMethodType( 3, "SourceShape3D", "Projection_3D");
853     hyp->AddArgMethod( "SetSource3DShape");
854     hyp->AddArgMethod( "SetSourceMesh");
855     hyp->AddArgMethod( "SetVertexAssociation", 4 );
856   }
857   else if ( hypType == "Prism_3D" ) {
858     algo->SetDimMethodType( 3, "Prism");
859   }
860   else if ( hypType == "RadialPrism_3D" ) {
861     algo->SetDimMethodType( 3, "Prism");
862   }
863   else if ( hypType == "NumberOfLayers" ) {
864     hyp->SetDimMethodType( 3, "NumberOfLayers", "RadialPrism_3D");
865     hyp->AddArgMethod( "SetNumberOfLayers" );
866   }
867   else if ( hypType == "LayerDistribution" ) {
868     hyp = new _pyLayerDistributionHypo( theCreationCmd );
869     hyp->SetDimMethodType( 3, "LayerDistribution", "RadialPrism_3D");
870 //     hyp->AddArgMethod( "SetSource3DShape");
871 //     hyp->AddArgMethod( "SetSourceMesh");
872 //     hyp->AddArgMethod( "SetVertexAssociation", 4 );
873   }
874
875   if ( algo->GetDim() ) {
876     algo->myType = hypType;
877     return algo;
878   }
879   return hyp;
880 }
881
882 //================================================================================
883 /*!
884  * \brief Convert the command adding a hypothesis to mesh into a smesh command
885   * \param theCmd - The command like mesh.AddHypothesis( geom, hypo )
886   * \param theAlgo - The algo that can create this hypo
887   * \retval bool - false if the command cant be converted
888  */
889 //================================================================================
890
891 bool _pyHypothesis::Addition2Creation( const Handle(_pyCommand)& theCmd,
892                                        const _pyID&              theMesh)
893 {
894   ASSERT(( theCmd->GetMethod() == "AddHypothesis" ));
895
896   if ( !IsWrappable( theMesh ))
897     return false;
898
899   myIsWrapped = true;
900
901   if ( myIsWrapped )
902   {
903     // mesh.AddHypothesis(geom,hyp) --> hyp = theMesh.myCreationMethod(args)
904     theCmd->SetResultValue( GetID() );
905     theCmd->SetObject( theMesh );
906     theCmd->SetMethod( myCreationMethod );
907     // set args
908     theCmd->RemoveArgs();
909     for ( int i = 1; i <= myArgs.Length(); ++i ) {
910       if ( !myArgs( i ).IsEmpty() )
911         theCmd->SetArg( i, myArgs( i ));
912       else
913         theCmd->SetArg( i, "[]");
914     }
915     // set a new creation command
916     GetCreationCmd()->Clear();
917     SetCreationCmd( theCmd );
918
919     // clear commands setting arg values
920     list < Handle(_pyCommand) >::iterator argCmd = myArgCommands.begin();
921     for ( ; argCmd != myArgCommands.end(); ++argCmd )
922       (*argCmd)->Clear();
923   }
924   else
925   {
926 //     // set arg commands after hypo creation
927 //     list<Handle(_pyCommand)>::iterator argCmd = myArgCommands.begin();
928 //     for ( ; argCmd != myArgCommands.end(); ++argCmd )
929 //       if ( !(*argCmd)->IsEmpty() && GetCommandNb() > (*argCmd)->GetOrderNb() )
930 //         theGen->ExchangeCommands( GetCreationCmd(), *argCmd );
931   }
932
933   // set unknown arg commands after hypo creation
934   Handle(_pyCommand) afterCmd = myIsWrapped ? theCmd : GetCreationCmd();
935   list<Handle(_pyCommand)>::iterator cmd = myUnknownCommands.begin();
936   for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
937     afterCmd->AddDependantCmd( *cmd );
938   }
939
940   return myIsWrapped;
941 }
942
943 //================================================================================
944 /*!
945  * \brief Remember hypothesis parameter values
946  * \param theCommand - The called hypothesis method
947  */
948 //================================================================================
949
950 void _pyHypothesis::Process( const Handle(_pyCommand)& theCommand)
951 {
952   ASSERT( !myIsAlgo );
953   // set args
954   int nbArgs = 0;
955   for ( int i = 1; i <= myArgMethods.Length(); ++i ) {
956     if ( myArgMethods( i ) == theCommand->GetMethod() ) {
957       while ( myArgs.Length() < nbArgs + myNbArgsByMethod( i ))
958         myArgs.Append( "[]" );
959       for ( int iArg = 1; iArg <= myNbArgsByMethod( i ); ++iArg )
960         myArgs( nbArgs + iArg ) = theCommand->GetArg( iArg ); // arg value
961       myArgCommands.push_back( theCommand );
962       return;
963     }
964     nbArgs += myNbArgsByMethod( i );
965   }
966   myUnknownCommands.push_back( theCommand );
967 }
968
969 //================================================================================
970 /*!
971  * \brief Finish conversion
972  */
973 //================================================================================
974
975 void _pyHypothesis::Flush()
976 {
977   if ( IsWrapped() ) {
978   }
979   else {
980     list < Handle(_pyCommand) >::iterator cmd = myArgCommands.begin();
981     for ( ; cmd != myArgCommands.end(); ++cmd ) {
982       // Add access to a wrapped mesh
983       theGen->AddMeshAccessorMethod( *cmd );
984       // Add access to a wrapped algorithm
985       theGen->AddAlgoAccessorMethod( *cmd );
986     }
987     cmd = myUnknownCommands.begin();
988     for ( ; cmd != myUnknownCommands.end(); ++cmd ) {
989       // Add access to a wrapped mesh
990       theGen->AddMeshAccessorMethod( *cmd );
991       // Add access to a wrapped algorithm
992       theGen->AddAlgoAccessorMethod( *cmd );
993     }
994   }
995   // forget previous hypothesis modifications
996   myArgCommands.clear();
997   myUnknownCommands.clear();
998 }
999
1000 //================================================================================
1001 /*!
1002  * \brief clear creation, arg and unkown commands
1003  */
1004 //================================================================================
1005
1006 void _pyHypothesis::ClearAllCommands()
1007 {
1008   GetCreationCmd()->Clear();
1009   list<Handle(_pyCommand)>::iterator cmd = myArgCommands.begin();
1010   for ( ; cmd != myArgCommands.end(); ++cmd )
1011     ( *cmd )->Clear();
1012   cmd = myUnknownCommands.begin();
1013   for ( ; cmd != myUnknownCommands.end(); ++cmd )
1014     ( *cmd )->Clear();
1015 }
1016
1017 //================================================================================
1018 /*!
1019  * \brief Remember hypothesis parameter values
1020   * \param theCommand - The called hypothesis method
1021  */
1022 //================================================================================
1023
1024 void _pyComplexParamHypo::Process( const Handle(_pyCommand)& theCommand)
1025 {
1026   // ex: hyp.SetLength(start, 1)
1027   //     hyp.SetLength(end,   0)
1028   ASSERT(( theCommand->GetMethod() == "SetLength" ));
1029   ASSERT(( theCommand->GetArg( 2 ).IsIntegerValue() ));
1030   int i = 2 - theCommand->GetArg( 2 ).IntegerValue();
1031   while ( myArgs.Length() < i )
1032     myArgs.Append( "[]" );
1033   myArgs( i ) = theCommand->GetArg( 1 ); // arg value
1034   myArgCommands.push_back( theCommand );
1035 }
1036
1037 //================================================================================
1038 /*!
1039  * \brief Convert methods of 1D hypotheses to my own methods
1040   * \param theCommand - The called hypothesis method
1041  */
1042 //================================================================================
1043
1044 void _pyLayerDistributionHypo::Process( const Handle(_pyCommand)& theCommand)
1045 {
1046   if ( theCommand->GetMethod() != "SetLayerDistribution" )
1047     return;
1048
1049   _pyID newName; // name for 1D hyp = "HypType" + "_Distribution"
1050
1051   const _pyID& hyp1dID = theCommand->GetArg( 1 );
1052   Handle(_pyHypothesis) hyp1d = theGen->FindHyp( hyp1dID );
1053   if ( hyp1d.IsNull() ) // apparently hypId changed at study restoration
1054     hyp1d = my1dHyp;
1055   else if ( !my1dHyp.IsNull() && hyp1dID != my1dHyp->GetID() ) {
1056     // 1D hypo is already set, so distribution changes and the old
1057     // 1D hypo is thrown away
1058     my1dHyp->ClearAllCommands();
1059   }
1060   my1dHyp = hyp1d;
1061   if ( my1dHyp.IsNull() )
1062     return; // something wrong :(
1063
1064   // make a new name for 1D hyp = "HypType" + "_Distribution"
1065   if ( my1dHyp->GetCreationCmd()->GetMethod() == "CreateHypothesis" ) {
1066     // not yet converted creation cmd
1067     TCollection_AsciiString hypTypeQuoted = my1dHyp->GetCreationCmd()->GetArg(1);
1068     TCollection_AsciiString hypType = hypTypeQuoted.SubString( 2, hypTypeQuoted.Length() - 1 );
1069     newName = hypType + "_Distribution";
1070     my1dHyp->GetCreationCmd()->SetResultValue( newName );
1071   }
1072   else {
1073     // already converted creation cmd
1074     newName = my1dHyp->GetCreationCmd()->GetResultValue();
1075   }
1076
1077   // as creation of 1D hyp was written later then it's edition,
1078   // we need to find all it's edition calls and process them
1079   list< Handle(_pyCommand) >& cmds = theGen->GetCommands();
1080   list< Handle(_pyCommand) >::iterator cmdIt = cmds.begin();
1081   for ( ; cmdIt != cmds.end(); ++cmdIt ) {
1082     const _pyID& objID = (*cmdIt)->GetObject();
1083     if ( objID == hyp1dID ) {
1084       my1dHyp->Process( *cmdIt );
1085       my1dHyp->GetCreationCmd()->AddDependantCmd( *cmdIt );
1086       ( *cmdIt )->SetObject( newName );
1087     }
1088   }
1089   if ( !myArgCommands.empty() )
1090     myArgCommands.front()->Clear();
1091   theCommand->SetArg( 1, newName );
1092   myArgCommands.push_back( theCommand );
1093   // copy hyp1d's creation method and args
1094 //   myCreationMethod = hyp1d->GetCreationMethod();
1095 //   myArgs           = hyp1d->GetArgs();
1096 //   // make them cleared at conversion
1097 //   myArgCommands = hyp1d->GetArgCommands();
1098
1099 //   // to be cleared at convertion only
1100 //   myArgCommands.push_back( theCommand );
1101 }
1102
1103 //================================================================================
1104 /*!
1105  * \brief 
1106   * \param theAdditionCmd - 
1107   * \param theMesh - 
1108   * \retval bool - 
1109  */
1110 //================================================================================
1111
1112 bool _pyLayerDistributionHypo::Addition2Creation( const Handle(_pyCommand)& theAdditionCmd,
1113                                                   const _pyID&              theMesh)
1114 {
1115   myIsWrapped = false;
1116
1117   if ( my1dHyp.IsNull() )
1118     return false;
1119
1120   // set "SetLayerDistribution()" after addition cmd
1121   theAdditionCmd->AddDependantCmd( myArgCommands.front() );
1122
1123   _pyID geom = theAdditionCmd->GetArg( 1 );
1124
1125   my1dHyp->SetMesh( theMesh );
1126   if ( !my1dHyp->Addition2Creation( theAdditionCmd, theMesh ))
1127     return false;
1128
1129   // clear "SetLayerDistribution()" cmd
1130   myArgCommands.front()->Clear();
1131
1132   // Convert my creation => me = RadialPrismAlgo.Get3DHypothesis()
1133
1134   // find RadialPrism algo created on <geom> for theMesh
1135   Handle(_pyHypothesis) algo = theGen->FindAlgo( geom, theMesh, this->GetType() );
1136   if ( !algo.IsNull() ) {
1137     GetCreationCmd()->SetObject( algo->GetID() );
1138     GetCreationCmd()->SetMethod( "Get3DHypothesis" );
1139     GetCreationCmd()->RemoveArgs();
1140     theAdditionCmd->AddDependantCmd( GetCreationCmd() );
1141     myIsWrapped = true;
1142   }
1143   return myIsWrapped;
1144 }
1145
1146 //================================================================================
1147 /*!
1148  * \brief 
1149  */
1150 //================================================================================
1151
1152 void _pyLayerDistributionHypo::Flush()
1153 {
1154   //my1dHyp.Nullify();
1155   //_pyHypothesis::Flush();
1156 }
1157
1158 //================================================================================
1159 /*!
1160  * \brief additionally to Addition2Creation, clears SetDistrType() command
1161   * \param theCmd - AddHypothesis() command
1162   * \param theMesh - mesh to which a hypothesis is added
1163   * \retval bool - convertion result
1164  */
1165 //================================================================================
1166
1167 bool _pyNumberOfSegmentsHyp::Addition2Creation( const Handle(_pyCommand)& theCmd,
1168                                                 const _pyID&              theMesh)
1169 {
1170   if ( IsWrappable( theMesh ) && myArgs.Length() > 1 ) {
1171     // scale factor (2-nd arg) is provided: clear SetDistrType(1) command
1172     bool scaleDistrType = false;
1173     list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
1174     for ( ; cmd != myUnknownCommands.rend(); ++cmd ) {
1175       if ( (*cmd)->GetMethod() == "SetDistrType" ) {
1176         if ( (*cmd)->GetArg( 1 ) == "1" ) {
1177           scaleDistrType = true;
1178           (*cmd)->Clear();
1179         }
1180         else if ( !scaleDistrType ) {
1181           // distribution type changed: remove scale factor from args
1182           myArgs.Remove( 2, myArgs.Length() );
1183           break;
1184         }
1185       }
1186     }
1187   }
1188   return _pyHypothesis::Addition2Creation( theCmd, theMesh );
1189 }
1190
1191 //================================================================================
1192 /*!
1193  * \brief remove repeated commands defining distribution
1194  */
1195 //================================================================================
1196
1197 void _pyNumberOfSegmentsHyp::Flush()
1198 {
1199   // find number of the last SetDistrType() command
1200   list<Handle(_pyCommand)>::reverse_iterator cmd = myUnknownCommands.rbegin();
1201   int distrTypeNb = 0;
1202   for ( ; !distrTypeNb && cmd != myUnknownCommands.rend(); ++cmd )
1203     if ( (*cmd)->GetMethod() == "SetDistrType" )
1204       distrTypeNb = (*cmd)->GetOrderNb();
1205
1206   // clear commands before the last SetDistrType()
1207   list<Handle(_pyCommand)> * cmds[2] = { &myArgCommands, &myUnknownCommands };
1208   for ( int i = 0; i < 2; ++i ) {
1209     set<TCollection_AsciiString> uniqueMethods;
1210     list<Handle(_pyCommand)> & cmdList = *cmds[i];
1211     for ( cmd = cmdList.rbegin(); cmd != cmdList.rend(); ++cmd )
1212     {
1213       bool clear = ( (*cmd)->GetOrderNb() < distrTypeNb );
1214       const TCollection_AsciiString& method = (*cmd)->GetMethod();
1215       if ( !clear || method == "SetNumberOfSegments" ) {
1216         bool isNewInSet = uniqueMethods.insert( method ).second;
1217         clear = !isNewInSet;
1218       }
1219       if ( clear )
1220         (*cmd)->Clear();
1221     }
1222     cmdList.clear();
1223   }
1224 }
1225
1226 //================================================================================
1227 /*!
1228  * \brief _pyAlgorithm constructor
1229  * \param theCreationCmd - The command like "algo = smeshgen.CreateHypothesis(type,lib)"
1230  */
1231 //================================================================================
1232
1233 _pyAlgorithm::_pyAlgorithm(const Handle(_pyCommand)& theCreationCmd)
1234   : _pyHypothesis( theCreationCmd )
1235 {
1236   myIsAlgo = true;
1237 }
1238
1239 //================================================================================
1240 /*!
1241  * \brief Convert the command adding an algorithm to mesh
1242   * \param theCmd - The command like mesh.AddHypothesis( geom, algo )
1243   * \param theMesh - The mesh needing this algo 
1244   * \retval bool - false if the command cant be converted
1245  */
1246 //================================================================================
1247   
1248 bool _pyAlgorithm::Addition2Creation( const Handle(_pyCommand)& theCmd,
1249                                       const _pyID&              theMeshID)
1250 {
1251   if ( IsWrappable( theMeshID )) {
1252
1253     myGeom = theCmd->GetArg( 1 );
1254
1255     // mesh.AddHypothesis(geom,algo) --> theMeshID.myCreationMethod()
1256     if ( _pyHypothesis::Addition2Creation( theCmd, theMeshID )) {
1257       theGen->SetAccessorMethod( GetID(), "GetAlgorithm()" );
1258       return true;
1259     }
1260   }
1261   return false;
1262 }
1263
1264 //================================================================================
1265 /*!
1266  * \brief Return starting position of a part of python command
1267   * \param thePartIndex - The index of command part
1268   * \retval int - Part position
1269  */
1270 //================================================================================
1271
1272 int _pyCommand::GetBegPos( int thePartIndex )
1273 {
1274   if ( IsEmpty() )
1275     return EMPTY;
1276   if ( myBegPos.Length() < thePartIndex )
1277     return UNKNOWN;
1278   return myBegPos( thePartIndex );
1279 }
1280
1281 //================================================================================
1282 /*!
1283  * \brief Store starting position of a part of python command
1284   * \param thePartIndex - The index of command part
1285   * \param thePosition - Part position
1286  */
1287 //================================================================================
1288
1289 void _pyCommand::SetBegPos( int thePartIndex, int thePosition )
1290 {
1291   while ( myBegPos.Length() < thePartIndex )
1292     myBegPos.Append( UNKNOWN );
1293   myBegPos( thePartIndex ) = thePosition;
1294 }
1295
1296 //================================================================================
1297 /*!
1298  * \brief Return substring of python command looking like ResultValue = Obj.Meth()
1299   * \retval const TCollection_AsciiString & - ResultValue substring
1300  */
1301 //================================================================================
1302
1303 const TCollection_AsciiString & _pyCommand::GetResultValue()
1304 {
1305   if ( GetBegPos( RESULT_IND ) == UNKNOWN )
1306   {
1307     int begPos = myString.Location( "=", 1, Length() );
1308     if ( begPos )
1309       myRes = GetWord( myString, begPos, false );
1310     else
1311       begPos = EMPTY;
1312     SetBegPos( RESULT_IND, begPos );
1313   }
1314   return myRes;
1315 }
1316
1317 //================================================================================
1318 /*!
1319  * \brief Return substring of python command looking like ResVal = Object.Meth()
1320   * \retval const TCollection_AsciiString & - Object substring
1321  */
1322 //================================================================================
1323
1324 const TCollection_AsciiString & _pyCommand::GetObject()
1325 {
1326   if ( GetBegPos( OBJECT_IND ) == UNKNOWN )
1327   {
1328     // beginning
1329     int begPos = GetBegPos( RESULT_IND ) + myRes.Length();
1330     if ( begPos < 1 )
1331       begPos = myString.Location( "=", 1, Length() ) + 1;
1332     // store
1333     myObj = GetWord( myString, begPos, true );
1334     SetBegPos( OBJECT_IND, begPos );
1335   }
1336   //SCRUTE(myObj);
1337   return myObj;
1338 }
1339
1340 //================================================================================
1341 /*!
1342  * \brief Return substring of python command looking like ResVal = Obj.Method()
1343   * \retval const TCollection_AsciiString & - Method substring
1344  */
1345 //================================================================================
1346
1347 const TCollection_AsciiString & _pyCommand::GetMethod()
1348 {
1349   if ( GetBegPos( METHOD_IND ) == UNKNOWN )
1350   {
1351     // beginning
1352     int begPos = GetBegPos( OBJECT_IND ) + myObj.Length();
1353     bool forward = true;
1354     if ( begPos < 1 ) {
1355       begPos = myString.Location( "(", 1, Length() ) - 1;
1356       forward = false;
1357     }
1358     // store
1359     myMeth = GetWord( myString, begPos, forward );
1360     SetBegPos( METHOD_IND, begPos );
1361   }
1362   //SCRUTE(myMeth);
1363   return myMeth;
1364 }
1365
1366 //================================================================================
1367 /*!
1368  * \brief Return substring of python command looking like ResVal = Obj.Meth(Arg1,...)
1369   * \retval const TCollection_AsciiString & - Arg<index> substring
1370  */
1371 //================================================================================
1372
1373 const TCollection_AsciiString & _pyCommand::GetArg( int index )
1374 {
1375   if ( GetBegPos( ARG1_IND ) == UNKNOWN )
1376   {
1377     // find all args
1378     int begPos = GetBegPos( METHOD_IND ) + myMeth.Length();
1379     if ( begPos < 1 )
1380       begPos = myString.Location( "(", 1, Length() ) + 1;
1381
1382     int i = 0, prevLen = 0;
1383     while ( begPos != EMPTY ) {
1384       begPos += prevLen;
1385       // check if we are looking at the closing parenthesis
1386       while ( begPos <= Length() && isspace( myString.Value( begPos )))
1387         ++begPos;
1388       if ( begPos > Length() || myString.Value( begPos ) == ')' )
1389         break;
1390       myArgs.Append( GetWord( myString, begPos, true, true ));
1391       SetBegPos( ARG1_IND + i, begPos );
1392       prevLen = myArgs.Last().Length();
1393       if ( prevLen == 0 )
1394         myArgs.Remove( myArgs.Length() ); // no more args
1395       i++;
1396     }
1397   }
1398   if ( myArgs.Length() < index )
1399     return theEmptyString;
1400   return myArgs( index );
1401 }
1402
1403 //================================================================================
1404 /*!
1405  * \brief Check if char is a word part
1406   * \param c - The character to check
1407   * \retval bool - The check result
1408  */
1409 //================================================================================
1410
1411 static inline bool isWord(const char c, const bool dotIsWord)
1412 {
1413   return
1414     !isspace(c) && c != ',' && c != '=' && c != ')' && c != '(' && ( dotIsWord || c != '.');
1415 }
1416
1417 //================================================================================
1418 /*!
1419  * \brief Looks for a word in the string and returns word's beginning
1420   * \param theString - The input string
1421   * \param theStartPos - The position to start the search, returning word's beginning
1422   * \param theForward - The search direction
1423   * \retval TCollection_AsciiString - The found word
1424  */
1425 //================================================================================
1426
1427 TCollection_AsciiString _pyCommand::GetWord( const TCollection_AsciiString & theString,
1428                                             int &      theStartPos,
1429                                             const bool theForward,
1430                                             const bool dotIsWord )
1431 {
1432   int beg = theStartPos, end = theStartPos;
1433   theStartPos = EMPTY;
1434   if ( beg < 1 || beg > theString.Length() )
1435     return theEmptyString;
1436
1437   if ( theForward ) { // search forward
1438     // beg
1439     while ( beg <= theString.Length() && !isWord( theString.Value( beg ), dotIsWord))
1440       ++beg;
1441     if ( beg > theString.Length() )
1442       return theEmptyString; // no word found
1443     // end
1444     end = beg + 1;
1445     while ( end <= theString.Length() && isWord( theString.Value( end ), dotIsWord))
1446       ++end;
1447     --end;
1448   }
1449   else {  // search backward
1450     // end
1451     while ( end > 0 && !isWord( theString.Value( end ), dotIsWord))
1452       --end;
1453     if ( end == 0 )
1454       return theEmptyString; // no word found
1455     beg = end - 1;
1456     while ( beg > 0 && isWord( theString.Value( beg ), dotIsWord))
1457       --beg;
1458     ++beg;
1459   }
1460   theStartPos = beg;
1461   //cout << theString << " ---- " << beg << " - " << end << endl;
1462   return theString.SubString( beg, end );
1463 }
1464
1465 //================================================================================
1466 /*!
1467  * \brief Look for position where not space char is
1468   * \param theString - The string 
1469   * \param thePos - The position to search from and which returns result
1470   * \retval bool - false if there are only space after thePos in theString
1471  * 
1472  * 
1473  */
1474 //================================================================================
1475
1476 bool _pyCommand::SkipSpaces( const TCollection_AsciiString & theString, int & thePos )
1477 {
1478   if ( thePos < 1 || thePos > theString.Length() )
1479     return false;
1480
1481   while ( thePos <= theString.Length() && isspace( theString.Value( thePos )))
1482     ++thePos;
1483
1484   return thePos <= theString.Length();
1485 }
1486
1487 //================================================================================
1488 /*!
1489  * \brief Modify a part of the command
1490   * \param thePartIndex - The index of the part
1491   * \param thePart - The new part string
1492   * \param theOldPart - The old part
1493  */
1494 //================================================================================
1495
1496 void _pyCommand::SetPart(int thePartIndex, const TCollection_AsciiString& thePart,
1497                         TCollection_AsciiString& theOldPart)
1498 {
1499   int pos = GetBegPos( thePartIndex );
1500   if ( pos <= Length() && theOldPart != thePart)
1501   {
1502     TCollection_AsciiString seperator;
1503     if ( pos < 1 ) {
1504       pos = GetBegPos( thePartIndex + 1 );
1505       if ( pos < 1 ) return;
1506       switch ( thePartIndex ) {
1507       case RESULT_IND: seperator = " = "; break;
1508       case OBJECT_IND: seperator = "."; break;
1509       case METHOD_IND: seperator = "()"; break;
1510       default:;
1511       }
1512     }      
1513     myString.Remove( pos, theOldPart.Length() );
1514     if ( !seperator.IsEmpty() )
1515       myString.Insert( pos , seperator );
1516     myString.Insert( pos, thePart );
1517     // update starting positions of the following parts
1518     int posDelta = thePart.Length() + seperator.Length() - theOldPart.Length();
1519     for ( int i = thePartIndex + 1; i <= myBegPos.Length(); ++i ) {
1520       if ( myBegPos( i ) > 0 )
1521         myBegPos( i ) += posDelta;
1522     }
1523     theOldPart = thePart;
1524   }
1525 }
1526
1527 //================================================================================
1528 /*!
1529  * \brief Set agrument
1530   * \param index - The argument index, it counts from 1
1531   * \param theArg - The argument string
1532  */
1533 //================================================================================
1534
1535 void _pyCommand::SetArg( int index, const TCollection_AsciiString& theArg)
1536 {
1537   FindAllArgs();
1538   int argInd = ARG1_IND + index - 1;
1539   int pos = GetBegPos( argInd );
1540   if ( pos < 1 ) // no index-th arg exist, append inexistent args
1541   {
1542     // find a closing parenthesis
1543     if ( int lastArgInd = GetNbArgs() ) {
1544       pos = GetBegPos( ARG1_IND + lastArgInd  - 1 ) + GetArg( lastArgInd ).Length();
1545       while ( pos > 0 && pos <= Length() && myString.Value( pos ) != ')' )
1546         ++pos;
1547     }
1548     else {
1549       pos = Length();
1550       while ( pos > 0 && myString.Value( pos ) != ')' )
1551         --pos;
1552     }
1553     if ( pos < 1 || myString.Value( pos ) != ')' ) { // no parentheses at all
1554       myString += "()";
1555       pos = Length();
1556     }
1557     while ( myArgs.Length() < index ) {
1558       if ( myArgs.Length() )
1559         myString.Insert( pos++, "," );
1560       myArgs.Append("None");
1561       myString.Insert( pos, myArgs.Last() );
1562       SetBegPos( ARG1_IND + myArgs.Length() - 1, pos );
1563       pos += myArgs.Last().Length();
1564     }
1565   }
1566   SetPart( argInd, theArg, myArgs( index ));
1567 }
1568
1569 //================================================================================
1570 /*!
1571  * \brief Empty arg list
1572  */
1573 //================================================================================
1574
1575 void _pyCommand::RemoveArgs()
1576 {
1577   if ( int pos = myString.Location( '(', 1, Length() ))
1578     myString.Trunc( pos );
1579   myString += ")";
1580   myArgs.Clear();
1581   if ( myBegPos.Length() >= ARG1_IND )
1582     myBegPos.Remove( ARG1_IND, myBegPos.Length() );
1583 }
1584
1585 //================================================================================
1586 /*!
1587  * \brief Set dependent commands after this one
1588  */
1589 //================================================================================
1590
1591 bool _pyCommand::SetDependentCmdsAfter() const
1592 {
1593   bool orderChanged = false;
1594   list< Handle(_pyCommand)>::const_reverse_iterator cmd = myDependentCmds.rbegin();
1595   for ( ; cmd != myDependentCmds.rend(); ++cmd ) {
1596     if ( (*cmd)->GetOrderNb() < GetOrderNb() ) {
1597       orderChanged = true;
1598       theGen->SetCommandAfter( *cmd, this );
1599       (*cmd)->SetDependentCmdsAfter();
1600     }
1601   }
1602   return orderChanged;
1603 }
1604 //================================================================================
1605 /*!
1606  * \brief Insert accessor method after theObjectID
1607   * \param theObjectID - id of the accessed object
1608   * \param theAcsMethod - name of the method giving access to the object
1609   * \retval bool - false if theObjectID is not found in the command string
1610  */
1611 //================================================================================
1612
1613 bool _pyCommand::AddAccessorMethod( _pyID theObjectID, const char* theAcsMethod )
1614 {
1615   if ( !theAcsMethod )
1616     return false;
1617   // start object search from the object, i.e. ignore result
1618   GetObject();
1619   int beg = GetBegPos( OBJECT_IND );
1620   if ( beg < 1 || beg > Length() )
1621     return false;
1622   while (( beg = myString.Location( theObjectID, beg, Length() )))
1623   {
1624     // check that theObjectID is not just a part of a longer ID
1625     int afterEnd = beg + theObjectID.Length();
1626     Standard_Character c = myString.Value( afterEnd );
1627     if ( !isalnum( c ) && c != ':' ) {
1628       // insertion
1629       int oldLen = Length();
1630       myString.Insert( afterEnd, (char*) theAcsMethod );
1631       myString.Insert( afterEnd, "." );
1632       // update starting positions of the parts following the modified one
1633       int posDelta = Length() - oldLen;
1634       for ( int i = 1; i <= myBegPos.Length(); ++i ) {
1635         if ( myBegPos( i ) > afterEnd )
1636           myBegPos( i ) += posDelta;
1637       }
1638       return true;
1639     }
1640     beg = afterEnd; // is a part - next search
1641   }
1642   return false;
1643 }
1644
1645 //================================================================================
1646 /*!
1647  * \brief Return method name giving access to an interaface object wrapped by python class
1648   * \retval const char* - method name
1649  */
1650 //================================================================================
1651
1652 const char* _pyObject::AccessorMethod() const
1653 {
1654   return 0;
1655 }