C#3DHat関数 (第6回) for VS2013/2015 Express
をグラフにすると上記のような図になる。
帽子に似ているからハット関数と呼ぶらしい。
これを今まで
CThreeD.cs C#3D立方体ワイヤーフレーム (第1回) for VS2013 Express
CBond.cs C#3D立方体ワイヤーフレーム (第2回) for VS2013 Express
CRubic.cs C#3D立方体ワイヤーフレーム (第3回) for VS2013 Express
Form1.cs C#3D立方体ワイヤーフレーム (第4回) for VS2013 Express
Zahyou.cs C#3D立方体ワイヤーフレーム (第5回) 座標を表示 for VS2013/2015 Express
で作ったものを流用して作る。
動いているのは、撮影時にZ軸の高さをF3,4キーで変化させているから。
プロジェクトファイル一覧は以上の通り。
Form1.cs ・・・ほぼ流用
CRubic.cs ・・・ほぼ流用
MathHat.cs ・・・新規 ハット関数生成部分
Grid2D.cs ・・・新規 Z=0のXYの格子状のメッシュを作成
Graph.cs ・・・新規 XYZ軸の枠を作成
Zahyou.cs ・・・ほぼ流用
CThreeD.cs ・・・ほぼ流用
Graphクラスで、XYZ軸を作成
Grid2Dクラスで格子状のメッシュを作成
MathHatクラスで
を計算し、Z軸を求める。
Grid2DクラスとGraphクラスを重ねるて、を作成する。
Form1クラス
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { CRubic m_pRubic;// = new CRubic(); bool nFlags = false; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ondraw(); } private void Form1_Load(object sender, EventArgs e) { //すべてのキーイベントをまずフォームが受け取り、処理が終了してからフォーカスのあるコントロールに渡されるようになります。 //フォームのKeyPreviewを切り替える this.KeyPreview = !this.KeyPreview; int w = pictureBox1.Width; int h = pictureBox1.Height; Point canvas_size = new Point(w, h); m_pRubic = new CRubic( 18000, canvas_size, 400); int scale = m_pRubic.m_ViewPolar.r; textBox2.Text = scale.ToString(); ondraw(); } void ondraw() { //描画先とするImageオブジェクトを作成する Bitmap canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height); //ImageオブジェクトのGraphicsオブジェクトを作成する Graphics gra = Graphics.FromImage(canvas); //Penオブジェクトの作成(幅1の黒色) //(この場合はPenを作成せずに、Pens.Blackを使っても良い) Pen pen = new Pen(Color.Blue, 1); //立方体 m_pRubic.DrawRubic(gra, pen, int.Parse(textBox2.Text)); pen.Dispose(); gra.Dispose(); //PictureBox1に表示する pictureBox1.Image = canvas; } private void pictureBox1_Click(object sender, EventArgs e) { } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { Point point = new Point(); point.X = e.X; point.Y = e.Y; if (e.Button == MouseButtons.Left) { nFlags = true; m_pRubic.SetClickPoint(point); } else if (e.Button == MouseButtons.Right) { nFlags = true; m_pRubic.SetClickPoint(point); } ondraw(); } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { Point point = new Point(); point.X = e.X; point.Y = e.Y; if (e.Button == MouseButtons.Left) { nFlags = false; } else if (e.Button == MouseButtons.Right) { nFlags = false; } ondraw(); } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { Point point = new Point(); point.X = e.X; point.Y = e.Y; if (nFlags && (e.Button == MouseButtons.Left)) { m_pRubic.TurnViewPoint(point); ondraw(); } else if (nFlags && (e.Button == MouseButtons.Right)) { m_pRubic.MoveCubes(point); ondraw(); } } private void button2_Click(object sender, EventArgs e) { pictureBox1.Refresh(); ondraw(); } private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.F1) { m_pRubic.m_ViewPolar.r = int.Parse(textBox2.Text)+100; m_pRubic.MoveCamera(1); textBox2.Text = m_pRubic.m_ViewPolar.r.ToString(); ondraw(); } else if (e.KeyData == Keys.F2) { m_pRubic.m_ViewPolar.r = int.Parse(textBox2.Text) - 100; m_pRubic.MoveCamera(1); textBox2.Text = m_pRubic.m_ViewPolar.r.ToString(); ondraw(); } else if (e.KeyData == Keys.F3) { m_pRubic.MoveCamera(203); ondraw(); } else if (e.KeyData == Keys.F4) { m_pRubic.MoveCamera(204); ondraw(); } else if (e.KeyData == Keys.Up) { m_pRubic.MoveCamera(101); ondraw(); } else if (e.KeyData == Keys.Down) { m_pRubic.MoveCamera(102); ondraw(); } else if (e.KeyData == Keys.Left) { m_pRubic.MoveCamera(103); ondraw(); } else if (e.KeyData == Keys.Right) { m_pRubic.MoveCamera(104); ondraw(); } else if (e.KeyData == Keys.A) { m_pRubic.MoveCamera(5); ondraw(); } else if (e.KeyData == Keys.Z) { m_pRubic.MoveCamera(6); ondraw(); } } } }
Form1_KeyDown()関数でキーイベント
F1ボタンで、視点半径+ (拡大)
F2ボタンで、視点半径ー
F3,F4でオブジェクトの拡大縮小。
十字キーで、上下、左右 回転。
CRubicクラス
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing; namespace WindowsFormsApplication1 { public partial class Form1 : Form { class CRubic { private Vertex m_ViewVertex; public Polar m_ViewPolar = new Polar(); private CThreeD m_pThreeD; private int m_scale; Polar m_OldViewPolar = new Polar(); Point m_ClickPoint = new Point(); private CBond[] m_pBond = new CBond[3]; private Zahyou m_pZahyou; //追加 private Graph m_pGraph; //グラフの枠 private Grid2D m_Grid2D; //2次元(XY)のグリッド private MathHat m_MathHat; //ハット型の関数 private Point m_canves; //キャンバスサイズ public int m_view_scale; //グラフやGriD2Dのサイズ /*============================================================================= 機能 メモリDCに描画する 引数 pDC : メモリデバイスコンテキストへのポインタ =============================================================================*/ public void DrawRubic(Graphics gra, Pen pen, int scale) { int i, j, k; i = 0; j = 0; k = 0; m_scale = scale; m_ViewPolar.r = m_scale; //テスト表示立方体 // m_pBond[0].DrawBond(gra, pen, m_ViewVertex); m_pZahyou.DrawBond(gra, pen, m_ViewVertex); m_MathHat.DrawBond(gra, pen, m_ViewVertex); } /*============================================================================= 機能 コンストラクタ =============================================================================*/ public CRubic(int scale, Point canves, int _view_scale) { int i, j, k; i = 0; j = 0; k = 0; Vertex[] center = new Vertex[4]; //絶対座標 m_pThreeD = new CThreeD(); m_scale = scale; m_canves = canves; m_view_scale = _view_scale; //テスト用 center[0] = new Vertex(); center[0].x = 0; center[0].y = 0; center[0].z = 0; m_pBond[0] = new CBond(center[0], ref m_pThreeD); //座標 center[1] = new Vertex(); center[1].x = 0; center[1].y = 0; center[1].z = 0; m_pZahyou = new Zahyou(400, center[1], ref m_pThreeD); //ハット関数 center[2] = new Vertex(); center[2].x = 0; center[2].y = 0; center[2].z = 0; m_MathHat = new MathHat(center[2], ref m_pThreeD, m_scale, m_canves, m_view_scale); //マウスがクリックされたら表示 m_MathHat.cal(); InitWorld(); TransferScreen(); } /*============================================================================= 機能 視点を初期化する =============================================================================*/ public void InitWorld() { m_ViewVertex = new Vertex(); m_ViewPolar.r = m_scale; m_ViewPolar.p = 0; m_ViewPolar.q = 0; m_pThreeD.PolarToVertex(m_ViewPolar, ref m_ViewVertex); } /*======================================================================== 機能 ルービックキューブを投影変換をする ========================================================================*/ public void TransferScreen() { int i, j, k; i = 0; j = 0; k = 0; m_pBond[0].TransferScreen(m_ViewPolar); m_pZahyou.TransferScreen(m_ViewPolar); m_MathHat.TransferScreen(m_ViewPolar); } /*======================================================================== 機能 マウスがクリックされた位置を覚えておく 引数 point : クリックされた位置 ========================================================================*/ public void SetClickPoint(Point point) { SetViewPolar(); m_ClickPoint.X = point.X; m_ClickPoint.Y = point.Y; } /*======================================================================== 機能 視点を回転させる 引数 point : 現在のマウスの位置 ========================================================================*/ public void TurnViewPoint(Point point) { double p, q; p = m_ClickPoint.X - point.X; q = m_ClickPoint.Y - point.Y; m_pThreeD.TurnPolar(ref m_ViewPolar, m_OldViewPolar, p / 200, q / 200); m_pThreeD.PolarToVertex(m_ViewPolar, ref m_ViewVertex); TransferScreen(); } public void MoveCubes(Point point) { double p, q; p = m_ClickPoint.X - point.X; q = m_ClickPoint.Y - point.Y; m_pBond[0].m_Center.x = -(int)p; m_pBond[0].m_Center.y = -(int)q; m_MathHat.m_Center.x = -(int)p; m_MathHat.m_Center.y = -(int)q; TransferScreen(); } /*======================================================================== 機能 現在の視点を記憶する ========================================================================*/ public void SetViewPolar() { m_OldViewPolar.r = m_ViewPolar.r; m_OldViewPolar.p = m_ViewPolar.p; m_OldViewPolar.q = m_ViewPolar.q; } //キーボードで操作 public void MoveCamera(int key) { double p = 0, q = 0; Point point = new Point(); if (key == 1) //F1 { //視点半径 r++ } else if (key == 2) //F2 { //視点半径 r-- } else if (key == 203) //F3 { m_MathHat.m_view_scale+=50; m_MathHat.cal(); } else if (key == 204) //F4 { m_MathHat.m_view_scale-=50; m_MathHat.cal(); } else if (key == 101) //X { q -= 10; //縦方向に回転 } else if (key == 102) //C { q += 10; //縦方向に回転 } else if (key == 103) //left { p -= 10; //横方向に回転 } else if (key == 104) //right { p += 10; //横方向に回転 } else if (key == 5) //A { //格子状のリセット m_MathHat.InitMathHat(); } else if (key == 6) //Z { m_MathHat.cal(); } m_pThreeD.TurnPolar(ref m_ViewPolar, m_OldViewPolar, p / 200, q / 200); m_pThreeD.PolarToVertex(m_ViewPolar, ref m_ViewVertex); TransferScreen(); } } } }
MathHatクラス
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing; namespace WindowsFormsApplication1 { public partial class Form1 : Form { class MathHat { public CThreeD m_pThreeD; public Vertex m_Center = new Vertex(); //相対座標の中心 Listm_Vertex = new List (); public int m_scale;//視点のRの距離 public int m_measure_scale;//分轄 public int m_view_scale;//大きさ private Graph m_pGraph; //グラフの枠 private Grid2D m_Grid2D; //2次元(XY)のグリッド private Point m_canves; //キャンバスのサイズ ZahyouMemori m_zmemo; //x,y,z軸の幅 public MathHat(Vertex pCenter, ref CThreeD pThreeD, int _scale, Point _canves, int _view_scale) { m_scale = _scale; m_canves = _canves; m_pThreeD = pThreeD; m_Center = pCenter; m_scale = _scale; m_view_scale = _view_scale; InitMathHat(); } /* ハット関数 [X,Y] = meshgrid(-8:.5:8); R = sqrt(X.^2 + Y.^2) + eps; Z = sin(R)./R; mesh(X,Y,Z,'EdgeColor','black') */ public void cal() { double R,x,y,z; List ver = new List (); ver = m_Grid2D.getVertex(); for (int i = 0; ver.Count > i; i++ ) { if(ver[i]!= null) { //整数値から、測りの倍率に修正 x = ver[i].tx / m_measure_scale; y = ver[i].ty / m_measure_scale; R = Math.Sqrt(x * x + y * y); if (R == 0) z = 1; else z = (Math.Sin(R) / R); ver[i].tz = z; //m_scale は視点R ver[i].z = (int)(z * m_view_scale * m_measure_scale); Vertex dmy = ver[i]; ToukousenColor(ref dmy); } } m_Grid2D.setVertex(ver); } public void ToukousenColor(ref Vertex ver) { double level = ver.z % 1000; /* if(ver.tx == 0 && ver.ty > -50 && ver.ty < 50) Console.WriteLine("x,y,z=" + ver.tx + "," + ver.ty + "," + ver.tz + " | " + "x,y,z=" + ver.x + "," + ver.y + "," + ver.z); */ Color pClr = Color.Blue; Color b5 = Color.Black; Color b4 = Color.Navy; Color b3 = Color.Red; Color b2 = Color.MidnightBlue; Color b1 = Color.MediumBlue; Color f1 = Color.Blue; Color f2 = Color.RoyalBlue; Color f3 = Color.DodgerBlue; Color f4 = Color.OldLace; Color f5 = Color.Cyan; Color f6 = Color.Red; if (level < -800) pClr = b5; if (level < -600 && -800 <= level) pClr = b4; if (level < -400 && -600 <= level) pClr = b3; if (level < -200 && -400 <= level) pClr = b2; if (level < 0 && -200 <= level) pClr = b1; if (level < 200 && 0 <= level) pClr = f1; if (level < 400 && 200 <= level) pClr = f2; if (level < 600 && 400 <= level) pClr = f3; if (level < 800 && 600 <= level) pClr = f4; if (level < 1000 && 800 <= level) pClr = f5; if (1000 <= level) pClr = f6; for (int i = 0; ver.bond2.Count > i; i++) ver.bond2[i].color = pClr; } //初期化 public void InitMathHat() { int len = 15; //XYZの範囲 m_measure_scale = 30; //メモリの倍率 int _haba = 15; //メッシュ幅 // m_measure_scale * len = X軸、Y軸の長さ // _hava = 10 でメッシュ m_zmemo = new ZahyouMemori(-len, len, -len, len, -len, len); Vertex[] center = new Vertex[2]; //絶対座標 // //グラフの枠 m_pGraph = new Graph(m_zmemo, m_Center, m_view_scale*2, ref m_pThreeD); //グリッド表示 m_Grid2D = new Grid2D(m_zmemo, m_Center, m_view_scale, _haba, m_measure_scale, ref m_pThreeD, m_canves); } /*============================================================================= 機能 頂点を初期化する 引数 x, y, z : 立方体の番号( -1 ~ 1 ) =============================================================================*/ public void InitVertex(ZahyouMemori zmemo, Vertex center) { } /*============================================================================= 機能 頂点を決める 引数 group: グループ番号 n : 線の番号 m : どこと繋がるか x, y, z : 端の座標 =============================================================================*/ public void SetVertex(int group, int n, List bond, int x, int y, int z) { Vertex ver = new Vertex(); ver.group = group; for (int i = 0; bond.Count > i; i++) ver.bond2.Add(bond[i]); ver.x = x; ver.y = y; ver.z = z; m_Vertex.Add(ver); } /*============================================================================= 機能 2次元座標系に変換する(回転行列をつくる) 引数 ViewPolar : 視点の極座標 =============================================================================*/ public void TransferScreen(Polar ViewPolar) { int i; Vertex ver = new Vertex(); for (i = 0; i < m_Vertex.Count; i++) { if (m_Vertex[i] != null) { ver = m_Vertex[i]; m_pThreeD.TransferScreen(ViewPolar, ref ver); m_Vertex[i] = ver; } } //グリッドと座標の枠回転 m_Grid2D.TransferScreen(ViewPolar); m_pGraph.TransferScreen(ViewPolar); } /*============================================================================= 機能 立方体を描画する 引数 pDC : メモリデバイスコンテキストへのポインタ ViewVertex : 視点の座標 =============================================================================*/ public void DrawBond(Graphics gra, Pen pen, Vertex ViewVertex) { int i, j; Point[] point = new Point[2]; i = 0; for (i = 0; i < m_Vertex.Count; i++) { if (m_Vertex[i] != null) { for (j = 0; j < m_Vertex[i].bond2.Count; j++) { int c = m_Vertex[i].bond2[j].next; //接続先 Color cl = m_Vertex[i].bond2[j].color; //接続色 pen.Color = cl; point[0].X = (int)m_Center.x + m_Vertex[i].point.X; point[0].Y = (int)m_Center.y + m_Vertex[i].point.Y; point[1].X = (int)m_Center.x + m_Vertex[c].point.X; point[1].Y = (int)m_Center.y + m_Vertex[c].point.Y; gra.DrawLine(pen, point[0], point[1]); } } } //グリッド格子と、グラフの枠表示 m_Grid2D.DrawBond(gra, pen, ViewVertex); m_pGraph.DrawBond(gra, pen, ViewVertex); } } } }
Grid2Dクラス
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing; namespace WindowsFormsApplication1 { public partial class Form1 : Form { class Grid2D { //絶対座標の表示 public CThreeD m_pThreeD; public Vertex m_Center = new Vertex(); //相対座標の中心 public ZahyouMemori m_pZmemo = new ZahyouMemori(); Listm_Vertex = new List (); //格子の座標情報 public int m_scale;//倍率 public int m_haba; //格子の幅 public int m_measure_scale; //分割数 private Point m_canves; //キャンバスサイズ public Grid2D(ZahyouMemori zmemo, Vertex pCenter, int _scale, int _haba, int _bunkatu, ref CThreeD pThreeD, Point _canves) { Point[] point = new Point[3]; m_pThreeD = pThreeD; m_Center = pCenter; m_scale = _scale; m_haba = _haba; m_measure_scale = _bunkatu; m_canves = _canves; InitGrid2D(zmemo, pCenter); } /*============================================================================= 機能 初期化する 引数 x, y, z : =============================================================================*/ public void InitGrid2D(ZahyouMemori zmemo, Vertex center) { InitVertex(zmemo, center); } /*============================================================================= 機能 頂点を初期化する 引数 x, y, z : 立方体の番号( -1 ~ 1 ) =============================================================================*/ public void InitVertex(ZahyouMemori zmemo, Vertex center) { m_pZmemo = zmemo; m_Center = center; double cx, cy, cz; int memori = m_measure_scale; //メモリの幅を更にmemoriで分轄 List result = new List (); Color B = Color.Brown; Color R = Color.Red; Color G = Color.Plum; Color O = Color.Olive; cx = center.x * m_scale; cy = center.y * m_scale; cz = center.z * m_scale; int i,j, cntx, cnty,cnt,cnty_num; cnt=0; cntx = 0; cnty = 0; for (i = zmemo.x1 * m_measure_scale; zmemo.x2 * m_measure_scale > i; i += m_haba) { cnty_num = cnty; //Y列の格子の数 cnty = 0; for (j = zmemo.y1 * m_measure_scale; zmemo.y2 * m_measure_scale > j; j += m_haba) { double xx, yy; xx = cx + m_measure_scale*i; yy = cy + m_measure_scale*j; //3D用の座標 MyPoint3D A = new MyPoint3D(xx, yy, cz + 0); //実際の値 A.setTrueValue(i,j,0); Lineinfo L; //線情報 //格納 result.Add(A); //コネクト情報 if (cnty > 0) { //ひとつ前の格子 result[cnt - 1]; と今を接続する result[cnt - 1].bond2.Add(L = new Lineinfo(cnt, R)); } if (cntx > 0) { //ひとつ前の格子 result[cnt - 1]; と今を接続する result[cnt - cnty_num].bond2.Add(L = new Lineinfo(cnt, G)); } cnt++; cnty++; } cntx++; } for (i = 0; result.Count > i; i++) { SetVertex(0, i, result[i].bond2, result[i]); } } /*============================================================================= 機能 頂点を決める 引数 group: グループ番号 n : 線の番号 m : どこと繋がるか x, y, z : 端の座標 =============================================================================*/ public void SetVertex(int group, int n, List bond, MyPoint3D result) { Vertex ver = new Vertex(); ver.group = group; for (int i = 0; bond.Count > i; i++) ver.bond2.Add(bond[i]); ver.x = result.x; ver.y = result.y; ver.z = result.z; ver.tx = result.tx; ver.ty = result.ty; ver.tz = result.tz; m_Vertex.Add(ver); } /*============================================================================= 機能 2次元座標系に変換する(回転行列をつくる) 引数 ViewPolar : 視点の極座標 =============================================================================*/ public void TransferScreen(Polar ViewPolar) { int i; Vertex ver = new Vertex(); for (i = 0; i < m_Vertex.Count; i++) { if (m_Vertex[i] != null) { ver = m_Vertex[i]; m_pThreeD.TransferScreen(ViewPolar, ref ver); m_Vertex[i] = ver; } } } /*============================================================================= 機能 立方体を描画する 引数 pDC : メモリデバイスコンテキストへのポインタ ViewVertex : 視点の座標 =============================================================================*/ public void DrawBond(Graphics gra, Pen pen, Vertex ViewVertex) { int i, j; Point[] point = new Point[2]; i = 0; for (i = 0; i < m_Vertex.Count; i++) { if (m_Vertex[i] != null) { for (j = 0; j < m_Vertex[i].bond2.Count; j++) { int c = m_Vertex[i].bond2[j].next; //接続先 Color cl = m_Vertex[i].bond2[j].color; //接続色 pen.Color = cl; point[0].X = (int)m_Center.x + m_Vertex[i].point.X; point[0].Y = (int)m_Center.y + m_Vertex[i].point.Y; point[1].X = (int)m_Center.x + m_Vertex[c].point.X; point[1].Y = (int)m_Center.y + m_Vertex[c].point.Y; int lenx = m_canves.X; int leny = m_canves.Y; if (point[0].X > 0 && point[0].X < lenx) if (point[0].Y > 0 && point[0].Y < leny) if (point[1].X > 0 && point[1].X < lenx) if (point[1].Y > 0 && point[1].Y < leny) gra.DrawLine(pen, point[0], point[1]); } } } } //座標をセット public void setVertex(List ver) { for (int i = 0; ver.Count > i; i++) { if(ver[i] != null) { m_Vertex[i].x = ver[i].x; m_Vertex[i].y = ver[i].y; m_Vertex[i].z = ver[i].z; } } } //座標をゲット public List getVertex() { return m_Vertex; } } } }
Graphクラス
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing; namespace WindowsFormsApplication1 { public partial class Form1 : Form { class ZahyouMemori { public int x1; public int x2; //x軸の範囲 public int y1; public int y2; //y軸の範囲 public int z1; public int z2; //z軸の範囲 public ZahyouMemori() { } public ZahyouMemori(int _x1, int _x2, //x軸の範囲 int _y1, int _y2, //y軸の範囲 int _z1, int _z2 //z軸の範囲 ) { x1 = _x1; x2 = _x2; y1 = _y1; y2 = _y2; z1 = _z1; z2 = _z2; } } class Graph { //絶対座標の表示 public CThreeD m_pThreeD; public Vertex m_Center = new Vertex(); //相対座標の中心 public ZahyouMemori m_pZmemo = new ZahyouMemori(); Listm_Vertex = new List (); public int m_scale; public Graph(ZahyouMemori zmemo, Vertex pCenter, int _scale, ref CThreeD pThreeD) { Point[] point = new Point[3]; m_pThreeD = pThreeD; m_Center = pCenter; m_scale = _scale; InitBond(zmemo, pCenter); } /*============================================================================= 機能 初期化する 引数 x, y, z : =============================================================================*/ public void InitBond(ZahyouMemori zmemo, Vertex center) { InitVertex(zmemo, center); } /*============================================================================= 機能 頂点を初期化する 引数 x, y, z : 立方体の番号( -1 ~ 1 ) =============================================================================*/ public void InitVertex(ZahyouMemori zmemo, Vertex center) { m_pZmemo = zmemo; m_Center = center; double cx, cy, cz; cx = center.x * m_scale; cy = center.y * m_scale; cz = center.z * m_scale; MyPoint3D[] A = new MyPoint3D[7]; A[0] = new MyPoint3D(cx + m_scale * zmemo.x1, cy + m_scale * zmemo.y1, cz + m_scale * zmemo.z1); //X軸 A[1] = new MyPoint3D(cx + m_scale * zmemo.x2, cy + m_scale * zmemo.y1, cz + m_scale * zmemo.z1); //Y軸 A[2] = new MyPoint3D(cx + m_scale * zmemo.x1, cy + m_scale * zmemo.y2, cz + m_scale * zmemo.z1); //Z軸 A[3] = new MyPoint3D(cx + m_scale * zmemo.x1, cy + m_scale * zmemo.y1, cz + m_scale * zmemo.z2); //YZ面 A[4] = new MyPoint3D(cx + m_scale * zmemo.x1, cy + m_scale * zmemo.y2, cz + m_scale * zmemo.z2); //XZ面 A[5] = new MyPoint3D(cx + m_scale * zmemo.x2, cy + m_scale * zmemo.y1, cz + m_scale * zmemo.z2); //YX面 A[6] = new MyPoint3D(cx + m_scale * zmemo.x2, cy + m_scale * zmemo.y2, cz + m_scale * zmemo.z1); Lineinfo [] L = new Lineinfo[9]; Color B = Color.Brown; Color R = Color.Red; Color G = Color.Plum; Color O = Color.Olive; //コネクト情報 A[0].bond2.Add(L[0] = new Lineinfo(1, R)); A[0].bond2.Add(L[1] = new Lineinfo(2, R)); A[0].bond2.Add(L[2] = new Lineinfo(3, R)); //YZ A[4].bond2.Add(L[3] = new Lineinfo(2, G)); A[4].bond2.Add(L[4] = new Lineinfo(3, G)); //ZX A[5].bond2.Add(L[5] = new Lineinfo(1, O)); A[5].bond2.Add(L[6] = new Lineinfo(3, O)); //YX A[6].bond2.Add(L[7] = new Lineinfo(1, B)); A[6].bond2.Add(L[8] = new Lineinfo(2, B)); List result = new List (); //格納 for (int i = 0; 7 > i; i++) { result.Add(A[i]); } for (int i = 0; result.Count > i; i++) { SetVertex(0, i, result[i].bond2, result[i].x, result[i].y, result[i].z); } } /*============================================================================= 機能 頂点を決める 引数 group: グループ番号 n : 線の番号 m : どこと繋がるか x, y, z : 端の座標 =============================================================================*/ public void SetVertex(int group, int n, List bond, double x, double y, double z) { Vertex ver = new Vertex(); ver.group = group; for (int i = 0; bond.Count > i; i++) ver.bond2.Add(bond[i]); ver.x = x; ver.y = y; ver.z = z; m_Vertex.Add(ver); } /*============================================================================= 機能 2次元座標系に変換する(回転行列をつくる) 引数 ViewPolar : 視点の極座標 =============================================================================*/ public void TransferScreen(Polar ViewPolar) { int i; Vertex ver = new Vertex(); for (i = 0; i < m_Vertex.Count; i++) { if (m_Vertex[i] != null) { ver = m_Vertex[i]; m_pThreeD.TransferScreen(ViewPolar, ref ver); m_Vertex[i] = ver; } } } /*============================================================================= 機能 立方体を描画する 引数 pDC : メモリデバイスコンテキストへのポインタ ViewVertex : 視点の座標 =============================================================================*/ public void DrawBond(Graphics gra, Pen pen, Vertex ViewVertex) { int i, j; Point[] point = new Point[2]; i = 0; for (i = 0; i < m_Vertex.Count; i++) { if (m_Vertex[i] != null) { for (j = 0; j < m_Vertex[i].bond2.Count; j++) { int c = m_Vertex[i].bond2[j].next; //接続先 Color cl = m_Vertex[i].bond2[j].color; //接続色 pen.Color = cl; point[0].X = (int)m_Center.x + m_Vertex[i].point.X; point[0].Y = (int)m_Center.y + m_Vertex[i].point.Y; point[1].X = (int)m_Center.x + m_Vertex[c].point.X; point[1].Y = (int)m_Center.y + m_Vertex[c].point.Y; int len = 10000; if (point[0].X > -len && point[0].X < len) if (point[0].Y > -len && point[0].Y < len) if (point[1].X > -len && point[1].X < len) if (point[1].Y > -len && point[1].Y < len) gra.DrawLine(pen, point[0], point[1]); } } } } } } }
Zahyouクラス
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing; namespace WindowsFormsApplication1 { public partial class Form1 : Form { class Zahyou { //絶対座標の表示 public CThreeD m_pThreeD; public Vertex m_Center = new Vertex(); //相対座標の中心 Listm_Vertex = new List (); public Zahyou(int len, Vertex pCenter, ref CThreeD pThreeD) { InitBond(len); m_pThreeD = pThreeD; m_Center = pCenter; } /*============================================================================= 機能 初期化する 引数 x, y, z : =============================================================================*/ public void InitBond(int len) { InitVertex(len, len, len); } /*============================================================================= 機能 頂点を初期化する 引数 x, y, z : 立方体の番号( -1 ~ 1 ) =============================================================================*/ public void InitVertex(int x, int y, int z) { MyPoint3D[] A = new MyPoint3D[6]; //X軸 A[0] = new MyPoint3D(x, 0, 0); A[1] = new MyPoint3D(-x, 0, 0); //Y軸 A[2] = new MyPoint3D(0, y, 0); A[3] = new MyPoint3D(0, -y, 0); //Z軸 A[4] = new MyPoint3D(0, 0, z); A[5] = new MyPoint3D(0, 0, -z); //コネクト情報 A[0].bond.Add(1); A[2].bond.Add(3); A[4].bond.Add(5); List result = new List (); //格納 for (int i = 0; 6 > i; i++) { result.Add(A[i]); } for (int i = 0; result.Count > i; i++) { SetVertex(0, i, result[i].bond, result[i].x, result[i].y, result[i].z); } } /*============================================================================= 機能 頂点を決める 引数 group: グループ番号 n : 線の番号 m : どこと繋がるか x, y, z : 端の座標 =============================================================================*/ public void SetVertex(int group, int n, List bond, int x, int y, int z) { Vertex ver = new Vertex(); ver.group = group; for (int i = 0; bond.Count > i; i++) ver.bond.Add(bond[i]); ver.x = x; ver.y = y; ver.z = z; m_Vertex.Add(ver); } /*============================================================================= 機能 2次元座標系に変換する(回転行列をつくる) 引数 ViewPolar : 視点の極座標 =============================================================================*/ public void TransferScreen(Polar ViewPolar) { int i; Vertex ver = new Vertex(); for (i = 0; i < m_Vertex.Count; i++) { if (m_Vertex[i] != null) { ver = m_Vertex[i]; m_pThreeD.TransferScreen(ViewPolar, ref ver); m_Vertex[i] = ver; } } } /*============================================================================= 機能 立方体を描画する 引数 pDC : メモリデバイスコンテキストへのポインタ ViewVertex : 視点の座標 =============================================================================*/ public void DrawBond(Graphics gra, Pen pen, Vertex ViewVertex) { int i, j; Point[] point = new Point[2]; i = 0; for (i = 0; i < m_Vertex.Count; i++) { if (m_Vertex[i] != null) { for (j = 0; j < m_Vertex[i].bond.Count; j++) { int c = m_Vertex[i].bond[j]; //接続先 point[0].X = m_Center.x + m_Vertex[i].point.X; point[0].Y = m_Center.y + m_Vertex[i].point.Y; point[1].X = m_Center.x + m_Vertex[c].point.X; point[1].Y = m_Center.y + m_Vertex[c].point.Y; gra.DrawLine(pen, point[0], point[1]); } } } } } } }
CThreeDクラス
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Drawing; namespace WindowsFormsApplication1 { public partial class Form1 : Form { //絶対座標の中心 static public int RUBIC_X = 350; static public int RUBIC_Y = 350; public class Lineinfo { public int next; //接続先 public Color color; //線の色 public Lineinfo() { } public Lineinfo(int _next, Color _color) { next = _next; color = _color; } } public class MyPoint3D { public double x; public double y; public double z; public double tx, ty, tz; //計算の実値 public Listbond = new List ();//接続先 public List bond2 = new List ();//接続先 public int num; public MyPoint3D() { } public MyPoint3D(double _x, double _y, double _z) { x = _x; y = _y; z = _z; } //実際値 public void setTrueValue(double _x, double _y, double _z) { tx = _x; ty = _y; tz = _z; } } //デカルト座標 public class Vertex { public int group; //グループ public List bond = new List ();//接続先 public List bond2 = new List ();//接続先 public double x, y, z; //3D座標用 public double tx, ty, tz; //計算の実値 public Point point; public Vertex() { } } //極座標 public class Polar { public int r; public double p, q; } //線の構造体 public class Bond { public Vertex vertex; public Vertex center = new Vertex(); //相対座標 } //面の構造体 public class Face { public Vertex[] vertex = new Vertex[4]; public Vertex center = new Vertex(); } class CThreeD { /*============================================================================= 機能 2次元座標系に変換する 引数 ViewPolar : 視点の極座標 vertex : 変換したい座標 =============================================================================*/ public void TransferScreen(Polar ViewPolar, ref Vertex pVertex) { double a; double[,] matrix = new double[3, 3]; Vertex vertex = new Vertex(); a = ViewPolar.r * Math.Cos(ViewPolar.q); /**************************************************************** 回転行列を作る ****************************************************************/ matrix[0, 0] = -1 * Math.Sin(ViewPolar.p); matrix[0, 1] = Math.Cos(ViewPolar.p); matrix[0, 2] = 0; matrix[1, 0] = -1 * Math.Sin(ViewPolar.q) * Math.Cos(ViewPolar.p); matrix[1, 1] = -1 * Math.Sin(ViewPolar.q) * Math.Sin(ViewPolar.p); matrix[1, 2] = Math.Cos(ViewPolar.q); matrix[2, 0] = -1 * Math.Cos(ViewPolar.q) * Math.Cos(ViewPolar.p); matrix[2, 1] = -1 * Math.Cos(ViewPolar.q) * Math.Sin(ViewPolar.p); matrix[2, 2] = -1 * Math.Sin(ViewPolar.q); /* X軸とY軸 -sin.p cos.p 0 -sin.q*cps.p -sin.q*sin.p cos.q -cos.q*cos.p -cos.q*sin.p -sin.q */ TransferVertex(matrix, ViewPolar, ref pVertex); } /*============================================================================= 機能 2次元座標系に変換する 引数 matrix[3] : 回転行列 ViewVertex : 視点の座標 =============================================================================*/ public void TransferVertex(double[,] matrix, Polar ViewPolar, ref Vertex pVertex) { double x, y, z; Vertex vertex = new Vertex(); PolarToVertex(ViewPolar, ref vertex); x = matrix[0, 0] * (pVertex.x - vertex.x) + matrix[0, 1] * (pVertex.y - vertex.y) + matrix[0, 2] * (pVertex.z - vertex.z); y = matrix[1, 0] * (pVertex.x - vertex.x) + matrix[1, 1] * (pVertex.y - vertex.y) + matrix[1, 2] * (pVertex.z - vertex.z); z = matrix[2, 0] * (pVertex.x - vertex.x) + matrix[2, 1] * (pVertex.y - vertex.y) + matrix[2, 2] * (pVertex.z - vertex.z); z = z / 300; pVertex.point.X = (int)(RUBIC_X + x / z); pVertex.point.Y = (int)(RUBIC_Y + y / z); } /*============================================================================= 機能 極座標を直行座標に変換する 引数 polar : 極座標の座標値 pVertex : 直行座標へのポインタ =============================================================================*/ public void PolarToVertex(Polar polar, ref Vertex pVertex) { pVertex.x = (int)(polar.r * Math.Cos(polar.q) * Math.Cos(polar.p)); pVertex.y = (int)(polar.r * Math.Cos(polar.q) * Math.Sin(polar.p)); pVertex.z = (int)(polar.r * Math.Sin(polar.q)); } /*============================================================================= 機能 極座標を回転移動する 引数 new_polar : 回転後の座標 old_polar : 回転させたい極座標の座標値 rotateP : Z軸を中心とした回転量 rotateQ : 原点を中心としてXY平面と垂直な回転量 =============================================================================*/ public void TurnPolar(ref Polar new_polar, Polar old_polar, double rotateP, double rotateQ) { new_polar.p = old_polar.p += rotateP; new_polar.q = old_polar.q += rotateQ; } } } }
終わり。