18 Star 133 Fork 63

编程语言算法集 / C-Sharp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Mandelbrot.cs 7.44 KB
一键复制 编辑 原始数据 按行查看 历史
Gerson Jr 提交于 2023-12-31 09:48 . Switch to file-scoped namespaces (#431)
using System;
using System.Drawing;
namespace Algorithms.Other;
/// <summary>
/// The Mandelbrot set is the set of complex numbers "c" for which the series
/// "z_(n+1) = z_n * z_n + c" does not diverge, i.e. remains bounded. Thus, a
/// complex number "c" is a member of the Mandelbrot set if, when starting with
/// "z_0 = 0" and applying the iteration repeatedly, the absolute value of
/// "z_n" remains bounded for all "n > 0". Complex numbers can be written as
/// "a + b*i": "a" is the real component, usually drawn on the x-axis, and "b*i"
/// is the imaginary component, usually drawn on the y-axis. Most visualizations
/// of the Mandelbrot set use a color-coding to indicate after how many steps in
/// the series the numbers outside the set cross the divergence threshold.
/// Images of the Mandelbrot set exhibit an elaborate and infinitely
/// complicated boundary that reveals progressively ever-finer recursive detail
/// at increasing magnifications, making the boundary of the Mandelbrot set a
/// fractal curve.
/// (description adapted from https://en.wikipedia.org/wiki/Mandelbrot_set)
/// (see also https://en.wikipedia.org/wiki/Plotting_algorithms_for_the_Mandelbrot_set).
/// </summary>
public static class Mandelbrot
{
/// <summary>
/// Method to generate the bitmap of the Mandelbrot set. Two types of coordinates
/// are used: bitmap-coordinates that refer to the pixels and figure-coordinates
/// that refer to the complex numbers inside and outside the Mandelbrot set. The
/// figure-coordinates in the arguments of this method determine which section
/// of the Mandelbrot set is viewed. The main area of the Mandelbrot set is
/// roughly between "-1.5 &lt; x &lt; 0.5" and "-1 &lt; y &lt; 1" in the figure-coordinates.
/// To save the bitmap the command 'GetBitmap().Save("Mandelbrot.png")' can be used.
/// </summary>
/// <param name="bitmapWidth">The width of the rendered bitmap.</param>
/// <param name="bitmapHeight">The height of the rendered bitmap.</param>
/// <param name="figureCenterX">The x-coordinate of the center of the figure.</param>
/// <param name="figureCenterY">The y-coordinate of the center of the figure.</param>
/// <param name="figureWidth">The width of the figure.</param>
/// <param name="maxStep">Maximum number of steps to check for divergent behavior.</param>
/// <param name="useDistanceColorCoding">Render in color or black and white.</param>
/// <returns>The bitmap of the rendered Mandelbrot set.</returns>
public static Bitmap GetBitmap(
int bitmapWidth = 800,
int bitmapHeight = 600,
double figureCenterX = -0.6,
double figureCenterY = 0,
double figureWidth = 3.2,
int maxStep = 50,
bool useDistanceColorCoding = true)
{
if (bitmapWidth <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(bitmapWidth),
$"{nameof(bitmapWidth)} should be greater than zero");
}
if (bitmapHeight <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(bitmapHeight),
$"{nameof(bitmapHeight)} should be greater than zero");
}
if (maxStep <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(maxStep),
$"{nameof(maxStep)} should be greater than zero");
}
var bitmap = new Bitmap(bitmapWidth, bitmapHeight);
var figureHeight = figureWidth / bitmapWidth * bitmapHeight;
// loop through the bitmap-coordinates
for (var bitmapX = 0; bitmapX < bitmapWidth; bitmapX++)
{
for (var bitmapY = 0; bitmapY < bitmapHeight; bitmapY++)
{
// determine the figure-coordinates based on the bitmap-coordinates
var figureX = figureCenterX + ((double)bitmapX / bitmapWidth - 0.5) * figureWidth;
var figureY = figureCenterY + ((double)bitmapY / bitmapHeight - 0.5) * figureHeight;
var distance = GetDistance(figureX, figureY, maxStep);
// color the corresponding pixel based on the selected coloring-function
bitmap.SetPixel(
bitmapX,
bitmapY,
useDistanceColorCoding ? ColorCodedColorMap(distance) : BlackAndWhiteColorMap(distance));
}
}
return bitmap;
}
/// <summary>
/// Black and white color-coding that ignores the relative distance. The Mandelbrot
/// set is black, everything else is white.
/// </summary>
/// <param name="distance">Distance until divergence threshold.</param>
/// <returns>The color corresponding to the distance.</returns>
private static Color BlackAndWhiteColorMap(double distance) =>
distance >= 1
? Color.FromArgb(255, 0, 0, 0)
: Color.FromArgb(255, 255, 255, 255);
/// <summary>
/// Color-coding taking the relative distance into account. The Mandelbrot set
/// is black.
/// </summary>
/// <param name="distance">Distance until divergence threshold.</param>
/// <returns>The color corresponding to the distance.</returns>
private static Color ColorCodedColorMap(double distance)
{
if (distance >= 1)
{
return Color.FromArgb(255, 0, 0, 0);
}
// simplified transformation of HSV to RGB
// distance determines hue
var hue = 360 * distance;
double saturation = 1;
double val = 255;
var hi = (int)Math.Floor(hue / 60) % 6;
var f = hue / 60 - Math.Floor(hue / 60);
var v = (int)val;
var p = 0;
var q = (int)(val * (1 - f * saturation));
var t = (int)(val * (1 - (1 - f) * saturation));
switch (hi)
{
case 0: return Color.FromArgb(255, v, t, p);
case 1: return Color.FromArgb(255, q, v, p);
case 2: return Color.FromArgb(255, p, v, t);
case 3: return Color.FromArgb(255, p, q, v);
case 4: return Color.FromArgb(255, t, p, v);
default: return Color.FromArgb(255, v, p, q);
}
}
/// <summary>
/// Return the relative distance (ratio of steps taken to maxStep) after which the complex number
/// constituted by this x-y-pair diverges. Members of the Mandelbrot set do not
/// diverge so their distance is 1.
/// </summary>
/// <param name="figureX">The x-coordinate within the figure.</param>
/// <param name="figureY">The y-coordinate within the figure.</param>
/// <param name="maxStep">Maximum number of steps to check for divergent behavior.</param>
/// <returns>The relative distance as the ratio of steps taken to maxStep.</returns>
private static double GetDistance(double figureX, double figureY, int maxStep)
{
var a = figureX;
var b = figureY;
var currentStep = 0;
for (var step = 0; step < maxStep; step++)
{
currentStep = step;
var aNew = a * a - b * b + figureX;
b = 2 * a * b + figureY;
a = aNew;
// divergence happens for all complex number with an absolute value
// greater than 4 (= divergence threshold)
if (a * a + b * b > 4)
{
break;
}
}
return (double)currentStep / (maxStep - 1);
}
}
C#
1
https://gitee.com/TheAlgorithms/C-Sharp.git
git@gitee.com:TheAlgorithms/C-Sharp.git
TheAlgorithms
C-Sharp
C-Sharp
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891