/* Ported from: https://rosettacode.org/wiki/Mandelbrot_set#C.23 Licensed under GNU Free Documentation License 1.2 */ using System; using Spectre.Console; namespace Canvas; public static class Mandelbrot { private const double MaxValueExtent = 2.0; private struct ComplexNumber { public double Real { get; } public double Imaginary { get; } public ComplexNumber(double real, double imaginary) { Real = real; Imaginary = imaginary; } public static ComplexNumber operator +(ComplexNumber x, ComplexNumber y) { return new ComplexNumber(x.Real + y.Real, x.Imaginary + y.Imaginary); } public static ComplexNumber operator *(ComplexNumber x, ComplexNumber y) { return new ComplexNumber(x.Real * y.Real - x.Imaginary * y.Imaginary, x.Real * y.Imaginary + x.Imaginary * y.Real); } public double Abs() { return Real * Real + Imaginary * Imaginary; } } public static Spectre.Console.Canvas Generate(int width, int height) { var canvas = new Spectre.Console.Canvas(width, height); var scale = 2 * MaxValueExtent / Math.Min(canvas.Width, canvas.Height); for (var i = 0; i < canvas.Height; i++) { var y = (canvas.Height / 2 - i) * scale; for (var j = 0; j < canvas.Width; j++) { var x = (j - canvas.Width / 2) * scale; var value = Calculate(new ComplexNumber(x, y)); canvas.SetPixel(j, i, GetColor(value)); } } return canvas; } private static double Calculate(ComplexNumber c) { const int MaxIterations = 1000; const double MaxNorm = MaxValueExtent * MaxValueExtent; var iteration = 0; var z = new ComplexNumber(); do { z = z * z + c; iteration++; } while (z.Abs() < MaxNorm && iteration < MaxIterations); return iteration < MaxIterations ? (double)iteration / MaxIterations : 0; } private static Color GetColor(double value) { const double MaxColor = 256; const double ContrastValue = 0.2; return new Color(0, 0, (byte)(MaxColor * Math.Pow(value, ContrastValue))); } }