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

■ 소용돌이 프랙탈(Vortex Fractal) 그리기

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


TestProject.zip


Complex.cs

 

 

using System;

 

namespace TestProject

{

    /// <summary>

    /// 복소수

    /// </summary>

    public class Complex

    {

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

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

 

        #region Field

 

        /// <summary>

        /// 실수부

        /// </summary>

        public double Real = 0d;

 

        /// <summary>

        /// 허수부

        /// </summary>

        public double Imaginary = 0d;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

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

 

        #region 크기 - Magnitude

 

        /// <summary>

        /// 크기

        /// </summary>

        public double Magnitude

        {

            get

            {

                return (Math.Sqrt(Real * Real + Imaginary * Imaginary));

            }

        }

 

        #endregion

        #region 제곱 크기 - MagnitudeSquared

 

        /// <summary>

        /// 제곱 크기

        /// </summary>

        public double MagnitudeSquared

        {

            get

            {

                return (Real * Real + Imaginary * Imaginary);

            }

        }

 

        #endregion

 

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

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

 

        #region 생성자 - Complex(real, imaginary)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="real">실수부</param>

        /// <param name="imaginary">허수부</param>

        public Complex(double real, double imaginary)

        {

            Real      = real;

            Imaginary = imaginary;

        }

 

        #endregion

        #region 생성자 - Complex(real)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="real">실수부</param>

        public Complex(double real)

        {

            Real      = real;

            Imaginary = 0d;

        }

 

        #endregion

 

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

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

 

        #region 파싱하기 - Parse(source)

 

        /// <summary>

        /// 파싱하기

        /// </summary>

        /// <param name="source">소스 문자열</param>

        /// <returns>복소수</returns>

        public static Complex Parse(string source)

        {

            source = source.Replace(" ", "");

            source = source.ToLower().Replace("i", "");

 

            char[] characterArray = { '+', '-' };

 

            int position = source.IndexOfAny(characterArray);

 

            if(position == 0)

            {

                position = source.IndexOfAny(characterArray, 1);

            }

 

            double real      = double.Parse(source.Substring(0, position));

            double imaginary = double.Parse(source.Substring(position));

 

            return new Complex(real, imaginary);

        }

 

        #endregion

 

        #region + 연산자 재정의하기 - +(c)

 

        /// <summary>

        /// + 연산자 재정의하기

        /// </summary>

        /// <param name="c">복소수</param>

        /// <returns>복소수</returns>

        public static Complex operator +(Complex c)

        {

            return new Complex(c.Real, c.Imaginary);

        }

 

        #endregion

        #region - 연산자 재정의하기 - -(c)

 

        /// <summary>

        /// - 연산자 재정의하기

        /// </summary>

        /// <param name="c">복소수</param>

        /// <returns>복소수</returns>

        public static Complex operator -(Complex c)

        {

            return new Complex(-c.Real, -c.Imaginary);

        }

 

        #endregion

 

        #region + 연산자 재정의하기 - +(c1, c2)

 

        /// <summary>

        /// + 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>복소수</returns>

        public static Complex operator +(Complex c1, Complex c2)

        {

            return new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);

        }

 

        #endregion

        #region - 연산자 재정의하기 - -(c1, c2)

 

        /// <summary>

        /// - 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>복소수</returns>

        public static Complex operator -(Complex c1, Complex c2)

        {

            return new Complex(c1.Real - c2.Real, c1.Imaginary - c2.Imaginary);

        }

 

        #endregion

        #region * 연산자 재정의하기 - *(c1, c2)

 

        /// <summary>

        /// * 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>복소수</returns>

        public static Complex operator *(Complex c1, Complex c2)

        {

            return new Complex

            (

                c1.Real * c2.Real - c1.Imaginary * c2.Imaginary,

                c1.Real * c2.Imaginary + c1.Imaginary * c2.Real

            );

        }

 

        #endregion

        #region / 연산자 재정의하기 - /(c1, c2)

 

        /// <summary>

        /// / 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>복소수</returns>

        public static Complex operator /(Complex c1, Complex c2)

        {

            double denominator = c2.Real * c2.Real + c2.Imaginary * c2.Imaginary;

 

            double real      = (c1.Real * c2.Real + c1.Imaginary * c2.Imaginary) / denominator;

            double imaginary = (c1.Imaginary * c2.Real - c1.Real * c2.Imaginary) / denominator;

 

            return new Complex(real, imaginary);

        }

 

        #endregion

 

        #region < 연산자 재정의하기 - <(c1, c2)

 

        /// <summary>

        /// < 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>처리 결과</returns>

        public static bool operator <(Complex c1, Complex c2)

        {

            return (c1.Magnitude < c2.Magnitude);

        }

 

        #endregion

        #region > 연산자 재정의하기 - >(c1, c2)

 

        /// <summary>

        /// > 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>처리 결과</returns>

        public static bool operator >(Complex c1, Complex c2)

        {

            return (c1.Magnitude > c2.Magnitude);

        }

 

        #endregion

        #region <= 연산자 재정의하기 - <=(c1, c2)

 

        /// <summary>

        /// <= 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>처리 결과</returns>

        public static bool operator <=(Complex c1, Complex c2)

        {

            return (c1.Magnitude <= c2.Magnitude);

        }

 

        #endregion

        #region >= 연산자 재정의하기 - >=(c1, c2)

 

        /// <summary>

        /// >= 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>처리 결과</returns>

        public static bool operator >=(Complex c1, Complex c2)

        {

            return (c1.Magnitude >= c2.Magnitude);

        }

 

        #endregion

        #region == 연산자 재정의하기 - ==(c1, c2)

 

        /// <summary>

        /// == 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>처리 결과</returns>

        public static bool operator ==(Complex c1, Complex c2)

        {

            return (c1.Real == c2.Real && c1.Imaginary == c2.Imaginary);

        }

 

        #endregion

        #region != 연산자 재정의하기 - !=(c1, c2)

 

        /// <summary>

        /// != 연산자 재정의하기

        /// </summary>

        /// <param name="c1">복소수 1</param>

        /// <param name="c2">복소수 2</param>

        /// <returns>처리 결과</returns>

        public static bool operator !=(Complex c1, Complex c2)

        {

            return !(c1 == c2);

        }

 

        #endregion

 

        #region 암시적 형변환 하기 - Complex(real)

 

        /// <summary>

        /// 암시적 형변환 하기

        /// </summary>

        /// <param name="real"></param>

        public static implicit operator Complex(double real)

        {

            return new Complex(real, 0);

        }

 

        #endregion

        #region 명시적 형변환 하기 - double(c)

 

        /// <summary>

        /// 명시적 형변환 하기

        /// </summary>

        /// <param name="c">복소수</param>

        public static explicit operator double(Complex c)

        {

            return c.Magnitude;

        }

 

        #endregion

 

        #region 동일 여부 구하기 - Equals(instance)

 

        /// <summary>

        /// 동일 여부 구하기

        /// </summary>

        /// <param name="instance">인스턴스</param>

        /// <returns>동일 여부</returns>

        public override bool Equals(object instance)

        {

            Complex c = instance as Complex;

 

            return this == c;

        }

 

        #endregion

        #region 해시 코드 구하기 - GetHashCode()

 

        /// <summary>

        /// 해시 코드 구하기

        /// </summary>

        /// <returns>해시 코드</returns>

        public override int GetHashCode()

        {

            return Real.GetHashCode() | Imaginary.GetHashCode();

        }

 

        #endregion

 

        #region 문자열 구하기 - ToString()

 

        /// <summary>

        /// 문자열 구하기

        /// </summary>

        /// <returns>문자열</returns>

        public override string ToString()

        {

            if(Imaginary == 0)

            {

                return string.Format("{0}", Real);

            }

 

            if(Real == 0)

            {

                return string.Format("{0}i", Imaginary);

            }

 

            if(Imaginary < 0)

            {

                return string.Format("{0} - {1}i", Real, Math.Abs(Imaginary));

            }

 

            return string.Format("{0} + {1}i", Real, Imaginary);

        }

 

        #endregion

        #region 문자열 구하기 - ToString(format)

 

        /// <summary>

        /// 문자열 구하기

        /// </summary>

        /// <param name="format">포맷</param>

        /// <returns>문자열</returns>

        public string ToString(string format)

        {

            if(Imaginary == 0)

            {

                return string.Format("{0:" + format + "}", Real);

            }

 

            if(Real == 0)

            {

                return string.Format("{0:" + format + "}i", Imaginary);

            }

 

            if(Imaginary < 0)

            {

                return string.Format("{0:" + format + "} - {1:" + format + "}i", Real, Math.Abs(Imaginary));

            }

 

            return string.Format("{0:" + format + "} + {1:" + format + "}i", Real, Imaginary);

        }

 

        #endregion

    }

}

 

 

MainForm.cs

 

 

using System;

using System.Collections.Generic;

using System.Drawing;

using System.Drawing.Imaging;

using System.Windows.Forms;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

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

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

 

        #region Field

 

        /// <summary>

        /// 최대 반복 카운트

        /// </summary>

        public int MaximumIterationCount;

 

        /// <summary>

        /// 복소수

        /// </summary>

        public Complex Complex;

 

        /// <summary>

        /// 색상 리스트

        /// </summary>

        public List<Color> ColorList = new List<Color>();

 

        #endregion

 

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

 

        #region Field

 

        /// <summary>

        /// 최소 X

        /// </summary>

        private const double MINIMUM_X = -2;

 

        /// <summary>

        /// 최대 X

        /// </summary>

        private const double MAXIMUM_X = 2;

 

        /// <summary>

        /// 최소 Y

        /// </summary>

        private const double MINIMUM_Y = -2;

 

        /// <summary>

        /// 최소 Y

        /// </summary>

        private const double MAXIMUM_Y = 2;

 

        /// <summary>

        /// 상자 그리기 여부

        /// </summary>

        private bool isDrawingBox;

 

        /// <summary>

        /// 시작 X

        /// </summary>

        private double startX;

        

        /// <summary>

        /// 시작 Y

        /// </summary>

        private double startY;

        

        /// <summary>

        /// 현재 X

        /// </summary>

        private double currentX;

        

        /// <summary>

        /// 현재 Y

        /// </summary>

        private double currentY;

 

        /// <summary>

        /// 최소 X

        /// </summary>

        private double minimumX;

        

        /// <summary>

        /// 최대 X

        /// </summary>

        private double maximumX;

 

        /// <summary>

        /// 최소 Y

        /// </summary>

        private double minimumY;

        

        /// <summary>

        /// 최대 Y

        /// </summary>

        private double maximumY;

 

        /// <summary>

        /// 비트맵

        /// </summary>

        private Bitmap bitmap;

 

        #endregion

 

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

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

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 이벤트를 설정한다.

 

            Load                            += Form_Load;

            this.saveAsMenuItem.Click       += saveAsMenuItem_Click;

            this.scaleX2MenuItem.Click      += scaleMenuItem_Click;

            this.scaleX4MenuItem.Click      += scaleMenuItem_Click;

            this.scaleX8MenuItem.Click      += scaleMenuItem_Click;

            this.fullScaleMenuItem.Click    += fullScaleMenuItem_Click;

            this.refreshMenuItem.Click      += refreshMenuItem_Click;

            this.setOptionMenuItem.Click    += setOptionMenuItem_Click;

            this.canvasPictureBox.MouseDown += canvasPictureBox_MouseDown;

            this.canvasPictureBox.MouseMove += canvasPictureBox_MouseMove;

            this.canvasPictureBox.MouseUp   += canvasPictureBox_MouseUp;

 

            #endregion

        }

 

        #endregion

 

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

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

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

 

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

 

        /// <summary>

        /// 폼 로드시 처리하기

        /// </summary>

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

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

        private void Form_Load(object sender, EventArgs e)

        {

            Show();

 

            Application.DoEvents();

 

            MaximumIterationCount = 64;

 

            Complex = new Complex(0.62, -0.55);

 

            ResetColorList();

 

            SettingForm form = new SettingForm();

 

            ColorList.Add(form.color40PictureBox.BackColor);

            ColorList.Add(form.color17PictureBox.BackColor);

            ColorList.Add(form.color18PictureBox.BackColor);

            ColorList.Add(form.color19PictureBox.BackColor);

            ColorList.Add(form.color20PictureBox.BackColor);

            ColorList.Add(form.color21PictureBox.BackColor);

            ColorList.Add(form.color22PictureBox.BackColor);

            ColorList.Add(form.color23PictureBox.BackColor);

 

            form.Close();

 

            this.fullScaleMenuItem.PerformClick();

        }

 

        #endregion

        #region 다른 이름으로 저장하기 메뉴 항목 클릭시 처리하기 - saveAsMenuItem_Click(sender, e)

 

        /// <summary>

        /// 다른 이름으로 저장하기 메뉴 항목 클릭시 처리하기

        /// </summary>

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

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

        private void saveAsMenuItem_Click(object sender, EventArgs e)

        {

            if(this.saveFileDialog.ShowDialog() == DialogResult.OK)

            {

                this.bitmap.Save(this.saveFileDialog.FileName);

 

                string fileName      = this.saveFileDialog.FileName;

                string fileExtension = fileName.Substring(fileName.LastIndexOf("."));

 

                switch(fileExtension)

                {

                    case ".bmp"  : this.bitmap.Save(fileName, ImageFormat.Bmp ); break;

                    case ".jpg"  :

                    case ".jpeg" : this.bitmap.Save(fileName, ImageFormat.Jpeg); break;

                    case ".gif"  : this.bitmap.Save(fileName, ImageFormat.Gif ); break;

                    case ".png"  : this.bitmap.Save(fileName, ImageFormat.Png ); break;

                    case ".tif"  :

                    case ".tiff" : this.bitmap.Save(fileName, ImageFormat.Tiff); break;

                }

            }

        }

 

        #endregion

        #region 스케일 메뉴 항목 클릭시 처리하기 - scaleMenuItem_Click(sender, e)

 

        /// <summary>

        /// 스케일 메뉴 항목 클릭시 처리하기

        /// </summary>

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

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

        private void scaleMenuItem_Click(object sender, EventArgs e)

        {

            MenuItem menuItem = sender as MenuItem;

 

            ScaleArea(int.Parse(menuItem.Tag.ToString()));

        }

 

        #endregion

        #region 전체 스케일 메뉴 항목 클릭시 처리하기 - fullScaleMenuItem_Click(sender, e)

 

        /// <summary>

        /// 전체 스케일 메뉴 항목 클릭시 처리하기

        /// </summary>

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

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

        private void fullScaleMenuItem_Click(object sender, EventArgs e)

        {

            this.minimumX = MINIMUM_X;

            this.maximumX = MAXIMUM_X;

            this.minimumY = MINIMUM_Y;

            this.maximumY = MAXIMUM_Y;

 

            Cursor = Cursors.WaitCursor;

 

            Application.DoEvents();

 

            DrawVortexFractal();

 

            Cursor = Cursors.Default;

 

            this.canvasPictureBox.Cursor = Cursors.Cross;

        }

 

        #endregion

        #region 새로 고침 메뉴 항목 클릭시 처리하기 - refreshMenuItem_Click(sender, e)

 

        /// <summary>

        /// 새로 고침 메뉴 항목 클릭시 처리하기

        /// </summary>

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

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

        private void refreshMenuItem_Click(object sender, EventArgs e)

        {

            ScaleArea(1);

        }

 

        #endregion

        #region 옵션 설정하기 메뉴 항목 클릭시 처리하기 - setOptionMenuItem_Click(sender, e)

 

        /// <summary>

        /// 옵션 설정하기 메뉴 항목 클릭시 처리하기

        /// </summary>

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

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

        private void setOptionMenuItem_Click(object sender, EventArgs e)

        {

            SettingForm form = new SettingForm();

 

            form.StartPosition = FormStartPosition.CenterParent;

 

            form.Initialize(this);

 

            form.ShowDialog(this);

        }

 

        #endregion

        #region 캔버스 픽처 박스 마우스 DOWN 처리하기 - canvasPictureBox_MouseDown(sender, e)

 

        /// <summary>

        /// 캔버스 픽처 박스 마우스 DOWN 처리하기

        /// </summary>

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

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

        private void canvasPictureBox_MouseDown(object sender, MouseEventArgs e)

        {

            this.isDrawingBox = true;

 

            this.startX = e.X;

            this.startY = e.Y;

 

            this.currentX = e.X;

            this.currentY = e.Y;

        }

 

        #endregion

        #region 캔버스 픽처 박스 마우스 이동시 처리하기 - canvasPictureBox_MouseMove(sender, e)

 

        /// <summary>

        /// 캔버스 픽처 박스 마우스 이동시 처리하기

        /// </summary>

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

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

        private void canvasPictureBox_MouseMove(object sender, MouseEventArgs e)

        {

            if(!this.isDrawingBox)

            {

                return;

            }

 

            this.currentX = e.X;

            this.currentY = e.Y;

            

            Bitmap   newBitmap         = new Bitmap(this.bitmap);

            Graphics newBitmapGraphics = Graphics.FromImage(newBitmap);

 

            newBitmapGraphics.DrawRectangle

            (

                Pens.Yellow,

                (int)(Math.Min(this.startX, this.currentX)),

                (int)(Math.Min(this.startY, this.currentY)),

                (int)(Math.Abs(this.startX - this.currentX)),

                (int)(Math.Abs(this.startY - this.currentY))

            );

 

            this.canvasPictureBox.Image = newBitmap;

        }

 

        #endregion

        #region 캔버스 픽처 박스 마우스 UP 처리하기 - canvasPictureBox_MouseUp(sender, e)

 

        /// <summary>

        /// 캔버스 픽처 박스 마우스 UP 처리하기

        /// </summary>

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

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

        private void canvasPictureBox_MouseUp(object sender, MouseEventArgs e)

        {

            if(!this.isDrawingBox)

            {

                return;

            }

 

            this.isDrawingBox = false;

 

            this.canvasPictureBox.Image = this.bitmap;

 

            this.currentX = e.X;

            this.currentY = e.Y;

 

            double x1 = Math.Min(this.startX, this.currentX);

            double x2 = Math.Max(this.startX, this.currentX);

 

            if(x1 == x2)

            {

                x2 = x1 + 1;

            }

 

            double y1 = Math.Min(this.startY, this.currentY);

            double y2 = Math.Max(this.startY, this.currentY);

 

            if(y1 == y2)

            {

                y2 = y1 + 1;

            }

 

            double factor = (this.maximumX - this.minimumX) / this.canvasPictureBox.ClientSize.Width;

 

            this.maximumX = this.minimumX + x2 * factor;

            this.minimumX = this.minimumX + x1 * factor;

 

            factor = (this.maximumY - this.minimumY) / this.canvasPictureBox.ClientSize.Height;

 

            this.maximumY = this.minimumY + y2 * factor;

            this.minimumY = this.minimumY + y1 * factor;

 

            Cursor = Cursors.WaitCursor;

 

            Application.DoEvents();

 

            DrawVortexFractal();

 

            Cursor = Cursors.Default;

 

            this.canvasPictureBox.Cursor = Cursors.Cross;

        }

 

        #endregion

 

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

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

 

        #region 색상 리스트 리셋하기 - ResetColorList()

 

        /// <summary>

        /// 색상 리스트 리셋하기

        /// </summary>

        public void ResetColorList()

        {

            ColorList = new List<Color>();

        }

 

        #endregion

 

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

 

        #region 화면비 조정하기 - AdjustAspect()

 

        /// <summary>

        /// 화면비 조정하기

        /// </summary>

        private void AdjustAspect()

        {

            double height;

            double width;

            double middle;

 

            double aspectDesired = (this.maximumY - this.minimumY) / (this.maximumX - this.minimumX);

            double canvasAspect  = this.canvasPictureBox.ClientSize.Height / (double)this.canvasPictureBox.ClientSize.Width;

 

            if(aspectDesired > canvasAspect)

            {

                width  = (this.maximumY - this.minimumY) / canvasAspect;

                middle = (this.minimumX + this.maximumX) / 2;

 

                this.minimumX = middle - width / 2;

                this.maximumX = middle + width / 2;

            }

            else

            {

                height = (this.maximumX - this.minimumX) * canvasAspect;

                middle = (this.minimumY + this.maximumY) / 2;

 

                this.minimumY = middle - height / 2;

                this.maximumY = middle + height / 2;

            }

        }

 

        #endregion

        #region 소용돌이 프랙탈 그리기 - DrawVortexFractal()

 

        /// <summary>

        /// 소용돌이 프랙탈 그리기

        /// </summary>

        private void DrawVortexFractal()

        {

            const int MAXIMUM_MAGNITUDE_SQUARED = 8;

 

            this.bitmap = new Bitmap

            (

                this.canvasPictureBox.ClientSize.Width,

                this.canvasPictureBox.ClientSize.Height

            );

 

            Graphics graphics = Graphics.FromImage(this.bitmap);

 

            graphics.Clear(this.canvasPictureBox.BackColor);

 

            this.canvasPictureBox.Image = this.bitmap;

 

            Application.DoEvents();

 

            AdjustAspect();

 

            int width  = this.canvasPictureBox.ClientRectangle.Width;

            int height = this.canvasPictureBox.ClientRectangle.Height;

 

            double real      = (this.maximumX - this.minimumX) / (width  - 1);

            double imaginary = (this.maximumY - this.minimumY) / (height - 1);

 

            int colorCount = ColorList.Count;

 

            double zReal = this.minimumX;

 

            for(int x = 0; x < width; x++)

            {

                double zImaginary = this.minimumY;

 

                for(int y = 0; y < height; y++)

                {

                    Complex z       = new Complex(zReal, zImaginary);

                    Complex zMinus1 = new Complex(zReal, zImaginary);

 

                    int colorValue = 1;

 

                    while((colorValue < MaximumIterationCount) && (z.MagnitudeSquared < MAXIMUM_MAGNITUDE_SQUARED))

                    {

                        Complex zPlus1 = z * z + Complex.Real + Complex.Imaginary * zMinus1;

 

                        zMinus1 = z;

 

                        z = zPlus1;

 

                        colorValue++;

                    }

 

                    this.bitmap.SetPixel(x, y, ColorList[colorValue % colorCount]);

 

                    zImaginary += imaginary;

                }

 

                zReal += real;

 

                if(x % 10 == 0)

                {

                    this.canvasPictureBox.Refresh();

                }

            }

 

            Text = string.Format

            (

                "소용돌이 프랙탈(Vortex Fractal) 그리기 : Vortex ({0}, {1}) - ({2}, {3})",

                this.minimumX.ToString("0.000000"),

                this.minimumY.ToString("0.000000"),

                this.maximumX.ToString("0.000000"),

                this.maximumY.ToString("0.000000")

            );

        }

 

        #endregion

        #region 영역 스케일 처리하기 - ScaleArea(scaleFactor)

 

        /// <summary>

        /// 영역 스케일 처리하기

        /// </summary>

        /// <param name="scaleFactor">스케일 팩터</param>

        private void ScaleArea(int scaleFactor)

        {

            double size = scaleFactor * (this.maximumX - this.minimumX);

 

            if(size > 3.2)

            {

                this.fullScaleMenuItem.PerformClick();

 

                return;

            }

 

            double middle = (this.minimumX + this.maximumX) / 2;

 

            this.minimumX = middle - size / 2;

            this.maximumX = middle + size / 2;

 

            size = scaleFactor * (this.maximumY - this.minimumY);

 

            if(size > 2.4)

            {

                this.fullScaleMenuItem.PerformClick();

 

                return;

            }

 

            middle = (this.minimumY + this.maximumY) / 2;

 

            this.minimumY = middle - size / 2;

            this.maximumY = middle + size / 2;

 

            Cursor = Cursors.WaitCursor;

 

            Application.DoEvents();

 

            DrawVortexFractal();

 

            Cursor = Cursors.Default;

 

            this.canvasPictureBox.Cursor = Cursors.Cross;

        }

 

        #endregion

    }

}

 

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

Posted by 사용자 icodebroker

댓글을 달아 주세요