174 lines
6.7 KiB
C#
174 lines
6.7 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|