// SMESH StdMeshers : implementaion of point distribution algorithm // // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // 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.salome-platform.org/ or email : webmaster.salome@opencascade.com // // // // File : StdMeshers_Distribution.cxx // Author : Alexandre SOLOVYOV // Module : SMESH // $Header$ #include "StdMeshers_Distribution.hxx" #include "CASCatch.hxx" #include #include Function::Function( const int conv ) : myConv( conv ) { } Function::~Function() { } bool Function::value( const double, double& f ) const { bool ok = true; if( myConv==0 ) { CASCatch_TRY { f = pow( 10, f ); } CASCatch_CATCH(Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); f = 0.0; ok = false; } } else if( myConv==1 && f<0.0 ) f = 0.0; return ok; } FunctionIntegral::FunctionIntegral( const Function* f, const double st ) : Function( -1 ), myFunc( const_cast( f ) ), myStart( st ) { } FunctionIntegral::~FunctionIntegral() { } bool FunctionIntegral::value( const double t, double& f ) const { f = myFunc ? myFunc->integral( myStart, t ) : 0; return myFunc!=0 && Function::value( t, f ); } double FunctionIntegral::integral( const double, const double ) const { return 0; } FunctionTable::FunctionTable( const std::vector& data, const int conv ) : Function( conv ) { myData = data; } FunctionTable::~FunctionTable() { } bool FunctionTable::value( const double t, double& f ) const { int i1, i2; if( !findBounds( t, i1, i2 ) ) return false; double x1 = myData[2*i1], y1 = myData[2*i1+1], x2 = myData[2*i2], y2 = myData[2*i2+1]; Function::value( x1, y1 ); Function::value( x2, y2 ); f = y1 + ( y2-y1 ) * ( t-x1 ) / ( x2-x1 ); return true; } double FunctionTable::integral( const int i ) const { if( i>=0 && iProcess( ( Standard_CString )str ); } CASCatch_CATCH(Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); ok = false; } if( !ok || !myExpr->IsDone() ) myExpr.Nullify(); myVars.ChangeValue( 1 ) = new Expr_NamedUnknown( "t" ); } FunctionExpr::~FunctionExpr() { } Standard_Boolean FunctionExpr::Value( Standard_Real T, Standard_Real& F ) { double f; Standard_Boolean res = value( T, f ); F = f; return res; } bool FunctionExpr::value( const double t, double& f ) const { if( myExpr.IsNull() ) return false; ( ( TColStd_Array1OfReal& )myValues ).ChangeValue( 1 ) = t; bool ok = true; CASCatch_TRY { f = myExpr->Expression()->Evaluate( myVars, myValues ); } CASCatch_CATCH(Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); f = 0.0; ok = false; } ok = Function::value( t, f ) && ok; return ok; } double FunctionExpr::integral( const double a, const double b ) const { double res = 0.0; CASCatch_TRY { math_GaussSingleIntegration _int( ( math_Function& )*this, a, b, 20 ); if( _int.IsDone() ) res = _int.Value(); } CASCatch_CATCH(Standard_Failure) { res = 0.0; MESSAGE( "Exception in integral calculating" ); } return res; } double dihotomySolve( Function& f, const double val, const double _start, const double _fin, const double eps, bool& ok ) { double start = _start, fin = _fin, start_val, fin_val; bool ok1, ok2; ok1 = f.value( start, start_val ); ok2 = f.value( fin, fin_val ); if( !ok1 || !ok2 ) { ok = false; return 0.0; } bool start_pos = start_val>=val, fin_pos = fin_val>=val; ok = true; while( fin-start>eps ) { double mid = ( start+fin )/2.0, mid_val; ok = f.value( mid, mid_val ); if( !ok ) return 0.0; //char buf[1024]; //sprintf( buf, "start=%f\nfin=%f\nmid_val=%f\n", float( start ), float( fin ), float( mid_val ) ); //MESSAGE( buf ); bool mid_pos = mid_val>=val; if( start_pos!=mid_pos ) { fin_pos = mid_pos; fin = mid; } else if( fin_pos!=mid_pos ) { start_pos = mid_pos; start = mid; } else { ok = false; break; } } return (start+fin)/2.0; } bool buildDistribution( const TCollection_AsciiString& f, const int conv, const double start, const double end, const int nbSeg, vector& data, const double eps ) { FunctionExpr F( f.ToCString(), conv ); return buildDistribution( F, start, end, nbSeg, data, eps ); } bool buildDistribution( const std::vector& f, const int conv, const double start, const double end, const int nbSeg, vector& data, const double eps ) { FunctionTable F( f, conv ); return buildDistribution( F, start, end, nbSeg, data, eps ); } bool buildDistribution( const Function& func, const double start, const double end, const int nbSeg, vector& data, const double eps ) { if( nbSeg<=0 ) return false; data.resize( nbSeg+1 ); data[0] = start; double J = func.integral( start, end ) / nbSeg; if( J<1E-10 ) return false; bool ok; //MESSAGE( "distribution:" ); //char buf[1024]; for( int i=1; i