+ _hypType = NONE;
+
+ const list <const SMESHDS_Hypothesis * >&hyps = GetUsedHypothesis(aMesh, aShape);
+ if (hyps.size() == 0)
+ {
+ aStatus = SMESH_Hypothesis::HYP_MISSING;
+ return false; // can't work without a hypothesis
+ }
+
+ // use only the first hypothesis
+ const SMESHDS_Hypothesis *theHyp = hyps.front();
+
+ string hypName = theHyp->GetName();
+
+ if (hypName == "LocalLength")
+ {
+ const StdMeshers_LocalLength * hyp =
+ dynamic_cast <const StdMeshers_LocalLength * >(theHyp);
+ ASSERT(hyp);
+ _value[ BEG_LENGTH_IND ] = _value[ END_LENGTH_IND ] = hyp->GetLength();
+ ASSERT( _value[ BEG_LENGTH_IND ] > 0 );
+ _hypType = LOCAL_LENGTH;
+ aStatus = SMESH_Hypothesis::HYP_OK;
+ }
+
+ else if (hypName == "NumberOfSegments")
+ {
+ const StdMeshers_NumberOfSegments * hyp =
+ dynamic_cast <const StdMeshers_NumberOfSegments * >(theHyp);
+ ASSERT(hyp);
+ _ivalue[ NB_SEGMENTS_IND ] = hyp->GetNumberOfSegments();
+ ASSERT( _ivalue[ NB_SEGMENTS_IND ] > 0 );
+ _ivalue[ DISTR_TYPE_IND ] = (int) hyp->GetDistrType();
+ switch (_ivalue[ DISTR_TYPE_IND ])
+ {
+ case StdMeshers_NumberOfSegments::DT_Scale:
+ _value[ SCALE_FACTOR_IND ] = hyp->GetScaleFactor();
+ break;
+ case StdMeshers_NumberOfSegments::DT_TabFunc:
+ _vvalue[ TAB_FUNC_IND ] = hyp->GetTableFunction();
+ break;
+ case StdMeshers_NumberOfSegments::DT_ExprFunc:
+ _svalue[ EXPR_FUNC_IND ] = hyp->GetExpressionFunction();
+ break;
+ case StdMeshers_NumberOfSegments::DT_Regular:
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ if (_ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_TabFunc ||
+ _ivalue[ DISTR_TYPE_IND ] == StdMeshers_NumberOfSegments::DT_ExprFunc)
+ _ivalue[ EXP_MODE_IND ] = (int) hyp->IsExponentMode();
+ _hypType = NB_SEGMENTS;
+ aStatus = SMESH_Hypothesis::HYP_OK;
+ }
+
+ else if (hypName == "Arithmetic1D")
+ {
+ const StdMeshers_Arithmetic1D * hyp =
+ dynamic_cast <const StdMeshers_Arithmetic1D * >(theHyp);
+ ASSERT(hyp);
+ _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
+ _value[ END_LENGTH_IND ] = hyp->GetLength( false );
+ ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
+ _hypType = ARITHMETIC_1D;
+ aStatus = SMESH_Hypothesis::HYP_OK;
+ }
+
+ else if (hypName == "StartEndLength")
+ {
+ const StdMeshers_StartEndLength * hyp =
+ dynamic_cast <const StdMeshers_StartEndLength * >(theHyp);
+ ASSERT(hyp);
+ _value[ BEG_LENGTH_IND ] = hyp->GetLength( true );
+ _value[ END_LENGTH_IND ] = hyp->GetLength( false );
+ ASSERT( _value[ BEG_LENGTH_IND ] > 0 && _value[ END_LENGTH_IND ] > 0 );
+ _hypType = BEG_END_LENGTH;
+ aStatus = SMESH_Hypothesis::HYP_OK;
+ }
+
+ else if (hypName == "Deflection1D")
+ {
+ const StdMeshers_Deflection1D * hyp =
+ dynamic_cast <const StdMeshers_Deflection1D * >(theHyp);
+ ASSERT(hyp);
+ _value[ DEFLECTION_IND ] = hyp->GetDeflection();
+ ASSERT( _value[ DEFLECTION_IND ] > 0 );
+ _hypType = DEFLECTION;
+ aStatus = SMESH_Hypothesis::HYP_OK;
+ }
+ else
+ aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+
+ return ( _hypType != NONE );
+}
+
+//=======================================================================
+//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;
+}