[Sie-announce] SIEコード [2002] getTotalLengthメソッドなどの実装開始

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2010年 9月 15日 (水) 23:21:42 JST


Revision: 2002
          http://sourceforge.jp/projects/sie/svn/view?view=rev&revision=2002
Author:   dhrname
Date:     2010-09-15 23:21:42 +0900 (Wed, 15 Sep 2010)

Log Message:
-----------
getTotalLengthメソッドなどの実装開始

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-13 14:13:29 UTC (rev 2001)
+++ branches/06x/061/org/w3c/dom/svg.js	2010-09-15 14:21:42 UTC (rev 2002)
@@ -2480,16 +2480,65 @@
 SVGPathElement.constructor = SVGElement;
 SVGPathElement.prototype = new SVGElement();
   /*float*/         SVGPathElement.prototype.getTotalLength = function() {
-    /*曲線の長さを積分を用いて出力
-     *
-     */
-    return (this.pathLength.baseVal.value);
+    var s = 0, nl = this.normalizedPathSegList;
+    for (var i=1,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);
+        s += Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2));
+      } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS) {
+        var ps = nl.getItem(i-1), dd = 0;
+        /*2点のハンドルを結んだ線分の3辺と、
+         *セグメントの始点と終点を結んだ1辺を足して2で割ったものを、ベジェ曲線の距離の近似値とする
+         *
+         *注意
+         *本来は積分とシンプソン法などの解析を使って、媒介曲線であるベジェ曲線の距離を割り出すのが、
+         *精密であり望ましいが、ここでは時間がかかりすぎるので別の方法をとる
+         */
+        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));
+        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));
+      }
+
+    }
+    this.pathLength.baseVal = s;
+    return s;
   };
   /*SVGPoint*/      SVGPathElement.prototype.getPointAtLength = function(/*float*/ distance ) {
-    
+    var seg = this.getPathSegAtLength(distance);
+    if (seg.pathSegType === SVGPathSeg.PATHSEG_LINETO_ABS) {
+    } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS) {
+    }
   };
   /*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 seg = nl.getItem(i);
+      if (seg.pathSegType === SVGPathSeg.PATHSEG_LINETO_ABS) {
+        var ps = nl.getItem(i-1);
+        distance -= Math.sqrt(Math.pow((seg.x-ps.x), 2) + Math.pow((seg.y-ps.y), 2));
+      } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS) {
+        var ps = nl.getItem(i-1), 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));
+        distance -= dd / 2;
+      } else if (seg.pathSegType === SVGPathSeg.MOVETO_ABS) {
+        ms = seg;
+      } else if (seg.pathSegType === SVGPathSeg.PATHSEG_CLOSEPATH) {
+        distance -= Math.sqrt(Math.pow((seg.x-ms.x), 2) + Math.pow((seg.y-ms.y), 2));
+      }
+      if (distance <= 0) {
+        return seg;
+      }
+    }
   };
   /*SVGPathSegClosePath*/    SVGPathElement.prototype.createSVGPathSegClosePath = function() {
     var _SVGPathSegClosePath = SVGPathSegClosePath;
@@ -4344,8 +4393,23 @@
 function SVGAnimateMotionElement(){
   SVGAnimationElement.apply(this);
   NAIBU.Clip[NAIBU.Clip.length] = this;
+  this.addEventListener("DOMAttrModified", function(evt){
+    if (evt.eventPhase === Event.BUBBLING_PHASE) {
+      return;
+    }
+    var tar = evt.target, name = evt.attrName;
+    if (name === "path") {
+      var d = tar.ownerDocument.createElementNS("http://www.w3.org/2000/svg", "path");
+      d.setAttributeNS(null, evt.newValue);
+      tar._path = d;
+      d = null;
+    }
+  }, false);
   this.addEventListener("beginEvent", function(evt) {
     var tar = evt.target;
+    tar._frame = function() {
+      var _tar = tar, tpn = _tar._path.normalizedPathSegList;
+    }
   }, false);
   this.addEventListener("endEvent", function(evt) {
     var tar = evt.target;




Sie-announce メーリングリストの案内
Back to archive index