+ double U1 = theReverse ? l : f;
+ double Un = theReverse ? f : l;
+ double param = U1;
+ double eltSize = a1;
+ if ( theReverse )
+ eltSize = -eltSize;
+
+ int nbParams = 0;
+ while ( true ) {
+ // computes a point on a curve <theC3d> at the distance <eltSize>
+ // from the point of parameter <param>.
+ double tol = Min( Precision::Confusion(), 0.01 * eltSize );
+ GCPnts_AbscissaPoint Discret( tol, theC3d, eltSize, param );
+ if ( !Discret.IsDone() ) break;
+ param = Discret.Parameter();
+ if ( f < param && param < l )
+ theParams.push_back( param );
+ else
+ break;
+ an = eltSize;
+ eltSize *= q;
+ ++nbParams;
+ if ( q < 1. && eltSize < 1e-100 )
+ return error("Too small common ratio causes too many segments");
+ }
+ if ( nbParams > 1 )
+ {
+ if ( Abs( param - Un ) < 0.2 * Abs( param - theParams.back() ))
+ {
+ compensateError( a1, Abs(eltSize), U1, Un, theLength, theC3d, theParams );
+ }
+ else if ( Abs( Un - theParams.back() ) <
+ 0.2 * Abs( theParams.back() - *(++theParams.rbegin())))
+ {
+ theParams.pop_back();
+ compensateError( a1, Abs(an), U1, Un, theLength, theC3d, theParams );
+ }
+ }
+ if (theReverse) theParams.reverse(); // NPAL18025
+
+ return true;
+ }
+
+ case FIXED_POINTS_1D:
+ {
+ const std::vector<double>& aPnts = _fpHyp->GetPoints();
+ std::vector<int> nbsegs = _fpHyp->GetNbSegments();
+
+ // sort normalized params, taking into account theReverse
+ TColStd_SequenceOfReal Params;
+ double tol = 1e-7 / theLength; // GCPnts_UniformAbscissa allows u2-u1 > 1e-7
+ for ( size_t i = 0; i < aPnts.size(); i++ )
+ {
+ if( aPnts[i] < tol || aPnts[i] > 1 - tol )
+ continue;
+ double u = theReverse ? ( 1 - aPnts[i] ) : aPnts[i];
+ int j = 1;
+ bool IsExist = false;
+ for ( ; j <= Params.Length(); j++ ) {
+ if ( Abs( u - Params.Value(j) ) < tol ) {
+ IsExist = true;
+ break;
+ }
+ if ( u < Params.Value(j) ) break;
+ }
+ if ( !IsExist ) Params.InsertBefore( j, u );
+ }
+
+ // transform normalized Params into real ones
+ std::vector< double > uVec( Params.Length() + 2 );
+ uVec[ 0 ] = theFirstU;
+ double abscissa;
+ for ( int i = 1; i <= Params.Length(); i++ )
+ {
+ abscissa = Params( i ) * theLength;
+ tol = Min( Precision::Confusion(), 0.01 * abscissa );
+ GCPnts_AbscissaPoint APnt( tol, theC3d, abscissa, theFirstU );
+ if ( !APnt.IsDone() )
+ return error( "GCPnts_AbscissaPoint failed");
+ uVec[ i ] = APnt.Parameter();
+ }
+ uVec.back() = theLastU;
+
+ // divide segments
+ if ( theReverse )
+ {
+ if ((int) nbsegs.size() > Params.Length() + 1 )
+ nbsegs.resize( Params.Length() + 1 );
+ std::reverse( nbsegs.begin(), nbsegs.end() );
+ }
+ if ( nbsegs.empty() )
+ {
+ nbsegs.push_back( 1 );
+ }
+ Params.InsertBefore( 1, 0.0 );
+ Params.Append( 1.0 );
+ double eltSize, segmentSize, par1, par2;
+ for ( size_t i = 0; i < uVec.size()-1; i++ )
+ {
+ par1 = uVec[ i ];
+ par2 = uVec[ i+1 ];
+ int nbseg = ( i < nbsegs.size() ) ? nbsegs[i] : nbsegs[0];
+ if ( nbseg == 1 )
+ {
+ theParams.push_back( par2 );
+ }
+ else
+ {
+ segmentSize = ( Params( i+2 ) - Params( i+1 )) * theLength;
+ eltSize = segmentSize / nbseg;
+ tol = Min( Precision::Confusion(), 0.01 * eltSize );
+ GCPnts_UniformAbscissa Discret( theC3d, eltSize, par1, par2, tol );
+ if ( !Discret.IsDone() )
+ return error( "GCPnts_UniformAbscissa failed");
+ if ( Discret.NbPoints() < nbseg + 1 ) {
+ eltSize = segmentSize / ( nbseg + 0.5 );
+ Discret.Initialize( theC3d, eltSize, par1, par2, tol );
+ }
+ int NbPoints = Discret.NbPoints();
+ for ( int i = 2; i <= NbPoints; i++ ) {
+ double param = Discret.Parameter(i);
+ theParams.push_back( param );
+ }
+ }
+ }
+ theParams.pop_back();
+
+ return true;
+ }
+
+ case DEFLECTION:
+ {
+ GCPnts_UniformDeflection Discret( theC3d, _value[ DEFLECTION_IND ], f, l, true );