From 09629ecde840e69c5ebe94b5c59a3cacc83b4964 Mon Sep 17 00:00:00 2001 From: dhrname Date: Mon, 30 Mar 2015 20:08:07 +0900 Subject: [PATCH] Modify a Math.qubicnewton function --- org/w3c/dom/smil.js | 30 ++++++++++++++---------------- tool/Spec/spec/SvgDomSpec.js | 2 +- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/org/w3c/dom/smil.js b/org/w3c/dom/smil.js index a8ac53c..9b62a7f 100644 --- a/org/w3c/dom/smil.js +++ b/org/w3c/dom/smil.js @@ -593,7 +593,7 @@ base("$from").of( { bezier = function (x1, y1, x2, y2, x3, y3, x4, y4) { return function (x) { /*三次方程式の解から、ベジェ曲線のyを求める*/ - var t = Math.qubicnewton([x4-3*(x3-x2)-x1, 3*(x3-2*x2+x1), 3*(x2-x1), x1-x]); + var t = Math.qubicnewton([x4-3*(x3-x2)-x1, 3*(x3-2*x2+x1), 3*(x2-x1), x1-x], x); y = (y4-3*(y3-y2)-y1)*t*t*t + 3*(y3-2*y2+y1)*t*t + 3*(y2-y1)*t + y1; return f(y); }; @@ -609,30 +609,28 @@ base("$from").of( { } } ).to = base("$from").$to; -/*ニュートン法により、三次方程式 a[0]x^3 + a[1]x^2 + a[2]x + a[3] の解を求める*/ -Math.qubicnewton = function(a) { - var eps = 0.01, //収束誤差 - b = 1, //初期値 - newb = 0; +/*ニュートン法により、三次方程式 a[0]x^3 + a[1]x^2 + a[2]x + a[3] の解を求める + * 引数bは初期値*/ +Math.qubicnewton = function(a, b) { + var eps = 1e-10, //収束誤差 + fb = f(b); + if (fb === 0) { + return b; + } /*限界の収束回数は100回とする*/ for (var i=0;i<100;++i) { - newb = b - f(b) / df(b); - if (Math.abs(b - newb) < eps) { - console.log(newb); - return newb; + if (Math.abs(fb) < eps) { + return b; } else { - b = newb; + b = b - fb / (3* a[0] *b*b + 2 * a[1] *b + a[2]); + fb = f(b); } } - return 0; //収束しなかった結果 + return b; //収束しなかった結果 /*与えられた三次方程式*/ function f(x) { return a[0] *x*x*x + a[1] *x*x + a[2]*x + a[3]; }; - /*与えられた三次方程式を微分したもの*/ - function df(x) { - return 3* a[0] *x*x + 2 * a[1] *x + a[2]; - } }; /*立方根(3乗根)を求める。Math.powだと負の値に対応していないため diff --git a/tool/Spec/spec/SvgDomSpec.js b/tool/Spec/spec/SvgDomSpec.js index 1a11bee..13ffcce 100644 --- a/tool/Spec/spec/SvgDomSpec.js +++ b/tool/Spec/spec/SvgDomSpec.js @@ -3267,7 +3267,7 @@ describe("SMIL Animation Spec", function() { calc.keySplines = k; calc.to.degit = 10; var b = bezier(0,0, k[0],k[1], k[2],k[3], 1,1), - epsiron = 1e-10; //誤差 + epsiron = 1e-6; //誤差 expect(calc.call()(0)).toBe(b(0).y.toFixed(10)); calc.to.from = from; expect(calc.call()(1)).toBe(b(1).y.toFixed(10)); -- 2.11.0