// ■簡便法による3次スプライン曲線の描画 Coded by Yutaka Shirai. // // 詳しい式の説明については、拙著「ExcelとVBAによる実用数値解析入門」の // 「5.4 スプライン補間 (6)もうひとつの簡便法」を参照してください。 // // 【自然条件の場合の解くべき式】 // ┌ ┐┌  ┐ // │2σ0 σ0 0 0 …  …  …  0  ││ P0'  │ // │ σ1 2(σ0+σ1) σ0 0 …  …  …  0  ││ P1'  │ // │ 0 σ2 2(σ1+σ2) σ1 …  …  …  0  ││ P2'  │ // │ : :    :    : : : :   : ││ : │ // │ 0 0 …    …  … σ(n-2) 2(σ(n-3)+σ(n-2)) σ(n-3)││P(n-2)'│ // │ 0 0 …    …  … 0 σ(n-1) 2σ(n-1)││P(n-1)'│ // └ ┘└ ┘ // ┌ ┐ //  │3(P1-P0)  │ // │3{(P1-P0)(σ1/σ0)+(P2-P1)(σ0/σ1)} │ // = │3{(P2-P1)(σ2/σ1)+(P3-P2)(σ1/σ2)} │ // │ : :    :    : : … …  0  │ // │3{(P(n-2)-P(n-3))(σ(n-2)/σ(n-3)+(P(n-1)-P(n-2))(σ(n-3)/σ(n-2)} │ //  │3{(P(n-1)-P(n-2)) │ //  └ ┘ #include "myWin.h" #include "stdlib.h" static HDC hbuf; static HBITMAP hBM; //描画用ビットマップ double currentX, currentY;int Frag; //直線描画座標値(プログラムで設定される) //--------設定を変えるときは以下の変更してください--------------------------------------------- #define NUMDATA 4 //通過点座標の数 double pnt[NUMDATA][2]={{0,0}, {0,2}, {2,0}, {2,2}}; //通過点座標(X,Y)の順に並べる double Sgm[NUMDATA-1]={1,1,1}; //σ(k+1):点幅が極端に異なるときの調整用(通常1) double ds=0.05; //計算刻み幅 double P0d[2]={1,1}; //固定条件のときのP0' double Pnd[2]={1,1}; //固定条件のときのPn' int Cond=true; //固定条件のときtrue, 自然条件のときFalse //--------設定変更 ここまで--------------------------------------------------------------------- // ■P0,Pn 以外の 右辺の計算 double func(double P1,double P2, double P3,double sgm1, double sgm2){ return 3 * ((P2 - P1) * sgm2 / sgm1 + (P3 - P2) * sgm1 / sgm2); } // ■三重対角方程式の解法 void TriDiag(double A[][3], double D[], double X[], int N){ double CC[NUMDATA]; double btemp = A[0][1]; X[0] = D[0] / btemp; for(int j=1;j=0; j--) X[j] = X[j] - CC[j + 1] * X[j + 1]; } // ■固定条件(P0',Pn'を固定的に与える) void fixCondition(double A[][3], double sgm[], double Pd[][NUMDATA], double Dd[][NUMDATA], int N){ double Dtemp[NUMDATA], Ptemp[NUMDATA];//A[0][0], A[N-1][N-1]の値は意味がない。 A[0 ][1] = 2 * (sgm[0] + sgm[1]); A[0 ][2] = sgm[0]; A[N - 3][0] = sgm[N - 2] ; A[N - 3][1] = 2 * (sgm[N - 3] + sgm[N - 2]); for(int k=2;k