+static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last,
+ double length, bool theReverse,
+ int nbSeg, Function& func,
+ list<double>& theParams)
+{
+ // never do this way
+ //OSD::SetSignal( true );
+
+ if (nbSeg <= 0)
+ return false;
+
+ MESSAGE( "computeParamByFunc" );
+
+ int nbPnt = 1 + nbSeg;
+ vector<double> x(nbPnt, 0.);
+
+ if (!buildDistribution(func, 0.0, 1.0, nbSeg, x, 1E-4))
+ return false;
+
+ MESSAGE( "Points:\n" );
+ char buf[1024];
+ for ( int i=0; i<=nbSeg; i++ )
+ {
+ sprintf( buf, "%f\n", float(x[i] ) );
+ MESSAGE( buf );
+ }
+
+
+
+ // apply parameters in range [0,1] to the space of the curve
+ double prevU = first;
+ double sign = 1.;
+ if (theReverse)
+ {
+ prevU = last;
+ sign = -1.;
+ }
+ for( int i = 1; i < nbSeg; i++ )
+ {
+ double curvLength = length * (x[i] - x[i-1]) * sign;
+ GCPnts_AbscissaPoint Discret( C3d, curvLength, prevU );
+ if ( !Discret.IsDone() )
+ return false;
+ double U = Discret.Parameter();
+ if ( U > first && U < last )
+ theParams.push_back( U );
+ else
+ return false;
+ prevU = U;
+ }
+ if ( theReverse )
+ theParams.reverse();
+ return true;
+}
+
+
+//================================================================================
+/*!
+ * \brief adjust internal node parameters so that the last segment length == an
+ * \param a1 - the first segment length
+ * \param an - the last segment length
+ * \param U1 - the first edge parameter
+ * \param Un - the last edge parameter
+ * \param length - the edge length
+ * \param C3d - the edge curve
+ * \param theParams - internal node parameters to adjust
+ * \param adjustNeighbors2an - to adjust length of segments next to the last one
+ * and not to remove parameters
+ */
+//================================================================================
+
+static void compensateError(double a1, double an,
+ double U1, double Un,
+ double length,
+ Adaptor3d_Curve& C3d,
+ list<double> & theParams,
+ bool adjustNeighbors2an = false)
+{
+ int i, nPar = theParams.size();
+ if ( a1 + an < length && nPar > 1 )
+ {
+ bool reverse = ( U1 > Un );
+ GCPnts_AbscissaPoint Discret(C3d, reverse ? an : -an, Un);
+ if ( !Discret.IsDone() )
+ return;
+ double Utgt = Discret.Parameter(); // target value of the last parameter
+ list<double>::reverse_iterator itU = theParams.rbegin();
+ double Ul = *itU++; // real value of the last parameter
+ double dUn = Utgt - Ul; // parametric error of <an>
+ if ( Abs(dUn) <= Precision::Confusion() )
+ return;
+ double dU = Abs( Ul - *itU ); // parametric length of the last but one segment
+ if ( adjustNeighbors2an || Abs(dUn) < 0.5 * dU ) { // last segment is a bit shorter than it should
+ // 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
+ dUn = Utgt - theParams.back();
+ }
+
+ double q = dUn / ( nPar - 1 );
+ if ( !adjustNeighbors2an )
+ {
+ q = dUn / ( Utgt - Un ); // (signed) factor of segment length change
+ for ( itU = theParams.rbegin(), i = 1; i < nPar; i++ ) {
+ double prevU = *itU;
+ (*itU) += dUn;
+ ++itU;
+ dUn = q * (*itU - prevU) * (prevU-U1)/(Un-U1);
+ }
+ }
+ else {
+ theParams.back() += dUn;
+ double sign = reverse ? -1 : 1;
+ double prevU = theParams.back();
+ itU = theParams.rbegin();
+ for ( ++itU, i = 2; i < nPar; ++itU, i++ ) {
+ double newU = *itU + dUn;
+ if ( newU*sign < prevU*sign ) {
+ prevU = *itU = newU;
+ dUn -= q;
+ }
+ else { // set U between prevU and next valid param
+ list<double>::reverse_iterator itU2 = itU;
+ ++itU2;
+ int nb = 2;
+ while ( (*itU2)*sign > prevU*sign ) {
+ ++itU2; ++nb;
+ }
+ dU = ( *itU2 - prevU ) / nb;
+ while ( itU != itU2 ) {
+ *itU += dU; ++itU;
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+//================================================================================
+/*!
+ * \brief Class used to clean mesh on edges when 0D hyp modified.
+ * Common approach doesn't work when 0D algo is missing because the 0D hyp is
+ * considered as not participating in computation whereas it is used by 1D algo.
+ */
+//================================================================================
+
+// struct VertexEventListener : public SMESH_subMeshEventListener
+// {
+// VertexEventListener():SMESH_subMeshEventListener(0) // won't be deleted by submesh
+// {}
+// /*!
+// * \brief Clean mesh on edges
+// * \param event - algo_event or compute_event itself (of SMESH_subMesh)
+// * \param eventType - ALGO_EVENT or COMPUTE_EVENT (of SMESH_subMesh)
+// * \param subMesh - the submesh where the event occures
+// */
+// void ProcessEvent(const int event, const int eventType, SMESH_subMesh* subMesh,
+// EventListenerData*, const SMESH_Hypothesis*)
+// {
+// if ( eventType == SMESH_subMesh::ALGO_EVENT) // all algo events
+// {
+// subMesh->ComputeStateEngine( SMESH_subMesh::MODIF_ALGO_STATE );
+// }
+// }
+// }; // struct VertexEventListener
+