module yamalib.math.spline;

private import y4d_draw.drawbase;
private import std.math;

private import yamalib.log.log;

/**
	B-スプラインクラス
*/
class BSpline {
	
    /**
     * 	B-スプライン曲線を算出します
     */
    static Point[] calcBSpline(inout PointInt[]  sample, uint divCnt) {
        double t, r;
        Point[] pts;
        int[] nv;
        double div = cast(double) divCnt;
        
        // 単純基底関数生成
        for (int i = 0; i < sample.length + 3; ++i) {
        	nv ~= i;
        }

        for (int i = 0; i < sample.length * div; ++i) {
            Point pt;

            t = i / div;

//            if (i == this.tmax * 10) {
//               //t>=tmax では基底関数は0になる
//  			t -= 0.001;
//          }

            for (int j = 0; j < sample.length; ++j) {
                r = baseN(j, 3, t, nv);
                pt.x += cast(double) (sample[j].x) * r;
                pt.y += cast(double) (sample[j].y) * r;
            }
            
            pts ~= pt;
        }
        
        return cleanUp(pts, divCnt);
    }

	
private:

	static Point[] cleanUp(inout Point[] pts, uint div) {
		if ( pts.length <= (div*2) || 0 > pts.length-(div*2) ) return null;
		if ( (div*2) > pts.length-(div*2) ) return null;
		return pts[ (div*2) .. length-(div*2) ];
	}

    static double baseN(int i, int k, double t, inout int[] nv) {
        double w1 = 0.0f;
        double w2 = 0.0f;

        if (k == 1) {
            if (t >= nv[i] && t < nv[i + 1]) {
                return 1.0;
            }
            return 0.0;
        }

//		Log.print(" i + k = %d, i + 1 = %d", i + k, i + 1);

        if ((nv[i + k] - nv[i + 1]) != 0) {
            w1 = ((nv[i + k] - t) / (nv[i + k] - nv[i + 1]))
                    * baseN(i + 1, k - 1, t, nv);
        }

        if ((nv[i + k - 1] - nv[i]) != 0) {
            w2 = ((t - nv[i]) / (nv[i + k - 1] - nv[i])) * baseN(i, k - 1, t, nv);
        }

        return (w1 + w2);
    }
    
    /// 2点間の距離を返す
    static double dist(double x1, double y1, double x2, double y2) {
        return .sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    static const int LC_TMAX_1 = 8;
    

}