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.salome-platform.org/ or email : webmaster.salome@opencascade.com
24 // File : StdMeshers_NumberOfSegments.cxx
25 // Moved here from SMESH_NumberOfSegments.cxx
26 // Author : Paul RASCLE, EDF
30 #include "StdMeshers_NumberOfSegments.hxx"
32 #include "StdMeshers_Distribution.hxx"
33 #include "SMESHDS_SubMesh.hxx"
34 #include "SMESH_Mesh.hxx"
36 #include <ExprIntrp_GenExp.hxx>
37 #include <Expr_Array1OfNamedUnknown.hxx>
38 #include <Expr_NamedUnknown.hxx>
39 #include <TColStd_Array1OfReal.hxx>
40 #include <TCollection_AsciiString.hxx>
42 #include <TopTools_IndexedMapOfShape.hxx>
44 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
48 #include <Standard_Failure.hxx>
51 #include <Standard_ErrorHandler.hxx>
53 #include "CASCatch.hxx"
58 const double PRECISION = 1e-7;
60 //=============================================================================
64 //=============================================================================
66 StdMeshers_NumberOfSegments::StdMeshers_NumberOfSegments(int hypId,
69 : SMESH_Hypothesis(hypId, studyId, gen),
71 _distrType(DT_Regular),
73 _convMode(1) //cut negative by default
75 _name = "NumberOfSegments";
79 //=============================================================================
83 //=============================================================================
85 StdMeshers_NumberOfSegments::~StdMeshers_NumberOfSegments()
89 //=============================================================================
93 //=============================================================================
95 StdMeshers_NumberOfSegments::BuildDistributionExpr( const char* expr,int nbSeg,int conv )
96 throw ( SALOME_Exception )
98 if( !buildDistribution( TCollection_AsciiString( ( Standard_CString )expr ), conv, 0.0, 1.0, nbSeg, _distr, 1E-4 ) )
103 const vector<double>&
104 StdMeshers_NumberOfSegments::BuildDistributionTab( const vector<double>& tab,
107 throw ( SALOME_Exception )
109 if( !buildDistribution( tab, conv, 0.0, 1.0, nbSeg, _distr, 1E-4 ) )
114 //=============================================================================
118 //=============================================================================
120 void StdMeshers_NumberOfSegments::SetNumberOfSegments(int segmentsNumber)
121 throw(SALOME_Exception)
123 int oldNumberOfSegments = _numberOfSegments;
124 if (segmentsNumber <= 0)
125 throw SALOME_Exception(LOCALIZED("number of segments must be positive"));
126 _numberOfSegments = segmentsNumber;
128 if (oldNumberOfSegments != _numberOfSegments)
129 NotifySubMeshesHypothesisModification();
132 //=============================================================================
136 //=============================================================================
138 int StdMeshers_NumberOfSegments::GetNumberOfSegments() const
140 return _numberOfSegments;
143 //================================================================================
147 //================================================================================
149 void StdMeshers_NumberOfSegments::SetDistrType(DistrType typ)
150 throw(SALOME_Exception)
152 if (typ < DT_Regular || typ > DT_ExprFunc)
153 throw SALOME_Exception(LOCALIZED("distribution type is out of range"));
155 if (typ != _distrType)
158 NotifySubMeshesHypothesisModification();
162 //================================================================================
166 //================================================================================
168 StdMeshers_NumberOfSegments::DistrType StdMeshers_NumberOfSegments::GetDistrType() const
173 //================================================================================
177 //================================================================================
179 void StdMeshers_NumberOfSegments::SetScaleFactor(double scaleFactor)
180 throw(SALOME_Exception)
182 if (_distrType != DT_Scale)
183 _distrType = DT_Scale;
184 //throw SALOME_Exception(LOCALIZED("not a scale distribution"));
185 if (scaleFactor < PRECISION)
186 throw SALOME_Exception(LOCALIZED("scale factor must be positive"));
187 //if (fabs(scaleFactor - 1.0) < PRECISION)
188 // throw SALOME_Exception(LOCALIZED("scale factor must not be equal to 1"));
190 if (fabs(_scaleFactor - scaleFactor) > PRECISION)
192 _scaleFactor = scaleFactor;
193 NotifySubMeshesHypothesisModification();
197 //================================================================================
201 //================================================================================
203 double StdMeshers_NumberOfSegments::GetScaleFactor() const
204 throw(SALOME_Exception)
206 if (_distrType != DT_Scale)
207 throw SALOME_Exception(LOCALIZED("not a scale distribution"));
211 //================================================================================
215 //================================================================================
217 void StdMeshers_NumberOfSegments::SetTableFunction(const vector<double>& table)
218 throw(SALOME_Exception)
220 if (_distrType != DT_TabFunc)
221 _distrType = DT_TabFunc;
222 //throw SALOME_Exception(LOCALIZED("not a table function distribution"));
223 if ( (table.size() % 2) != 0 )
224 throw SALOME_Exception(LOCALIZED("odd size of vector of table function"));
227 double prev = -PRECISION;
228 bool isSame = table.size() == _table.size();
231 for (i=0; i < table.size()/2; i++) {
232 double par = table[i*2];
233 double val = table[i*2+1];
242 val = pow( 10.0, val );
244 } catch(Standard_Failure) {
246 } CASCatch_CATCH(Standard_Failure) {
248 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
249 throw SALOME_Exception( LOCALIZED( "invalid value"));
253 else if( _convMode==1 && val<0.0 )
256 if ( par<0 || par > 1)
257 throw SALOME_Exception(LOCALIZED("parameter of table function is out of range [0,1]"));
258 if ( fabs(par-prev)<PRECISION )
259 throw SALOME_Exception(LOCALIZED("two parameters are the same"));
261 throw SALOME_Exception(LOCALIZED("value of table function is not positive"));
266 double oldpar = _table[i*2];
267 double oldval = _table[i*2+1];
268 if (fabs(par - oldpar) > PRECISION || fabs(val - oldval) > PRECISION)
275 throw SALOME_Exception(LOCALIZED("value of table function is not positive"));
280 NotifySubMeshesHypothesisModification();
284 //================================================================================
288 //================================================================================
290 const vector<double>& StdMeshers_NumberOfSegments::GetTableFunction() const
291 throw(SALOME_Exception)
293 if (_distrType != DT_TabFunc)
294 throw SALOME_Exception(LOCALIZED("not a table function distribution"));
298 //================================================================================
299 /*! check if only 't' is unknown variable in expression
301 //================================================================================
302 bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr )
304 Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr );
306 return sub->GetName()=="t";
309 for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ )
311 Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i );
312 Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub );
315 if( name->GetName()!="t" )
319 res = isCorrectArg( sub );
324 //================================================================================
325 /*! this function parses the expression 'str' in order to check if syntax is correct
326 * ( result in 'syntax' ) and if only 't' is unknown variable in expression ( result in 'args' )
328 //================================================================================
329 bool process( const TCollection_AsciiString& str, int convMode,
330 bool& syntax, bool& args,
331 bool& non_neg, bool& non_zero,
332 bool& singulars, double& sing_point )
334 bool parsed_ok = true;
335 Handle( ExprIntrp_GenExp ) myExpr;
342 myExpr = ExprIntrp_GenExp::Create();
343 myExpr->Process( str.ToCString() );
345 } catch(Standard_Failure) {
347 } CASCatch_CATCH(Standard_Failure) {
349 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
355 if( parsed_ok && myExpr->IsDone() )
358 args = isCorrectArg( myExpr->Expression() );
361 bool res = parsed_ok && syntax && args;
371 FunctionExpr f( str.ToCString(), convMode );
373 for( int i=0; i<=max; i++ )
375 double t = double(i)/double(max), val;
376 if( !f.value( t, val ) )
391 return res && non_neg && non_zero && ( !singulars );
394 //================================================================================
398 //================================================================================
400 void StdMeshers_NumberOfSegments::SetExpressionFunction(const char* expr)
401 throw(SALOME_Exception)
403 if (_distrType != DT_ExprFunc)
404 _distrType = DT_ExprFunc;
405 //throw SALOME_Exception(LOCALIZED("not an expression function distribution"));
407 // remove white spaces
408 TCollection_AsciiString str((Standard_CString)expr);
414 bool syntax, args, non_neg, singulars, non_zero;
416 bool res = process( str, _convMode, syntax, args, non_neg, non_zero, singulars, sing_point );
420 throw SALOME_Exception(LOCALIZED("invalid expression syntax"));
422 throw SALOME_Exception(LOCALIZED("only 't' may be used as function argument"));
424 throw SALOME_Exception(LOCALIZED("only non-negative function can be used as density"));
428 sprintf( buf, "Function has singular point in %.3f", sing_point );
429 throw SALOME_Exception( buf );
432 throw SALOME_Exception(LOCALIZED("f(t)=0 cannot be used as density"));
441 NotifySubMeshesHypothesisModification();
445 //================================================================================
449 //================================================================================
451 const char* StdMeshers_NumberOfSegments::GetExpressionFunction() const
452 throw(SALOME_Exception)
454 if (_distrType != DT_ExprFunc)
455 throw SALOME_Exception(LOCALIZED("not an expression function distribution"));
456 return _func.c_str();
459 //================================================================================
463 //================================================================================
465 void StdMeshers_NumberOfSegments::SetConversionMode( int conv )
466 throw(SALOME_Exception)
468 // if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc)
469 // throw SALOME_Exception(LOCALIZED("not a functional distribution"));
471 if( conv != _convMode )
474 NotifySubMeshesHypothesisModification();
478 //================================================================================
482 //================================================================================
484 int StdMeshers_NumberOfSegments::ConversionMode() const
485 throw(SALOME_Exception)
487 // if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc)
488 // throw SALOME_Exception(LOCALIZED("not a functional distribution"));
492 //=============================================================================
496 //=============================================================================
498 ostream & StdMeshers_NumberOfSegments::SaveTo(ostream & save)
500 save << _numberOfSegments << " " << (int)_distrType;
504 save << " " << _scaleFactor;
508 save << " " << _table.size();
509 for (i=0; i < _table.size(); i++)
510 save << " " << _table[i];
513 save << " " << _func;
520 if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc)
521 save << " " << _convMode;
526 //=============================================================================
530 //=============================================================================
532 istream & StdMeshers_NumberOfSegments::LoadFrom(istream & load)
537 // read number of segments
540 _numberOfSegments = a;
542 load.clear(ios::badbit | load.rdstate());
544 // read second stored value. It can be two variants here:
545 // 1. If the hypothesis is stored in old format (nb.segments and scale factor),
546 // we wait here the scale factor, which is double.
547 // 2. If the hypothesis is stored in new format
548 // (nb.segments, distr.type, some other params.),
549 // we wait here the ditribution type, which is integer
551 isOK = (load >> scale_factor);
552 a = (int)scale_factor;
554 // try to interprete ditribution type,
555 // supposing that this hypothesis was written in the new format
558 if (a < DT_Regular || a > DT_ExprFunc)
559 _distrType = DT_Regular;
561 _distrType = (DistrType) a;
564 load.clear(ios::badbit | load.rdstate());
566 // parameters of distribution
577 load.clear(ios::badbit | load.rdstate());
578 // this can mean, that the hypothesis is stored in old format
579 _distrType = DT_Regular;
580 _scaleFactor = scale_factor;
589 _table.resize(a, 0.);
591 for (i=0; i < _table.size(); i++)
597 load.clear(ios::badbit | load.rdstate());
602 load.clear(ios::badbit | load.rdstate());
603 // this can mean, that the hypothesis is stored in old format
604 _distrType = DT_Regular;
605 _scaleFactor = scale_factor;
612 isOK = (load >> str);
617 load.clear(ios::badbit | load.rdstate());
618 // this can mean, that the hypothesis is stored in old format
619 _distrType = DT_Regular;
620 _scaleFactor = scale_factor;
629 if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc)
635 load.clear(ios::badbit | load.rdstate());
641 //=============================================================================
645 //=============================================================================
647 ostream & operator <<(ostream & save, StdMeshers_NumberOfSegments & hyp)
649 return hyp.SaveTo( save );
652 //=============================================================================
656 //=============================================================================
658 istream & operator >>(istream & load, StdMeshers_NumberOfSegments & hyp)
660 return hyp.LoadFrom( load );
663 //================================================================================
665 * \brief Initialize number of segments by the mesh built on the geometry
666 * \param theMesh - the built mesh
667 * \param theShape - the geometry of interest
668 * \retval bool - true if parameter values have been successfully defined
670 //================================================================================
672 bool StdMeshers_NumberOfSegments::SetParametersByMesh(const SMESH_Mesh* theMesh,
673 const TopoDS_Shape& theShape)
675 if ( !theMesh || theShape.IsNull() )
678 _numberOfSegments = 0;
679 _distrType = DT_Regular;
682 TopTools_IndexedMapOfShape edgeMap;
683 TopExp::MapShapes( theShape, TopAbs_EDGE, edgeMap );
684 SMESHDS_Mesh* aMeshDS = const_cast< SMESH_Mesh* >( theMesh )->GetMeshDS();
685 for ( int i = 1; i <= edgeMap.Extent(); ++i )
687 // get current segment length
688 SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( edgeMap( i ));
689 if ( eSubMesh && eSubMesh->NbElements())
690 _numberOfSegments += eSubMesh->NbElements();
695 _numberOfSegments /= nbEdges;