+//================================================================================
+/*!
+ * \brief Tune parameters to fit "SegmentLengthAroundVertex" hypothesis
+ * \param theC3d - wire curve
+ * \param theLength - curve length
+ * \param theParameters - internal nodes parameters to modify
+ * \param theVf - 1st vertex
+ * \param theVl - 2nd vertex
+ */
+//================================================================================
+
+void StdMeshers_Regular_1D::redistributeNearVertices (SMESH_Mesh & theMesh,
+ Adaptor3d_Curve & theC3d,
+ double theLength,
+ std::list< double > & theParameters,
+ const TopoDS_Vertex & theVf,
+ const TopoDS_Vertex & theVl)
+{
+ double f = theC3d.FirstParameter(), l = theC3d.LastParameter();
+ size_t nPar = theParameters.size();
+ for ( int isEnd1 = 0; isEnd1 < 2; ++isEnd1 )
+ {
+ const TopoDS_Vertex & V = isEnd1 ? theVf : theVl;
+ const StdMeshers_SegmentLengthAroundVertex* hyp = getVertexHyp (theMesh, V );
+ if ( hyp ) {
+ double vertexLength = hyp->GetLength();
+ if ( vertexLength > theLength / 2.0 )
+ continue;
+ if ( isEnd1 ) { // to have a segment of interest at end of theParameters
+ theParameters.reverse();
+ std::swap( f, l );
+ }
+ if ( _hypType == NB_SEGMENTS )
+ {
+ compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
+ }
+ else if ( nPar <= 3 )
+ {
+ if ( !isEnd1 )
+ vertexLength = -vertexLength;
+ double tol = Min( Precision::Confusion(), 0.01 * vertexLength );
+ GCPnts_AbscissaPoint Discret( tol, theC3d, vertexLength, l );
+ if ( Discret.IsDone() ) {
+ if ( nPar == 0 )
+ theParameters.push_back( Discret.Parameter());
+ else {
+ double L = GCPnts_AbscissaPoint::Length( theC3d, theParameters.back(), l);
+ if ( vertexLength < L / 2.0 )
+ theParameters.push_back( Discret.Parameter());
+ else
+ compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
+ }
+ }
+ }
+ else
+ {
+ // recompute params between the last segment and a middle one.
+ // find size of a middle segment
+ smIdType nHalf = ( nPar-1 ) / 2;
+ list< double >::reverse_iterator itU = theParameters.rbegin();
+ std::advance( itU, nHalf );
+ double Um = *itU++;
+ double Lm = GCPnts_AbscissaPoint::Length( theC3d, Um, *itU);
+ double L = GCPnts_AbscissaPoint::Length( theC3d, *itU, l);
+ static StdMeshers_Regular_1D* auxAlgo = 0;
+ if ( !auxAlgo ) {
+ auxAlgo = new StdMeshers_Regular_1D( _gen->GetANewId(), _gen );
+ auxAlgo->_hypType = BEG_END_LENGTH;
+ }
+ auxAlgo->_value[ BEG_LENGTH_IND ] = Lm;
+ auxAlgo->_value[ END_LENGTH_IND ] = vertexLength;
+ double from = *itU, to = l;
+ if ( isEnd1 ) {
+ std::swap( from, to );
+ std::swap( auxAlgo->_value[ BEG_LENGTH_IND ], auxAlgo->_value[ END_LENGTH_IND ]);
+ }
+ list<double> params;
+ if ( auxAlgo->computeInternalParameters( theMesh, theC3d, L, from, to, params, false ))
+ {
+ if ( isEnd1 ) params.reverse();
+ while ( 1 + nHalf-- )
+ theParameters.pop_back();
+ theParameters.splice( theParameters.end(), params );
+ }
+ else
+ {
+ compensateError(0, vertexLength, f, l, theLength, theC3d, theParameters, true );
+ }
+ }
+ if ( isEnd1 )
+ theParameters.reverse();
+ }
+ }
+}
+
+bool StdMeshers_Regular_1D::computeBetaLaw(
+ Adaptor3d_Curve& theC3d,
+ std::list<double>& theParams,
+ double f,
+ double theLength,
+ double beta,
+ int nbSegments,
+ bool theReverse
+ )
+{
+ // Implemented with formula, where h is the position of a point on the segment [0,1]:
+ // ratio=(1+beta)/(beta -1)
+ // zlog=log(ratio)
+ // puiss=exp(zlog*(1-h))
+ // rapp=(1-puiss)/(1+puiss)
+ // f(h) =1+beta*rapp
+ //
+ // Look at https://gitlab.onelab.info/gmsh/gmsh/-/commit/d581b381f2b8639fba40f2e771e2573d1a0f8424
+ // Especially gmsh/src/mesh/meshGEdge.cpp, 507: createPoints()