Salome HOME
PAL10237. Add StdMeshers_AutomaticLength 1D hypothesis
[modules/smesh.git] / src / StdMeshers / StdMeshers_NumberOfSegments.cxx
1 //  SMESH SMESH : implementaion of SMESH idl descriptions
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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : StdMeshers_NumberOfSegments.cxx
25 //           Moved here from SMESH_NumberOfSegments.cxx
26 //  Author : Paul RASCLE, EDF
27 //  Module : SMESH
28 //  $Header$
29
30 using namespace std;
31 #include "StdMeshers_NumberOfSegments.hxx"
32 #include <Standard_ErrorHandler.hxx>
33 #include <TCollection_AsciiString.hxx>
34 #include <ExprIntrp_GenExp.hxx>
35 #include <Expr_NamedUnknown.hxx>
36
37 const double PRECISION = 1e-7;
38
39 //=============================================================================
40 /*!
41  *  
42  */
43 //=============================================================================
44
45 StdMeshers_NumberOfSegments::StdMeshers_NumberOfSegments(int hypId, int studyId,
46         SMESH_Gen * gen)
47   : SMESH_Hypothesis(hypId, studyId, gen),
48     _numberOfSegments(1),
49     _distrType(DT_Regular),
50     _scaleFactor(1.),
51     _expMode(false)
52 {
53   _name = "NumberOfSegments";
54   _param_algo_dim = 1; 
55 }
56
57 //=============================================================================
58 /*!
59  *  
60  */
61 //=============================================================================
62
63 StdMeshers_NumberOfSegments::~StdMeshers_NumberOfSegments()
64 {
65 }
66
67 //=============================================================================
68 /*!
69  *  
70  */
71 //=============================================================================
72
73 void StdMeshers_NumberOfSegments::SetNumberOfSegments(int segmentsNumber)
74 throw(SALOME_Exception)
75 {
76         int oldNumberOfSegments = _numberOfSegments;
77         if (segmentsNumber <= 0)
78                 throw
79                         SALOME_Exception(LOCALIZED("number of segments must be positive"));
80         _numberOfSegments = segmentsNumber;
81
82         if (oldNumberOfSegments != _numberOfSegments)
83                 NotifySubMeshesHypothesisModification();
84 }
85
86 //=============================================================================
87 /*!
88  *  
89  */
90 //=============================================================================
91
92 int StdMeshers_NumberOfSegments::GetNumberOfSegments() const
93 {
94         return _numberOfSegments;
95 }
96
97 //================================================================================
98 /*!
99  * 
100  */
101 //================================================================================
102
103 void StdMeshers_NumberOfSegments::SetDistrType(DistrType typ)
104   throw(SALOME_Exception)
105 {
106   if (typ < DT_Regular || typ > DT_ExprFunc)
107     throw SALOME_Exception(LOCALIZED("distribution type is out of range"));
108
109   if (typ != _distrType)
110   {
111     _distrType = typ;
112     NotifySubMeshesHypothesisModification();
113   }
114 }
115
116 //================================================================================
117 /*!
118  * 
119  */
120 //================================================================================
121
122 StdMeshers_NumberOfSegments::DistrType StdMeshers_NumberOfSegments::GetDistrType() const
123 {
124   return _distrType;
125 }
126
127 //================================================================================
128 /*!
129  * 
130  */
131 //================================================================================
132
133 void StdMeshers_NumberOfSegments::SetScaleFactor(double scaleFactor)
134   throw(SALOME_Exception)
135 {
136   if (_distrType != DT_Scale)
137     throw SALOME_Exception(LOCALIZED("not a scale distribution"));
138   if (scaleFactor < PRECISION)
139     throw SALOME_Exception(LOCALIZED("scale factor must be positive"));
140   if (fabs(scaleFactor - 1.0) < PRECISION)
141     throw SALOME_Exception(LOCALIZED("scale factor must not be equal to 1"));
142
143   if (fabs(_scaleFactor - scaleFactor) > PRECISION)
144   {
145     _scaleFactor = scaleFactor;
146     NotifySubMeshesHypothesisModification();
147   }
148 }
149
150 //================================================================================
151 /*!
152  * 
153  */
154 //================================================================================
155
156 double StdMeshers_NumberOfSegments::GetScaleFactor() const
157   throw(SALOME_Exception)
158 {
159   if (_distrType != DT_Scale)
160     throw SALOME_Exception(LOCALIZED("not a scale distribution"));
161   return _scaleFactor;
162 }
163
164 //================================================================================
165 /*!
166  * 
167  */
168 //================================================================================
169
170 void StdMeshers_NumberOfSegments::SetTableFunction(const std::vector<double>& table)
171   throw(SALOME_Exception)
172 {
173   if (_distrType != DT_TabFunc)
174     throw SALOME_Exception(LOCALIZED("not a table function distribution"));
175   if ( (table.size() % 2) != 0 )
176     throw SALOME_Exception(LOCALIZED("odd size of vector of table function"));
177
178   int i;
179   double prev = -PRECISION;
180   bool isSame = table.size() == _table.size();
181
182   for (i=0; i < table.size()/2; i++) {
183     double par = table[i*2];
184     double val = table[i*2+1];
185     if ( par<0 || par > 1)
186       throw SALOME_Exception(LOCALIZED("parameter of table function is out of range [0,1]"));
187     if ( fabs(par-prev)<PRECISION )
188       throw SALOME_Exception(LOCALIZED("two parameters are the same"));
189     if (val < PRECISION)
190       throw SALOME_Exception(LOCALIZED("value of table function is not positive"));
191     if (isSame)
192     {
193       double oldpar = _table[i*2];
194       double oldval = _table[i*2+1];
195       if (fabs(par - oldpar) > PRECISION || fabs(val - oldval) > PRECISION)
196         isSame = false;
197     }
198     prev = par;
199   }
200
201   if (!isSame)
202   {
203     _table = table;
204     NotifySubMeshesHypothesisModification();
205   }
206 }
207
208 //================================================================================
209 /*!
210  * 
211  */
212 //================================================================================
213
214 const std::vector<double>& StdMeshers_NumberOfSegments::GetTableFunction() const
215   throw(SALOME_Exception)
216 {
217   if (_distrType != DT_TabFunc)
218     throw SALOME_Exception(LOCALIZED("not a table function distribution"));
219   return _table;
220 }
221
222 //================================================================================
223 /*! check if only 't' is unknown variable in expression
224  */
225 //================================================================================
226 bool isCorrect( const Handle( Expr_GeneralExpression )& expr )
227 {
228   if( expr.IsNull() )
229     return true;
230     
231   bool res = true;
232   for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ )
233   {
234     Handle( Expr_GeneralExpression ) subexpr = expr->SubExpression( i );
235     Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( subexpr );
236     if( !name.IsNull() )
237     {
238       if( name->GetName()!="t" )
239         res = false;
240     }
241     else
242       res = isCorrect( subexpr );
243   }
244   return res;
245 }
246
247 //================================================================================
248 /*! this function parses the expression 'str' in order to check if syntax is correct
249  *  ( result in 'syntax' ) and if only 't' is unknown variable in expression ( result in 'args' )
250  */
251 //================================================================================
252 void casProcess( const TCollection_AsciiString& str, bool& syntax, bool& args )
253 {
254   // check validity of expression
255   syntax = false;
256   args = false;
257   try
258   {
259     Handle( ExprIntrp_GenExp ) gen = ExprIntrp_GenExp::Create();
260     gen->Process( str );
261         
262     if( gen->IsDone() ) 
263     {
264       syntax = true;
265       args = isCorrect( gen->Expression() );
266     }
267   }
268   catch (Standard_Failure)
269   {
270   }
271 }
272
273 //================================================================================
274 /*!
275  * 
276  */
277 //================================================================================
278
279 void StdMeshers_NumberOfSegments::SetExpressionFunction(const char* expr)
280   throw(SALOME_Exception)
281 {
282   if (_distrType != DT_ExprFunc)
283     throw SALOME_Exception(LOCALIZED("not an expression function distribution"));
284
285   // remove white spaces
286   TCollection_AsciiString str((Standard_CString)expr);
287   str.RemoveAll(' ');
288   str.RemoveAll('\t');
289   str.RemoveAll('\r');
290   str.RemoveAll('\n');
291
292   bool syntax, args;
293   casProcess( str, syntax, args );
294   if( !syntax )
295     throw SALOME_Exception(LOCALIZED("invalid expression syntax"));
296   if( !args )
297     throw SALOME_Exception(LOCALIZED("only 't' may be used as function argument"));
298
299   string func(str.ToCString());
300   if (_func != func)
301   {
302     _func = func;
303     NotifySubMeshesHypothesisModification();
304   }
305 }
306
307 //================================================================================
308 /*!
309  * 
310  */
311 //================================================================================
312
313 const char* StdMeshers_NumberOfSegments::GetExpressionFunction() const
314   throw(SALOME_Exception)
315 {
316   if (_distrType != DT_ExprFunc)
317     throw SALOME_Exception(LOCALIZED("not an expression function distribution"));
318   return _func.c_str();
319 }
320
321 //================================================================================
322 /*!
323  * 
324  */
325 //================================================================================
326
327 void StdMeshers_NumberOfSegments::SetExponentMode(bool isExp)
328   throw(SALOME_Exception)
329 {
330   if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc)
331     throw SALOME_Exception(LOCALIZED("not a functional distribution"));
332
333   if (isExp != _expMode)
334   {
335     _expMode = isExp;
336     NotifySubMeshesHypothesisModification();
337   }
338 }
339
340 //================================================================================
341 /*!
342  * 
343  */
344 //================================================================================
345
346 bool StdMeshers_NumberOfSegments::IsExponentMode() const
347   throw(SALOME_Exception)
348 {
349   if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc)
350     throw SALOME_Exception(LOCALIZED("not a functional distribution"));
351   return _expMode;
352 }
353
354 //=============================================================================
355 /*!
356  *  
357  */
358 //=============================================================================
359
360 ostream & StdMeshers_NumberOfSegments::SaveTo(ostream & save)
361 {
362   save << _numberOfSegments << " " << (int)_distrType;
363   switch (_distrType)
364   {
365   case DT_Scale:
366     save << " " << _scaleFactor;
367     break;
368   case DT_TabFunc:
369     int i;
370     save << " " << _table.size();
371     for (i=0; i < _table.size(); i++)
372       save << " " << _table[i];
373     break;
374   case DT_ExprFunc:
375     save << " " << _func;
376     break;
377   case DT_Regular:
378   default:
379     break;
380   }
381
382   if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc)
383     save << " " << (int)_expMode;
384   
385   return save;
386 }
387
388 //=============================================================================
389 /*!
390  *  
391  */
392 //=============================================================================
393
394 istream & StdMeshers_NumberOfSegments::LoadFrom(istream & load)
395 {
396   bool isOK = true;
397   int a;
398
399   // read number of segments
400   isOK = (load >> a);
401   if (isOK)
402     _numberOfSegments = a;
403   else
404     load.clear(ios::badbit | load.rdstate());
405
406   // read ditribution type
407   isOK = (load >> a);
408   if (isOK)
409   {
410     if (a < DT_Regular || a > DT_ExprFunc)
411       _distrType = DT_Regular;
412     else
413       _distrType = (DistrType) a;
414   }
415   else
416     load.clear(ios::badbit | load.rdstate());
417
418   // parameters of distribution
419   double b;
420   switch (_distrType)
421   {
422   case DT_Scale:
423     {
424       isOK = (load >> b);
425       if (isOK)
426         _scaleFactor = b;
427       else
428         load.clear(ios::badbit | load.rdstate());
429     }
430     break;
431   case DT_TabFunc:
432     {
433       isOK = (load >> a);
434       if (isOK)
435         _table.resize(a, 0.);
436       else
437         load.clear(ios::badbit | load.rdstate());
438       int i;
439       for (i=0; i < _table.size(); i++)
440       {
441         isOK = (load >> b);
442         if (isOK)
443           _table[i] = b;
444         else
445           load.clear(ios::badbit | load.rdstate());
446       }
447     }
448     break;
449   case DT_ExprFunc:
450     {
451       string str;
452       isOK = (load >> str);
453       if (isOK)
454         _func = str;
455       else
456         load.clear(ios::badbit | load.rdstate());
457     }
458     break;
459   case DT_Regular:
460   default:
461     break;
462   }
463
464   if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc)
465   {
466     isOK = (load >> a);
467     if (isOK)
468       _expMode = (bool) a;
469     else
470       load.clear(ios::badbit | load.rdstate());
471   }
472
473   return load;
474 }
475
476 //=============================================================================
477 /*!
478  *  
479  */
480 //=============================================================================
481
482 ostream & operator <<(ostream & save, StdMeshers_NumberOfSegments & hyp)
483 {
484   return hyp.SaveTo( save );
485 }
486
487 //=============================================================================
488 /*!
489  *  
490  */
491 //=============================================================================
492
493 istream & operator >>(istream & load, StdMeshers_NumberOfSegments & hyp)
494 {
495   return hyp.LoadFrom( load );
496 }