ドラゴン曲線

Windowsフォームアプリケーションに、ボタンとラベル、タイマーを配置。

点P1と点P2があるとき、ベクトルP1→P2 をcos45°倍の長さにして、 P1中心に反時計回りに45度回転させたベクトルをつくる。P1にそのベクトルを足した先にある点を点P3とする。
点P1, P3と、点 P2,P3に対して再帰的に上の操作を繰り返す。(順序が大事。)


2015_09_02_02


using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private static Bitmap bmp;
        private int depth = 0;
        private Pen pen;
        private Rectangle rect;

        public Form1()
        {
            InitializeComponent();
            pen = Pens.Aqua;
            this.BackColor = Color.Black;
            this.Text = "ドラゴン曲線";
            label1.Text = "深度 =";
            label1.ForeColor = Color.LimeGreen;
            bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            DrawDragonCurve(depth);
            label1.Text = "深度 = " + depth.ToString();
            depth++;
            if (depth >= 18) {
                timer1.Stop();
                this.button1.Enabled = true;
                this.button1.Text = "実行";
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {
            bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            rect = new Rectangle(0,0, bmp.Width , bmp.Height);
            depth = 0;
            this.button1.Enabled = false;
            this.button1.Text = "実行中....";
            timer1.Start();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.DrawImage(bmp, 0, 0,bmp.Width, bmp.Height);
        }
        public void DrawDragonCurve(int depth)
        {
            bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            (Graphics.FromImage(bmp)).FillRectangle(Brushes.Black, rect);

            PointF p1 = new PointF(bmp.Width * 0.25f, bmp.Height * 0.65f);
            PointF p2 = new PointF(bmp.Width * 0.85f, bmp.Height * 0.65f);
            Draw(bmp, p1, p2, depth);
            Invalidate();
        }

        private void Draw(Bitmap bmp, PointF p1, PointF p2, int depth)
        {
            if (depth == 0)
            {
                (Graphics.FromImage(bmp)).DrawLine(pen, p1.X, p1.Y, p2.X, p2.Y);
            }
            else
            {
                float dx = p2.X - p1.X;
                float dy = p2.Y - p1.Y;
                PointF p3 = new PointF((float)(dx + dy) / 2 + p1.X, (float)(-dx + dy) / 2 + p1.Y);
                Draw(bmp, p1, p3, depth - 1);
                Draw(bmp, p2, p3, depth - 1);
            }
        }

    }
}


参考:Gushwellさん