C#で(PictureBoxに)マンデルブロ集合を描く
PictureBoxを使うとOnPaintイベントハンドラをoverrideしなくても描画できるみたいだった。Formのコンストラクタの中で描画したらRefresh()メソッドを呼ばなくてもImageが表示されていた(Formを作成した後にImageを更新した場合にはRefreshが必要だった)。ついでに今回は自作の複素数クラスではなくNumericsのComplexを使ったのでコンパイルにはNumerics.dllを参照する必要がある。
csc /reference:System.Numerics.dll ファイル名
実数部はプロパティRealで、虚数部はImaginaryで取得できる。発散の判断をするために原点からの距離を知りたいのでComplex.Abs()を使用した。理論的なことは知らないが絶対値が一度2を超えてしまうと収束しないらしいので。
※#タグが使えるようになったというのでC#のタグをつけまくろうかしらん。#C#
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; using System.Drawing.Imaging; using System.Numerics; namespace WindowsFormsApplication1 { public partial class Form1 : Form { Image image; int width = 800; int height = 500; public Complex Pixel2Complex(int i, int j, Complex c, double unit) { double a, b; a = c.Real + unit * i; b = c.Imaginary - unit * j; return new Complex(a, b); } void DrawFractal() { Complex leftUpPosition = new Complex(-2.35, 1.25); double pixelUnit = 0.005; int iteration = 200; Complex[] z = new Complex[iteration + 1]; Complex zc; Brush[] palet = { new SolidBrush(Color.Black), // 0 new SolidBrush(Color.Blue), // 1 new SolidBrush(Color.FromArgb(140, 255, 255)), // 2 new SolidBrush(Color.FromArgb(255, 170, 170)), // 3 new SolidBrush(Color.Red), // 4 new SolidBrush(Color.Purple), // 5 new SolidBrush(Color.Yellow), // 6 new SolidBrush(Color.YellowGreen), // 7 new SolidBrush(Color.FromArgb(255, 0, 170)), // 8 new SolidBrush(Color.SeaGreen), // 9 new SolidBrush(Color.FromArgb(255, 200, 0)), // 10 new SolidBrush(Color.Silver), // 11 new SolidBrush(Color.FromArgb(255, 160, 0)), // 12 new SolidBrush(Color.SpringGreen), // 13 new SolidBrush(Color.FromArgb(255, 200, 255)), // 14 new SolidBrush(Color.FromArgb(0, 170, 170)), // 15 new SolidBrush(Color.FromArgb(0, 250, 0)), // 16 new SolidBrush(Color.FromArgb(0, 200, 0)), // 17 new SolidBrush(Color.FromArgb(0, 150, 0)), // 18 new SolidBrush(Color.FromArgb(0, 100, 0)), // 19 new SolidBrush(Color.FromArgb(0, 50, 0)), // 20 new SolidBrush(Color.White) // 21 }; int MaxCycle = palet.Length - 1; Graphics g = Graphics.FromImage(image); int imax = image.Width; int jmax = image.Height; double n_progress = imax / 100.0; double s; int i; int j; int k; for (i = 0; i < imax; i++) { for (j = 0; j < jmax; j++) { z[0] = Pixel2Complex(i, j, leftUpPosition, pixelUnit); zc = z[0]; for (k = 0; k < iteration; k++) { z[k + 1] = z[k] * z[k] + zc; s = Complex.Abs(z[k]); if (s > 2.0) { g.FillRectangle(palet[0], i, j, 1, 1); break; } } if (k == iteration) { int n; for (n = 1; n < MaxCycle; n++) { s = Complex.Abs(z[iteration] - z[iteration - n]); if (s < pixelUnit) { g.FillRectangle(palet[n], i, j, 1, 1); break; } } if (n == MaxCycle) { g.FillRectangle(palet[MaxCycle], i, j, 1, 1); } } } } } public Form1() { InitializeComponent(); image = new Bitmap(width, height); this.pictureBox1.Image = image; DrawFractal(); } } }