첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

■ 아르키메데스 나선(Archimedes Spiral) 그리기

------------------------------------------------------------------------------------------------------------------------


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

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요