+//=======================================================================
+//function : compensateError
+//purpose : adjust theParams so that the last segment length == an
+//=======================================================================
+
+static void compensateError(double a1, double an,
+ double U1, double Un,
+ double length,
+ GeomAdaptor_Curve& C3d,
+ list<double> & theParams)
+{
+ int i, nPar = theParams.size();
+ if ( a1 + an < length && nPar > 1 )
+ {
+ list<double>::reverse_iterator itU = theParams.rbegin();
+ double Ul = *itU++;
+ // dist from the last point to the edge end <Un>, it should be equal <an>
+ double Ln = GCPnts_AbscissaPoint::Length( C3d, Ul, Un );
+ double dLn = an - Ln; // error of <an>
+ if ( Abs( dLn ) <= Precision::Confusion() )
+ return;
+ double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
+ double dUn = dLn * Abs( Un - U1 ) / length; // parametric error of <an>
+ if ( dUn < 0.5 * dU ) { // last segment is a bit shorter than it should
+ dUn = -dUn; // move the last parameter to the edge beginning
+ }
+ else { // last segment is much shorter than it should -> remove the last param and
+ theParams.pop_back(); nPar--; // move the rest points toward the edge end
+ Ln = GCPnts_AbscissaPoint::Length( C3d, theParams.back(), Un );
+ dUn = ( an - Ln ) * Abs( Un - U1 ) / length;
+ if ( dUn < 0.5 * dU )
+ dUn = -dUn;
+ }
+ if ( U1 > Un )
+ dUn = -dUn;
+ double q = dUn / ( nPar - 1 );
+ for ( itU = theParams.rbegin(), i = 1; i < nPar; itU++, i++ ) {
+ (*itU) += dUn;
+ dUn -= q;
+ }
+ }
+}
+
+/*!
+ * \brief This class provides interface for a density function
+ */
+class Function
+{
+public:
+ Function(bool expMode) : _expMode(expMode) {}
+ double operator() (double t) const;
+ virtual bool IsReady() const = 0;
+protected:
+ virtual double compute(double t) const = 0;
+private:
+ bool _expMode;
+};
+
+/*!
+ * \brief This class provides computation of density function given by a table
+ */
+class TabFunction: public Function
+{
+public:
+ TabFunction(const vector<double>& table, bool expMode);
+ virtual bool IsReady() const;
+protected:
+ virtual double compute(double t) const;
+private:
+ const vector<double>& _table;
+};
+
+/*!
+ * \brief This class provides computation of density function given by an expression
+ */
+class ExprFunction: public Function
+{
+public:
+ ExprFunction(const char* expr, bool expMode);
+ virtual bool IsReady() const;
+protected:
+ virtual double compute(double t) const;
+private:
+ Handle(Expr_GeneralExpression) _expression;
+ Expr_Array1OfNamedUnknown _var;
+ mutable TColStd_Array1OfReal _val;
+};
+
+double Function::operator() (double t) const
+{
+ double res = compute(t);
+ if (_expMode)
+ res = pow(10, res);
+ return res;
+}
+
+TabFunction::TabFunction(const vector<double>& table, bool expMode)
+ : Function(expMode),
+ _table(table)
+{
+}
+
+bool TabFunction::IsReady() const
+{
+ return true;
+}
+
+double TabFunction::compute (double t) const
+{
+ //find place of <t> in table
+ int i;
+ for (i=0; i < _table.size()/2; i++)
+ if (_table[i*2] > t)
+ break;
+ if (i >= _table.size()/2)
+ i = _table.size()/2 - 1;
+
+ if (i == 0)
+ return _table[1];
+
+ // interpolate function value on found interval
+ // (t - x[i-1]) / (x[i] - x[i-1]) = (y - f[i-1]) / (f[i] - f[i-1])
+ // => y = f[i-1] + (f[i] - f[i-1]) * (t - x[i-1]) / (x[i] - x[i-1])
+ double x1 = _table[(i-1)*2];
+ double x2 = _table[i*2];
+ double y1 = _table[(i-1)*2+1];
+ double y2 = _table[i*2+1];
+ if (x2 - x1 < Precision::Confusion())
+ throw SALOME_Exception("TabFunction::compute : confused points");
+ return y1 + (y2 - y1) * ((t - x1) / (x2 - x1));
+}
+
+ExprFunction::ExprFunction(const char* expr, bool expMode)
+ : Function(expMode),
+ _var(1,1),
+ _val(1,1)
+{
+ Handle( ExprIntrp_GenExp ) gen = ExprIntrp_GenExp::Create();
+ gen->Process(TCollection_AsciiString((char*)expr));
+ if (gen->IsDone())
+ {
+ _expression = gen->Expression();
+ _var(1) = new Expr_NamedUnknown("t");
+ }
+}
+
+bool ExprFunction::IsReady() const
+{
+ return !_expression.IsNull();
+}
+
+double ExprFunction::compute (double t) const
+{
+ ASSERT(!_expression.IsNull());
+ _val(1) = t;
+ return _expression->Evaluate(_var, _val);
+}
+
+//================================================================================