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

■ 테오 스파이럴(Spiral of Theodorus) 그리기

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


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

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// 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)

        {

            int triangleCount = int.Parse(this.triangleCountTextBox.Text);

 

            List<PointF> edgePointList = GetTheodorusPointList(triangleCount);

 

            this.canvasPictureBox.Image = GetTheodorusSpiralBitmap

            (

                edgePointList,

                this.canvasPictureBox.ClientSize,

                this.outlineCheckBox.Checked,

                this.fillCheckBox.Checked

            );

        }

 

        #endregion

 

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

 

        #region 테오 포인트 리스트 구하기 - GetTheodorusPointList(triangleCount)

 

        /// <summary>

        /// 테오 포인트 리스트 구하기

        /// </summary>

        /// <param name="triangleCount">삼각형 수</param>

        /// <returns>테오 포인트 리스트</returns>

        private List<PointF> GetTheodorusPointList(int triangleCount)

        {

            List<PointF> edgePointList = new List<PointF>();

 

            float theta  = 0;

            float radius = 1;

 

            for(int i = 1; i <= triangleCount + 1; i++)

            {

                radius = (float)Math.Sqrt(i);

 

                edgePointList.Add

                (

                    new PointF

                    (

                        radius * (float)Math.Cos(theta),

                        radius * (float)Math.Sin(theta)

                    )

                );

 

                theta -= (float)Math.Atan2(1, radius);

            }

 

            return edgePointList;

        }

 

        #endregion

        #region 무지개 색상 배열 구하기 - GetRainbowColorArray(alpha)

 

        /// <summary>

        /// 무지개 색상 배열 구하기

        /// </summary>

        /// <param name="alpha">알파</param>

        /// <returns>무지개 색상 배열</returns>

        private Color[] GetRainbowColorArray(byte alpha)

        {

            return new Color[]

            {

                Color.FromArgb(alpha, 255, 0  , 0  ),

                Color.FromArgb(alpha, 255, 255, 0  ),

                Color.FromArgb(alpha, 255, 128, 0  ),

                Color.FromArgb(alpha, 0  , 255, 0  ),

                Color.FromArgb(alpha, 0  , 255, 255),

                Color.FromArgb(alpha, 0  , 0  , 255),

                Color.FromArgb(alpha, 255, 0  , 255)

            };

        }

 

        #endregion

        #region 브러시 배열 구하기 - GetBrushArray(colorArray)

 

        /// <summary>

        /// 브러시 배열 구하기

        /// </summary>

        /// <param name="colorArray">색상 배열</param>

        /// <returns>브러시 배열</returns>

        private Brush[] GetBrushArray(Color[] colorArray)

        {

            int colorCount = colorArray.Length;

 

            Brush[] brushArray = new Brush[colorCount];

 

            for(int i = 0; i < colorCount; i++)

            {

                brushArray[i] = new SolidBrush(colorArray[i]);

            }

 

            return brushArray;

        }

 

        #endregion

        #region 테두리 값 설정하기 - SetBoundaryValue(pointList, minimumX, maximumX, minimumY, maximumY)

 

        /// <summary>

        /// 테두리 값 설정하기

        /// </summary>

        /// <param name="pointList">포인트 리스트</param>

        /// <param name="minimumX">최소 X</param>

        /// <param name="maximumX">최대 X</param>

        /// <param name="minimumY">최소 Y</param>

        /// <param name="maximumY">최대 Y</param>

        private void SetBoundaryValue(List<PointF> pointList, out float minimumX, out float maximumX, out float minimumY, out float maximumY)

        {

            minimumX = pointList[0].X;

            maximumX = minimumX;

            minimumY = pointList[0].Y;

            maximumY = minimumY;

 

            foreach(PointF point in pointList)

            {

                if(minimumX > point.X)

                {

                    minimumX = point.X;

                }

 

                if(maximumX < point.X)

                {

                    maximumX = point.X;

                }

 

                if(minimumY > point.Y)

                {

                    minimumY = point.Y;

                }

 

                if(maximumY < point.Y)

                {

                    maximumY = point.Y;

                }

            }

        }

 

        #endregion

        #region 그리기 매핑 설정하기 - SetDrawingMapping(graphics, drawingRectangle, targetRectangle, stretch)

 

        /// <summary>

        /// 그리기 매핑 설정하기

        /// </summary>

        /// <param name="graphics">그래픽스</param>

        /// <param name="drawingRectangle">그리기 사각형</param>

        /// <param name="targetRectangle">타겟 사각형</param>

        /// <param name="stretch">늘리기 여부</param>

        private void SetDrawingMapping(Graphics graphics, RectangleF drawingRectangle, RectangleF targetRectangle, bool stretch)

        {

            if((targetRectangle.Width < 1) || (targetRectangle.Height < 1))

            {

                return;

            }

 

            graphics.ResetTransform();

 

            float drawingCenterX = (drawingRectangle.Left + drawingRectangle.Right ) / 2;

            float drawingCenterY = (drawingRectangle.Top  + drawingRectangle.Bottom) / 2;

 

            graphics.TranslateTransform(-drawingCenterX, -drawingCenterY);

 

            float scaleX = targetRectangle.Width  / drawingRectangle.Width;

            float scaleY = targetRectangle.Height / drawingRectangle.Height;

 

            if(!stretch)

            {

                scaleX = Math.Min(scaleX, scaleY);

                scaleY = scaleX;

            }

 

            graphics.ScaleTransform(scaleX, scaleY, MatrixOrder.Append);

 

            float graphicsCenterX = (targetRectangle.Left + targetRectangle.Right ) / 2;

            float graphicsCenterY = (targetRectangle.Top  + targetRectangle.Bottom) / 2;

 

            graphics.TranslateTransform(graphicsCenterX, graphicsCenterY, MatrixOrder.Append);

        }

 

        #endregion

        #region 테오 스파이럴 비트맵 구하기 - GetTheodorusSpiralBitmap(edgePointList, size, outlineTriangle, fillTriangle)

 

        /// <summary>

        /// 테오 스파이럴 비트맵 구하기

        /// </summary>

        /// <param name="edgePointList">에지 포인트 리스트</param>

        /// <param name="size">크기</param>

        /// <param name="outlineTriangle">삼각형 외곽선 그리기 여부</param>

        /// <param name="fillTriangle">삼각형 채우기 여부</param>

        /// <returns>비트맵</returns>

        private Bitmap GetTheodorusSpiralBitmap(List<PointF> edgePointList, Size size, bool outlineTriangle, bool fillTriangle)

        {

            int width  = size.Width;

            int height = size.Height;

 

            Bitmap bitmap = new Bitmap(width, height);

 

            using(Graphics graphics = Graphics.FromImage(bitmap))

            {

                graphics.SmoothingMode = SmoothingMode.AntiAlias;

 

                graphics.Clear(Color.White);

 

                Color[] colorArray = GetRainbowColorArray(255);

                Brush[] brushArray = GetBrushArray(colorArray);

 

                float minimumX;

                float maximumX;

                float minimumY;

                float maximumY;

 

                SetBoundaryValue(edgePointList, out minimumX, out maximumX, out minimumY, out maximumY);

 

                RectangleF drawingRectangle = new RectangleF

                (

                    minimumX,

                    minimumY,

                    maximumX - minimumX,

                    maximumY - minimumY

                );

 

                RectangleF targetRectangle = new RectangleF

                (

                    5,

                    5,

                    width  - 10,

                    height - 10

                );

 

                SetDrawingMapping(graphics, drawingRectangle, targetRectangle, false);

 

                using(Pen pen = new Pen(Color.Black, 0))

                {

                    int brushCount = brushArray.Length;

 

                    for(int i = edgePointList.Count - 1; i > 0; i--)

                    {

                        PointF[] pointArray =

                        {

                            new PointF(0, 0),

                            new PointF(edgePointList[i].X, edgePointList[i].Y),

                            new PointF(edgePointList[i - 1].X, edgePointList[i - 1].Y),

                        };

 

                        if(fillTriangle)

                        {

                            graphics.FillPolygon(brushArray[i % brushCount], pointArray);

                        }

 

                        if(outlineTriangle)

                        {

                            graphics.DrawPolygon(pen, pointArray);

                        }

                    }

                }

            }

 

            return bitmap;

        }

 

        #endregion

    }

}

 

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

Posted by 사용자 icodebroker

댓글을 달아 주세요