+ theParams.clear();
+
+ double f = theFirstU, l = theLastU;
+
+ switch( _hypType )
+ {
+ case LOCAL_LENGTH:
+ case MAX_LENGTH:
+ case NB_SEGMENTS: {
+
+ double eltSize = 1;
+ if ( _hypType == MAX_LENGTH )
+ {
+ double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup
+ if (nbseg <= 0)
+ nbseg = 1; // degenerated edge
+ eltSize = theLength / nbseg;
+ }
+ else if ( _hypType == LOCAL_LENGTH )
+ {
+ // Local Length hypothesis
+ double nbseg = ceil(theLength / _value[ BEG_LENGTH_IND ]); // integer sup
+
+ // NPAL17873:
+ bool isFound = false;
+ if (theConsiderPropagation && !_mainEdge.IsNull()) // propagated from some other edge
+ {
+ // Advanced processing to assure equal number of segments in case of Propagation
+ SMESH_subMesh* sm = theMesh.GetSubMeshContaining(_mainEdge);
+ if (sm) {
+ bool computed = sm->IsMeshComputed();
+ if (!computed) {
+ if (sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) {
+ _gen->Compute( theMesh, _mainEdge, /*anUpward=*/true);
+ computed = sm->IsMeshComputed();
+ }
+ }
+ if (computed) {
+ SMESHDS_SubMesh* smds = sm->GetSubMeshDS();
+ int nb_segments = smds->NbElements();
+ if (nbseg - 1 <= nb_segments && nb_segments <= nbseg + 1) {
+ isFound = true;
+ nbseg = nb_segments;
+ }
+ }
+ }
+ }
+ if (!isFound) // not found by meshed edge in the propagation chain, use precision
+ {
+ double aPrecision = _value[ PRECISION_IND ];
+ double nbseg_prec = ceil((theLength / _value[ BEG_LENGTH_IND ]) - aPrecision);
+ if (nbseg_prec == (nbseg - 1)) nbseg--;
+ }
+
+ if (nbseg <= 0)
+ nbseg = 1; // degenerated edge
+ eltSize = theLength / nbseg;
+ }
+ else
+ {
+ // Number Of Segments hypothesis
+ int NbSegm = _ivalue[ NB_SEGMENTS_IND ];
+ if ( NbSegm < 1 ) return false;
+ if ( NbSegm == 1 ) return true;
+
+ switch (_ivalue[ DISTR_TYPE_IND ])
+ {
+ case StdMeshers_NumberOfSegments::DT_Scale:
+ {
+ double scale = _value[ SCALE_FACTOR_IND ];
+
+ if (fabs(scale - 1.0) < Precision::Confusion()) {
+ // special case to avoid division by zero
+ for (int i = 1; i < NbSegm; i++) {
+ double param = f + (l - f) * i / NbSegm;
+ theParams.push_back( param );
+ }
+ } else {
+ // general case of scale distribution
+ if ( theReverse )
+ scale = 1.0 / scale;
+
+ double alpha = pow(scale, 1.0 / (NbSegm - 1));
+ double factor = (l - f) / (1.0 - pow(alpha, NbSegm));
+
+ for (int i = 1; i < NbSegm; i++) {
+ double param = f + factor * (1.0 - pow(alpha, i));
+ theParams.push_back( param );
+ }
+ }
+ const double lenFactor = theLength/(l-f);
+ list<double>::iterator u = theParams.begin(), uEnd = theParams.end();
+ for ( ; u != uEnd; ++u )
+ {
+ GCPnts_AbscissaPoint Discret( theC3d, ((*u)-f) * lenFactor, f );
+ if ( Discret.IsDone() )
+ *u = Discret.Parameter();
+ }
+ return true;
+ }
+ break;
+ case StdMeshers_NumberOfSegments::DT_TabFunc:
+ {
+ FunctionTable func(_vvalue[ TAB_FUNC_IND ], _ivalue[ CONV_MODE_IND ]);
+ return computeParamByFunc(theC3d, f, l, theLength, theReverse,
+ _ivalue[ NB_SEGMENTS_IND ], func,
+ theParams);
+ }
+ break;
+ case StdMeshers_NumberOfSegments::DT_ExprFunc:
+ {
+ FunctionExpr func(_svalue[ EXPR_FUNC_IND ].c_str(), _ivalue[ CONV_MODE_IND ]);
+ return computeParamByFunc(theC3d, f, l, theLength, theReverse,
+ _ivalue[ NB_SEGMENTS_IND ], func,
+ theParams);
+ }
+ break;
+ case StdMeshers_NumberOfSegments::DT_Regular:
+ eltSize = theLength / _ivalue[ NB_SEGMENTS_IND ];
+ break;
+ default:
+ return false;
+ }
+ }
+ GCPnts_UniformAbscissa Discret(theC3d, eltSize, f, l);
+ if ( !Discret.IsDone() )
+ return error( "GCPnts_UniformAbscissa failed");
+
+ int NbPoints = Discret.NbPoints();
+ for ( int i = 2; i < NbPoints; i++ )
+ {
+ double param = Discret.Parameter(i);
+ theParams.push_back( param );
+ }
+ compensateError( eltSize, eltSize, f, l, theLength, theC3d, theParams ); // for PAL9899
+ return true;
+ }
+
+ case BEG_END_LENGTH: {
+
+ // geometric progression: SUM(n) = ( a1 - an * q ) / ( 1 - q ) = theLength
+
+ double a1 = _value[ BEG_LENGTH_IND ];
+ double an = _value[ END_LENGTH_IND ];
+ double q = ( theLength - a1 ) / ( theLength - an );
+ if ( q < theLength/1e6 || 1.01*theLength < a1 + an)
+ return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
+ "for an edge of length "<<theLength);
+
+ double U1 = theReverse ? l : f;
+ double Un = theReverse ? f : l;
+ double param = U1;
+ double eltSize = theReverse ? -a1 : a1;
+ while ( 1 ) {
+ // computes a point on a curve <theC3d> at the distance <eltSize>
+ // from the point of parameter <param>.
+ GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
+ if ( !Discret.IsDone() ) break;
+ param = Discret.Parameter();
+ if ( f < param && param < l )
+ theParams.push_back( param );
+ else
+ break;
+ eltSize *= q;
+ }
+ compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
+ if (theReverse) theParams.reverse(); // NPAL18025
+ return true;
+ }
+
+ case ARITHMETIC_1D: {
+
+ // arithmetic progression: SUM(n) = ( an - a1 + q ) * ( a1 + an ) / ( 2 * q ) = theLength
+
+ double a1 = _value[ BEG_LENGTH_IND ];
+ double an = _value[ END_LENGTH_IND ];
+ if ( 1.01*theLength < a1 + an)
+ return error ( SMESH_Comment("Invalid segment lengths (")<<a1<<" and "<<an<<") "<<
+ "for an edge of length "<<theLength);
+
+ double q = ( an - a1 ) / ( 2 *theLength/( a1 + an ) - 1 );
+ int n = int(fabs(q) > numeric_limits<double>::min() ? ( 1+( an-a1 )/q ) : ( 1+theLength/a1 ));
+
+ double U1 = theReverse ? l : f;
+ double Un = theReverse ? f : l;
+ double param = U1;
+ double eltSize = a1;
+ if ( theReverse ) {
+ eltSize = -eltSize;
+ q = -q;
+ }
+ while ( n-- > 0 && eltSize * ( Un - U1 ) > 0 ) {
+ // computes a point on a curve <theC3d> at the distance <eltSize>
+ // from the point of parameter <param>.
+ GCPnts_AbscissaPoint Discret( theC3d, eltSize, param );
+ if ( !Discret.IsDone() ) break;
+ param = Discret.Parameter();
+ if ( param > f && param < l )
+ theParams.push_back( param );
+ else
+ break;
+ eltSize += q;
+ }
+ compensateError( a1, an, U1, Un, theLength, theC3d, theParams );
+ if (theReverse) theParams.reverse(); // NPAL18025
+
+ return true;
+ }
+
+ case FIXED_POINTS_1D: {
+ const std::vector<double>& aPnts = _fpHyp->GetPoints();
+ const std::vector<int>& nbsegs = _fpHyp->GetNbSegments();
+ int i = 0;
+ TColStd_SequenceOfReal Params;
+ for(; i<aPnts.size(); i++) {
+ if( aPnts[i]<0.0001 || aPnts[i]>0.9999 ) continue;
+ int j=1;
+ bool IsExist = false;
+ for(; j<=Params.Length(); j++) {
+ if( fabs(aPnts[i]-Params.Value(j)) < 1e-4 ) {
+ IsExist = true;
+ break;
+ }
+ if( aPnts[i]<Params.Value(j) ) break;
+ }
+ if(!IsExist) Params.InsertBefore(j,aPnts[i]);
+ }
+ double par2, par1, lp;
+ par1 = f;
+ lp = l;
+ double sign = 1.0;
+ if(theReverse) {
+ par1 = l;
+ lp = f;
+ sign = -1.0;
+ }
+ double eltSize, segmentSize = 0.;
+ double currAbscissa = 0;
+ for(i=0; i<Params.Length(); i++) {
+ int nbseg = ( i > nbsegs.size()-1 ) ? nbsegs[0] : nbsegs[i];
+ segmentSize = Params.Value(i+1)*theLength - currAbscissa;
+ currAbscissa += segmentSize;
+ GCPnts_AbscissaPoint APnt(theC3d, sign*segmentSize, par1);
+ if( !APnt.IsDone() )
+ return error( "GCPnts_AbscissaPoint failed");
+ par2 = APnt.Parameter();
+ eltSize = segmentSize/nbseg;
+ GCPnts_UniformAbscissa Discret(theC3d, eltSize, par1, par2);
+ if(theReverse)
+ Discret.Initialize(theC3d, eltSize, par2, par1);
+ else
+ Discret.Initialize(theC3d, eltSize, par1, par2);
+ if ( !Discret.IsDone() )
+ return error( "GCPnts_UniformAbscissa failed");
+ int NbPoints = Discret.NbPoints();
+ list<double> tmpParams;
+ for(int i=2; i<NbPoints; i++) {
+ double param = Discret.Parameter(i);
+ tmpParams.push_back( param );
+ }
+ if (theReverse) {
+ compensateError( eltSize, eltSize, par2, par1, segmentSize, theC3d, tmpParams );
+ tmpParams.reverse();
+ }
+ else {
+ compensateError( eltSize, eltSize, par1, par2, segmentSize, theC3d, tmpParams );
+ }
+ list<double>::iterator itP = tmpParams.begin();
+ for(; itP != tmpParams.end(); itP++) {
+ theParams.push_back( *(itP) );
+ }
+ theParams.push_back( par2 );
+
+ par1 = par2;
+ }
+ // add for last
+ int nbseg = ( nbsegs.size() > Params.Length() ) ? nbsegs[Params.Length()] : nbsegs[0];
+ segmentSize = theLength - currAbscissa;
+ eltSize = segmentSize/nbseg;
+ GCPnts_UniformAbscissa Discret;
+ if(theReverse)
+ Discret.Initialize(theC3d, eltSize, par1, lp);
+ else
+ Discret.Initialize(theC3d, eltSize, lp, par1);
+ if ( !Discret.IsDone() )
+ return error( "GCPnts_UniformAbscissa failed");
+ int NbPoints = Discret.NbPoints();
+ list<double> tmpParams;
+ for(int i=2; i<NbPoints; i++) {
+ double param = Discret.Parameter(i);
+ tmpParams.push_back( param );
+ }
+ if (theReverse) {
+ compensateError( eltSize, eltSize, lp, par1, segmentSize, theC3d, tmpParams );
+ tmpParams.reverse();
+ }
+ else {
+ compensateError( eltSize, eltSize, par1, lp, segmentSize, theC3d, tmpParams );
+ }
+ list<double>::iterator itP = tmpParams.begin();
+ for(; itP != tmpParams.end(); itP++) {
+ theParams.push_back( *(itP) );
+ }
+
+ if (theReverse) {
+ theParams.reverse(); // NPAL18025
+ }
+ return true;
+ }
+
+ case DEFLECTION: {
+
+ GCPnts_UniformDeflection Discret(theC3d, _value[ DEFLECTION_IND ], f, l, true);
+ if ( !Discret.IsDone() )
+ return false;
+
+ int NbPoints = Discret.NbPoints();
+ for ( int i = 2; i < NbPoints; i++ )
+ {
+ double param = Discret.Parameter(i);
+ theParams.push_back( param );
+ }
+ return true;
+ }
+
+ default:;
+ }
+
+ return false;