⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fractalset.cs

📁 A fractal is generally "a rough or fragmented geometric shape that can be split into parts, each of
💻 CS
字号:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Threading;

namespace Fractals
{
	public class FractalSet : IDisposable
	{
		protected int _MaxIter = 512;
		protected int _MaxColors;
		protected int _MaxMagSquared = 4;

		protected int[] _Color = 
		{
			Color.Black.ToArgb(),
			Color.Chocolate.ToArgb(),
			Color.Beige.ToArgb(),
			Color.Cyan.ToArgb(),
			Color.DarkCyan.ToArgb(),
			Color.Aqua.ToArgb(),
			Color.Blue.ToArgb(),
			Color.DarkBlue.ToArgb(),
			Color.Red.ToArgb(),
			Color.DarkRed.ToArgb(),
			Color.Green.ToArgb(),
			Color.DarkGreen.ToArgb(),
			Color.Violet.ToArgb(),
			Color.DarkViolet.ToArgb(),
			Color.Yellow.ToArgb(),
			Color.White.ToArgb()
		};

		private Rectangle _ZoomRect;
		private Point _LastPoint;
		private bool _MouseDown;

		public delegate void UpdateReadoutsDelegate( double realCenter, double imgCenter, double scale );
		public UpdateReadoutsDelegate ReadoutsDelegate;

		protected bool _WorkStopped = false; 
		protected object _Lock = new object(); 
		protected ManualResetEvent _ResetEvent = new ManualResetEvent(false);
		protected delegate void UpdateImageDelegate(Bitmap ColBmp, int Col);
		protected Thread _Thread;

		protected Bitmap _bmp ; 
		protected PictureBox _PictureBox;

		protected int _width = 0;
		protected int _height = 0;

		protected double _realCenter = 0.0;
		protected double _imgCenter = 0.0;
		protected double _realMin = -2.0;
		protected double _imgMin = -2.0;
		protected double _deltaReal;
		protected double _deltaImg;

		public FractalSet()
		{
			_MaxColors = _Color.Length;
		}

		protected void Draw()
		{
			int band = 5;
			Bitmap bm = new Bitmap( band, _PictureBox.Height );

			UpdateImageDelegate UpdateDelegate = new UpdateImageDelegate( UpdateImage );
			int Col = 0;
			object[] args = new object[] {bm, Col};

			for( int i = 0 ; i < _width && WorkStopped == false ; i+=band )
			{
				for( int k = 0 ; k < band && WorkStopped == false ; k++ )
				{
					double RealC = _realMin + _deltaReal * (i + k);
					for( int j = 0 ; j < _height && WorkStopped == false ; j++ )
					{
						double ImaginaryC = _imgMin + _deltaImg * j;
						bm.SetPixel( k, j, GetColorVal( RealC, ImaginaryC ) );
					}
				}
				//Copy a column to the large bitmap
				args[1] = i;
           
				IAsyncResult ares = _PictureBox.BeginInvoke( UpdateDelegate, args );
				if( WorkStopped == false )
				{
					WaitHandle[] arr = new WaitHandle[2];
					arr[0] = _ResetEvent;
					arr[1] = ares.AsyncWaitHandle;
					WaitHandle.WaitAny( arr );
				}
			}
		}

		protected virtual Color GetColorVal( double r, double i )
		{
			return( Color.Black );
		}

		public void Start( PictureBox pb )
		{
			DisableMouseHandlers();

			_PictureBox = pb;
			_PictureBox.MouseDown += new MouseEventHandler(_PictureBox_MouseDown);
			_PictureBox.MouseMove += new MouseEventHandler(_PictureBox_MouseMove);
			_PictureBox.MouseUp += new MouseEventHandler(_PictureBox_MouseUp);
			Start();
		}

		public void DisableMouseHandlers()
		{
			if( _PictureBox != null )
			{
				_PictureBox.MouseDown -= new MouseEventHandler(_PictureBox_MouseDown);
				_PictureBox.MouseMove -= new MouseEventHandler(_PictureBox_MouseMove);
				_PictureBox.MouseUp -= new MouseEventHandler(_PictureBox_MouseUp);
			}
		}

		private void Start()
		{
			if( (_Thread != null) && (_Thread.IsAlive) )
			{
				Kill();
			}
			CreateGraphicsObjects();
			ThreadStart ts = new ThreadStart( Draw );
			_Thread = new Thread( ts );
			//_Thread.Priority = ThreadPriority.BelowNormal; //Option
			_Thread.IsBackground = true;
			WorkStopped = false;
			_Thread.Start();
		}

		private void CreateGraphicsObjects()
		{
			if( _bmp == null )
			{
				_bmp = new Bitmap( _PictureBox.Width, _PictureBox.Height );
				_PictureBox.BackgroundImage = _bmp;
			}
			else
			{
				if( (_bmp.Width != _PictureBox.Width) || (_bmp.Height != _PictureBox.Height) )
				{
					_bmp.Dispose();
					_bmp = new Bitmap( _PictureBox.Width, _PictureBox.Height );
					_PictureBox.BackgroundImage = _bmp;
				}
			}

			_width = _bmp.Width;
			_height = _bmp.Height;

			_realMin = _realCenter - _deltaReal * _width / 2;
			_imgMin = _imgCenter - _deltaImg * _height / 2;

			if( ReadoutsDelegate != null )
			{
				ReadoutsDelegate( _realCenter, _imgCenter, _deltaReal );
			}

			//Make a bitmap to draw user selection on
			Bitmap bmp = new Bitmap( _PictureBox.Width, _PictureBox.Height );
			if( _PictureBox.Image != null )
			{
				_PictureBox.Image.Dispose();
			}
			_PictureBox.Image = bmp;
		}

		protected void UpdateImage( Bitmap ColBmp, int Col )
		{
			Graphics g = null;
			try
			{
				g = Graphics.FromImage( _PictureBox.BackgroundImage );
				g.DrawImage( ColBmp, Col, 0, ColBmp.Width, _height );
				_PictureBox.Refresh();
				Application.DoEvents();
			}
			finally
			{
				if( g != null )
				{
					g.Dispose();
				}
			}
		}

		public void Kill()
		{
			if( _Thread == null )
			{
				return;
			}
			if( _Thread.IsAlive == false )
			{
				return;
			}
			WorkStopped = true;
			_ResetEvent.Set();
			//Wait for thread to die
			_Thread.Join();
			WorkStopped = false;
			_ResetEvent.Reset();
		}
	
		protected bool WorkStopped
		{
			get
			{
				bool b;
				lock(_Lock)
				{
					b = _WorkStopped;
				}
				return b;
			}
			set
			{
				lock(_Lock)
				{
					_WorkStopped = value;
				}
			}
		}

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				//Called by Dispose()
				if (_Thread != null) 
				{
					Kill();
				}
			}
		}

		private void DrawSelection( Rectangle ZoomRect )
		{
			if( _PictureBox.Image == null ) 
			{
				return;
			}
			Graphics g = Graphics.FromImage( _PictureBox.Image );

			ClearSelection( g );
			Pen pen = new Pen( Color.LightBlue, 2 );
			pen.DashPattern = new Single[] {1, 1, 2, 1};
			g.DrawRectangle( pen, ZoomRect );
			_ZoomRect = ZoomRect;
			_PictureBox.Refresh();
		}

		private void ClearSelection( Graphics g )
		{
			g.Clear( Color.Transparent );
		}

		private void ClearSelection()
		{
			Graphics  g  = Graphics.FromImage( _PictureBox.Image );
			g.Clear( Color.Transparent );
		}
			
		private void _PictureBox_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e ) //Handles _PictureBox.MouseDown
		{
			_MouseDown = true;
			_LastPoint = new Point( e.X, e.Y );
		}

		private void _PictureBox_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			if( _MouseDown )
			{
				int X1, Y1, X2, Y2;
				X1 = Math.Min( e.X, _LastPoint.X );
				X2 = Math.Max( e.X, _LastPoint.X ) - X1;
				Y1 = Math.Min( e.Y, _LastPoint.Y );
				Y2 = Math.Max( e.Y, _LastPoint.Y ) - Y1;
				Rectangle NewSelRect = new Rectangle( X1, Y1, X2, Y2 );
				DrawSelection( NewSelRect );
			}
		}

		private void _PictureBox_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) 
		{
			_MouseDown = false;
			int X1, Y1, X2, Y2;
			if( (e.X == _LastPoint.X) && (e.Y == _LastPoint.Y) )
			{
				double xCenter = _width / 2;
				double yCenter = _height / 2;
				double deltaReal = (e.X - xCenter) * _deltaReal;
				double deltaImg = (e.Y - yCenter) * _deltaImg;
				_realCenter += deltaReal;
				_imgCenter += deltaImg;
				Start();
			}
			else
			{
				//User may have selected from right to left
				X1 = Math.Min( e.X, _LastPoint.X );
				X2 = Math.Max( e.X, _LastPoint.X );
				Y1 = Math.Min( e.Y, _LastPoint.Y );
				Y2 = Math.Max( e.Y, _LastPoint.Y );
				//If tiny selection, assume accidental mouseup
				if( Math.Abs(X1 - X2) < 3 || Math.Abs(Y1 - Y2) < 3 ) 
				{
					ClearSelection();
				}
				else
				{
					Zoom( X1, Y1, X2, Y2 );
				}
			}
		}

		public void ZoomIn()
		{
			_deltaReal /= 2;
			_deltaImg /= 2;
			_realMin = _realCenter - (_width / 2) * _deltaReal;
			_imgMin = _imgCenter - (_height / 2) * _deltaImg;
			Start();
		}

		public void ZoomOut()
		{
			_deltaReal *= 2;
			_deltaImg *= 2;
			_realMin = _realCenter - (_width / 2) * _deltaReal;
			_imgMin = _imgCenter - (_height / 2) * _deltaImg;
			Start();
		}

		private void Zoom( int X1, int Y1, int X2, int Y2 )
		{
			double realMin = _realCenter - (_width / 2) * _deltaReal;
			double realMax = _realCenter + (_width / 2) * _deltaReal;
			double imgMin = _imgCenter - (_height / 2) * _deltaImg;
			double imgMax = _imgCenter + (_height / 2) * _deltaImg;
			double Old_realMin = realMin;
			double Old_imgMin = imgMin;
			double Old_realMax = realMax;
			double Old_imgMax = imgMax;

			realMin += (double)X1 * _deltaReal;
			realMax = Old_realMin + (double)X2 * _deltaReal;
			imgMin += (double)Y1 * _deltaImg;
			imgMax = Old_imgMin + (double)Y2 * _deltaImg;
			if( (realMin == realMax) || (imgMin == imgMax ) )
			{
				ClearSelection();
				return;
			}

			_realCenter = (realMin + realMax) / 2;
			_imgCenter = (imgMin + imgMax) / 2;

			_deltaReal = (realMax - realMin) / _width;
			_deltaImg = (imgMax - imgMin) / _height;
			if( _deltaReal > _deltaImg )
			{
				_deltaImg = _deltaReal;
			}
			else
			{
				_deltaReal = _deltaImg;
			}

			Start();
		}

		public void SaveBitmap( string fn, ImageFormat format )
		{
			if( _bmp != null )
			{
				_bmp.Save( fn, format );
			}
		}

		public Bitmap Image
		{
			get { return( _bmp ); }
		}

		public int Iterations
		{
			get { return( _MaxIter ); }
			set { _MaxIter = value; }
		}

		public int[] ColorMap
		{
			get { return( _Color ); }
			set { _Color = value; }
		}

		public double Scale
		{
			get { return( _deltaReal ); }
			set { _deltaReal = value; _deltaImg = value; }
		}

		public double RealCenter
		{
			get { return( _realCenter ); }
			set { _realCenter = value; }
		}

		public double ImgCenter
		{
			get { return( _imgCenter ); }
			set { _imgCenter = value; }
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -