Version: 6.3.1

src/StdMeshers/StdMeshers_NumberOfSegments.cxx

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