SVG + ECMAScript(JavaScript) で遊んでみた

とりあえず,何とか収束するようになったので,アップしてみる.


多体問題で,バネ(ばね)運動をベースに差分化してみたら,なぜか発散してしまった.
で,摩擦係数みたいのを追加したら,収束したw

はっきりいって,式的にあっているか知らん.TouchGraph見たいなものを作りたかったから,
JavaScriptでもできそうだなと思って,やってみた.
はじめはただ単にJavaScriptでやろうとしたんだけど,HTMLじゃ線引けないジャン.

ってことで,急遽SVGでチャレンジ.
にしても,ECMAScriptというかJavaScriptというか,どんなプロパティとかメソッドとか
あるのかわかりにくくてやんなるね.見よう見まねで何とかかけたけどさ.

そろそろ,体系的に勉強する必要ありそう...


あ,ちなみに,このSVG
http://www.adobe.com/svg/viewer/install/main.html
から,プラグインを落として,ソースをhogehoge.svgとかいう名前で
保存してやって,開けばうまくいくはず.

ちなみに,Opera8 じゃ動かないもよう.OperaのサポートしているSVGじゃ動かないし,
プラグイン追加してみたけど,うんともすんとも言わん.ようわからん.
さらにFireFoxも,SVGを表示した後何かしようとすると毎回落ちる.これもようわからん.
さらにさらに,なぜかノートパソコンにAdobeプラグインをインストールすると,
毎回インストールに失敗しましたと出る.さっぱりわからん.

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20001102//EN"
  "http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd">

<svg>





<script type="text/ecmascript">
<![CDATA[
c01 = document.getElementById('c01');
c02 = document.getElementById('c02');
c03 = document.getElementById('c03');
c04 = document.getElementById('c04');
c05 = document.getElementById('c05');
dt  = 10;
obs = [c01, c02, c03, c04, c05];
bns = [ 
  [c01, c02, 2000, 200, 500],
  [c01, c03, 2000, 200, 500],
  [c02, c03, 2000, 200, 500],
  [c01, c04, 2000, 200, 500],
  [c02, c04, 2000, 200, 500],
  [c03, c04, 2000, 200, 500],
  [c01, c05, 2000, 200, 500],
//  [c02, c05, 2000, 200, 500],
  [c03, c05, 2000, 200, 500],
  [c04, c05, 2000, 200, 500],
];
m01 = document.getElementById('m01');
msg = document.getElementById('msg');

obj       = null;
offset_x  = 0;
offset_y  = 0;

function down(e) { 
  obj = e.target;
  offset_x = obj.getAttribute("cx") - evt.getClientX();
  offset_y = obj.getAttribute("cy") - evt.getClientY();
}
function up() {
  obj = null;
  reset();
}

function move(e) {
  if (!obj) return;
 obj.setAttribute("cx", evt.getClientX() + offset_x);
 obj.setAttribute("cy", evt.getClientY() + offset_y);

  for (i in bns) {
    line = document.getElementById(get_line_id(i));
    line.setAttribute("x1", bns[i][0].getAttribute("cx"));
    line.setAttribute("y1", bns[i][0].getAttribute("cy"));
    line.setAttribute("x2", bns[i][1].getAttribute("cx"));
    line.setAttribute("y2", bns[i][1].getAttribute("cy"));
  }
  return false;
}

function set_time_func() {
  setTimeout('time_event_func()', dt);
}

function time_event_func() {
  if (obj) return;
  do_motion();
  set_time_func();
}

function do_motion() {
  for (i in bns) {
    bane(bns[i]);
  }
  
  mx = my = mr = 0;
  for (i in obs) {
    x = obs[i].getAttribute("cx");
    y = obs[i].getAttribute("cy");
    r = obs[i].getAttribute("r");
    mx -= - r * x;
    my -= - r * y;
    mr -= - r;
  }
  m01.setAttribute("cx", mx / mr);
  m01.setAttribute("cy", my / mr);
  
  for (i in bns) {
    line = document.getElementById(get_line_id(i));
    line.setAttribute("x1", bns[i][0].getAttribute("cx"));
    line.setAttribute("y1", bns[i][0].getAttribute("cy"));
    line.setAttribute("x2", bns[i][1].getAttribute("cx"));
    line.setAttribute("y2", bns[i][1].getAttribute("cy"));
  }


}

function get_line_id(i) { return "line_id_" + i; }

function init() {
  svg = document.getElementsByTagName("svg");
  for (i in bns) {
    line = document.createElement("line");
    line.setAttribute("id", get_line_id(i));
    line.setAttribute("x1", 0);
    line.setAttribute("y1", 0);
    line.setAttribute("x2", 0);
    line.setAttribute("y2", 0);
    svg.item(0).appendChild(line);
  }


  reset();
}

function reset() {
  for (i in obs) init_p(obs[i]);
  set_time_func();
}
function init_p(e) {
  e.setAttribute("px", e.getAttribute("cx"));
  e.setAttribute("py", e.getAttribute("cy"));
}



function bane(param) {
  a   = param[0];
  b   = param[1];
  k   = param[2];
  l   = param[3];
  frc = param[4];
  
  xa0 = a.getAttribute("px");
  ya0 = a.getAttribute("py");
  xa1 = a.getAttribute("cx");
  ya1 = a.getAttribute("cy");
  ra  = a.getAttribute("r");
  
  xb0 = b.getAttribute("px");
  yb0 = b.getAttribute("py");
  xb1 = b.getAttribute("cx");
  yb1 = b.getAttribute("cy");
  rb  = b.getAttribute("r");
  
  dx0 = xa0 - xb0;
  dy0 = ya0 - yb0;
  dx1 = xa1 - xb1;
  dy1 = ya1 - yb1;
  dl0 = Math.sqrt(dx0 * dx0 + dy0 * dy0);
  dl1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
  r  = ra + rb;
  f0 = k   * (dl0 - l) * dt * dt / 1000000;
  f1 = frc * (dl1 - dl0)    * dt / 1000;
  
  xa2 = 2 * xa1 - xa0 - (rb / r) * ((dx0 / dl0) * f0 + f1 * dx1 / dl0) / ra;
  ya2 = 2 * ya1 - ya0 - (rb / r) * ((dy0 / dl0) * f0 + f1 * dy1 / dl0) / ra;
  xb2 = 2 * xb1 - xb0 + (ra / r) * ((dx0 / dl0) * f0 + f1 * dx1 / dl0) / rb;
  yb2 = 2 * yb1 - yb0 + (ra / r) * ((dy0 / dl0) * f0 + f1 * dy1 / dl0) / rb;
  
  a.setAttribute("cx", xa2);
  a.setAttribute("cy", ya2);
  b.setAttribute("cx", xb2);
  b.setAttribute("cy", yb2);
  
  a.setAttribute("px", xa1);
  a.setAttribute("py", ya1);
  b.setAttribute("px", xb1);
  b.setAttribute("py", yb1);
}


init();


]]>
</script>
  <text id="msg" x="10" y="30" font-size="18">msg</text>
  <circle id="c01" style="fill:white;stroke:black;" cx="200" cy="400" r="10"
    onmousedown="down(evt)" onmouseup="up()" onmousemove="move(evt)"/>
  <circle id="c02" style="fill:white;stroke:black;" cx="400" cy="400" r="15"
    onmousedown="down(evt)" onmouseup="up()" onmousemove="move(evt)"/>
  <circle id="c03" style="fill:white;stroke:black;" cx="400" cy="100" r="20"
    onmousedown="down(evt)" onmouseup="up()" onmousemove="move(evt)"/>
  <circle id="c04" style="fill:white;stroke:black;" cx="100" cy="400" r="17"
    onmousedown="down(evt)" onmouseup="up()" onmousemove="move(evt)"/>
  <circle id="c05" style="fill:white;stroke:black;" cx="240" cy="100" r="13"
    onmousedown="down(evt)" onmouseup="up()" onmousemove="move(evt)"/>
  <circle id="m01" style="fill:black;stroke:black;" cx="200" cy="100" r="1"/>

</svg>