OSDN Git Service

Lighten a spline mode
authordhrname <dhrname@users.sourceforge.jp>
Mon, 30 Mar 2015 12:05:22 +0000 (21:05 +0900)
committerdhrname <dhrname@users.sourceforge.jp>
Mon, 30 Mar 2015 12:05:22 +0000 (21:05 +0900)
org/w3c/dom/smil.js

index 9b62a7f..ef8781b 100644 (file)
@@ -587,19 +587,33 @@ base("$from").of( {
        return f;\r
      } else if (this.mode === "spline") {\r
        this.to.call();\r
-       var x = 0,\r
-           y = 0,\r
-           that = this,\r
-           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], 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
-           tk = this.keySplines;\r
-       return bezier(0, 0, tk[0], tk[1], tk[2], tk[3], 1, 1);\r
+       var tk = this.keySplines,\r
+           x2 = tk[0],\r
+           y2 = tk[1],\r
+           x3 = tk[2],\r
+           y3 = tk[3],\r
+           x4 = 1,\r
+           y4 = 1,\r
+           Ax = x4-3*(x3-x2),\r
+           Bx = 3*(x3-2*x2),\r
+           Cx = 3*x2,\r
+           Ay = (y4-3*(y3-y2)),\r
+           By = 3*(y3-2*y2),\r
+           Cy = 3*y2,\r
+           _newton = Math.qubicnewton; //高速化のためのエイリアス\r
+       tk = x2 = y2 = x3 = y3 = x4 = y4 = void 0;\r
+       return function (x) {\r
+          /*3次ベジェ曲線は媒介曲線\r
+           *x = (x4-3*(x3-x2)-x1)*t*t*t + 3*(x3-2*x2+x1)*t*t + 3*(x2-x1)*t + x1\r
+           *y = (y4-3*(y3-y2)-y1)*t*t*t + 3*(y3-2*y2+y1)*t*t + 3*(y2-y1)*t + y1\r
+           * ただし、0 <= t <= 1\r
+           * スプラインモードの場合、x1 = y1 = 0, x4 = y4 = 1\r
+           * ベジェ曲線のxの式が三次方程式であるため、その解 t から、ベジェ曲線の y を求める\r
+           * なお、ニュートン法の初期値はxとする\r
+           * なぜなら、xの式をみると、xが増加傾向となるスプラインモードでは、係数が負となる可能性が低いため*/\r
+          var t = _newton(Ax, Bx, Cx, -x, x);\r
+          return f(Ay*t*t*t + By*t*t + Cy*t);\r
+        };\r
      } else if (this.mode === "discrete") {\r
        return function (t) {\r
          return isNaN(t) ? this.string\r
@@ -609,28 +623,25 @@ base("$from").of( {
    }\r
 } ).to = base("$from").$to;\r
 \r
-/*ニュートン法により、三次方程式 a[0]x^3 + a[1]x^2 + a[2]x + a[3] の解を求める\r
+/*ニュートン法により、三次方程式 a0x^3 + a1x^2 + a2x + a3 の解を求める\r
  * 引数bは初期値*/\r
-Math.qubicnewton = function(a, b) {\r
-  var eps = 1e-10, //収束誤差\r
-      fb = f(b);\r
+Math.qubicnewton = function(a0, a1, a2, a3, b) {\r
+  var eps = 1e-10,                          //収束誤差\r
+      fb = a0 *b*b*b + a1 *b*b + a2*b + a3, //方程式の結果\r
+      _abs = Math.abs;                      //高速化のための関数のエイリアス\r
   if (fb === 0) {\r
     return b;\r
   }\r
   /*限界の収束回数は100回とする*/\r
   for (var i=0;i<100;++i) {\r
-    if (Math.abs(fb) < eps) {\r
+    if (_abs(fb) < eps) {\r
       return b;\r
     } else {\r
-      b =  b - fb / (3* a[0] *b*b + 2 * a[1] *b + a[2]);\r
-      fb = f(b);\r
+      b =  b - fb / (3* a0 *b*b + 2 * a1 *b + a2);\r
+      fb = a0 *b*b*b + a1 *b*b + a2*b + a3;\r
     }\r
   }\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
 \r
 /*立方根(3乗根)を求める。Math.powだと負の値に対応していないため\r