첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ MainForm.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 개시자 포인트 리스트
        /// </summary>
        private List<PointF> initiatorPointList;

        /// <summary>
        /// 스케일 팩터
        /// </summary>
        private float scaleFactor;

        /// <summary>
        /// 생성자 델타 세타
        /// </summary>
        private List<float> generatorDeltaTheta;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            #region 이벤트를 설정한다.

            this.drawButton.Click += drawButton_Click;

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 그리기 버튼 클릭시 처리하기 - drawButton_Click(sender, e)

        /// <summary>
        /// 그리기 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void drawButton_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            Application.DoEvents();

            this.initiatorPointList = new List<PointF>();

            float sqrt3  = (float)Math.Sqrt(3.0);
            float side1  = (this.canvasPictureBox.ClientSize.Height - 10f) / 2f;
            float side2  = (this.canvasPictureBox.ClientSize.Width  - 10f) / 2f / sqrt3 * 2f;
            float side   = Math.Min(side1, side2);
            float height = side * sqrt3 / 2f;
            float y1     = (this.canvasPictureBox.ClientSize.Height - 2 * side) / 2;
            float y2     = y1 + side / 2;
            float y3     = y2 + side;
            float y4     = y1 + 2 * side;
            float x1     = (this.canvasPictureBox.ClientSize.Width - 2 * height) / 2;
            float x2     = x1 + height;
            float x3     = x2 + height;

            this.initiatorPointList.Add(new PointF(x1, y2));
            this.initiatorPointList.Add(new PointF(x2, y1));
            this.initiatorPointList.Add(new PointF(x3, y2));
            this.initiatorPointList.Add(new PointF(x3, y3));
            this.initiatorPointList.Add(new PointF(x2, y4));
            this.initiatorPointList.Add(new PointF(x1, y3));
            this.initiatorPointList.Add(new PointF(x1, y2));

            this.scaleFactor = (float)(1.0 / 3.0);

            this.generatorDeltaTheta = new List<float>();

            float piOver3 = (float)(Math.PI / 3f);

            this.generatorDeltaTheta.Add(0           );
            this.generatorDeltaTheta.Add(piOver3     );
            this.generatorDeltaTheta.Add(piOver3     );
            this.generatorDeltaTheta.Add(-2 * piOver3);
            this.generatorDeltaTheta.Add(-piOver3    );
            this.generatorDeltaTheta.Add(-piOver3    );
            this.generatorDeltaTheta.Add(2 * piOver3 );

            int depth = int.Parse(this.depthTextBox.Text);

            Bitmap bitmap = new Bitmap
            (
                this.canvasPictureBox.ClientSize.Width,
                this.canvasPictureBox.ClientSize.Height
            );

            this.canvasPictureBox.Image = bitmap;

            using(Graphics graphics = Graphics.FromImage(bitmap))
            {
                graphics.SmoothingMode = SmoothingMode.AntiAlias;

                DrawSnowFlakeFractal(graphics, depth);
            }

            Cursor = Cursors.Default;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 눈송이 에지 그리기 - DrawSnowFlakeEdge(graphics, depth, point1, theta, distance)

        /// <summary>
        /// 눈송이 에지 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        /// <param name="depth">깊이</param>
        /// <param name="point1">포인트 1</param>
        /// <param name="theta">세타</param>
        /// <param name="distance">거리</param>
        private void DrawSnowFlakeEdge(Graphics graphics, int depth, ref PointF point1, float theta, float distance)
        {
            if(depth == 0)
            {
                PointF point2 = new PointF
                (
                    (float)(point1.X + distance * Math.Cos(theta)),
                    (float)(point1.Y + distance * Math.Sin(theta))
                );

                graphics.DrawLine(Pens.Blue, point1, point2);

                point1 = point2;

                return;
            }

            distance *= this.scaleFactor;

            for(int i = 0; i < this.generatorDeltaTheta.Count; i++)
            {
                theta += this.generatorDeltaTheta[i];

                DrawSnowFlakeEdge(graphics, depth - 1, ref point1, theta, distance);
            }
        }

        #endregion
        #region 눈송이 프랙탈 그리기 - DrawSnowFlakeFractal(graphics, depth)

        /// <summary>
        /// 눈송이 프랙탈 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        /// <param name="depth">깊이</param>
        private void DrawSnowFlakeFractal(Graphics graphics, int depth)
        {
            graphics.Clear(this.canvasPictureBox.BackColor);

            for(int i = 1; i < this.initiatorPointList.Count; i++)
            {
                PointF point1 = this.initiatorPointList[i - 1];
                PointF point2 = this.initiatorPointList[i    ];

                float deltaX = point2.X - point1.X;
                float deltaY = point2.Y - point1.Y;
                float length = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
                float theta  = (float)Math.Atan2(deltaY, deltaX);

                DrawSnowFlakeEdge(graphics, depth, ref point1, theta, length);
            }
        }

        #endregion
    }
}
728x90
반응형
그리드형
Posted by 사용자 icodebroker

댓글을 달아 주세요