Back to index

salome-smesh  6.5.0
StdMeshers_NumberOfSegments.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH SMESH : implementaion of SMESH idl descriptions
00024 //  File   : StdMeshers_NumberOfSegments.cxx
00025 //           Moved here from SMESH_NumberOfSegments.cxx
00026 //  Author : Paul RASCLE, EDF
00027 //  Module : SMESH
00028 //
00029 #include "StdMeshers_NumberOfSegments.hxx"
00030 
00031 #include "StdMeshers_Distribution.hxx"
00032 #include "SMESHDS_SubMesh.hxx"
00033 #include "SMESH_Mesh.hxx"
00034 #include "SMESH_Comment.hxx"
00035 
00036 #include <ExprIntrp_GenExp.hxx>
00037 #include <Expr_Array1OfNamedUnknown.hxx>
00038 #include <Expr_NamedUnknown.hxx>
00039 #include <TColStd_Array1OfReal.hxx>
00040 #include <TCollection_AsciiString.hxx>
00041 #include <TopExp.hxx>
00042 #include <TopTools_IndexedMapOfShape.hxx>
00043 
00044 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
00045 #define NO_CAS_CATCH
00046 #endif
00047 
00048 #include <Standard_Failure.hxx>
00049 
00050 #ifdef NO_CAS_CATCH
00051 #include <Standard_ErrorHandler.hxx>
00052 #endif
00053 
00054 #include <Basics_Utils.hxx>
00055 
00056 using namespace std;
00057 
00058 const double PRECISION = 1e-7;
00059 
00060 //=============================================================================
00064 //=============================================================================
00065 
00066 StdMeshers_NumberOfSegments::StdMeshers_NumberOfSegments(int         hypId,
00067                                                          int         studyId,
00068                                                          SMESH_Gen * gen)
00069   : SMESH_Hypothesis(hypId, studyId, gen),
00070     _numberOfSegments(15),//issue 19923
00071     _distrType(DT_Regular),
00072     _scaleFactor(1.),
00073     _convMode(1)  //cut negative by default
00074 {
00075   _name = "NumberOfSegments";
00076   _param_algo_dim = 1;
00077 }
00078 
00079 //=============================================================================
00083 //=============================================================================
00084 
00085 StdMeshers_NumberOfSegments::~StdMeshers_NumberOfSegments()
00086 {
00087 }
00088 
00089 //=============================================================================
00093 //=============================================================================
00094 const vector<double>&
00095 StdMeshers_NumberOfSegments::BuildDistributionExpr( const char* expr,int nbSeg,int conv )
00096   throw ( SALOME_Exception )
00097 {
00098   if( !buildDistribution( TCollection_AsciiString( ( Standard_CString )expr ), conv, 0.0, 1.0, nbSeg, _distr, 1E-4 ) )
00099     _distr.resize( 0 );
00100   return _distr;
00101 }
00102 
00103 const vector<double>&
00104 StdMeshers_NumberOfSegments::BuildDistributionTab( const vector<double>& tab,
00105                                                    int nbSeg,
00106                                                    int conv )
00107   throw ( SALOME_Exception )
00108 {
00109   if( !buildDistribution( tab, conv, 0.0, 1.0, nbSeg, _distr, 1E-4 ) )
00110     _distr.resize( 0 );
00111   return _distr;
00112 }
00113 
00114 //=============================================================================
00118 //=============================================================================
00119 
00120 void StdMeshers_NumberOfSegments::SetNumberOfSegments(int segmentsNumber)
00121 throw(SALOME_Exception)
00122 {
00123   int oldNumberOfSegments = _numberOfSegments;
00124   if (segmentsNumber <= 0)
00125     throw SALOME_Exception(LOCALIZED("number of segments must be positive"));
00126   _numberOfSegments = segmentsNumber;
00127 
00128   if (oldNumberOfSegments != _numberOfSegments)
00129     NotifySubMeshesHypothesisModification();
00130 }
00131 
00132 //=============================================================================
00136 //=============================================================================
00137 
00138 int StdMeshers_NumberOfSegments::GetNumberOfSegments() const
00139 {
00140   return _numberOfSegments;
00141 }
00142 
00143 //================================================================================
00147 //================================================================================
00148 
00149 void StdMeshers_NumberOfSegments::SetDistrType(DistrType typ)
00150   throw(SALOME_Exception)
00151 {
00152   if (typ < DT_Regular || typ > DT_ExprFunc)
00153     throw SALOME_Exception(LOCALIZED("distribution type is out of range"));
00154 
00155   if (typ != _distrType)
00156   {
00157     _distrType = typ;
00158     NotifySubMeshesHypothesisModification();
00159   }
00160 }
00161 
00162 //================================================================================
00166 //================================================================================
00167 
00168 StdMeshers_NumberOfSegments::DistrType StdMeshers_NumberOfSegments::GetDistrType() const
00169 {
00170   return _distrType;
00171 }
00172 
00173 //================================================================================
00177 //================================================================================
00178 
00179 void StdMeshers_NumberOfSegments::SetScaleFactor(double scaleFactor)
00180   throw(SALOME_Exception)
00181 {
00182   if (_distrType != DT_Scale)
00183     _distrType = DT_Scale;
00184     //throw SALOME_Exception(LOCALIZED("not a scale distribution"));
00185   if (scaleFactor < PRECISION)
00186     throw SALOME_Exception(LOCALIZED("scale factor must be positive"));
00187   //if (fabs(scaleFactor - 1.0) < PRECISION)
00188   //  throw SALOME_Exception(LOCALIZED("scale factor must not be equal to 1"));
00189 
00190   if (fabs(_scaleFactor - scaleFactor) > PRECISION)
00191   {
00192     _scaleFactor = scaleFactor;
00193     NotifySubMeshesHypothesisModification();
00194   }
00195 }
00196 
00197 //================================================================================
00201 //================================================================================
00202 
00203 double StdMeshers_NumberOfSegments::GetScaleFactor() const
00204   throw(SALOME_Exception)
00205 {
00206   if (_distrType != DT_Scale)
00207     throw SALOME_Exception(LOCALIZED("not a scale distribution"));
00208   return _scaleFactor;
00209 }
00210 
00211 //================================================================================
00215 //================================================================================
00216 
00217 void StdMeshers_NumberOfSegments::SetTableFunction(const vector<double>& table)
00218   throw(SALOME_Exception)
00219 {
00220   if (_distrType != DT_TabFunc)
00221     _distrType = DT_TabFunc;
00222   //throw SALOME_Exception(LOCALIZED("not a table function distribution"));
00223   if ( (table.size() % 2) != 0 )
00224     throw SALOME_Exception(LOCALIZED("odd size of vector of table function"));
00225 
00226   int i;
00227   double prev = -PRECISION;
00228   bool isSame = table.size() == _table.size();
00229 
00230   bool pos = false;
00231   for (i=0; i < table.size()/2; i++) {
00232     double par = table[i*2];
00233     double val = table[i*2+1];
00234     if( _convMode==0 )
00235     {
00236       try {
00237 #ifdef NO_CAS_CATCH
00238         OCC_CATCH_SIGNALS;
00239 #endif
00240         val = pow( 10.0, val );
00241       } catch(Standard_Failure) {
00242         Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00243         throw SALOME_Exception( LOCALIZED( "invalid value"));
00244         return;
00245       }
00246     }
00247     else if( _convMode==1 && val<0.0 )
00248       val = 0.0;
00249 
00250     if ( par<0 || par > 1)
00251       throw SALOME_Exception(LOCALIZED("parameter of table function is out of range [0,1]"));
00252     if ( fabs(par-prev)<PRECISION )
00253       throw SALOME_Exception(LOCALIZED("two parameters are the same"));
00254     if ( val < 0 )
00255       throw SALOME_Exception(LOCALIZED("value of table function is not positive"));
00256     if( val>PRECISION )
00257       pos = true;
00258     if (isSame)
00259     {
00260       double oldpar = _table[i*2];
00261       double oldval = _table[i*2+1];
00262       if (fabs(par - oldpar) > PRECISION || fabs(val - oldval) > PRECISION)
00263         isSame = false;
00264     }
00265     prev = par;
00266   }
00267 
00268   if( !pos )
00269     throw SALOME_Exception(LOCALIZED("value of table function is not positive"));
00270 
00271   if( pos && !isSame )
00272   {
00273     _table = table;
00274     NotifySubMeshesHypothesisModification();
00275   }
00276 }
00277 
00278 //================================================================================
00282 //================================================================================
00283 
00284 const vector<double>& StdMeshers_NumberOfSegments::GetTableFunction() const
00285   throw(SALOME_Exception)
00286 {
00287   if (_distrType != DT_TabFunc)
00288     throw SALOME_Exception(LOCALIZED("not a table function distribution"));
00289   return _table;
00290 }
00291 
00292 //================================================================================
00295 //================================================================================
00296 bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr )
00297 {
00298   Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr );
00299   if( !sub.IsNull() )
00300     return sub->GetName()=="t";
00301 
00302   bool res = true;
00303   for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ )
00304   {
00305     Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i );
00306     Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub );
00307     if( !name.IsNull() )
00308     {
00309       if( name->GetName()!="t" )
00310         res = false;
00311     }
00312     else
00313       res = isCorrectArg( sub );
00314   }
00315   return res;
00316 }
00317 
00318 //================================================================================
00322 //================================================================================
00323 bool process( const TCollection_AsciiString& str, int convMode,
00324               bool& syntax, bool& args,
00325               bool& non_neg, bool& non_zero,
00326               bool& singulars, double& sing_point )
00327 {
00328   Kernel_Utils::Localizer loc;
00329 
00330   bool parsed_ok = true;
00331   Handle( ExprIntrp_GenExp ) myExpr;
00332   try {
00333 #ifdef NO_CAS_CATCH
00334     OCC_CATCH_SIGNALS;
00335 #endif
00336     myExpr = ExprIntrp_GenExp::Create();
00337     myExpr->Process( str.ToCString() );
00338   } catch(Standard_Failure) {
00339     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00340     parsed_ok = false;
00341   }
00342 
00343   syntax = false;
00344   args = false;
00345   if( parsed_ok && myExpr->IsDone() )
00346   {
00347     syntax = true;
00348     args = isCorrectArg( myExpr->Expression() );
00349   }
00350 
00351   bool res = parsed_ok && syntax && args;
00352   if( !res )
00353     myExpr.Nullify();
00354 
00355   non_neg = true;
00356   singulars = false;
00357   non_zero = false;
00358 
00359   if( res )
00360   {
00361     FunctionExpr f( str.ToCString(), convMode );
00362     const int max = 500;
00363     for( int i=0; i<=max; i++ )
00364     {
00365       double t = double(i)/double(max), val;
00366       if( !f.value( t, val ) )
00367       {
00368         sing_point = t;
00369         singulars = true;
00370         break;
00371       }
00372       if( val<0 )
00373       {
00374         non_neg = false;
00375         break;
00376       }
00377       if( val>PRECISION )
00378         non_zero = true;
00379     }
00380   }
00381 
00382   return res && non_neg && non_zero && ( !singulars );
00383 }
00384 
00385 //================================================================================
00389 //================================================================================
00390 
00391 void StdMeshers_NumberOfSegments::SetExpressionFunction(const char* expr)
00392   throw(SALOME_Exception)
00393 {
00394   if (_distrType != DT_ExprFunc)
00395     _distrType = DT_ExprFunc;
00396     //throw SALOME_Exception(LOCALIZED("not an expression function distribution"));
00397 
00398   string func = CheckExpressionFunction( expr, _convMode );
00399   if( _func != func )
00400   {
00401     _func = func;
00402     NotifySubMeshesHypothesisModification();
00403   }
00404 }
00405 
00406 //=======================================================================
00407 //function : CheckExpressionFunction
00408 //purpose  : Checks validity of  the expression of the function f(t), e.g. "sin(t)".
00409 //           In case of validity returns a cleaned expression
00410 //=======================================================================
00411 
00412 std::string
00413 StdMeshers_NumberOfSegments::CheckExpressionFunction( const std::string& expr,
00414                                                       const int          convMode)
00415     throw (SALOME_Exception)
00416 {
00417   // remove white spaces
00418   TCollection_AsciiString str((Standard_CString)expr.c_str());
00419   str.RemoveAll(' ');
00420   str.RemoveAll('\t');
00421   str.RemoveAll('\r');
00422   str.RemoveAll('\n');
00423 
00424   bool syntax, args, non_neg, singulars, non_zero;
00425   double sing_point;
00426   bool res = process( str, convMode, syntax, args, non_neg, non_zero, singulars, sing_point );
00427   if( !res )
00428   {
00429     if( !syntax )
00430       throw SALOME_Exception(SMESH_Comment("invalid expression syntax: ") << str );
00431     if( !args )
00432       throw SALOME_Exception(LOCALIZED("only 't' may be used as function argument"));
00433     if( !non_neg )
00434       throw SALOME_Exception(LOCALIZED("only non-negative function can be used"));
00435     if( singulars )
00436     {
00437       char buf[1024];
00438       sprintf( buf, "Function has singular point in %.3f", sing_point );
00439       throw SALOME_Exception( buf );
00440     }
00441     if( !non_zero )
00442       throw SALOME_Exception(LOCALIZED("f(t)=0 cannot be used"));
00443   }
00444  
00445   return str.ToCString();
00446 }
00447 
00448 //================================================================================
00452 //================================================================================
00453 
00454 const char* StdMeshers_NumberOfSegments::GetExpressionFunction() const
00455   throw(SALOME_Exception)
00456 {
00457   if (_distrType != DT_ExprFunc)
00458     throw SALOME_Exception(LOCALIZED("not an expression function distribution"));
00459   return _func.c_str();
00460 }
00461 
00462 //================================================================================
00466 //================================================================================
00467 
00468 void StdMeshers_NumberOfSegments::SetConversionMode( int conv )
00469   throw(SALOME_Exception)
00470 {
00471 //   if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc)
00472 //     throw SALOME_Exception(LOCALIZED("not a functional distribution"));
00473 
00474   if( conv != _convMode )
00475   {
00476     _convMode = conv;
00477     NotifySubMeshesHypothesisModification();
00478   }
00479 }
00480 
00481 //================================================================================
00485 //================================================================================
00486 
00487 int StdMeshers_NumberOfSegments::ConversionMode() const
00488   throw(SALOME_Exception)
00489 {
00490 //   if (_distrType != DT_TabFunc && _distrType != DT_ExprFunc)
00491 //     throw SALOME_Exception(LOCALIZED("not a functional distribution"));
00492   return _convMode;
00493 }
00494 
00495 //=============================================================================
00499 //=============================================================================
00500 
00501 ostream & StdMeshers_NumberOfSegments::SaveTo(ostream & save)
00502 {
00503   int listSize = _edgeIDs.size();
00504   save << _numberOfSegments << " " << (int)_distrType;
00505   switch (_distrType)
00506   {
00507   case DT_Scale:
00508     save << " " << _scaleFactor;
00509     break;
00510   case DT_TabFunc:
00511     int i;
00512     save << " " << _table.size();
00513     for (i=0; i < _table.size(); i++)
00514       save << " " << _table[i];
00515     break;
00516   case DT_ExprFunc:
00517     save << " " << _func;
00518     break;
00519   case DT_Regular:
00520   default:
00521     break;
00522   }
00523 
00524   if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc)
00525     save << " " << _convMode;
00526 
00527   if ( _distrType != DT_Regular && listSize > 0 ) {
00528     save << " " << listSize;
00529     for ( int i = 0; i < listSize; i++ )
00530       save << " " << _edgeIDs[i];
00531     save << " " << _objEntry;
00532   }
00533   
00534   return save;
00535 }
00536 
00537 //=============================================================================
00541 //=============================================================================
00542 
00543 istream & StdMeshers_NumberOfSegments::LoadFrom(istream & load)
00544 {
00545   bool isOK = true;
00546   int a;
00547 
00548   // read number of segments
00549   isOK = (load >> a);
00550   if (isOK)
00551     _numberOfSegments = a;
00552   else
00553     load.clear(ios::badbit | load.rdstate());
00554 
00555   // read second stored value. It can be two variants here:
00556   // 1. If the hypothesis is stored in old format (nb.segments and scale factor),
00557   //    we wait here the scale factor, which is double.
00558   // 2. If the hypothesis is stored in new format
00559   //    (nb.segments, distr.type, some other params.),
00560   //    we wait here the ditribution type, which is integer
00561   double scale_factor;
00562   isOK = (load >> scale_factor);
00563   a = (int)scale_factor;
00564 
00565   // try to interprete ditribution type,
00566   // supposing that this hypothesis was written in the new format
00567   if (isOK)
00568   {
00569     if (a < DT_Regular || a > DT_ExprFunc)
00570       _distrType = DT_Regular;
00571     else
00572       _distrType = (DistrType) a;
00573   }
00574   else
00575     load.clear(ios::badbit | load.rdstate());
00576 
00577   // parameters of distribution
00578   double b;
00579   switch (_distrType)
00580   {
00581   case DT_Scale:
00582     {
00583       isOK = (load >> b);
00584       if (isOK)
00585         _scaleFactor = b;
00586       else
00587       {
00588         load.clear(ios::badbit | load.rdstate());
00589         // this can mean, that the hypothesis is stored in old format
00590         _distrType = DT_Regular;
00591         _scaleFactor = scale_factor;
00592       }
00593     }
00594     break;
00595   case DT_TabFunc:
00596     {
00597       isOK = (load >> a);
00598       if (isOK)
00599       {
00600         _table.resize(a, 0.);
00601         int i;
00602         for (i=0; i < _table.size(); i++)
00603         {
00604           isOK = (load >> b);
00605           if (isOK)
00606             _table[i] = b;
00607           else
00608             load.clear(ios::badbit | load.rdstate());
00609         }
00610       }
00611       else
00612       {
00613         load.clear(ios::badbit | load.rdstate());
00614         // this can mean, that the hypothesis is stored in old format
00615         _distrType = DT_Regular;
00616         _scaleFactor = scale_factor;
00617       }
00618     }
00619     break;
00620   case DT_ExprFunc:
00621     {
00622       string str;
00623       isOK = (load >> str);
00624       if (isOK)
00625         _func = str;
00626       else
00627       {
00628         load.clear(ios::badbit | load.rdstate());
00629         // this can mean, that the hypothesis is stored in old format
00630         _distrType = DT_Regular;
00631         _scaleFactor = scale_factor;
00632       }
00633     }
00634     break;
00635   case DT_Regular:
00636   default:
00637     break;
00638   }
00639 
00640   if (_distrType == DT_TabFunc || _distrType == DT_ExprFunc)
00641   {
00642     isOK = (load >> a);
00643     if (isOK)
00644       _convMode = a;
00645     else
00646       load.clear(ios::badbit | load.rdstate());
00647   }
00648 
00649   // load reversed edges IDs
00650   int intVal;
00651   isOK = (load >> intVal);
00652   if ( isOK && _distrType != DT_Regular && intVal > 0 ) {
00653     _edgeIDs.reserve( intVal );
00654     for (int i = 0; i < _edgeIDs.capacity() && isOK; i++) {
00655       isOK = (load >> intVal);
00656       if ( isOK ) _edgeIDs.push_back( intVal );
00657     }
00658     isOK = (load >> _objEntry);
00659   }
00660 
00661   return load;
00662 }
00663 
00664 //=============================================================================
00668 //=============================================================================
00669 
00670 ostream & operator <<(ostream & save, StdMeshers_NumberOfSegments & hyp)
00671 {
00672   return hyp.SaveTo( save );
00673 }
00674 
00675 //=============================================================================
00679 //=============================================================================
00680 
00681 istream & operator >>(istream & load, StdMeshers_NumberOfSegments & hyp)
00682 {
00683   return hyp.LoadFrom( load );
00684 }
00685 
00686 //================================================================================
00693 //================================================================================
00694 
00695 bool StdMeshers_NumberOfSegments::SetParametersByMesh(const SMESH_Mesh*   theMesh,
00696                                                       const TopoDS_Shape& theShape)
00697 {
00698   if ( !theMesh || theShape.IsNull() )
00699     return false;
00700 
00701   _numberOfSegments = 0;
00702   _distrType = DT_Regular;
00703 
00704   int nbEdges = 0;
00705   TopTools_IndexedMapOfShape edgeMap;
00706   TopExp::MapShapes( theShape, TopAbs_EDGE, edgeMap );
00707   SMESHDS_Mesh* aMeshDS = const_cast< SMESH_Mesh* >( theMesh )->GetMeshDS();
00708   for ( int i = 1; i <= edgeMap.Extent(); ++i )
00709   {
00710     // get current segment length
00711     SMESHDS_SubMesh * eSubMesh = aMeshDS->MeshElements( edgeMap( i ));
00712     if ( eSubMesh && eSubMesh->NbElements())
00713       _numberOfSegments += eSubMesh->NbElements();
00714 
00715     ++nbEdges;
00716   }
00717   if ( nbEdges )
00718     _numberOfSegments /= nbEdges;
00719 
00720   if (_numberOfSegments == 0) _numberOfSegments = 1;
00721 
00722   return nbEdges;
00723 }
00724 //================================================================================
00729 //================================================================================
00730 
00731 bool StdMeshers_NumberOfSegments::SetParametersByDefaults(const TDefaults&  dflts,
00732                                                           const SMESH_Mesh* /*theMesh*/)
00733 {
00734   return (_numberOfSegments = dflts._nbSegments );
00735 }
00736 
00737 //=============================================================================
00741 //=============================================================================
00742 
00743 void StdMeshers_NumberOfSegments::SetReversedEdges( std::vector<int>& ids )
00744 {
00745   if ( ids != _edgeIDs ) {
00746     _edgeIDs = ids;
00747 
00748     NotifySubMeshesHypothesisModification();
00749   }
00750 }
00751