bezier = function (x1, y1, x2, y2, x3, y3, x4, y4) {\r
return function (x) {\r
/*三次方程式の解から、ベジェ曲線のyを求める*/\r
- var t = Math.qubicnewton([x4-3*(x3-x2)-x1, 3*(x3-2*x2+x1), 3*(x2-x1), x1-x]);\r
+ var t = Math.qubicnewton([x4-3*(x3-x2)-x1, 3*(x3-2*x2+x1), 3*(x2-x1), x1-x], x);\r
y = (y4-3*(y3-y2)-y1)*t*t*t + 3*(y3-2*y2+y1)*t*t + 3*(y2-y1)*t + y1;\r
return f(y);\r
};\r
}\r
} ).to = base("$from").$to;\r
\r
-/*ニュートン法により、三次方程式 a[0]x^3 + a[1]x^2 + a[2]x + a[3] の解を求める*/\r
-Math.qubicnewton = function(a) {\r
- var eps = 0.01, //収束誤差\r
- b = 1, //初期値\r
- newb = 0;\r
+/*ニュートン法により、三次方程式 a[0]x^3 + a[1]x^2 + a[2]x + a[3] の解を求める\r
+ * 引数bは初期値*/\r
+Math.qubicnewton = function(a, b) {\r
+ var eps = 1e-10, //収束誤差\r
+ fb = f(b);\r
+ if (fb === 0) {\r
+ return b;\r
+ }\r
/*限界の収束回数は100回とする*/\r
for (var i=0;i<100;++i) {\r
- newb = b - f(b) / df(b);\r
- if (Math.abs(b - newb) < eps) {\r
- console.log(newb);\r
- return newb;\r
+ if (Math.abs(fb) < eps) {\r
+ return b;\r
} else {\r
- b = newb;\r
+ b = b - fb / (3* a[0] *b*b + 2 * a[1] *b + a[2]);\r
+ fb = f(b);\r
}\r
}\r
- return 0; //収束しなかった結果\r
+ return b; //収束しなかった結果\r
/*与えられた三次方程式*/\r
function f(x) {\r
return a[0] *x*x*x + a[1] *x*x + a[2]*x + a[3];\r
};\r
- /*与えられた三次方程式を微分したもの*/\r
- function df(x) {\r
- return 3* a[0] *x*x + 2 * a[1] *x + a[2];\r
- }\r
};\r
\r
/*立方根(3乗根)を求める。Math.powだと負の値に対応していないため\r
calc.keySplines = k;\r
calc.to.degit = 10;\r
var b = bezier(0,0, k[0],k[1], k[2],k[3], 1,1),\r
- epsiron = 1e-10; //誤差\r
+ epsiron = 1e-6; //誤差\r
expect(calc.call()(0)).toBe(b(0).y.toFixed(10));\r
calc.to.from = from;\r
expect(calc.call()(1)).toBe(b(1).y.toFixed(10));\r