UNPKG

clay-core

Version:

Provide a more friendly web-side drawing interface!

79 lines (67 loc) 2.75 kB
/** * Cardinal三次插值 * ---------------------------- * Hermite拟合的计算是,确定二个点和二个点的斜率 * 用一个y=ax(3)+bx(2)+cx+d的三次多项式来求解 * 而Cardinal是建立在此基础上 * 给定需要拟合的二个点和第一个点的前一个点+最后一个点的后一个点 * 第一个点的斜率由第一个点的前一个点和第二个点的斜率确定 * 第二个点的斜率由第一个点和第二个点的后一个点的斜率确定 */ clay.cardinal = function () { var scope = { "t": 0 }; // 根据x值返回y值 var i; var cardinal = function (x) { if (scope.hs) { i = -1; // 寻找记录x实在位置的区间 // 这里就是寻找对应的拟合函数 while (i + 1 < scope.hs.x.length && (x > scope.hs.x[i + 1] || (i == -1 && x >= scope.hs.x[i + 1]))) { i += 1; } if (i == -1 || i >= scope.hs.h.length) throw new Error('Coordinate crossing!'); return scope.hs.h[i](x); } else { throw new Error('You shoud first set the position!'); } }; // 设置张弛系数【应该在点的位置设置前设置】 cardinal.setU = function (t) { if (_is_number(t)) { scope.t = t; } else { throw new Error('Expecting a figure!'); } return cardinal; }; // 设置点的位置 // 参数格式:[[x,y],[x,y],...] // 至少二个点 cardinal.setP = function (points) { scope.hs = { "x": [], "h": [] }; var flag, slope = (points[1][1] - points[0][1]) / (points[1][0] - points[0][0]), temp; scope.hs.x[0] = points[0][0]; for (flag = 1; flag < points.length; flag++) { if (points[flag][0] <= points[flag - 1][0]) throw new Error('The point position should be increamented!'); scope.hs.x[flag] = points[flag][0]; // 求点斜率 temp = flag < points.length - 1 ? (points[flag + 1][1] - points[flag - 1][1]) / (points[flag + 1][0] - points[flag - 1][0]) : (points[flag][1] - points[flag - 1][1]) / (points[flag][0] - points[flag - 1][0]); // 求解二个点直接的拟合方程 // 第一个点的前一个点直接取第一个点 // 最后一个点的后一个点直接取最后一个点 scope.hs.h[flag - 1] = clay.hermite().setU(scope.t).setP(points[flag - 1][0], points[flag - 1][1], points[flag][0], points[flag][1], slope, temp); slope = temp; } return cardinal; }; return cardinal; };