X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshers%2FStdMeshers_NumberOfSegments.cxx;h=76cd67965ccfda360d1dfd8f9ab4c64f322a2e8a;hp=44ac15909556441460b8eb169bfee02e39b2ad42;hb=c63ee099ad2b149bd70136839c973e8910137bc5;hpb=8672ad3e7621ac25fffa8517599afa84ffea509a diff --git a/src/StdMeshers/StdMeshers_NumberOfSegments.cxx b/src/StdMeshers/StdMeshers_NumberOfSegments.cxx index 44ac15909..76cd67965 100644 --- a/src/StdMeshers/StdMeshers_NumberOfSegments.cxx +++ b/src/StdMeshers/StdMeshers_NumberOfSegments.cxx @@ -17,7 +17,7 @@ // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // // @@ -27,12 +27,23 @@ // Module : SMESH // $Header$ -using namespace std; #include "StdMeshers_NumberOfSegments.hxx" -#include -#include + +#include "StdMeshers_Distribution.hxx" +#include "SMESHDS_SubMesh.hxx" +#include "SMESH_Mesh.hxx" + +#include "CASCatch.hxx" + #include +#include #include +#include +#include +#include +#include + +using namespace std; const double PRECISION = 1e-7; @@ -48,10 +59,10 @@ StdMeshers_NumberOfSegments::StdMeshers_NumberOfSegments(int hypId, int studyId, _numberOfSegments(1), _distrType(DT_Regular), _scaleFactor(1.), - _expMode(false) + _convMode(1) //cut negative by default { _name = "NumberOfSegments"; - _param_algo_dim = 1; + _param_algo_dim = 1; } //============================================================================= @@ -64,6 +75,28 @@ StdMeshers_NumberOfSegments::~StdMeshers_NumberOfSegments() { } +//============================================================================= +/*! + * + */ +//============================================================================= +const std::vector& StdMeshers_NumberOfSegments::BuildDistributionExpr( const char* expr, int nbSeg, int conv ) +throw ( SALOME_Exception ) +{ + if( !buildDistribution( TCollection_AsciiString( ( Standard_CString )expr ), conv, 0.0, 1.0, nbSeg, _distr, 1E-4 ) ) + _distr.resize( 0 ); + return _distr; +} + +const std::vector& StdMeshers_NumberOfSegments::BuildDistributionTab( const std::vector& tab, + int nbSeg, int conv ) +throw ( SALOME_Exception ) +{ + if( !buildDistribution( tab, conv, 0.0, 1.0, nbSeg, _distr, 1E-4 ) ) + _distr.resize( 0 ); + return _distr; +} + //============================================================================= /*! * @@ -137,8 +170,8 @@ void StdMeshers_NumberOfSegments::SetScaleFactor(double scaleFactor) throw SALOME_Exception(LOCALIZED("not a scale distribution")); if (scaleFactor < PRECISION) throw SALOME_Exception(LOCALIZED("scale factor must be positive")); - if (fabs(scaleFactor - 1.0) < PRECISION) - throw SALOME_Exception(LOCALIZED("scale factor must not be equal to 1")); + //if (fabs(scaleFactor - 1.0) < PRECISION) + // throw SALOME_Exception(LOCALIZED("scale factor must not be equal to 1")); if (fabs(_scaleFactor - scaleFactor) > PRECISION) { @@ -179,15 +212,34 @@ void StdMeshers_NumberOfSegments::SetTableFunction(const std::vector& ta double prev = -PRECISION; bool isSame = table.size() == _table.size(); + bool pos = false; for (i=0; i < table.size()/2; i++) { double par = table[i*2]; double val = table[i*2+1]; + if( _convMode==0 ) + { + CASCatch_TRY + { + val = pow( 10.0, val ); + } + CASCatch_CATCH(Standard_Failure) + { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + throw SALOME_Exception( LOCALIZED( "invalid value")); + return; + } + } + else if( _convMode==1 && val<0.0 ) + val = 0.0; + if ( par<0 || par > 1) throw SALOME_Exception(LOCALIZED("parameter of table function is out of range [0,1]")); if ( fabs(par-prev)PRECISION ) + pos = true; if (isSame) { double oldpar = _table[i*2]; @@ -198,7 +250,10 @@ void StdMeshers_NumberOfSegments::SetTableFunction(const std::vector& ta prev = par; } - if (!isSame) + if( !pos ) + throw SALOME_Exception(LOCALIZED("value of table function is not positive")); + + if( pos && !isSame ) { _table = table; NotifySubMeshesHypothesisModification(); @@ -223,23 +278,24 @@ const std::vector& StdMeshers_NumberOfSegments::GetTableFunction() const /*! check if only 't' is unknown variable in expression */ //================================================================================ -bool isCorrect( const Handle( Expr_GeneralExpression )& expr ) +bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr ) { - if( expr.IsNull() ) - return true; - + Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr ); + if( !sub.IsNull() ) + return sub->GetName()=="t"; + bool res = true; for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ ) { - Handle( Expr_GeneralExpression ) subexpr = expr->SubExpression( i ); - Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( subexpr ); + Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i ); + Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub ); if( !name.IsNull() ) { if( name->GetName()!="t" ) - res = false; + res = false; } else - res = isCorrect( subexpr ); + res = isCorrectArg( sub ); } return res; } @@ -249,25 +305,63 @@ bool isCorrect( const Handle( Expr_GeneralExpression )& expr ) * ( result in 'syntax' ) and if only 't' is unknown variable in expression ( result in 'args' ) */ //================================================================================ -void casProcess( const TCollection_AsciiString& str, bool& syntax, bool& args ) +bool process( const TCollection_AsciiString& str, int convMode, + bool& syntax, bool& args, + bool& non_neg, bool& non_zero, + bool& singulars, double& sing_point ) { - // check validity of expression + bool parsed_ok = true; + Handle( ExprIntrp_GenExp ) myExpr; + CASCatch_TRY + { + myExpr = ExprIntrp_GenExp::Create(); + myExpr->Process( str.ToCString() ); + } + CASCatch_CATCH(Standard_Failure) + { + Handle(Standard_Failure) aFail = Standard_Failure::Caught(); + parsed_ok = false; + } + syntax = false; args = false; - try + if( parsed_ok && myExpr->IsDone() ) { - Handle( ExprIntrp_GenExp ) gen = ExprIntrp_GenExp::Create(); - gen->Process( str ); - - if( gen->IsDone() ) - { - syntax = true; - args = isCorrect( gen->Expression() ); - } + syntax = true; + args = isCorrectArg( myExpr->Expression() ); } - catch (Standard_Failure) + + bool res = parsed_ok && syntax && args; + if( !res ) + myExpr.Nullify(); + + non_neg = true; + singulars = false; + non_zero = false; + + if( res ) { + FunctionExpr f( str.ToCString(), convMode ); + const int max = 500; + for( int i=0; i<=max; i++ ) + { + double t = double(i)/double(max), val; + if( !f.value( t, val ) ) + { + sing_point = t; + singulars = true; + break; + } + if( val<0 ) + { + non_neg = false; + break; + } + if( val>PRECISION ) + non_zero = true; + } } + return res && non_neg && non_zero && ( !singulars ); } //================================================================================ @@ -289,15 +383,31 @@ void StdMeshers_NumberOfSegments::SetExpressionFunction(const char* expr) str.RemoveAll('\r'); str.RemoveAll('\n'); - bool syntax, args; - casProcess( str, syntax, args ); - if( !syntax ) - throw SALOME_Exception(LOCALIZED("invalid expression syntax")); - if( !args ) - throw SALOME_Exception(LOCALIZED("only 't' may be used as function argument")); + bool syntax, args, non_neg, singulars, non_zero; + double sing_point; + bool res = process( str, _convMode, syntax, args, non_neg, non_zero, singulars, sing_point ); + if( !res ) + { + if( !syntax ) + throw SALOME_Exception(LOCALIZED("invalid expression syntax")); + if( !args ) + throw SALOME_Exception(LOCALIZED("only 't' may be used as function argument")); + if( !non_neg ) + throw SALOME_Exception(LOCALIZED("only non-negative function can be used as density")); + if( singulars ) + { + char buf[1024]; + sprintf( buf, "Function has singular point in %.3f", sing_point ); + throw SALOME_Exception( buf ); + } + if( !non_zero ) + throw SALOME_Exception(LOCALIZED("f(t)=0 cannot be used as density")); - string func(str.ToCString()); - if (_func != func) + return; + } + + std::string func = expr; + if( _func != func ) { _func = func; NotifySubMeshesHypothesisModification(); @@ -324,15 +434,15 @@ const char* StdMeshers_NumberOfSegments::GetExpressionFunction() const */ //================================================================================ -void StdMeshers_NumberOfSegments::SetExponentMode(bool isExp) +void StdMeshers_NumberOfSegments::SetConversionMode( int conv ) throw(SALOME_Exception) { if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc) throw SALOME_Exception(LOCALIZED("not a functional distribution")); - if (isExp != _expMode) + if( conv != _convMode ) { - _expMode = isExp; + _convMode = conv; NotifySubMeshesHypothesisModification(); } } @@ -343,12 +453,12 @@ void StdMeshers_NumberOfSegments::SetExponentMode(bool isExp) */ //================================================================================ -bool StdMeshers_NumberOfSegments::IsExponentMode() const +int StdMeshers_NumberOfSegments::ConversionMode() const throw(SALOME_Exception) { if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc) throw SALOME_Exception(LOCALIZED("not a functional distribution")); - return _expMode; + return _convMode; } //============================================================================= @@ -380,7 +490,7 @@ ostream & StdMeshers_NumberOfSegments::SaveTo(ostream & save) } if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc) - save << " " << (int)_expMode; + save << " " << _convMode; return save; } @@ -403,8 +513,18 @@ istream & StdMeshers_NumberOfSegments::LoadFrom(istream & load) else load.clear(ios::badbit | load.rdstate()); - // read ditribution type - isOK = (load >> a); + // read second stored value. It can be two variants here: + // 1. If the hypothesis is stored in old format (nb.segments and scale factor), + // we wait here the scale factor, which is double. + // 2. If the hypothesis is stored in new format + // (nb.segments, distr.type, some other params.), + // we wait here the ditribution type, which is integer + double scale_factor; + isOK = (load >> scale_factor); + a = (int)scale_factor; + + // try to interprete ditribution type, + // supposing that this hypothesis was written in the new format if (isOK) { if (a < DT_Regular || a > DT_ExprFunc) @@ -425,24 +545,36 @@ istream & StdMeshers_NumberOfSegments::LoadFrom(istream & load) if (isOK) _scaleFactor = b; else + { load.clear(ios::badbit | load.rdstate()); + // this can mean, that the hypothesis is stored in old format + _distrType = DT_Regular; + _scaleFactor = scale_factor; + } } break; case DT_TabFunc: { isOK = (load >> a); if (isOK) + { _table.resize(a, 0.); + int i; + for (i=0; i < _table.size(); i++) + { + isOK = (load >> b); + if (isOK) + _table[i] = b; + else + load.clear(ios::badbit | load.rdstate()); + } + } else - load.clear(ios::badbit | load.rdstate()); - int i; - for (i=0; i < _table.size(); i++) { - isOK = (load >> b); - if (isOK) - _table[i] = b; - else - load.clear(ios::badbit | load.rdstate()); + load.clear(ios::badbit | load.rdstate()); + // this can mean, that the hypothesis is stored in old format + _distrType = DT_Regular; + _scaleFactor = scale_factor; } } break; @@ -453,7 +585,12 @@ istream & StdMeshers_NumberOfSegments::LoadFrom(istream & load) if (isOK) _func = str; else + { load.clear(ios::badbit | load.rdstate()); + // this can mean, that the hypothesis is stored in old format + _distrType = DT_Regular; + _scaleFactor = scale_factor; + } } break; case DT_Regular: @@ -465,7 +602,7 @@ istream & StdMeshers_NumberOfSegments::LoadFrom(istream & load) { isOK = (load >> a); if (isOK) - _expMode = (bool) a; + _convMode = a; else load.clear(ios::badbit | load.rdstate()); } @@ -494,3 +631,40 @@ istream & operator >>(istream & load, StdMeshers_NumberOfSegments & hyp) { return hyp.LoadFrom( load ); } + +//================================================================================ +/*! + * \brief Initialize number of segments by the mesh built on the geometry + * \param theMesh - the built mesh + * \param theShape - the geometry of interest + * \retval bool - true if parameter values have been successfully defined + */ +//================================================================================ + +bool StdMeshers_NumberOfSegments::SetParametersByMesh(const SMESH_Mesh* theMesh, + const TopoDS_Shape& theShape) +{ + if ( !theMesh || theShape.IsNull() ) + return false; + + _numberOfSegments = 0; + _distrType = DT_Regular; + + int nbEdges = 0; + TopTools_IndexedMapOfShape edgeMap; + TopExp::MapShapes( theShape, TopAbs_EDGE, edgeMap ); + for ( int i = 1; i <= edgeMap.Extent(); ++i ) + { + // get current segment length + SMESHDS_Mesh* aMeshDS = const_cast< SMESH_Mesh* >( theMesh )->GetMeshDS(); + SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( edgeMap( i )); + if ( eSubMesh && eSubMesh->NbElements()) + _numberOfSegments += eSubMesh->NbElements(); + + ++nbEdges; + } + if ( nbEdges ) + _numberOfSegments /= nbEdges; + + return nbEdges; +}