00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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),
00070 _distrType(DT_Regular),
00071 _scaleFactor(1.),
00072 _convMode(1)
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
00184 if (scaleFactor < PRECISION)
00185 throw SALOME_Exception(LOCALIZED("scale factor must be positive"));
00186
00187
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
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
00396
00397
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
00459
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
00478
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
00536 isOK = (load >> a);
00537 if (isOK)
00538 _numberOfSegments = a;
00539 else
00540 load.clear(ios::badbit | load.rdstate());
00541
00542
00543
00544
00545
00546
00547
00548 double scale_factor;
00549 isOK = (load >> scale_factor);
00550 a = (int)scale_factor;
00551
00552
00553
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
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
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
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
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
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
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* )
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