|
|
|
// Mandelbrot 0.1: A demonstration of Qt#
|
|
|
|
//
|
|
|
|
// Copyright 2002 Marcus Urban
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License
|
|
|
|
// as published by the Free Software Foundation; either version 2
|
|
|
|
// of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
// NOTE:
|
|
|
|
// Variables with names like PlotXMin are in the cartesian coordinate plane.
|
|
|
|
// Those with names like ImageXMin was in a translated coordinate system
|
|
|
|
// where (0, 0) is the upper-left corner.
|
|
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
using Qt;
|
|
|
|
|
|
|
|
|
|
|
|
// This struct is a simple implementation of complex numbers.
|
|
|
|
// It was originally in a separate file because it is useful
|
|
|
|
// in its own right. It is included here file only to make the
|
|
|
|
// compilation process simpler of new users.
|
|
|
|
|
|
|
|
public struct Complex {
|
|
|
|
|
|
|
|
private double re, im;
|
|
|
|
//private int x;
|
|
|
|
|
|
|
|
public Complex (double re, double im)
|
|
|
|
{
|
|
|
|
this.re = re;
|
|
|
|
this.im = im;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static implicit operator Complex (double re)
|
|
|
|
{
|
|
|
|
return new Complex (re, 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public double Re
|
|
|
|
{
|
|
|
|
get { return re; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public double Im
|
|
|
|
{
|
|
|
|
get { return im; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public static double Abs (Complex a)
|
|
|
|
{
|
|
|
|
return Math.Abs (a.re) >= Math.Abs (a.im) ?
|
|
|
|
Math.Abs (a.re) * Math.Sqrt( 1.0 + (a.im/a.re)*(a.im/a.re) ) :
|
|
|
|
Math.Abs (a.im) * Math.Sqrt( 1.0 + (a.re/a.im)*(a.re/a.im) );
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Complex operator + (Complex a, Complex b)
|
|
|
|
{
|
|
|
|
return new Complex (a.re + b.re, a.im + b.im);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Complex operator - (Complex a, Complex b)
|
|
|
|
{
|
|
|
|
return new Complex (a.re - b.re, a.im - b.im);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Complex operator * (Complex a, Complex b)
|
|
|
|
{
|
|
|
|
return new Complex ( a.re*b.re - a.im*b.im, a.im*b.re + a.re*b.im );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Division isn't pretty. Do it later.
|
|
|
|
|
|
|
|
public override string ToString ()
|
|
|
|
{
|
|
|
|
return this.re.ToString () + "+" + this.im.ToString () + "i";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class Mandelbrot {
|
|
|
|
|
|
|
|
public static int Iterations ( Complex c )
|
|
|
|
{
|
|
|
|
const int MaximumIterations = 16;
|
|
|
|
Complex value = c;
|
|
|
|
int currentDepth = 1;
|
|
|
|
|
|
|
|
while ( Complex.Abs(value) < 2.0 && currentDepth <= MaximumIterations ) {
|
|
|
|
++currentDepth;
|
|
|
|
value = (value * value) + c;
|
|
|
|
}
|
|
|
|
return currentDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void Main (string[] args)
|
|
|
|
{
|
|
|
|
TTQApplication app = new TTQApplication (args);
|
|
|
|
|
|
|
|
ImageDialog dialog = new ImageDialog (null, "Mandelbrot", false, 0);
|
|
|
|
dialog.Show ();
|
|
|
|
app.SetMainWidget (dialog);
|
|
|
|
app.Exec ();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class ImageDialog : TTQDialog {
|
|
|
|
|
|
|
|
const double DefaultPlotXMin = -2.0;
|
|
|
|
const double DefaultPlotXMax = 2.0;
|
|
|
|
const double DefaultPlotYMin = -1.5;
|
|
|
|
const double DefaultPlotYMax = 1.5;
|
|
|
|
|
|
|
|
TTQHBoxLayout dialogLayout;
|
|
|
|
TTQGridLayout gridLayout;
|
|
|
|
TTQVBoxLayout leftLayout;
|
|
|
|
TTQHBoxLayout buttonLayout;
|
|
|
|
TTQPushButton redrawButton;
|
|
|
|
TTQLabel pixmapLabel;
|
|
|
|
TTQSizePolicy fixedSizePolicy;
|
|
|
|
|
|
|
|
TTQLabel XMinLabel, XMaxLabel, YMinLabel, YMaxLabel;
|
|
|
|
TTQLineEdit editXMin, editXMax, editYMin, editYMax;
|
|
|
|
|
|
|
|
public ImageDialog (TTQWidget parent, string name, bool modal, WidgetFlags fl):
|
|
|
|
base (parent, name, modal, fl)
|
|
|
|
{
|
|
|
|
if (name == string.Empty)
|
|
|
|
SetName ("imageDialog");
|
|
|
|
SetCaption ("Mandelbrot Image");
|
|
|
|
|
|
|
|
dialogLayout = new TTQHBoxLayout (this, 11, 6);
|
|
|
|
gridLayout = new TTQGridLayout (null, 1, 1, 0, 6, "gridLayout");
|
|
|
|
leftLayout = new TTQVBoxLayout (null, 0, 6, "leftLayout");
|
|
|
|
|
|
|
|
fixedSizePolicy = new TTQSizePolicy ();
|
|
|
|
fixedSizePolicy.SetHorData (TTQSizePolicy.SizeType.Fixed);
|
|
|
|
fixedSizePolicy.SetVerData (TTQSizePolicy.SizeType.Fixed);
|
|
|
|
|
|
|
|
XMinLabel = new TTQLabel ("Xmin", this);
|
|
|
|
XMinLabel.SetSizePolicy (fixedSizePolicy);
|
|
|
|
gridLayout.AddWidget (XMinLabel, 0, 0);
|
|
|
|
|
|
|
|
XMaxLabel = new TTQLabel ("Xmax", this);
|
|
|
|
XMaxLabel.SetSizePolicy(fixedSizePolicy);
|
|
|
|
gridLayout.AddWidget (XMaxLabel, 1, 0);
|
|
|
|
|
|
|
|
YMinLabel = new TTQLabel ("Ymin", this);
|
|
|
|
YMinLabel.SetSizePolicy (fixedSizePolicy);
|
|
|
|
gridLayout.AddWidget (YMinLabel, 2, 0);
|
|
|
|
|
|
|
|
YMaxLabel = new TTQLabel ("Ymax", this);
|
|
|
|
YMaxLabel.SetSizePolicy (fixedSizePolicy);
|
|
|
|
gridLayout.AddWidget (YMaxLabel, 3, 0);
|
|
|
|
|
|
|
|
TTQDoubleValidator validator = new TTQDoubleValidator (this);
|
|
|
|
|
|
|
|
editXMin = new TTQLineEdit (this, "editXMin");
|
|
|
|
editXMin.SetText (Convert.ToString (DefaultPlotXMin));
|
|
|
|
editXMin.SetValidator (validator);
|
|
|
|
gridLayout.AddWidget (editXMin, 0, 1);
|
|
|
|
|
|
|
|
editXMax = new TTQLineEdit (this, "editXMax");
|
|
|
|
editXMax.SetText (Convert.ToString(DefaultPlotXMax));
|
|
|
|
editXMax.SetValidator (validator);
|
|
|
|
gridLayout.AddWidget (editXMax, 1, 1);
|
|
|
|
|
|
|
|
editYMin = new TTQLineEdit (this, "editYMin");
|
|
|
|
editYMin.SetText (Convert.ToString(DefaultPlotYMin));
|
|
|
|
editYMin.SetValidator (validator);
|
|
|
|
gridLayout.AddWidget (editYMin, 2, 1);
|
|
|
|
|
|
|
|
editYMax = new TTQLineEdit (this, "editYMax");
|
|
|
|
editYMax.SetText (Convert.ToString(DefaultPlotYMax));
|
|
|
|
editYMax.SetValidator (validator);
|
|
|
|
gridLayout.AddWidget (editYMax, 3, 1);
|
|
|
|
|
|
|
|
leftLayout.AddLayout (gridLayout);
|
|
|
|
TTQSpacerItem spacer1 = new TTQSpacerItem (0, 0, 0, 0);
|
|
|
|
leftLayout.AddItem (spacer1);
|
|
|
|
|
|
|
|
buttonLayout = new TTQHBoxLayout (null, 0, 6, "buttonLayout");
|
|
|
|
TTQSpacerItem spacer2 = new TTQSpacerItem (0, 0, 0, 0);
|
|
|
|
buttonLayout.AddItem (spacer2);
|
|
|
|
|
|
|
|
redrawButton = new TTQPushButton ("Redraw", this);
|
|
|
|
redrawButton.SetDefault (true);
|
|
|
|
buttonLayout.AddWidget (redrawButton);
|
|
|
|
|
|
|
|
TTQSpacerItem spacer3 = new TTQSpacerItem (0, 0, 0, 0);
|
|
|
|
buttonLayout.AddItem (spacer3);
|
|
|
|
|
|
|
|
leftLayout.AddLayout (buttonLayout);
|
|
|
|
|
|
|
|
dialogLayout.AddLayout (leftLayout);
|
|
|
|
TTQSpacerItem spacer4 = new TTQSpacerItem (0, 0, 0, 0);
|
|
|
|
dialogLayout.AddItem (spacer4);
|
|
|
|
|
|
|
|
pixmapLabel = new TTQLabel (this, "pixmapLabel", 0);
|
|
|
|
pixmapLabel.SetScaledContents (true);
|
|
|
|
dialogLayout.AddWidget (pixmapLabel);
|
|
|
|
|
|
|
|
TTQObject.Connect (redrawButton, TQT_SIGNAL ("clicked()"), this, TQT_SLOT ("Redraw()"));
|
|
|
|
|
|
|
|
Redraw ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TTQImage MandelbrotImage ()
|
|
|
|
{
|
|
|
|
int depth;
|
|
|
|
double real, imag;
|
|
|
|
|
|
|
|
double PlotXMin = Convert.ToDouble ( editXMin.Text () );
|
|
|
|
double PlotXMax = Convert.ToDouble ( editXMax.Text () );
|
|
|
|
double PlotYMin = Convert.ToDouble ( editYMin.Text () );
|
|
|
|
double PlotYMax = Convert.ToDouble ( editYMax.Text () );
|
|
|
|
|
|
|
|
int ImageXMax = pixmapLabel.Width ();
|
|
|
|
int ImageYMax = pixmapLabel.Height ();
|
|
|
|
|
|
|
|
TTQImage image = new TTQImage (ImageXMax, ImageYMax, 32, 0);
|
|
|
|
|
|
|
|
for (int x = 0; x <= ImageXMax - 1; x+=1) {
|
|
|
|
for (int y = 0; y <= ImageYMax - 1; y+=1) {
|
|
|
|
real = (PlotXMax - PlotXMin)/ImageXMax * x + PlotXMin;
|
|
|
|
imag = (PlotYMin - PlotYMax)/ImageYMax * y + PlotYMax;
|
|
|
|
depth = Mandelbrot.Iterations ( new Complex (real, imag) );
|
|
|
|
image.SetPixel ( x, y, (uint) depth*16 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Redraw ()
|
|
|
|
{
|
|
|
|
TTQSize s = pixmapLabel.BaseSize ();
|
|
|
|
pixmapLabel.Resize (400,300);
|
|
|
|
TTQApplication.SetOverrideCursor ( new TTQCursor( (int) CursorShape.WaitCursor ));
|
|
|
|
TTQImage image = MandelbrotImage ();
|
|
|
|
TTQPixmap pixmap = new TTQPixmap (image);
|
|
|
|
pixmapLabel.SetPixmap( pixmap);
|
|
|
|
image.Dispose ();
|
|
|
|
pixmap.Dispose ();
|
|
|
|
this.AdjustSize ();
|
|
|
|
TTQApplication.RestoreOverrideCursor ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|