[Sie-announce] SIEコード [2003] getTotalLengthとgetPointAtLengthとgetPathSegAtLengthメソッドの実装

Zurück zum Archiv-Index

svnno****@sourc***** svnno****@sourc*****
2010年 9月 16日 (木) 23:17:29 JST


Revision: 2003
          http://sourceforge.jp/projects/sie/svn/view?view=rev&revision=2003
Author:   dhrname
Date:     2010-09-16 23:17:29 +0900 (Thu, 16 Sep 2010)

Log Message:
-----------
getTotalLengthとgetPointAtLengthとgetPathSegAtLengthメソッドの実装
set要素のイベントの修正

Modified Paths:
--------------
    branches/06x/061/org/w3c/dom/svg.js

Modified: branches/06x/061/org/w3c/dom/svg.js
===================================================================
--- branches/06x/061/org/w3c/dom/svg.js	2010-09-15 14:21:42 UTC (rev 2002)
+++ branches/06x/061/org/w3c/dom/svg.js	2010-09-16 14:17:29 UTC (rev 2003)
@@ -2500,10 +2500,9 @@
         dd += Math.sqrt(Math.pow((seg.x2-seg.x1), 2) + Math.pow((seg.y2-seg.y1), 2));
         dd += Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2));
         s += dd / 2;
-      } else if (seg.pathSegType === SVGPathSeg.MOVETO_ABS) {
-        ms = seg;
       } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CLOSEPATH) {
-        s += Math.sqrt(Math.pow((seg.x-ms.x), 2) + Math.pow((seg.y-ms.y), 2));
+        var ps = nl.getItem(i-1), ms = nl.getItem(0);
+        s += Math.sqrt(Math.pow((ps.x-ms.x), 2) + Math.pow((ps.y-ms.y), 2));
       }
 
     }
@@ -2511,14 +2510,52 @@
     return s;
   };
   /*SVGPoint*/      SVGPathElement.prototype.getPointAtLength = function(/*float*/ distance ) {
-    var seg = this.getPathSegAtLength(distance);
+    var segn = this.getPathSegAtLength(distance), x = 0, y = 0, nl = this.normalizedPathSegList, seg = nl.getItem(segn);
+    var s = this.ownerDocument.documentElement.createSVGPoint();
+    if ((segn-1) <= 0) {
+      s.x = seg.x;
+      s.y = seg.y;
+      return s;
+    }
+    var ps = nl.getItem(segn-1);
     if (seg.pathSegType === SVGPathSeg.PATHSEG_LINETO_ABS) {
+      var segl = Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2));
+      var t = (segl + this._dis) / segl;
+      s.x = ps.x + t * (seg.x-ps.x);
+      s.y = ps.y + t * (seg.y-ps.y);
     } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS) {
+      var dd = 0;
+      dd += Math.sqrt(Math.pow((seg.x1-ps.x), 2) + Math.pow((seg.y1-ps.y), 2));
+      dd += Math.sqrt(Math.pow((seg.x2-seg.x1), 2) + Math.pow((seg.y2-seg.y1), 2));
+      dd += Math.sqrt(Math.pow((seg.x2-seg.x1), 2) + Math.pow((seg.y2-seg.y1), 2));
+      dd += Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2));
+      var segl = dd / 2;
+      var t = (segl + this._dis) / segl;
+      /*以下はベジェ曲線の公式について、パラメータtによってまとめて整理したものを、
+       *使って、ポイントの座標を演算する
+       */
+      s.x = (3*seg.x1 + seg.x - 3*seg.x2 - ps.x) * Math.pow(t, 3)
+           +3*(ps.x - 2*seg.x1 + seg.x2) * Math.pow(t, 2)
+           +3*(seg.x1 - ps.x) * t
+           +ps.x;
+      s.y = (3*seg.y1 + seg.y - 3*seg.y2 - ps.y) * Math.pow(t, 3)
+           +3*(ps.y - 2*seg.y1 + seg.y2) * Math.pow(t, 2)
+           +3*(seg.y1 - ps.y) * t
+           +ps.y;
+    } else if (seg.pathSegType === SVGPathSeg.MOVETO_ABS) {
+      s.x = seg.x;
+      s.y = seg.y;
+    } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CLOSEPATH) {
+      var ms = nl.getItem(0), segl = Math.sqrt(Math.pow((seg.x-mx.x), 2) + Math.pow((seg.y-ms.y), 2));
+      var t = (segl + this._dis) / segl;
+      s.x = ms.x + t * (seg.x-ms.x);
+      s.y = ms.y + t * (seg.y-ms.y);
     }
+    return s;
   };
   /*unsigned long*/ SVGPathElement.prototype.getPathSegAtLength = function(/*float*/ distance ) {
-    var nl = this.normalizedPathSegList;
-    for (var i=1,nln=nl.numberOfItems,ms=null;i<nln;++i) {
+    var nl = this.normalizedPathSegList; //仕様ではpathSegList
+    for (var i=0,nln=nl.numberOfItems,ms=null;i<nln;++i) {
       var seg = nl.getItem(i);
       if (seg.pathSegType === SVGPathSeg.PATHSEG_LINETO_ABS) {
         var ps = nl.getItem(i-1);
@@ -2530,15 +2567,23 @@
         dd += Math.sqrt(Math.pow((seg.x2-seg.x1), 2) + Math.pow((seg.y2-seg.y1), 2));
         dd += Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2));
         distance -= dd / 2;
-      } else if (seg.pathSegType === SVGPathSeg.MOVETO_ABS) {
-        ms = seg;
+        dd = null;
       } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CLOSEPATH) {
-        distance -= Math.sqrt(Math.pow((seg.x-ms.x), 2) + Math.pow((seg.y-ms.y), 2));
+        var ps = nl.getItem(i-1), ms = nl.getItem(0);
+        distance -= Math.sqrt(Math.pow((ps.x-ms.x), 2) + Math.pow((ps.y-ms.y), 2));
       }
       if (distance <= 0) {
-        return seg;
+        /*_disプロパティは前述のgetPointAtLengthメソッドで使う*/
+        this._dis = distance;
+        distance = null;
+        return i;
       }
     }
+    /*もし、distanceがパスの距離よりも長い場合、
+     *最後のセグメントの番号を返す
+     *なお、これはSVG1.1の仕様の想定外のこと
+     */
+    return (nl.numberOfItems - 1);
   };
   /*SVGPathSegClosePath*/    SVGPathElement.prototype.createSVGPathSegClosePath = function() {
     var _SVGPathSegClosePath = SVGPathSegClosePath;
@@ -4240,7 +4285,7 @@
     } else {
       tar = this.targetElement;
     }
-    if (!offset) {
+    if (!offset && offset !== 0) {
       offset = NAIBU.Time.Max;
     }
     f(this, offset, tar, t);




Sie-announce メーリングリストの案内
Zurück zum Archiv-Index