球面上にN個の点を均等に配置したい。その4

N個の数を数えてみたら、N個ではなかった。それを修正する。
黄金比を半分にし、点の間隔を2倍にした。
地球でいえば、南極点が出ないようにループの条件を変える。
将来的に速度を要求するので、それを優先して球体の点を生成するコードを書き直した。(結果から言えば、正確ではない。しかしここで妥協して次に進む)
これ以上の速度は期待できまい!
あんなに苦労したのに、コードに直すとたかだ数行ですむのね。
座標変換は、そもそもこれではダメだ。


追記
もしかして、これは3D花火に応用出来そうだ。
全方向へ均等に爆発させる。夏になるころに考えよう。


canvas を消すのではなく、alpha値を加え、薄く消していく。
これは、しだれ柳の花火に使えそう。

<!DOCTYPE html>
  <meta charset="UTF-8">
  <title>test</title>
  <style>
body,
canvas { background : black; }

  </style>
<body>
<canvas width="1024" height="1024"></canvas>
<script>

function createSpherePoint (n /* 球体の点の数 */, r /*球体の半径*/) {
  if (arguments.length < 2 || n < 1)
    throw new Error;
  
  var A = Math.asin;
  var C = Math.cos;
  var S = Math.sin;
  var G = (Math.sqrt (5) + 1) / 4;
  var B = n + 0.5;
  var D = Math.PI * 2 * (G - 1);
  var F; // = フィナボッチ数
  var R = [ ];
  
  for (var a = 0, b = 1, c = n, d; --c; )
    d = b, F = b += a, a = d;

  for (var a, b, c, d = -n, e = 0; d < n; d += 2)
    R[e++] = [ (b = C (a = A (d / B)) * r) * C (c = D * d), b * S (c) , S (a) * r ];
  
  return R;
}



function draw (a, b) {
  var A = 0, B = 0;
  var ctx = a.getContext ('2d');
  var x = 512;
  var y = 512;
  var w = +a.width;
  var h = +a.height;
  var DEG = Math.PI / 180;
  var z = 300;

  return function () {
    ctx.fillStyle = 'RGBA(0,0,0,.25)';
    ctx.fillRect (0,0, w,h);

    for (var i = 0; i < b.length; i++) {
      var px = b[i][0];
      var py = b[i][1];
      var pz = b[i][2];
      
      var deg0 = A * DEG;
      var deg1 = B * DEG;
      var sin = Math.sin (deg0);
      var cos = Math.cos (deg0);
      var sin2 = Math.sin (deg1);
      var cos2 = Math.cos (deg1);
      
      var tx = px * cos + pz * sin;
      var ty = py;
      var tz = px * sin - pz * cos;
      
      px = tx * cos2 + ty * sin2;
      py = tx * sin2 - ty * cos2;
      
      var zz = ( z + tz) / z;
      var sz = 5 * zz;
      
      ctx.fillStyle = '#c40';
      ctx.fillRect (x + px * zz, y - py * zz, sz, sz);
    }
    A += 1.5;
    B += 0.1;
  };
}


setInterval (draw (
  document.querySelector ('canvas'),
  createSpherePoint (100, 200)
), 33);

</script>