using System; using System.Diagnostics; using System.Drawing; using System.IO; using System.Numerics; using System.Windows.Forms; namespace MandelbrotSet { class Program { #region Params private static int MaxIterations = 96; // int: Höhe des Ausgabebilds in Pixeln. Nicht größer als 20000 setzen! private static int Height = 1000; // int: Höhe des Ausgabebilds in Pixeln. Nicht größer als 20000 setzen! private static int Width;// int: Breite des Ausgabebilds in Pixeln. Nicht größer als 20000 setzen! private static string Filename = "plot"; // Dateiname private const double Xmin = -2.0; // double: Untere Grenze des Definitionsbereichs des Plots private const double Xmax = 1.0; // double: Obere Grenze des Definitionsbereichs des Plots private const double Ymin = -1.0; // double: Untere Grenze des Wertebereichs des Plots private const double Ymax = 1.0; // double: Obere Grenze des Wertebereichs des Plots private const double HueFactor = 360.0; private const double Mathwidth = Xmax - Xmin; private const double Mathheight = Ymax - Ymin; private static Color Corecolor { get; } = Color.Black; #endregion private static BigInteger _pixelsDrawn; private static Bitmap _map; static Program() { _pixelsDrawn = 0; } static void Main(string[] args) { if (args.Length >= 1) { Filename = args[0]; if (args.Length >= 2) { if (int.TryParse(args[1], out var newHeight)) { Height = newHeight; Console.WriteLine($"Parameter Höhe wurde auf {Height} gesetzt!."); } else { Console.WriteLine($"\"{args[1]}\" ist keine gültige Höhenangabe!"); Console.WriteLine($"Parameter Höhe wurde auf Standardwert ({Height}) zurückgesetzt!."); } if (args.Length >= 3) { if (int.TryParse(args[2], out var newMaxIterations)) { MaxIterations = newMaxIterations; Console.WriteLine($"Parameter Iterationen wurde auf {MaxIterations} gesetzt!."); } else { Console.WriteLine($"\"{args[2]}\" ist keine gültige Iterationsangabe!"); Console.WriteLine($"Parameter Iterationen wurde auf Standardwert ({MaxIterations}) zurückgesetzt!."); } } } } Filename = $"{Filename}-{Height}px-{MaxIterations}it.bmp"; Console.WriteLine($"Parameter Dateiname wurde auf \"{Filename}\" gesetzt!."); Width = Height * 3 / 2; try { _map = new Bitmap(Width, Height); } catch (Exception e) { Console.WriteLine("Bitmap kann nicht erstellt werden: " + e.Message); return; } Stopwatch watch; Console.WriteLine("Beginning Task...\n├─── Drawing Mandelbrot..."); watch = Stopwatch.StartNew(); DrawMandelbrot(); Console.WriteLine($"│ └─── Mandelbrot drawn!\nDEBUG: { _pixelsDrawn.ToString()} pixels were drawn.\nSuccessfully rendered in {((double)watch.ElapsedMilliseconds / 1000.0).ToString()} seconds!\n├─── Saving bitmap..."); watch = Stopwatch.StartNew(); _map.Save(Filename); Console.WriteLine($"│ ├─── Saved as \"{Filename}\"!\n│ Successfully saved in {((double)watch.ElapsedMilliseconds / 1000.0).ToString()} seconds!\nFinished Task!"); Process.Start(Filename); } private static int Constrain(int value, int min, int max) => value < min ? min : (value > max ? max : value); private static Color ColorFromHue(double hue) { double r, g, b, x; int R, G, B; hue %= 360.0; x = 1.0 - Math.Abs(hue / 60.0 % 2.0 - 1); #region COLOR MODE if (hue < 60.0) { r = 1.0; g = x; b = 0.0; } else if (hue < 120.0) { r = x; g = 1.0; b = 0.0; } else if (hue < 180.0) { r = 0.0; g = 1.0; b = x; } else if (hue < 240.0) { r = 0.0; g = x; b = 1.0; } else if (hue < 300.0) { r = x; g = 0.0; b = 1.0; } else { r = 1.0; g = 0.0; b = x; } #endregion R = Constrain((int)Math.Round(r * 255), 0, 255); G = Constrain((int)Math.Round(g * 255), 0, 255); B = Constrain((int)Math.Round(b * 255), 0, 255); return Color.FromArgb(R, G, B); } static double XtoMath(int xb) => Xmin + xb * Mathwidth / Width; static double YtoMath(int yb) => Ymax - yb * Mathheight / Height; private static void DrawMandelbrot() { int y, x, iterations; double xd, yd; for (y = 0; y < Height; y++) { if (y % 100 == 99) Console.WriteLine($"│ ├─── Progress: {(double)(y + 1) * 100.0 / (double)Height}%"); yd = YtoMath(y); for (x = 0; x < Width; x++) { xd = XtoMath(x); iterations = MandelbrotIterations(new Complex(xd, yd), Complex.Zero); if (iterations == -1) { _map.SetPixel(x, y, Corecolor); _pixelsDrawn++; continue; } _map.SetPixel(x, y, ColorFromHue(((double)iterations / (double)MaxIterations) * HueFactor)); _pixelsDrawn++; } } } private static Complex NextItem(Complex point, Complex z) => new Complex(z.Real * z.Real - z.Imaginary * z.Imaginary + point.Real, 2.0 * z.Real * z.Imaginary + point.Imaginary); private static int MandelbrotIterations(Complex point, Complex z, int depth = 0) { if (depth > MaxIterations) return -1; if (z.Magnitude >= 2.0) return depth; return MandelbrotIterations(point, NextItem(point, z), depth + 1); } } }