スプライン その 5


https://ja.wikipedia.org/wiki/B-スプライン曲線 より

B-spline : Basis spline

t ノット m 個の実数

bi,n : B-スプライン基底関数(B-spline basis function)(買った本では,Si,n Ni,d)

  bj,0(t) 	階数(order)が 1 の時,
	t の範囲により,1 または 0 .
  bj,n(t) 
	(t-tj)/(t(j+n)-tj)*(bj,n-1)(t) + (t(j+n+1)-t)/(t(j+n+1)-t(j+1))*(b(j+1,n-1))(t)
  Kodatuno の NURBS_Func.cpp NURBS_Func::CalcBSbasis がこれにあたる.

    n == 3	制御点は 4
	bezier
		double	t  = 1./div_c*index ;
		double	b0 = (1.-t)*(1.-t)*(1.-t) ;	//	(1-t)^3
		double	b1 = 3.*t  *(1.-t)*(1.-t) ;	//	3 * (1-t)^2 * t
		double	b2 = 3.*(1.-t)*t*t ;		//	3 * (1-t) * t^2
		double	b3 = t*t*t ;			//	t^3
		double	px = (b0*q0.x) + (b1*q1.x) + (b2*q2.x) + (b3*q3.x) ;
		double	py = (b0*q0.y) + (b1*q1.y) + (b2*q2.y) + (b3*q3.y) ;
		double	pz = (b0*q0.z) + (b1*q1.z) + (b2*q2.z) + (b3*q3.z) ;
	b_spline
		double	t  = 1./div_c*index ;
		double	n0 = 1./6 * (1.-t)*(1.-t)*(1.-t) ;
		double	n1 = 1./2 * t*t*t - t*t + 2./3 ;
		double	n2 =-1./2 * t*t*t + 1./2 * t*t + 1./2 *t + 1./6 ;
		double	n3 = 1./6 * t*t*t ;
		double	px = (b0*q0.x) + (b1*q1.x) + (b2*q2.x) + (b3*q3.x) ;
		double	py = (b0*q0.y) + (b1*q1.y) + (b2*q2.y) + (b3*q3.y) ;
		double	pz = (b0*q0.z) + (b1*q1.z) + (b2*q2.z) + (b3*q3.z) ;

    n == 2
	bezier
		(1-t)^2
		2 * t * (1-t)
		t^2
	b_spline
		1/2 * (   t*t - 2*t + 1)
		1/2 * (-2*t*t + 2*t + 1)
		1/2 * t*t ;

  数学入門 P.163 コックス ド ブールのアルゴリズム

  コードのサンプルは,次の所にあったがよくわからず.
      https://en.wikipedia.org/wiki/De_Boor's_algorithm


IGES_Parser.cpp K , M の数は IGES の値に対して +1 している. N は K + M (IGES の値に対しては K+M+2). IGES_PARSER::GetNurbsCPara body.NurbsC[TypeCount[_NURBSC]].K = CatchStringI(&p) + 1; // 総和記号の上側添字(コントロールポイント-1)の値 body.NurbsC[TypeCount[_NURBSC]].M = CatchStringI(&p) + 1; // 基底関数の階数 body.NurbsC[TypeCount[_NURBSC]].N = body.NurbsC[TypeCount[_NURBSC]].K + body.NurbsC[TypeCount[_NURBSC]].M; // ノットベクトルの数 IGES_PARSER::GetNurbsSPara body.NurbsS[TypeCount[_NURBSS]].K[0] = CatchStringI(&p) + 1; // u方向コントロールポイントの数 body.NurbsS[TypeCount[_NURBSS]].K[1] = CatchStringI(&p) + 1; // v方向コントロールポイントの数 body.NurbsS[TypeCount[_NURBSS]].M[0] = CatchStringI(&p) + 1; // 基底関数のu方向階数 body.NurbsS[TypeCount[_NURBSS]].M[1] = CatchStringI(&p) + 1; // 基底関数のv方向階数 body.NurbsS[TypeCount[_NURBSS]].N[0] = body.NurbsS[TypeCount[_NURBSS]].K[0] + body.NurbsS[TypeCount[_NURBSS]].M[0]; // u方向ノットベクトルの数 body.NurbsS[TypeCount[_NURBSS]].N[1] = body.NurbsS[TypeCount[_NURBSS]].K[1] + body.NurbsS[TypeCount[_NURBSS]].M[1]; // v方向ノットベクトルの数 S , T は N 個. W , cp は K 個. ノットベクトル T コンピュータグラフィックス P.31 より k+1 個の制御点をもつ n 次 B スプライン曲線の場合には,以下に示すような (n+k+2) 個の要素からなるベクトルとなる. T = [t0 , t1, ... t(n+k+1)] ( ti≦t(i+1) )
// Function: CalcBSbasis // Bスプライン基底関数を計算し、計算結果を返す // // Parameters: // t - ノット  // knot[] - ノットベクトル // N - ノットベクトルの数 // I - Bspl基底関数下添字の1つ目(0~) // M - 階数(Bspl基底関数下添字の2つ目) // // Return: // 計算結果 double NURBS_Func::CalcBSbasis(double t, double knot[],int N,int I,int M) { // 階数(order)が1の時 if(M == 1){ // 注目中のノットの値がノットベクトルの終端値と同じ場合、基底関数が1を取りうる範囲をknot[I+1]も含むようにする // こうしないと、このときだけ全ての基底関数値が0になってしまう。 if(t==knot[N-1]){ if(knot[I] <= t && t <= knot[I+1]) { return 1.0; } else { return 0.0; } } else{ if(knot[I] <= t && t < knot[I+1]) { return 1.0; } else { return 0.0; } } } // それ以外の時 else{ double n1=0.0; double n2=0.0; double denom; denom = knot[I+M-1] - knot[I]; // 分母 if(denom > 0.0){ n1 = (t-knot[I])/denom * CalcBSbasis(t,knot,N,I,M-1); // 1項目 } denom = knot[I+M] - knot[I+1]; if(denom > 0.0){ n2 = (knot[I+M]-t)/denom * CalcBSbasis(t,knot,N,I+1,M-1); // 2項目 } return(n1+n2); } }
参考にさせてもらった所
  http://www-mm.hm.t.kanazawa-u.ac.jp/research/kodatuno/
  http://ibiblio.org/e-notes/Splines/b-spline.js
  https://ci.nii.ac.jp/els/contentscinii_20171206193127.pdf?id=ART0009956858