• ベストアンサー

CANVASで網目模様を描く方法を教えて下さい

添付画像のような網目模様を、CANVAS で作画する方法を探しています。 白黒で影や色づけは全くいりません。 コードの具体例をお教えいただけますでしょうか。 よろしくお願いいたします。

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

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

長いので分割します <!DOCTYPE html>  <meta charset="UTF-8">  <title>3D</title>  <style>   canvas { background : #aaa; }  </style> <body> <canvas width="1024" height="700"></canvas> <script> function ball (r, n, n1) {  var rst = [], a = [], b = [], c = [];  var pi = Math.PI, sin = Math.sin, cos = Math.cos;  var k = 2 * pi / n1, k2 = pi / n;  var i, i_, j, s, r2, yb;  var r2 = sin (k2) * r, h2 = cos (k2) * r, yr = r2, yt = h2;    for (i = 0; i <= n1; i++) {   s = k * i;   a[i] = sin (s);   b[i] = cos (s);  }    for (i = 0; i < n1; i++) {   rst[i] = [    [0, r, 0],    [a[i] * r2, h2, b[i] * r2],    [a[i_= i +1 ] * r2, h2, b[i_] * r2]   ];   c[i] = [    [a[i_ = i + 1] * r2, -h2, b[i_] * r2],    [a[i] * r2, -h2, b[i] * r2],    [0, -r, 0]   ];  }    for (i = 2; i < n; i++) {   s = k2 * i;   yr2 = sin (s) * r;   yb = cos (s) * r;      for (j = 0; j < n1; j++) {    rst.push ([     [a[j] * yr, yt, b[j] * yr],     [a[j] * yr2, yb, b[j] * yr2],     [a[j+1] * yr2, yb, b[j+1] * yr2],     [a[j+1] *yr, yt, b[j+1] * yr]    ]);   }   yt = yb;   yr = yr2;  }  return rst.concat (c); } function rotation3D (m, x, y, z) {  var deg = Math.PI / 180, sin = Math.sin, cos = Math.cos;  var xc = cos (x * deg), xs = sin (x * deg);  var yc = cos (y * deg), ys = sin (y * deg);  var zc = cos (z * deg), zs = sin (z * deg);    var x0 = xc * yc, y0 = xc * ys * zs - xs * zc, z0 = xc * ys * zc + xs * zs;  var x1 = xs * yc, y1 = xs * ys * zs + xc * zc, z1 = xs * ys * zc - xc * zs;  var x2 = -ys, y2 = yc * zs, z2 = yc * zc;    var i, j, a, b, c, d, e, s;  var rst = [];  for (i = 0; a = m[i]; rst[i++] = s)   for (j = 0, s = []; b = a[j]; j++)    s[j] = [     x0 * (c = b[0]) + y0 * (d = b[1]) + z0 * (e = b[2]),     x1 * c + y1 * d + z1 * e,     x2 * c + y2 * d + z2 * e    ];  return rst; } //面の法線ベクトルを求める function crossProduct (ary) {  var rst = [];  var i, s;  var p0, p1, p2;  var x0, x1, x2, y0, y1, y2, z0, z1, z2;  var px, py, pz, qx, qy, qz;    for (i = 0; s = ary[i]; i += 1) {   p0 = s[0]; p1 = s[1]; p2 = s[2];   x0 = p0[0]; x1 = p1[0]; x2 = p2[0];   y0 = p0[1]; y1 = p1[1]; y2 = p2[1];   z0 = p0[2]; z1 = p1[2]; z2 = p2[2];   px = x1 - x0; py = y1 - y0; pz = z1 - z0; //p   qx = x2 - x1; qy = y2 - y1; qz = z2 - z1; //q   rst[i] = [    py * qz - pz * qy,    pz * qx - px * qz,    px * qy - py * qx   ];  }  return rst; } //明るさを求める function brightness (ary, v, el) {  var lx = v[0], ly = v[1], lz = v[2];  var lv = Math.sqrt (lx * lx + ly * ly + lz * lz);  var i, a, x, y, z, rst = [];  var c, b = 1 - el;  for (i = 0; a = ary[i]; i++) {   x = a[0]; y = a[1]; z = a[2];   tv = Math.sqrt (x * x + y * y + z * z);   inp = x * lx + y * ly + z * lz;   len = inp / (lv * tv);   rst[i] = el + Math.cos (Math.acos (len)) * b;  }  return rst; } //3Dの物体を2Dの座標へと変換する function cov3to2 (m, zz, sc) {  var rst = [], a, b, c, d, s, i, j, t;  for (i = 0; d = m[i]; i++) {   a = d[0];   for (c = [], j = 0; b = a[j]; j++) {    c[j] = [b[0] / (t = (zz + b[2]) / sc), b[1] / t];   }   rst[i] = [c, d[1]];  }  return rst; } function canvas_draw_create (c, o) {  var ctx = c.getContext ('2d');  var x = c.width / 2 + o[0];  var y = c.height / 2 + o[1];  var rgb = [50, 150,255];  var int = Math.floor;  ctx.lineWidth = 1;  return {   draw:    function (a, b) {//面を描く     ctx.beginPath ();     ctx.fillStyle =      'rgb(' +      int (rgb[0] * b) + ',' +      int (rgb[1] * b) + ',' +      int (rgb[2] * b) +      ')';     ctx.moveTo (x + a[0][0], y - a[0][1]);     for (i = 1; b = a[i++]; )      ctx.lineTo (x + b[0], y - b[1]);     ctx.lineTo (x + a[0][0], y - a[0][1]);     ctx.closePath();     ctx.fill();    },   cls:    function () {     ctx.fillStyle = 'RGBA(160,160,160,1)';     ctx.fillRect (0,0, c.width, c.height);    }   }; } function draw (a, dw) {  var i, b, c;  dw.cls ();  for (i = 0; c = a[i++]; ) {//面の3点だけでベクトルの外積の向きで判断   b = c[0];   if (0 >= ((b[2][0] - b[1][0]) * (b[0][1] - b[1][1]) -    (b[2][1] - b[1][1]) * (b[0][0] - b[1][0]))   )    dw.draw (b, c[1]);  } }

その他の回答 (6)

回答No.7

もうすでに最初の質問内容と違っています。 質問しなおすべきです。

mqm
質問者

お礼

大変に素晴らしい作画方法をご指導いただき、感謝の念に絶えません。 私が教えていただきたかった最初の内容は、格子模型の円柱と半球を表示させることでした。 babu 先生の名作はプロの作品として、多くの企業から依頼を受けるような内容と思います。 私のような初学者に使えるような単純なモデルのコードを勉強するために ご指示に従って、簡単な模型のコード分析の質問をさせていただきました。 ぜひ、その内容に目をお通しいただけますでしょうか。 http://okwave.jp/qa/q9163064.html 重ねて御礼を申し上げます。

回答No.6

//その2 var hoge = (function _ () {  var z = rotation3D (ball (18, 20, 40), 23.43,0,0);  var v = canvas_draw_create (document.querySelector ('canvas'), [0,0]);  var h = [[[1, 1, -1]]];  return function () {   h = rotation3D (h, 1, 0, 0);   z = rotation3D (z, 0, 1, 0);   var bb = brightness (crossProduct (z), h[0][0], .5);   for (var i = 0, I = z.length, d = []; i < I; i++) {    d[i] = [z[i], bb[i]];   }   draw (cov3to2 (d, 50, 600), v);  }; }) (); setInterval (hoge, 1000/60); </script> 面の明るさを計算できるようになりました。 光源のベクトルも回転しています。 アドバイスありがとうございます。 しかし、私的な考えではありますが、図解で説明するつもりはありません。 むしろ質問者様がどのように理解し自分のモノにしたのかをブログに掲載するべきです。

mqm
質問者

お礼

素晴らしい作品を教えていただき、ありがとうございます。 ぜひとも単調な青色ではなく、 この画像のような光沢を作ることができるかどうかをお教え下さい。 http://thumbs.media.smithsonianmag.com//filer/Design-daily-Planet-631.jpg__800x600_q85_crop.jpg この球体は、世界で一番有名な新聞記者の勤務先の社章です。 https://i.ytimg.com/vi/ULoPr-VtAl8/maxresdefault.jpg それでは、よろしくお願いします。

回答No.4

#1,2,3 です 訂正があります。球体のモデリングにミスがありました。 回転機能にもミスがありました。 誠にもって申し訳ありませんでした。 お詫びと言っては何なのですが、球体をタイマーを使って動かせるようにしてみました。 微笑んでいただければ幸いです。 <!DOCTYPE html>  <meta charset="UTF-8">  <title>3D</title>  <style>   canvas { background : #fff; }  </style> <body> <canvas width="1024" height="512"></canvas> <script> function ball (r, n, n1) {  var rst = [], a = [], b = [], c = [];  var pi = Math.PI, sin = Math.sin, cos = Math.cos;  var k = 2 * pi / n1, k2 = pi / n;  var i, i_, j, s, r2, yb;  var r2 = sin (k2) * r, h2 = cos (k2) * r, yr = r2, yt = h2;    for (i = 0; i <= n1; i++) {   s = k * i;   a[i] = sin (s);   b[i] = cos (s);  }    for (i = 0; i < n1; i++) {   rst[i] = [    [0, r, 0],    [a[i] * r2, h2, b[i] * r2],    [a[i_= i +1 ] * r2, h2, b[i_] * r2]   ];   c[i] = [    [a[i_ = i + 1] * r2, -h2, b[i_] * r2],    [a[i] * r2, -h2, b[i] * r2],    [0, -r, 0]   ];  }    for (i = 2; i < n; i++) {   s = k2 * i;   yr2 = sin (s) * r;   yb = cos (s) * r;      for (j = 0; j < n1; j++) {    rst.push ([     [a[j] * yr, yt, b[j] * yr],     [a[j] * yr2, yb, b[j] * yr2],     [a[j+1] * yr2, yb, b[j+1] * yr2],     [a[j+1] *yr, yt, b[j+1] * yr]    ]);   }   yt = yb;   yr = yr2;  }  return rst.concat (c); } function rotation3D (m, x, y, z) {  var deg = Math.PI / 180, sin = Math.sin, cos = Math.cos;  var xc = cos (x * deg), xs = sin (x * deg);  var yc = cos (y * deg), ys = sin (y * deg);  var zc = cos (z * deg), zs = sin (z * deg);    var x0 = xc * yc, y0 = xc * ys * zs - xs * zc, z0 = xc * ys * zc + xs * zs;  var x1 = xs * yc, y1 = xs * ys * zs + xc * zc, z1 = xs * ys * zc - xc * zs;  var x2 = -ys, y2 = yc * zs, z2 = yc * zc;    var i, j, a, b, c, d, e, s;  var rst = [];  for (i = 0; a = m[i]; rst[i++] = s)   for (j = 0, s = []; b = a[j]; j++)    s[j] = [     x0 * (c = b[0]) + y0 * (d = b[1]) + z0 * (e = b[2]),     x1 * c + y1 * d + z1 * e,     x2 * c + y2 * d + z2 * e    ];  return rst; } //3Dの物体を2Dの座標へと変換する function cov3to2 (m, zz, sc) {  var rst = [], a, b, c, s, i, j, t;  for (i = 0; a = m[i]; rst[i++] = c)   for (c = [], j = 0; b = a[j]; j++)    c[j] = [b[0] / (t = (zz + b[2]) / sc), b[1] / t];  return rst; } function canvas_draw_create (c, o) {  var ctx = c.getContext ('2d');  var x = c.width / 2 + o[0];  var y = c.height / 2 + o[1];  ctx.lineWidth = 1;  ctx.strokeStyle = 'rgb(0,0,0)';  return {   draw:    function (a) {//面を描く     ctx.beginPath ();     ctx.moveTo (x + a[0][0], y - a[0][1]);     for (i = 1; b = a[i++]; )      ctx.lineTo (x + b[0], y - b[1]);     ctx.lineTo (x + a[0][0], y - a[0][1]);     ctx.stroke();    },   cls:    function () {     ctx.fillRect (0,0, c.width, c.height);     ctx.fillStyle = 'RGB(255,255,255)';    }   }; } function draw (a, dw) {  dw.cls ();  for (var i = 0, b; b = a[i++]; ) {//面の3点だけでベクトルの外積の向きで判断   if (0 >= ((b[2][0] - b[1][0]) * (b[0][1] - b[1][1]) -    (b[2][1] - b[1][1]) * (b[0][0] - b[1][0]))   )    dw.draw (b);  } } var hoge = (function _ (f, a, b, c) {  var z = ball (15, 18, 36);  var v = canvas_draw_create (document.querySelector ('canvas'), [0,0]);    return function () {   z = f (z, a, b, c);   draw (cov3to2 (z, 50, 600), v);  }; }) (rotation3D, .7, 1, .5); setInterval (hoge, 20); </script>

mqm
質問者

お礼

大変にお世話になりました。 このような難解な課題を解決していただき、お礼の言葉だけで感謝を表わすことはできません。 ぜひとも、Blog などにコードと実際の画像作成例を両方とも掲載されて、アドレスをこの質問サイトにご紹介下さい。 そうすれば、たくさんの人たちがこの回答例を学びたいと口コミが広がるのではないかと思います。 やがては各方面から、画像変換の教育講演を依頼したいというような声が届くことと思われます。 ソースコードと3D画像処理の playground 様表示をしていただければ、多くのプログラマーが学習しようと blog の人気が高まることと思います。 質問用のメールボックスをご用意なされば、スパム攻勢を受けずに必要な声だけを受け取ることができるのではないでしょうか。 ご参考までに、blog を活用した回答の例をご紹介させて下さい。 http://okwave.jp/qa/q9107791.html 回答4番のように、blog と連動して画像をふんだんに使った解説をしていただいた見本をご覧下さい。 それでは、これからも御指導をよろしくお願いいたします。

回答No.3

#1,2 です。 回転機能を追加。 座標系を訂正。 文字制限のため癖で短く。 球体は書き直しました。 <!DOCTYPE html>  <meta charset="UTF-8">  <title>3D</title>  <style>   canvas { background : #ddd; }  </style> <body> <canvas width="1024" height="512"></canvas> <script> function prism (r, h, n, n1) {  var i, j, k, x, y, yn, z;  var rst = [], top = [], btm = [], b = [0], c = [r];  var sin = -Math.sin (k = 2 * Math.PI / n), cos = Math.cos (k);  var h1 = h / n1, h2 = h / 2;  for (i = 0; i < n; ) {   top[i] = [x = b[i], h2, z = c[i]];   btm[i] = [z, -h2, x];   b[++i] = x * cos - z * sin;   c[i] = x * sin + z * cos;  }  for (y = h2, i = 0; i < n1; i++, y = yn)   for (x = b[0], z = c[0], yn = y - h1, j = 1; j <= n; j++)    rst.push ([[x, y, z], [x, yn, z],     [x = b[j], yn, z = c[j]], [x, y, z]]);  return [top].concat (rst, [btm]); } function ball (r, n, n1) {  var rst = [], a = [], b = [], c = [];  var pi = Math.PI, sin = Math.sin, cos = Math.cos;  var k = 2 * pi / n1, k2 = pi / n;  var i, i_, j, s, r2, yb;  var r2 = sin (k2) * r, h2 = cos (k2) * r, yr = r2, yt = h2;    for (i = 0; i <= n1; i++) {   s = k * i;   a[i] = sin (s);   b[i] = cos (s);  }    for (i = 0; i < n1; i++) {   rst[i] = [    [0, r, 0],    [a[i] * r2, h2, b[i] * r2],    [a[i_= i +1 ] * r2, h2, b[i_] * r2]   ];   c[i] = [    [a[i_ = i + 1] * r2, -h2, b[i_] * r2],    [a[i] * r2, -h2, b[i] * r2],    [0, -r, 0]   ];  }    for (i = 2; i < n -1; i++) {   s = k2 * i;   yr2 = sin (s) * r;   yb = cos (s) * r;      for (j = 0; j < n1; j++) {    rst.push ([     [a[j] * yr, yt, b[j] * yr],     [a[j] * yr2, yb, b[j] * yr2],     [a[j+1] * yr2, yb, b[j+1] * yr2],     [a[j+1] *yr, yt, b[j+1] * yr]    ]);   }   yt = yb;   yr = yr2;  }  return rst.concat ([c]); } //各x,y,z座標に移動する関数 function move3D (m, x, y, z) {  var rst = [], a, b, i, j, s0, s1, buf;  for (i = 0; a = m[i]; rst[i++] = c)   for (j = 0, c = []; b = a[j]; c[j++] = b)    (b[0] += x, b[1] += y, b[2] += z);  return rst; } function rotation3D (m, x, y, z) {  var deg = Math.PI / 180, sin = Math.sin, cos = Math.cos;  var xc = cos (x * deg), xs = sin (x * deg);  var yc = cos (y * deg), ys = sin (y * deg);  var zc = cos (z * deg), zs = sin (z * deg);    var x0 = xc * yc, y0 = xc * ys * zs - xs * zc, z0 = xc * ys * zc + xs * zs;  var x1 = xs * yc, y1 = xs * ys * zs + xc * zc, z1 = xs * ys * zc - xc * zs;  var x2 = -xs, y2 = yc * zs, z2 = yc * zc;    var i, j, a, b, c, d, e, s;  var rst = [];  for (i = 0; a = m[i]; rst[i++] = s)   for (j = 0, s = []; b = a[j]; j++)    s[j] = [     x0 * (c = b[0]) + y0 * (d = b[1]) + z0 * (e = b[2]),     x1 * c + y1 * d + z1 * e,     x2 * c + y2 * d + z2 * e    ];  return rst; } //3Dの物体を2Dの座標へと変換する function cov3to2 (m, zz, sc) {  var rst = [], a, b, c, s, i, j, t;  for (i = 0; a = m[i]; rst[i++] = c)   for (c = [], j = 0; b = a[j]; j++)    c[j] = [b[0] / (t = (zz + b[2]) / sc), b[1] / t];  return rst; } //描く function draw (c, a, o) {  var ctx = c.getContext ('2d');  var x = c.width / 2 + o[0];  var y = c.height / 2 + o[1];  var i, b, f, p;  ctx.lineWidth = 1;  ctx.strokeStyle = 'rgb(0,0,0)';    for (i = 0; b = a[i++]; )   if (0 >= (b[2][0] - b[1][0]) * (b[0][1] - b[1][1]) -    (b[2][1] - b[1][1]) * (b[0][0] - b[1][0])) {    ctx.beginPath ();    ctx.moveTo (x + b[0][0], y - b[0][1]);    for (j = 1; p = b[j++]; )     ctx.lineTo (x + p[0], y - p[1]);    ctx.lineTo (x + b[0][0], y - b[0][1]);    ctx.stroke();   } } draw (  document.querySelector ('canvas'),  cov3to2 (move3D (prism (8, 16, 24, 10), 0, -12, 0), 50, 700),  [200, -150] ); draw (  document.querySelector ('canvas'),  cov3to2 (rotation3D (ball (15, 18, 36), 0,-20,-40), 50, 600),  [-200, 0] ); </script>

回答No.2

#1 です。 球体の曲線をあきらめて投稿。 分割線を増やせばなんとか。 でもサンプル図のようにするには回転が必要なようです。 <!DOCTYPE html>  <meta charset="UTF-8">  <title>3D</title>  <style>   canvas { background : #ddd; }  </style> <body> <canvas width="1024" height="512"></canvas> <script> //3Dの物体を多角形の平面の集合(配列)として考える //平面は、[x,y,z]の座標をn個もった配列として考える //平面の各頂点の順序は反時計周りとする //多角柱 function prism (r, h, n, n1) {  var rst = [], top = [], btm = [], bx = [], bz = [];  var k = 2 * Math.PI / n;  var h1 = h / n1, h2 = h / 2;  var i, j, s, x, y, z;  var xl, xr, yt, yb, zf, zb;  //前処理として高さ(h)を無視してn角形のxとzを求める  for (i = s = 0; i <= n; i++) {   bx[i] = x = Math.sin (s) * r;   bz[i] = z = Math.cos (s) * r;   top[i] = [x, h2, z];//上部   btm[i] = [x, -h2, z];//下部   s += k;  }  rst.push (top);//最初に上部を登録  //側面の四角形の平面を作る  yt = h2;  for (i = 0; i < n1; i++) {   yb = yt - h1;   x = bx[0];   z = bz[0];   for (j = 1; j <= n; j++)    rst.push ([     [x, yt, z], [x, yb, z],//左上,左下     [x = bx[j], yb, z = bz[j]], [x, yt, z] //右下,右上    ]);   yt = yb;  }  rst.push (btm.reverse ());//下部を登録  return rst; } function ball (r, n, n1) {  var rst = [], bx = [], bz = [];  var k = 2 * Math.PI / n1;  var i, j, s, yr, yt, yb;    for (i = s = 0; i <= n1; i++) {   bx[i] = Math.sin (s);   bz[i] = Math.cos (s);   s += k;  }    yr = 0;  yt = r;    for (i = 1; i <= n; i++) {   yr2 = Math.sin (180 / n * i * Math.PI / 180) * r;   yb = Math.cos (180 / n * i * Math.PI / 180) * r;      for (j = 0; j < n1; j++)    rst.push ([     [bx[j] * yr, yt, bz[j] * yr],     [bx[j] * yr2, yb, bz[j] * yr2],     [bx[j+1] * yr2, yb, bz[j+1] * yr2],     [bx[j+1] *yr, yt, bz[j+1] * yr]    ]);   yt = yb;   yr = yr2;  }  return rst; } //各x,y,z座標に移動する関数 function move3D (m, x, y, z) {  var rst = [];  var s0, s1, buf;  while (s0 = m.shift ()) {   buf = [];   while (s1 = s0.shift ()) {    s1[0] += x;    s1[1] += y;    s1[2] += z    buf.push (s1);   }   rst.push (buf);  }  return rst; } //3Dの物体を2Dの座標へと変換する function cov3to2 (m, zz, sc) {  var rst = [];  var s0, s1, buf, s, i;  for (i = 0; s0 = m[i++]; ) {   buf = [];   while (s1 = s0.shift ()) {    s = (zz + s1[2]) / sc;    s1[0] /= s;    s1[1] /= s;    buf.push (s1);   }   rst.push (buf);  }  return rst; } //描く function draw (c, a, o) {  var ctx = c.getContext ('2d');  var ox = c.width / 2 + o[0];  var oy = c.height / 2 + o[1];  var b, p;  ctx.lineWidth = 1;  ctx.strokeStyle = 'rgb(0,0,0)';    for (var i = 0; b = a[i++]; ) {   p = (b[2][0] - b[1][0]) * (b[0][1] - b[1][1]) -     (b[2][1] - b[1][1]) * (b[0][0] - b[1][0]);   if (p <= 0) {    ctx.beginPath ();    ctx.moveTo (ox + b[0][0], oy + b[0][1]);    for (j = 1; p = b[j++]; ) {     ctx.lineTo (ox + p[0], oy + p[1]);    }    ctx.lineTo (ox + b[0][0], oy + b[0][1]);    ctx.stroke();   }  } } draw (  document.querySelector ('canvas'),  cov3to2 (move3D (prism (4, 9, 24, 10), 0, 8, 0), 30, 500),  [200, -200] ); draw (  document.querySelector ('canvas'),  cov3to2 (move3D (ball (7, 18, 36), 0, 8, 0), 30, 500),  [-200, -200] ); </script>

回答No.1

興味があったので書いてみた。もちろんコードはイケてない。 コメントも最初は書いていたのだけれど、眠くなったので。 球体も曲線が面倒なのでパス。 全角空白を半角に置換してください。 <!DOCTYPE html>  <meta charset="UTF-8">  <title>3D</title>  <style> canvas { background : #ddd; }  </style> <body> <canvas width="1024" height="512"></canvas> <script> //3Dの物体を多角形の平面の集合(配列)として考える //平面は、[x,y,z]の座標をn個もった配列として考える //球体よりも多角柱が簡単そうなのでその平面の集合体を作る関数を作る function prism (r, h, n0, n1) {  var rst = [];  //前処理として高さ(h)を無視してn角形のxとzを求める  var ax = [], az = [];  var k = 360 / n0;  for (var i = 0; i <= n0; i++) {    ax.push (Math.sin (k * i * Math.PI / 180) * r);    az.push (Math.cos (k * i * Math.PI / 180) * r);  }  var hh = h / 2;//中心座標の高さを0にしたいので2で割る  //まず上部と下部の面を同時に作る  var t = [], b = [];  for (var i = 0; i <= n0; i++) {    t.push ([ax[i], hh, az[i]]);    b.push ([ax[i], -hh, az[i]]);  }  rst.push (t);  //側面の四角形の平面を作る  var y0, y1;  for (var i = 0; i < n1; i ++) {    y0 = hh - (h / n1) * i;    y1 = hh - (h / n1) * (i + 1);    for (var j = 0; j < n0; j++) {      rst.push ([        [ax[j], y0, az[j]],        [ax[j], y1, az[j]],        [ax[j+1], y1, az[j+1]],        [ax[j+1], y0, az[j+1]]      ]);    }  }  rst.push (b.reverse ());  return rst; } //多角柱を作ってみる var takakutyuu = prism (4, 9, 24, 10); //回転するのは面倒なのでパス //各x,y,z座標に移動する関数 function move3D (m, x, y, z) {  var rst = [];  var s0, s1, buf;  while (s0 = m.shift ()) {    buf = [];    while (s1 = s0.shift ()) {      s1[0] += x;      s1[1] += y;      s1[2] += z      buf.push (s1);    }    rst.push (buf);  }  return rst; } //移動させてみる takakutyuu = move3D (takakutyuu, 0, 8, 0); //3Dの物体を2Dの座標へと変換する function cov3to2 (m, zz, sc) {  var rst = [];  var s0, s1, buf, s;  while (s0 = m.shift ()) {    buf = [];    while (s1 = s0.shift ()) {      s = (zz + s1[2]) / sc;      s1[0] /= s;      s1[1] /= s;      buf.push (s1);    }    rst.push (buf);  }  return rst; } //描く function draw (c, a, o) {  var ctx = c.getContext ('2d');  var ox = c.width / 2 + o[0];  var oy = c.height / 2 + o[1];  var b, p;  ctx.lineWidth = 1;  ctx.strokeStyle = 'rgb(0,0,0)';    for (var i = 0; b = a[i++]; ) {    p = (b[2][0] - b[1][0]) * (b[0][1] - b[1][1]) -        (b[2][1] - b[1][1]) * (b[0][0] - b[1][0]);    if (p <= 0) {      ctx.beginPath ();      ctx.moveTo (ox + b[0][0], oy + b[0][1]);      for (j = 1; p = b[j++]; ) {        ctx.lineTo (ox + p[0], oy + p[1]);      }      ctx.lineTo (ox + b[0][0], oy + b[0][1]);      ctx.stroke();    }  } } draw (  document.querySelector ('canvas'),  cov3to2 (takakutyuu, 20, 500),  [200, -200] ); </script>