• ベストアンサー

canvasで完全二分木を描画したいのですが

JavaScriptのcanvasを使って、画像の様な完全二分木を描画したいです。 木の深さをrとし、rは任意で変更できるようにしたいと考えています。 canvasのサイズは1000x1000程度で、r=4くらいまで対応できるものであれば幸いです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

//その2: ほぼここからは、やっつけで書いたので綺麗ではありません。                    var tree = NTree.create (5); //ここを弄る! NTree.create (4,3) とかでもおもしろい?        tree.setAutoNumber (tree.seed, 1);                           (function (tree) {          var canvas = document.querySelector ('canvas');          var ctx = canvas.getContext('2d');          var r = 10;          var mx = canvas.width;          var my = canvas.height;          var stepY = tree.getMaxDepth () + 1;         var nd = tree.getAllNodes ();         var i, j, cx, cy, d, row, n, s, c;        var gnd = [ ];              for (i = 0; n = nd[i]; i += 1) {      d = tree.getDepth (n);     if ('undefined' === typeof gnd[d])    gnd[d] = [ ];    gnd[d].push (n);   }   for (i = 0; row = gnd[i]; i += 1) { cy = my / stepY * i + r; for (j = 0; n = row[j]; j += 1) { cx = mx / (row.length) / 2 + (mx / row.length * j); n.x = cx; n.y = cy; } } ctx.textAlign = "center"; ctx.textBaseline ="middle";  ctx.font = Math.floor (r * 1.4) +"px 'Times New Roman'";      for (i = 0; n = nd[i]; i += 1) {    cx = n.x;     cy = n.y;      for (j = 0; c = n.child[j]; j += 1) {       ctx.beginPath ();        ctx.moveTo (cx, cy);        ctx.lineTo (c.x, c.y)         ctx.stroke ();         }          ctx.beginPath ();          ctx.strokeStyle = 'rgb(0,0,0)';          ctx.fillStyle = 'rgb(255, 255, 255)';          ctx.arc (cx, cy, r, 0, Math.PI*2);          ctx.fill ();          ctx.fillStyle = 'rgb(0, 0,0)';          ctx.fillText(n.number + '', cx, cy + r/ 8);         ctx.stroke ();         }                }) (tree);            </script>     

その他の回答 (1)

回答No.1

あけおめことよろ。 無駄に長いので分割しました。 全角空白は半角に置換してください。 <!DOCTYPE html> <meta charset="utf-8"> <title>n木分</title> </head> <body>  <canvas width="1000" height="300"></canvas>      <script>               (function () {              function Node (parent) {        this.parent = parent;         this.child = new Array ();         }                   //_________                              function NTree (seed) {          this.seed = seed;          }                         function grow (n) {        var seed = this.seed;       var buf = find (seed, []);      var ary = [ ], i, c, j;         if (0 === buf.length)    buf = [seed];    for (i = 0; c = buf[i]; i += 1) for (j = 0; j < n; j += 1) c.child[j] = new Node (c); } function firstNode (n) { return n.child[0] ? n.child[0]: null; } function nextSibling (n) {  var p = n.parent, no;   var c = p.child;       if (p)     if (no = c.indexOf (n) + 1)      if (no < c.length)       return c[no];               return null;         }                            function getAllNodes (node) {          if (1 > arguments.length)          node = this.seed;                    var rst = [ ];          var n, b = node;                  B:        while (n = b)        if (! (rst.push (n), b = firstNode (n)))       while (! (b = nextSibling (n)))      if (node === (n = n.parent))     break B;        return rst;   }   function maxDepth (mx, n) { return Math.max (this.getDepth (n), mx); } function getMaxDepth (node) { if (1 > arguments.length) node = this.seed; return getAllNodes.call (this).reduce (maxDepth.bind (this), 0);  }         function getDepth (node) {     var cnt = 0;      var p = node;              while (p = p.parent)        cnt += 1;                 return cnt;          }                              function setNumber (nd, i) {          nd.number = this + i;          }                           function setAutoNumber (node, no) {        switch (arguments.length) {        case 0 :       node = this.seed;      case 1 :     no = 0;    }      var nd = getAllNodes.call (this, node);  var gd = [ ], d, i, n; for (i = 0; n = nd[i]; i += 1) { d = this.getDepth (n); if ('undefined' === typeof gd[d]) gd[d] = [ ]; gd[d].push (n); } Array.prototype.concat.apply ([], gd) .forEach (setNumber, no); }           function find (node, buf) {     var child = node.child;             for (var i = 0, c; c = child[i]; i += 1)        hasChildNodes (c)        ? find (c, buf)         : buf.push (c);                   return buf;          }                              function hasChildNodes (node) {          return !! node.child.length;          }                         function create (depth, n) {        if (2 > arguments.length)       n = 2;           var seed = new Node (null);    var tree = new NTree (seed);    var i;    for (i = 0; i < depth; i += 1) tree.grow (n); return tree; } NTree.prototype.grow = grow; NTree.prototype.getAllNodes = getAllNodes; NTree.prototype.getMaxDepth = getMaxDepth; NTree.prototype.getDepth = getDepth; NTree.prototype.setAutoNumber = setAutoNumber;     NTree.create = create;       this.NTree = NTree;     }) ();

関連するQ&A

  • 描画するときの画像の色を変えたい

    こんにちは。 html5でcanvasに画像を描画しているのですが、この時に画像の色調を変える方法はありますでしょうか? 画像はアルファ付きのpngで、周囲が透明の白い図形です。 この図形を例えば青っぽく描画したり、赤っぽく描画したりしたいのですが、javascriptで可能でしょうか?

  • ROP2での描画について

    WinAPI(C言語)でペイントのようなアプリを作成しているのですが、 例えば、写真のような画像の上に任意の色で塗りつぶした四角形を描画し、 それを元の画像に戻す場合は、SetROP2関数は使用できないのでしょうか? 当初R2_NOTを指定すればいいと思っていたのですが、 これはR2_NOTで描画した画像の上にR2_NOTで描画すれば以前の画像に戻りますが、 白や黒の任意のブラシで塗りつぶした場合にそれを元の画像に戻す方法はありますか? ご教示願います。

  • photoshopのキャンバスサイズについて

    wondowsXP PhotoShopCS3を使用しています。 画像を切り抜いた後、キャンバスの大きさを切り抜いた画像の大きさにフィットさせるような機能はないのでしょうか? Fireworksだと、「キャンバスにフィット」というような機能があったと思うのですが。。。 また、そうした機能が無かった場合、どのようにして、画像の大きさにキャンバスサイズを合わせるのでしょうか? 画像解像度を変更して、キャンバスサイズを変えるのは存じているのですが、コレだと画像まで拡大縮小されてしまいます。 初歩てきな質問で恐縮ですが、ご教授の程よろしくお願いいたします。

  • canvas を android で見ると...?

    スマートフォンを持っていない者です... ある小さな雑貨店の簡単なウェブサイトを作りたいのですが、 簡単なグラフを表示するためcanvasを用いたjavascriptを呼ぶhtmlを試作しました。 このhtmlをPCのブラウザ(Firefox)で見るとちゃんと表示されますが、 はたしてこれはandroidスマートフォンでも表示されるのだろうかと考えると、 いくつか疑問点がでてきました。 androidスマートフォンに関して基本的なことを知らないのですが、 ご教授いただければありがたいです。 1) URLについて PCで見るURL(例えば http://oshiete.goo.ne.jp/)は、androidスマートフォンでもそのまま閲覧できるのでしょうか。 2) javascriptのcanvasについて androidスマートフォンのブラウザはcanvasに対応していますか? 3) 画面サイズについて いろいろな機種が出ていますが、androidスマートフォン用のウェブサイトのhtmlを書くとすると、 画面サイズはどのくらいだとして設計するとよいのでしょうか。 とんちんかんな質問をしていたらすみません。 よろしくお願いします。

  • フォトショップエレメンツのカンバスサイズについて

    フォトショップエレメンツで画像を開いて イメージメニュー→サイズ変更→カンバスサイズ を開くと現在のファイルサイズが1.37Mと表示されます。もとの画像は200KB程度なのに、です。これはなぜなのでしょうか?どんな意味があるのでしょう?詳しい方どうぞ回答よろしくお願い致します。

  • キャンバスサイズ変更可能な廉価なソフト

    PhotoShopとPaintShopを使っています。キャンバスサイズ変更は、PaintShopがやりやすいと思っています。 画像ソフトはレイヤーの貼り付けとキャンバスサイズを大きくした際に背景色を指定して枠を付けることを良く使いますが、その他の効果の機能など殆ど使いません。PCを多く用意する際に、PhotoShopなどの高額商品を購入するのではなく、必要な機能を含む廉価なソフトがあればと思っています。 そこで、キャンバスサイズ変更可能な廉価なソフトでお勧めのものを教えてください。 よろしくお願いします。

  • drawImageの描画順序の指定について

    いつもお世話になっております。 drawImageメソッドを使用し、Canvasへ画像を描画するプログラムを作成しています。 画像は全部3枚あり、座標をずらしてすべて重ねて表示します。 画像のファイルサイズはすべて異なります。 画像描画のタイミングは選択中のセレクトボックスの項目に変更があった場合です。 この際、フォームの情報によって描画順序を決定します。 本題ですが、現在のコーディングですと、指定した描画順序のとおりに描画されません。 複数の画像に対してonloadを使用しており、画像の読み込みが完了した順番に描画 されているような気がします。指定したとおりに描画できる方法はないでしょうか? ・html <canvas id=main width=160 height=160 style=border:1px solid gray></canvas> <form> <hr> 描画順序 <select name=order onChange=Main(this.form)> <option value=0>1,2,3</p> <option value=1>1,3,2</p> <option value=2>2,1,3</p> <option value=3>2,3,1</p> <option value=4>3,1,2</p> <option value=5>3,2,1</p> </select> </form> ・外部ファイル(js) function Main(f) { var canvas = document.getElementById('main'); if (!canvas || !canvas.getContext) { return false; } var Canvas = canvas.getContext('2d'); Canvas.clearRect(0, 0, 320, 240); var Image1 = new Image(); var Image2 = new Image(); var Image3 = new Image(); if (f.order.value == 0) { Image1.onload = function() { Canvas.drawImage(Image1, 0, 0); } Image2.onload = function() { Canvas.drawImage(Image2, 20, 20); } Image3.onload = function() { Canvas.drawImage(Image3, 40, 40); } Image1.src = GetImageFileName(1); Image2.src = GetImageFileName(2); Image3.src = GetImageFileName(3); } else if (f.order.value == 1) { Image1.onload = function() { Canvas.drawImage(Image1, 0, 0); } Image3.onload = function() { Canvas.drawImage(Image3, 20, 20); } Image2.onload = function() { Canvas.drawImage(Image2, 40, 40); } Image1.src = GetImageFileName(1); Image3.src = GetImageFileName(3); Image2.src = GetImageFileName(2); } else if (f.order.value == 2) { Image2.onload = function() { Canvas.drawImage(Image2, 0, 0); } Image1.onload = function() { Canvas.drawImage(Image1, 20, 20); } Image3.onload = function() { Canvas.drawImage(Image3, 40, 40); } Image2.src = GetImageFileName(2); Image3.src = GetImageFileName(3); :(以降省略) よろしくお願いいたします。

  • 「ラバーバンド」について

    Javascript/HTML5でマウスの動作を追跡する「ラバーバンド」をしたいのですが。 可能でしょうか、教えていただけないでしょうか。 Canvas上に描画した矩形を選択しその矩形のサイズをラバーバンドを使用しながら 変更させたいため。 よろしくお願いします。

  • 画像の描画順を操作するようなことはできますか?

    こんにちは。Webアプリを開発させられています。適当にASPでだましだましやってきましたが、クライアントサイドでの処理についての要求が多く、やむなくJavaScriptを勉強することになりました。 もともと、Web開発なんて念頭にしていませんでしたし、知識も少ないので四苦八苦しています。 今困っているのは画像の描画順です。 とくになにもしなければ、ソースに書かれている順番に描画されるようですが、この描画順を、ソースに書かれている順番によらずに、任意に操作することはできませんでしょうか? これが簡単にできるのかどうかすら判断がつかない初心者です。大変恐れ入りますが、どなたか教えてください。よろしくお願いします。

  • ワードにおけるテキストボックスの挿入

    ワードにおいてテキストボックスを挿入しようとすると先に「描画キャンバス」なるものが出てきます。 そうなるとテキストボックスと描画キャンバス両方のサイズを変更しないといけません。マウスだけで変更できるならまだいいのですが、描画キャンバスはマウスでは変更できずわざわざプロパティ画面みたいなのを開いたあとでサイズを数値指定するしかないようですが。数値指定なので一発でちょうどいいサイズになることはないと思うのですが、何かいい方法はないでしょうか? ダラダラと書いた文章の途中途中にテキストボックスを入れようかと思っています。2行のところもあれば10行のところもあります。 どうすれば効率よくテキストボックスを挿入できるでしょうか? ご教授よろしくお願いします。

専門家に質問してみよう