1 // SMESH SMESH : implementaion of SMESH idl descriptions
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : StdMeshers_NumberOfSegments.cxx
25 // Moved here from SMESH_NumberOfSegments.cxx
26 // Author : Paul RASCLE, EDF
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 #include <CASCatch_CatchSignals.hxx>
37 #include <CASCatch_Failure.hxx>
38 #include <CASCatch_ErrorHandler.hxx>
40 #include <Expr_Array1OfNamedUnknown.hxx>
41 #include <TColStd_Array1OfReal.hxx>
44 const double PRECISION = 1e-7;
46 //=============================================================================
50 //=============================================================================
52 StdMeshers_NumberOfSegments::StdMeshers_NumberOfSegments(int hypId, int studyId,
54 : SMESH_Hypothesis(hypId, studyId, gen),
56 _distrType(DT_Regular),
60 _name = "NumberOfSegments";
64 //=============================================================================
68 //=============================================================================
70 StdMeshers_NumberOfSegments::~StdMeshers_NumberOfSegments()
74 //=============================================================================
78 //=============================================================================
80 void StdMeshers_NumberOfSegments::SetNumberOfSegments(int segmentsNumber)
81 throw(SALOME_Exception)
83 int oldNumberOfSegments = _numberOfSegments;
84 if (segmentsNumber <= 0)
86 SALOME_Exception(LOCALIZED("number of segments must be positive"));
87 _numberOfSegments = segmentsNumber;
89 if (oldNumberOfSegments != _numberOfSegments)
90 NotifySubMeshesHypothesisModification();
93 //=============================================================================
97 //=============================================================================
99 int StdMeshers_NumberOfSegments::GetNumberOfSegments() const
101 return _numberOfSegments;
104 //================================================================================
108 //================================================================================
110 void StdMeshers_NumberOfSegments::SetDistrType(DistrType typ)
111 throw(SALOME_Exception)
113 if (typ < DT_Regular || typ > DT_ExprFunc)
114 throw SALOME_Exception(LOCALIZED("distribution type is out of range"));
116 if (typ != _distrType)
119 NotifySubMeshesHypothesisModification();
123 //================================================================================
127 //================================================================================
129 StdMeshers_NumberOfSegments::DistrType StdMeshers_NumberOfSegments::GetDistrType() const
134 //================================================================================
138 //================================================================================
140 void StdMeshers_NumberOfSegments::SetScaleFactor(double scaleFactor)
141 throw(SALOME_Exception)
143 if (_distrType != DT_Scale)
144 throw SALOME_Exception(LOCALIZED("not a scale distribution"));
145 if (scaleFactor < PRECISION)
146 throw SALOME_Exception(LOCALIZED("scale factor must be positive"));
147 if (fabs(scaleFactor - 1.0) < PRECISION)
148 throw SALOME_Exception(LOCALIZED("scale factor must not be equal to 1"));
150 if (fabs(_scaleFactor - scaleFactor) > PRECISION)
152 _scaleFactor = scaleFactor;
153 NotifySubMeshesHypothesisModification();
157 //================================================================================
161 //================================================================================
163 double StdMeshers_NumberOfSegments::GetScaleFactor() const
164 throw(SALOME_Exception)
166 if (_distrType != DT_Scale)
167 throw SALOME_Exception(LOCALIZED("not a scale distribution"));
171 //================================================================================
175 //================================================================================
177 void StdMeshers_NumberOfSegments::SetTableFunction(const std::vector<double>& table)
178 throw(SALOME_Exception)
180 if (_distrType != DT_TabFunc)
181 throw SALOME_Exception(LOCALIZED("not a table function distribution"));
182 if ( (table.size() % 2) != 0 )
183 throw SALOME_Exception(LOCALIZED("odd size of vector of table function"));
186 double prev = -PRECISION;
187 bool isSame = table.size() == _table.size();
190 for (i=0; i < table.size()/2; i++) {
191 double par = table[i*2];
192 double val = table[i*2+1];
193 if ( par<0 || par > 1)
194 throw SALOME_Exception(LOCALIZED("parameter of table function is out of range [0,1]"));
195 if ( fabs(par-prev)<PRECISION )
196 throw SALOME_Exception(LOCALIZED("two parameters are the same"));
198 throw SALOME_Exception(LOCALIZED("value of table function is not positive"));
203 double oldpar = _table[i*2];
204 double oldval = _table[i*2+1];
205 if (fabs(par - oldpar) > PRECISION || fabs(val - oldval) > PRECISION)
212 throw SALOME_Exception(LOCALIZED("value of table function is not positive"));
217 NotifySubMeshesHypothesisModification();
221 //================================================================================
225 //================================================================================
227 const std::vector<double>& StdMeshers_NumberOfSegments::GetTableFunction() const
228 throw(SALOME_Exception)
230 if (_distrType != DT_TabFunc)
231 throw SALOME_Exception(LOCALIZED("not a table function distribution"));
235 //================================================================================
236 /*! check if only 't' is unknown variable in expression
238 //================================================================================
239 bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr )
241 Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr );
243 return sub->GetName()=="t";
246 for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ )
248 Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i );
249 Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub );
252 if( name->GetName()!="t" )
256 res = isCorrectArg( sub );
261 //================================================================================
262 /*! this function parses the expression 'str' in order to check if syntax is correct
263 * ( result in 'syntax' ) and if only 't' is unknown variable in expression ( result in 'args' )
265 //================================================================================
266 bool process( const TCollection_AsciiString& str,
267 bool& syntax, bool& args,
268 bool& non_neg, bool& non_zero,
269 bool& singulars, double& sing_point )
271 Handle( ExprIntrp_GenExp ) myExpr = ExprIntrp_GenExp::Create();
272 myExpr->Process( str.ToCString() );
274 if( myExpr->IsDone() )
277 args = isCorrectArg( myExpr->Expression() );
280 bool res = syntax && args;
290 OSD::SetSignal( true );
291 CASCatch_CatchSignals aCatchSignals;
292 aCatchSignals.Activate();
294 Expr_Array1OfNamedUnknown myVars( 1, 1 );
295 TColStd_Array1OfReal myValues( 1, 1 );
296 myVars.ChangeValue( 1 ) = new Expr_NamedUnknown( "t" );
299 for( int i=0; i<=max; i++ )
301 double t = double(i)/double(max);
302 myValues.ChangeValue( 1 ) = t;
305 res = myExpr->Expression()->Evaluate( myVars, myValues );
307 CASCatch_CATCH(CASCatch_Failure)
309 aCatchSignals.Deactivate();
310 Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught();
323 aCatchSignals.Deactivate();
325 return res && non_neg && ( !singulars );
328 //================================================================================
332 //================================================================================
334 void StdMeshers_NumberOfSegments::SetExpressionFunction(const char* expr)
335 throw(SALOME_Exception)
337 if (_distrType != DT_ExprFunc)
338 throw SALOME_Exception(LOCALIZED("not an expression function distribution"));
340 // remove white spaces
341 TCollection_AsciiString str((Standard_CString)expr);
347 bool syntax, args, non_neg, singulars, non_zero;
349 bool res = true;//process( str, syntax, args, non_neg, non_zero, singulars, sing_point );
353 throw SALOME_Exception(LOCALIZED("invalid expression syntax"));
355 throw SALOME_Exception(LOCALIZED("only 't' may be used as function argument"));
357 throw SALOME_Exception(LOCALIZED("only non-negative function can be used as density"));
361 sprintf( buf, "Function has singular point in %.3f", sing_point );
362 throw SALOME_Exception( buf );
365 throw SALOME_Exception(LOCALIZED("f(t)=0 cannot be used as density"));
370 std::string func = expr;
374 NotifySubMeshesHypothesisModification();
378 //================================================================================
382 //================================================================================
384 const char* StdMeshers_NumberOfSegments::GetExpressionFunction() const
385 throw(SALOME_Exception)
387 if (_distrType != DT_ExprFunc)
388 throw SALOME_Exception(LOCALIZED("not an expression function distribution"));
389 return _func.c_str();
392 //================================================================================
396 //================================================================================
398 void StdMeshers_NumberOfSegments::SetExponentMode(bool isExp)
399 throw(SALOME_Exception)
401 if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc)
402 throw SALOME_Exception(LOCALIZED("not a functional distribution"));
404 if (isExp != _expMode)
407 NotifySubMeshesHypothesisModification();
411 //================================================================================
415 //================================================================================
417 bool StdMeshers_NumberOfSegments::IsExponentMode() const
418 throw(SALOME_Exception)
420 if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc)
421 throw SALOME_Exception(LOCALIZED("not a functional distribution"));
425 //=============================================================================
429 //=============================================================================
431 ostream & StdMeshers_NumberOfSegments::SaveTo(ostream & save)
433 save << _numberOfSegments << " " << (int)_distrType;
437 save << " " << _scaleFactor;
441 save << " " << _table.size();
442 for (i=0; i < _table.size(); i++)
443 save << " " << _table[i];
446 save << " " << _func;
453 if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc)
454 save << " " << (int)_expMode;
459 //=============================================================================
463 //=============================================================================
465 istream & StdMeshers_NumberOfSegments::LoadFrom(istream & load)
470 // read number of segments
473 _numberOfSegments = a;
475 load.clear(ios::badbit | load.rdstate());
477 // read second stored value. It can be two variants here:
478 // 1. If the hypothesis is stored in old format (nb.segments and scale factor),
479 // we wait here the scale factor, which is double.
480 // 2. If the hypothesis is stored in new format
481 // (nb.segments, distr.type, some other params.),
482 // we wait here the ditribution type, which is integer
484 isOK = (load >> scale_factor);
485 a = (int)scale_factor;
487 // try to interprete ditribution type,
488 // supposing that this hypothesis was written in the new format
491 if (a < DT_Regular || a > DT_ExprFunc)
492 _distrType = DT_Regular;
494 _distrType = (DistrType) a;
497 load.clear(ios::badbit | load.rdstate());
499 // parameters of distribution
510 load.clear(ios::badbit | load.rdstate());
511 // this can mean, that the hypothesis is stored in old format
512 _distrType = DT_Regular;
513 _scaleFactor = scale_factor;
522 _table.resize(a, 0.);
524 for (i=0; i < _table.size(); i++)
530 load.clear(ios::badbit | load.rdstate());
535 load.clear(ios::badbit | load.rdstate());
536 // this can mean, that the hypothesis is stored in old format
537 _distrType = DT_Regular;
538 _scaleFactor = scale_factor;
545 isOK = (load >> str);
550 load.clear(ios::badbit | load.rdstate());
551 // this can mean, that the hypothesis is stored in old format
552 _distrType = DT_Regular;
553 _scaleFactor = scale_factor;
562 if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc)
568 load.clear(ios::badbit | load.rdstate());
574 //=============================================================================
578 //=============================================================================
580 ostream & operator <<(ostream & save, StdMeshers_NumberOfSegments & hyp)
582 return hyp.SaveTo( save );
585 //=============================================================================
589 //=============================================================================
591 istream & operator >>(istream & load, StdMeshers_NumberOfSegments & hyp)
593 return hyp.LoadFrom( load );