첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
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 Pen[] penArray =
        {
            Pens.Red,
            Pens.Green,
            Pens.Purple,
            Pens.Blue,
            Pens.Magenta
        };

        #endregion

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

        #region 생성자 - MainForm()

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

            #region 이벤트를 설정한다.

            this.drawButton.Click        += drawButton_Click;
            this.canvasPictureBox.Resize += canvasPictureBox_Resize;
            this.canvasPictureBox.Paint  += canvasPictureBox_Paint;

            #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)
        {
            this.canvasPictureBox.Refresh();
        }

        #endregion
        #region 캔버스 픽처 박스 크기 조정시 처리하기 - canvasPictureBox_Resize(sender, e)

        /// <summary>
        /// 캔버스 픽처 박스 크기 조정시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void canvasPictureBox_Resize(object sender, EventArgs e)
        {
            this.canvasPictureBox.Refresh();
        }

        #endregion
        #region 캔버스 픽처 박스 페인트시 처리하기 - canvasPictureBox_Paint(sender, e)

        /// <summary>
        /// 캔버스 픽처 박스 페인트시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void canvasPictureBox_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(this.canvasPictureBox.BackColor);

            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

            try
            {
                float a           = float.Parse(this.aTextBox.Text);
                int   spiralCount = int.Parse(this.spiralCountTextBox.Text);

                float angleStep  = (float)(2 * Math.PI / spiralCount);
                float startAngle = 0;

                PointF centerPoint = new PointF
                (
                    this.canvasPictureBox.ClientSize.Width  / 2,
                    this.canvasPictureBox.ClientSize.Height / 2
                );

                e.Graphics.DrawLine
                (
                    Pens.Black,
                    centerPoint.X,
                    0,
                    centerPoint.X,
                    this.canvasPictureBox.ClientSize.Height
                );

                e.Graphics.DrawLine
                (
                    Pens.Black,
                    0,
                    centerPoint.Y,
                    this.canvasPictureBox.ClientSize.Width,
                    centerPoint.Y
                );

                Rectangle rectangle = new Rectangle(25, 50, 150, 150);

                float maximumR = GetDistance(centerPoint, rectangle);

                for(int i = 0; i < spiralCount; i++)
                {
                    List<PointF> pointList = GetSpiralPointList(centerPoint, a, startAngle, maximumR);

                    e.Graphics.DrawLines(this.penArray[i % this.penArray.Length], pointList.ToArray());

                    startAngle += angleStep;
                }

                e.Graphics.DrawRectangle(Pens.Black, rectangle);
            }
            catch(Exception exception)
            {
                MessageBox.Show(exception.Message);
            }
        }

        #endregion

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

        #region 거리 구하기 - GetDistance(point1, point2)

        /// <summary>
        /// 거리 구하기
        /// </summary>
        /// <param name="point1">포인트 1</param>
        /// <param name="point2">포인트 2</param>
        /// <returns>거리</returns>
        private float GetDistance(PointF point1, PointF point2)
        {
            float deltaX = point1.X - point2.X;
            float deltaY = point1.Y - point2.Y;

            return (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
        }

        #endregion
        #region 거리 구하기 - GetDistance(point, rectangle)

        /// <summary>
        /// 거리 구하기
        /// </summary>
        /// <param name="point">포인트</param>
        /// <param name="rectangle">사각형</param>
        /// <returns>거리</returns>
        private float GetDistance(PointF point, Rectangle rectangle)
        {
            float maximumDistance = GetDistance(point, new PointF(rectangle.Left, rectangle.Top));

            float testDistance = GetDistance(point, new PointF(rectangle.Left, rectangle.Bottom));

            if(maximumDistance < testDistance)
            {
                maximumDistance = testDistance;
            }

            testDistance = GetDistance(point, new PointF(rectangle.Right, rectangle.Top));

            if(maximumDistance < testDistance)
            {
                maximumDistance = testDistance;
            }
            
            testDistance = GetDistance(point, new PointF(rectangle.Right, rectangle.Bottom));

            if(maximumDistance < testDistance)
            {
                maximumDistance = testDistance;
            }

            return maximumDistance;
        }

        #endregion
        #region 극 좌표계를 데카르트 좌표계로 변환하기 - ConvertPolarCoordinatesToCartesianCoordinates(r, theta, x, y)

        /// <summary>
        /// 극 좌표계를 데카르트 좌표계로 변환하기
        /// </summary>
        /// <param name="r">R</param>
        /// <param name="theta">세타</param>
        /// <param name="x">X</param>
        /// <param name="y">Y</param>
        private void ConvertPolarCoordinatesToCartesianCoordinates(float r, float theta, out float x, out float y)
        {
            x = (float)(r * Math.Cos(theta));
            y = (float)(r * Math.Sin(theta));
        }

        #endregion
        #region 나선 포인트 리스트 구하기 - GetSpiralPointList(centerPoint, a, angleOffset, maximumR)

        /// <summary>
        /// 나선 포인트 리스트 구하기
        /// </summary>
        /// <param name="centerPoint">중심 포인트</param>
        /// <param name="a">A</param>
        /// <param name="angleOffset">각도 오프셋</param>
        /// <param name="maximumR">최대 R</param>
        /// <returns>나선 포인트 리스트</returns>
        private List<PointF> GetSpiralPointList(PointF centerPoint, float a, float angleOffset, float maximumR)
        {
            List<PointF> pointList = new List<PointF>();

            const float DELTA_THETA = (float)(5 * Math.PI / 180);

            for(float theta = 0; ; theta += DELTA_THETA)
            {
                float r = a * theta;

                float x;
                float y;

                ConvertPolarCoordinatesToCartesianCoordinates(r, theta + angleOffset, out x, out y);

                x += centerPoint.X;
                y += centerPoint.Y;

                pointList.Add(new PointF((float)x, (float)y));

                if(r > maximumR)
                {
                    break;
                }
            }
            return pointList;
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요