// ■ランダムドット表示プログラム // 一枚の絵で立体視可能な「ランダムドット」を表示します。 // 描き方については、拙著「Visual C#による 明解 アルゴリズム入門」を参照されたい。 // // @ usingのところにSystem.Drawing.Drawing2Dを追加する。 // A public Form1()以外をコピーする。 // B フォームにcomboBox1, textBox1を追加する。 // C textBox1のTextプロパティを「0.2」にする。 // D form1のLoadイベントにform1_Load, comboBox1のSelectedIndexChangedイベントに // comboBox1_SelectedIndexChangedを指定する。 // E 実行してcomboBox1から表示したい図形を選択する(初期値はsin(R)/Rとなっている)。 // using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Drawing2D; // これをusingするしておくこと namespace randamDot { public partial class Form1 : Form { public Matrix matrix = new Matrix(); public string 処理; public Form1() { InitializeComponent(); } private double SinR_dev_R(double X, double Y) { double R = Math.Sqrt(X * X + Y * Y); if (R <= 0.0000001) return 1.0; return Math.Sin(R) / R; } private double 半球(double X, double Y) { double R = Math.Sqrt(X * X + Y * Y); if (R > 5) return -1.0; R = R / 5; return Math.Sqrt(1 - R * R) - 1; } private double 円筒(double X, double Y) { double R = Math.Abs(X); if (R > 5) return -1.0; R = R / 5; return Math.Sqrt(1 - R * R) - 1; } private double ピラミッド(double X, double Y) { double XX = Math.Abs(X); double R = Math.Abs(Y); if (XX > R) R = XX; if (R > 5) return -1; R = R / 2.5; return 1 - R; } private double fmod(double D, double M) { return D - (int)(D / M) * M; } private double 上下開き(double X, double Y) { double R = Math.Sqrt(X * X + Y * Y); if (R >= 10) return 0; else if (fmod(R, 4.0) > 2.0) return Y / 10; else return -Y / 10; } private double 双曲放物線(double X, double Y) { return (X * X - Y * Y) / 50; } private double 二次錘面(double X, double Y) { return 1 - Math.Sqrt(X * X + Y * Y) / 5; } private double 十字(double X, double Y) { double XX = Math.Abs(X); double YY = Math.Abs(Y); if (XX > 5 || YY > 5) return -1; else if (XX < 1 || YY < 1) return 1; else return -1; } private double Def_Exp(double X, double Y) { double XX = X / 5; double YY = Y / 5; double R = XX * XX + YY * YY; return (XX - YY) * Math.Exp(-R); } private double mult_R(double X, double Y) { double XX = fmod(X, 4) - 2; double YY = fmod(Y, 4) - 2; double R = Math.Sqrt(XX * XX + YY * YY); if (R > 1) return 0; else return Math.Sqrt(1 - R * R); } private double func10(double X, double Y) { return (Math.Cos(X / 1.5) + Math.Sin(Y / 1.5)) / 2; } private double func11(double X, double Y) { double XX = X / 3; double YY = Y / 3; if (XX > 0) XX = -XX; if (YY > 0) YY = -YY; return Math.Exp(XX + YY) * 2 - 1; } private double 関数呼出(double X, double Y) { int ID = comboBox1.SelectedIndex; switch (ID) { case 0: return SinR_dev_R(X, Y); case 1: return 半球(X, Y); case 2: return 円筒(X, Y); case 3: return ピラミッド(X, Y); case 4: return 上下開き(X, Y); case 5: return 双曲放物線(X, Y); case 6: return 二次錘面(X, Y); case 7: return 十字(X, Y); case 8: return Def_Exp(X, Y); case 9: return mult_R(X, Y); case 10: return func10(X, Y); case 11: return func11(X, Y); } return 0; } public void ドット表示(PaintEventArgs e) { double X1 = -12; double X2 = 12; double Y1 = 10; double Y2 = -10; double R0 = double.Parse(textBox1.Text); double UNIT = 6; double XY = 1; int Loop = 3000; double Period = (X2 - X1) / 6; double Z0 = R0 * Period; double R, X, Y, Z; Pen pen = new Pen(Color.Black, 0.001F); Brush brush = new SolidBrush(Color.Black); e.Graphics.Clear(Color.White); float XX = (float)(Period / 6.0); float YY = (float)(Y1 * 1.1); e.Graphics.DrawEllipse(pen, -XX, YY, 0.1F, 0.1F); e.Graphics.DrawEllipse(pen, XX, YY, 0.1F, 0.1F); Random RD = new Random(); for (int i = 0; i < Loop; i++) { R = RD.NextDouble(); Y = R * (Y2 - Y1) + Y1; Z = 関数呼出(X1, Y); R = RD.NextDouble(); X = (Period + Math.Abs(Z0 * Z)) * R + X1; while (X <= X2) { double XP = (X - (X1 + X2) * 0.5) * UNIT; double YP = (Y - (Y1 + Y2) * 0.5) * UNIT; e.Graphics.FillRectangle(brush, (float)(X - 0.025), (float)(Y - 0.025), 0.1F, 0.1F); Z = 関数呼出(X + Period * 0.5, Y); X = X + Period - XY * Z0 * Z; } } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.Clear(Color.White); e.Graphics.Transform = matrix; if (処理 != "") ドット表示(e); Pen pen = new Pen(Color.Black, 0.001F); e.Graphics.Transform = matrix; e.Graphics.DrawLine(pen, -12F, 10F, 12F, 10F); e.Graphics.DrawLine(pen, -12F, -10F, 12F, -10F); e.Graphics.DrawLine(pen, -12F, 10F, -12F, -10F); e.Graphics.DrawLine(pen, 12F, 10F, 12F, -10F); } private void window(float X1, float Y1, float X2, float Y2) { float W = this.Width; float H = this.Height; float SX = W / (X2 - X1); float SY = H / (Y2 - Y1); matrix.Scale(SX, SY); matrix.Translate(-X1, -Y1); } private void Form1_Load(object sender, EventArgs e) { 処理 = ""; window(-12F * 1.2F, 12F * 1.4F, 10F * 1.4F, -10F * 1.4F); comboBox1.Items.Clear(); comboBox1.Items.Add("sin(R)/R"); comboBox1.Items.Add("半球"); comboBox1.Items.Add("円筒"); comboBox1.Items.Add("ピラミッド"); comboBox1.Items.Add("上下開き"); comboBox1.Items.Add("双曲放物面"); comboBox1.Items.Add("二次錘面"); comboBox1.Items.Add("十字"); comboBox1.Items.Add("(x-y)exp(-(x*x+y*y))"); comboBox1.Items.Add("繰返し"); comboBox1.Items.Add("cos(x)+sin(y)"); comboBox1.Items.Add("exp(-(abs(x)+abs(y))"); comboBox1.SelectedIndex = 0; } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { 処理 = "Exe"; this.Invalidate(); } } }