Mandelbrot in C# , the sources!
Hello everybody,
yesterday I posted a link to
mandelbrot in c# on the
microsoft.public.dotnet.framework.drawing usenet group . Morten Wennevik reply to me and argued that a lot of code were missing. So, today I post the complete sources. He also said that Visual studio isn't mandatory to build a .Net Windows application. He is right! So I will also give the way to compile it without Visual Studio .net, just with the framework:
Step 1 Create a directory for the project
Step 2 In this directory put a text file named fractalform.cs (personnaly I used a UTF-8 format with Notepad) containing the following:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace mandelbrot
{
/// <summary>
/// Description résumée de Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
Complex C1,C2,C3;
private System.Windows.Forms.Button trace;
private System.Windows.Forms.PictureBox BoiteImage;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox hgx;
private System.Windows.Forms.TextBox hgy;
private System.Windows.Forms.TextBox bdy;
private System.Windows.Forms.TextBox bdx;
private System.Windows.Forms.Label label2;
/// <summary>
/// Variable nécessaire au concepteur.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Requis pour la prise en charge du Concepteur Windows Forms
//
InitializeComponent();
//
// TODO : ajoutez le code du constructeur après l'appel à InitializeComponent
//
}
/// <summary>
/// Nettoyage des ressources utilisées.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Code généré par le Concepteur Windows Form
/// <summary>
/// Méthode requise pour la prise en charge du concepteur - ne modifiez pas
/// le contenu de cette méthode avec l'éditeur de code.
/// </summary>
private void InitializeComponent()
{
this.trace = new System.Windows.Forms.Button();
this.BoiteImage = new System.Windows.Forms.PictureBox();
this.hgx = new System.Windows.Forms.TextBox();
this.hgy = new System.Windows.Forms.TextBox();
this.bdy = new System.Windows.Forms.TextBox();
this.bdx = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// trace
//
this.trace.Location = new System.Drawing.Point(512, 8);
this.trace.Name = "trace";
this.trace.Size = new System.Drawing.Size(80, 32);
this.trace.TabIndex = 12;
this.trace.Text = "trace";
this.trace.Click += new System.EventHandler(this.button1_Click);
//
// BoiteImage
//
this.BoiteImage.Location = new System.Drawing.Point(24, 56);
this.BoiteImage.Name = "BoiteImage";
this.BoiteImage.Size = new System.Drawing.Size(584, 416);
this.BoiteImage.TabIndex = 13;
this.BoiteImage.TabStop = false;
//
// hgx
//
this.hgx.Location = new System.Drawing.Point(32, 24);
this.hgx.Name = "hgx";
this.hgx.Size = new System.Drawing.Size(80, 20);
this.hgx.TabIndex = 14;
this.hgx.Text = "-1,5";
//
// hgy
//
this.hgy.Location = new System.Drawing.Point(128, 24);
this.hgy.Name = "hgy";
this.hgy.Size = new System.Drawing.Size(80, 20);
this.hgy.TabIndex = 15;
this.hgy.Text = "-1,5";
//
// bdy
//
this.bdy.Location = new System.Drawing.Point(304, 24);
this.bdy.Name = "bdy";
this.bdy.Size = new System.Drawing.Size(80, 20);
this.bdy.TabIndex = 16;
this.bdy.Text = "1,5";
//
// bdx
//
this.bdx.Location = new System.Drawing.Point(216, 24);
this.bdx.Name = "bdx";
this.bdx.Size = new System.Drawing.Size(80, 20);
this.bdx.TabIndex = 17;
this.bdx.Text = "1,5";
//
// label1
//
this.label1.Location = new System.Drawing.Point(88, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(64, 23);
this.label1.TabIndex = 19;
this.label1.Text = "hautgauche";
//
// label2
//
this.label2.Location = new System.Drawing.Point(272, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(64, 16);
this.label2.TabIndex = 20;
this.label2.Text = "BasDroite";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(632, 470);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.bdx);
this.Controls.Add(this.bdy);
this.Controls.Add(this.hgy);
this.Controls.Add(this.hgx);
this.Controls.Add(this.BoiteImage);
this.Controls.Add(this.trace);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// Point d'entrée principal de l'application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
int nbPix=1000;
double diagDest;
int x,y;
Bitmap Imag;
Color col;
int iDiv;
Complex c= new Complex();
//define the complex plan zone
Complex cHG = new Complex(Convert.ToDouble( this.hgx.Text),Convert.ToDouble( this.hgy.Text));
Complex cBD = new Complex(Convert.ToDouble(this.bdx.Text),Convert.ToDouble(this.bdy.Text));
diagDest=Convert.ToDouble( this.hgx.Text)-Convert.ToDouble( this.bdx.Text);
//instantiate the bitmap
Imag = new Bitmap(nbPix ,nbPix);
//scan the bitmap
for(x=0;x<Imag.Size.Width;x++)
for(y=0;y<Imag.Size.Height;y++)
{
//convert the pixel coordinate into a complex number
c = new Complex(diagDest*x/nbPix,diagDest*y/nbPix)-cHG;
//calculate divergence
iDiv = c.diverg();
//choose the color of the pixel
if (iDiv >= 255)
//if it converge it's black
col = System.Drawing.Color.FromArgb(255,0,0,0);
else //if it is not it depend of the speed
col = System.Drawing.Color.FromArgb(128,iDiv,iDiv,iDiv);
//set the pixel color
Imag.SetPixel(x,y,col );
}
//draw the image
BoiteImage.SizeMode = PictureBoxSizeMode.StretchImage ;
BoiteImage.ClientSize = new Size(Imag.Size.Width, Imag.Size.Height);
BoiteImage.Image = (Image) Imag ;
}
}
}
Step 3Put a second file named cplx.cs
containing the following
using System;// to include the basic libraries
namespace mandelbrot//a namespace groups classes working together,
{
// The main class
class Complex
{
//constants
const int IMAX_ITER = 255 ;// number of iterations to estimate the divergence
const double MODUL_LIMIT = 2;//
public double x;//pretty close to c++ syntax,
//"public" indicates that the users of the class can access this property...
public double y;
//////////////////////////
//constructors
//the basic one , do nothing but is mandatory for operators overloading
public Complex()
{}
//the main constructor
public Complex(double i, double j)
{
x = i;
y = j;
}
//////////////////////////
//Operators overloading
//plus
public static Complex operator +(Complex c1,Complex c2)
{
Complex temp = new Complex();
temp.x = (c1.x)+(c2.x);
temp.y = c1.y+c2.y;
return temp;
}
//minus
public static Complex operator -(Complex c1,Complex c2)
{
Complex temp = new Complex();
temp.x = (c1.x)-(c2.x);
temp.y = c1.y-c2.y;
return temp;
}
// multiplication, a little more complicated
public static Complex operator *(Complex c1,Complex c2)
{
Complex temp = new Complex();
temp.x = c1.x*c2.x-c1.y*c2.y;
temp.y = c1.y*c2.x+c1.x*c2.y;
return temp;
}
/////////////////////
//methods
//Module, used to measure the complex number
public double Module()
{
double temp;
temp = System.Math.Sqrt( x*x+y*y);
return temp ;
}
//use to measure the divergence of the complex number
//the number return is use to define the color of the affix's point
public int diverg()
{
int i=0 ;
Complex c = new Complex(x,y) ;
while (i<IMAX_ITER && c.Module()<MODUL_LIMIT)
{
c = c*c+this;//yep "*" and "+" are the operator we've just overload.
i++;
}
return i;//the number of iteration is return to set the color
}
}
}
Step 4 Now open a command line window on the directory you've just create.
type the folowing:
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\csc.exe /target:winexe /recurse:*.*
(You may have to replace C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\ by your computer's c# compiler path.)
That's all folks, thanks to Morten Wennevik!
Comments are welcome!