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

728x90
반응형
728x170

TestProject.zip
다운로드

▶ MainForm.cs

using System;
using System.Collections.Generic;
using System.Drawing;
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 height = 0.75f * 
            (
                Math.Min
                (
                    this.canvasPictureBox.ClientSize.Width,
                    this.canvasPictureBox.ClientSize.Height
                ) - 20
            );
            float width  = (float)(height / Math.Sqrt(3.0) * 2);
            float y3     = this.canvasPictureBox.ClientSize.Height - 10;
            float y1     = y3 - height;
            float x3     = canvasPictureBox.ClientSize.Height / 2;
            float x1     = x3 - width / 2;
            float x2     = x1 + width;

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

            this.scaleFactor = 1 / 3f;

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

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

            this.generatorDeltaTheta.Add(0);
            this.generatorDeltaTheta.Add(-piOver3);
            this.generatorDeltaTheta.Add(2 * piOver3);
            this.generatorDeltaTheta.Add(-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 = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                DrawSnowFlakeFractal(graphics, depth);
            }

            this.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 p1 = this.initiatorPointList[i - 1];
                PointF p2 = this.initiatorPointList[i];

                float dx     = p2.X - p1.X;
                float dy     = p2.Y - p1.Y;
                float length = (float)Math.Sqrt(dx * dx + dy * dy);
                float theta  = (float)Math.Atan2(dy, dx);

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

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

댓글을 달아 주세요