// 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 ImageDialog dialog; 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) { TQApplication app = new TQApplication (args); dialog = new ImageDialog (null, "Mandelbrot", false, 0); dialog.SetGeometry(0, 0, 550, 300 ); dialog.Show(); app.SetMainWidget (dialog); app.Exec (); } } public class PicLabel: TQFrame { TQPixmap newPixmap; int newWidth = 400; int newHeight = 300; public PicLabel( TQWidget parent, string name, WidgetFlags flags ): base( parent, name, flags ) { SetBackgroundMode (Qt.BackgroundMode.NoBackground); resizeEvent += new ResizeEvent (PerformResize); paintEvent += new PaintEvent (PerformPaint); } protected void PerformResize (TQResizeEvent e) { Console.WriteLine("Resizing to {0} by {1}", e.Size().Width(), e.Size().Height() ); newWidth = e.Size().Width(); newHeight = e.Size().Height(); } protected void PerformPaint(TQPaintEvent e ) { Console.WriteLine("Making a new image {0} by {1}", newWidth, newHeight ); TQImage image = Mandelbrot.dialog.MandelbrotImage( newWidth, newHeight ); newPixmap = new TQPixmap( image ); BitBlt(this, 0, 0, newPixmap, 0, 0, -1, -1, RasterOp.CopyROP, false); Console.WriteLine("PerformPaint"); } } public class ImageDialog : TQDialog { const double DefaultPlotXMin = -2.0; const double DefaultPlotXMax = 2.0; const double DefaultPlotYMin = -1.5; const double DefaultPlotYMax = 1.5; TQHBoxLayout dialogLayout; TQGridLayout gridLayout; TQVBoxLayout leftLayout; TQHBoxLayout buttonLayout; TQPushButton redrawButton; public PicLabel pixmapLabel; TQSizePolicy fixedSizePolicy; TQLabel XMinLabel, XMaxLabel, YMinLabel, YMaxLabel; TQLineEdit editXMin, editXMax, editYMin, editYMax; public ImageDialog (TQWidget parent, string name, bool modal, WidgetFlags fl): base (parent, name, modal, fl) { if (name == string.Empty) SetName ("imageDialog"); SetCaption ("Mandelbrot Image"); dialogLayout = new TQHBoxLayout (this, 11, 6); gridLayout = new TQGridLayout (null, 1, 1, 0, 6, "gridLayout"); leftLayout = new TQVBoxLayout (null, 0, 6, "leftLayout"); fixedSizePolicy = new TQSizePolicy ( TQSizePolicy.SizeType.Fixed, TQSizePolicy.SizeType.Fixed, false ); XMinLabel = new TQLabel ("Xmin", this); XMinLabel.SetSizePolicy (fixedSizePolicy); gridLayout.AddWidget (XMinLabel, 0, 0); XMaxLabel = new TQLabel ("Xmax", this); XMaxLabel.SetSizePolicy(fixedSizePolicy); gridLayout.AddWidget (XMaxLabel, 1, 0); YMinLabel = new TQLabel ("Ymin", this); YMinLabel.SetSizePolicy (fixedSizePolicy); gridLayout.AddWidget (YMinLabel, 2, 0); YMaxLabel = new TQLabel ("Ymax", this); YMaxLabel.SetSizePolicy (fixedSizePolicy); gridLayout.AddWidget (YMaxLabel, 3, 0); TQDoubleValidator validator = new TQDoubleValidator (this); editXMin = new TQLineEdit (this, "editXMin"); editXMin.SetSizePolicy( fixedSizePolicy ); editXMin.SetText (Convert.ToString (DefaultPlotXMin)); editXMin.SetValidator (validator); gridLayout.AddWidget (editXMin, 0, 1); editXMax = new TQLineEdit (this, "editXMax"); editXMax.SetSizePolicy( fixedSizePolicy ); editXMax.SetText (Convert.ToString(DefaultPlotXMax)); editXMax.SetValidator (validator); gridLayout.AddWidget (editXMax, 1, 1); editYMin = new TQLineEdit (this, "editYMin"); editYMin.SetSizePolicy( fixedSizePolicy ); editYMin.SetText (Convert.ToString(DefaultPlotYMin)); editYMin.SetValidator (validator); gridLayout.AddWidget (editYMin, 2, 1); editYMax = new TQLineEdit (this, "editYMax"); editYMax.SetSizePolicy( fixedSizePolicy ); editYMax.SetText (Convert.ToString(DefaultPlotYMax)); editYMax.SetValidator (validator); gridLayout.AddWidget (editYMax, 3, 1); leftLayout.AddLayout (gridLayout); TQSpacerItem spacer1 = new TQSpacerItem (0, 0, 0, 0); leftLayout.AddItem (spacer1); buttonLayout = new TQHBoxLayout (null, 0, 6, "buttonLayout"); TQSpacerItem spacer2 = new TQSpacerItem (0, 0, 0, 0); buttonLayout.AddItem (spacer2); redrawButton = new TQPushButton ("Redraw", this); redrawButton.SetSizePolicy ( fixedSizePolicy ); redrawButton.SetDefault (true); buttonLayout.AddWidget (redrawButton); TQSpacerItem spacer3 = new TQSpacerItem (0, 0, 0, 0); buttonLayout.AddItem (spacer3); leftLayout.AddLayout (buttonLayout); dialogLayout.AddLayout (leftLayout); TQSpacerItem spacer4 = new TQSpacerItem (0, 0, 0, 0); dialogLayout.AddItem (spacer4); pixmapLabel = new PicLabel (this, "pixmapLabel", 0); //pixmapLabel.SetScaledContents (true); pixmapLabel.SetSizePolicy( TQSizePolicy.SizeType.Minimum, TQSizePolicy.SizeType.Minimum, false ); pixmapLabel.SetGeometry( 0, 0, 400, 300 ); pixmapLabel.Show(); pixmapLabel.Resize(400,300); dialogLayout.AddWidget (pixmapLabel); //TQImage image = MandelbrotImage( 400, 300 ); //pixmapLabel.SetPixmap( new TQPixmap( image ) ); TQObject.Connect (redrawButton, TQT_SIGNAL ("clicked()"), pixmapLabel, TQT_SLOT ("Repaint()")); //Redraw (); } public TQImage MandelbrotImage ( int width, int height) { 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 = width; int ImageYMax = height; TQImage image = new TQImage (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; } }