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

■ 별난 끌개 프랙탈(Strange Attractor Fractal) 그리기

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


TestProject.zip


MainForm.cs

 

 

using System;

using System.Drawing;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 비트맵

        /// </summary>

        private Bitmap bitmap;

 

        /// <summary>

        /// 이미지 너비

        /// </summary>

        private double imageWidth;

        

        /// <summary>

        /// 이미지 높이

        /// </summary>

        private double imageHeight;

 

        /// <summary>

        /// 계수 배열

        /// </summary>

        private double[] coefficientArray = new double[12];

 

        /// <summary>

        /// X

        /// </summary>

        private double x;

        

        /// <summary>

        /// Y

        /// </summary>

        private double y;

        

        /// <summary>

        /// X 최소값

        /// </summary>

        private double xMinimum;

        

        /// <summary>

        /// X 최대값

        /// </summary>

        private double xMaximuma;

        

        /// <summary>

        /// Y 최소값

        /// </summary>

        private double yMinimum;

        

        /// <summary>

        /// Y 최대값

        /// </summary>

        private double yMaximum;

        

        /// <summary>

        /// 너비

        /// </summary>

        private double width;

        

        /// <summary>

        /// 높이

        /// </summary>

        private double height;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            Load                                          += Form_Load;

            this.coefficientComboBox.SelectedIndexChanged += coefficientComboBox_SelectedIndexChanged;

            this.showAxesCheckBox.CheckedChanged          += showAxesCheckBox_CheckedChanged;

            this.drawButton.Click                         += drawButton_Click;

            this.canvasPictureBox.Resize                  += canvasPictureBox_Resize;

            this.timer.Tick                               += timer_Tick;

 

            #endregion

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

 

        /// <summary>

        /// 폼 로드시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_Load(object sender, EventArgs e)

        {

            this.coefficientComboBox.SelectedIndex = 0;

 

            DrawNewImage();

        }

 

        #endregion

        #region 계수 콤보 박스 선택 인덱스 변경시 처리하기 - coefficientComboBox_SelectedIndexChanged(sender, e)

 

        /// <summary>

        /// 계수 콤보 박스 선택 인덱스 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void coefficientComboBox_SelectedIndexChanged(object sender, EventArgs e)

        {

            DrawNewImage();

        }

 

        #endregion

        #region 축 표시 체크 박스 체크 변경시 처리하기 - showAxesCheckBox_CheckedChanged(sender, e)

 

        /// <summary>

        /// 축 표시 체크 박스 체크 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void showAxesCheckBox_CheckedChanged(object sender, EventArgs e)

        {

            DrawNewImage();

        }

 

        #endregion

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

 

        /// <summary>

        /// 그리기 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void drawButton_Click(object sender, EventArgs e)

        {

            this.timer.Enabled = !this.timer.Enabled;

 

            if(this.timer.Enabled)

            {

                this.drawButton.Text = "중단";

            }

            else

            {

                this.drawButton.Text = "그리기";

            }

        }

 

        #endregion

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

 

        /// <summary>

        /// 캔버스 픽처 박스 크기 조정시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void canvasPictureBox_Resize(object sender, EventArgs e)

        {

            DrawNewImage();

        }

 

        #endregion

        #region 타이머 틱 처리하기 - timer_Tick(sender, e)

 

        /// <summary>

        /// 타이머 틱 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void timer_Tick(object sender, EventArgs e)

        {

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

            {

                double newX = this.coefficientArray[0] + this.coefficientArray[1] * this.x +

                    this.coefficientArray[2] * this.x * this.x + this.coefficientArray[3] * this.x * this.y +

                    this.coefficientArray[4 ] * this.y + this.coefficientArray[5] * this.y * this.y;

                double newY = this.coefficientArray[6] + this.coefficientArray[7] * this.x +

                    this.coefficientArray[8] * this.x * this.x + this.coefficientArray[9] * this.x * this.y +

                    this.coefficientArray[10] * this.y + this.coefficientArray[11] * this.y * this.y;

 

                this.x = newX;

                this.y = newY;

 

                int xPixel = (int)Math.Round((this.x - this.xMinimum) / this.width * this.imageWidth);

                int yPixel = (int)Math.Round(this.imageHeight - (this.y - this.yMinimum) / this.height * this.imageHeight - 1);

 

                if((xPixel >= 0) && (xPixel < this.imageWidth) && (yPixel >= 0) && (yPixel < this.imageHeight))

                {

                    this.bitmap.SetPixel(xPixel, yPixel, Color.Blue);

                }

            }

 

            this.canvasPictureBox.Refresh();

        }

 

        #endregion

 

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

 

        #region 계수 설정하기 - SetCoefficient(coefficientString)

 

        /// <summary>

        /// 계수 설정하기

        /// </summary>

        /// <param name="coefficientString">계수 문자열</param>

        private void SetCoefficient(string coefficientString)

        {

            if(coefficientString.Length == 0)

            {

                return;

            }

 

            const int aASCII = (int)'A';

 

            string[] itemArray = coefficientString.Split(' ');

 

            char[] coefficientCharacterArray = itemArray[0].ToUpper().ToCharArray();

 

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

            {

                coefficientArray[i] = -1.2 + ((int)coefficientCharacterArray[i] - aASCII) * 0.1;

            }

 

            this.xMinimum  = double.Parse(itemArray[1]);

            this.xMaximuma = double.Parse(itemArray[2]);

            this.yMinimum  = double.Parse(itemArray[3]);

            this.yMaximum  = double.Parse(itemArray[4]);

 

            this.width  = this.xMaximuma - this.xMinimum;

            this.height = this.yMaximum  - this.yMinimum;

        }

 

        #endregion

        #region 새 이미지 그리기 - DrawNewImage()

 

        /// <summary>

        /// 새 이미지 그리기

        /// </summary>

        private void DrawNewImage()

        {

            if(this.canvasPictureBox.ClientSize.Width <= 0 || this.canvasPictureBox.ClientSize.Height <= 0)

            {

                return;

            }

 

            this.imageWidth  = this.canvasPictureBox.ClientSize.Width;

            this.imageHeight = this.canvasPictureBox.ClientSize.Height;

 

            SetCoefficient(this.coefficientComboBox.Text);

 

            this.x = 0;

            this.y = 0;

 

            this.bitmap = new Bitmap((int)this.imageWidth, (int)this.imageHeight);

 

            this.canvasPictureBox.BackgroundImage = this.bitmap;

 

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

            {

                graphics.Clear(Color.Black);

 

                if(this.showAxesCheckBox.Checked)

                {

                    int xPixel = (int)Math.Round((0 - this.xMinimum) / this.width * this.imageWidth);

                    int yPixel = (int)Math.Round(this.imageHeight - (0 - this.yMinimum) / this.height * this.imageHeight - 1);

 

                    graphics.DrawLine(Pens.Red, xPixel, 0, xPixel, this.canvasPictureBox.ClientSize.Height);


                    graphics.DrawLine(Pens.Red, 0, yPixel, this.canvasPictureBox.ClientSize.Width, yPixel);

 

                    for(float i = -5; i <= 5; i += 0.1f)

                    {

                        xPixel = (int)Math.Round((i - this.xMinimum) / this.width * this.imageWidth);

 

                        graphics.DrawLine(Pens.Orange, xPixel, yPixel - 3, xPixel, yPixel + 3);

                    }

 

                    for(float i = -5; i <= 5; i += 1)

                    {

                        xPixel = (int)Math.Round((i - this.xMinimum) / this.width * this.imageWidth);

 

                        graphics.DrawLine(Pens.Yellow, xPixel, yPixel - 5, xPixel, yPixel + 5);

                    }

 

                    xPixel = (int)Math.Round((0 - this.xMinimum) / this.width * this.imageWidth);

 

                    for(float i = -5; i <= 5; i += 0.1f)

                    {

                        yPixel = (int)Math.Round(this.imageHeight - (i - this.yMinimum) / this.height * this.imageHeight - 1);

 

                        graphics.DrawLine(Pens.Orange, xPixel - 3, yPixel, xPixel + 3, yPixel);

                    }

 

                    for(float i = -5; i <= 5; i += 1)

                    {

                        yPixel = (int)Math.Round(this.imageHeight - (i - this.yMinimum) / this.height * this.imageHeight - 1);

 

                        graphics.DrawLine(Pens.Yellow, xPixel - 5, yPixel, xPixel + 5, yPixel);

                    }

                }

            }

 

            this.canvasPictureBox.Invalidate();

        }

 

        #endregion

    }

}

 

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

Posted by 사용자 icodebroker

댓글을 달아 주세요