曼德勃罗集是一个著名的数学概念,它在复平面上定义,并以其复杂的边界和美丽的图案而闻名。本文将介绍一个软件工具,它允许用户探索曼德勃罗集,并生成相应的图像。用户可以通过界面操作来调整视窗,保存图像和参数。
当程序启动时,主图像尚未计算。为了获得曼德勃罗集的概览,只需点击位于顶部工具栏的“计算”按钮。除了主图像外,窗口右上角还有两个面板,“预览”和“鸟瞰图”。
预览提供了当前曼德勃罗集视图的一个小图像。与主图像不同,预览始终是最新的,因为出于性能原因,主图像需要点击“计算”才能刷新。
鸟瞰图提供了曼德勃罗集的概览,并且永远不会改变。用户可以通过在鸟瞰图窗口上拖动鼠标来选择新的视窗。此时,预览会更新,同时更新视窗的数值。主图像仍然需要点击“计算”以反映变化。鸟瞰图有助于放大或快速跳转到集合的另一部分。
它显示了视窗的图像,自动缩放以适应可用空间。用户可以在主图像上拖动鼠标来选择新的视窗。与鸟瞰图不同,新的视窗是相对于当前选定的视窗的。
窗口顶部有一些控件可以编辑数值。以下是它们的描述。
“宽度”和“高度”给出了由曼德勃罗程序创建的位图的大小(以像素为单位)。为了避免奇怪的图像,必须保持“宽度”和“高度”之间的比例与曼德勃罗集上的视窗比例相同。复选框“自动调整”允许程序在用户更改视窗时更改“高度”值(如果需要)。由于用户可以手动更改“宽度”和“高度”的值,按钮“调整比例”会强制更新“高度”值。一个注释给出了当前比例,供那些想要手工进行一些计算的人使用。
XMin、XMax、YMin和YMax定义了曼德勃罗集上的视窗。这些值可以手动编辑,其他控件会自动更新。一个注释显示了当前视窗的比例。
最大迭代次数设置了给定点被分类为曼德勃罗集外的迭代次数。尝试一些不同的值可能会很有趣。注意,生成的图像是每像素24位,因此最大迭代次数会给出模256的相似结果。
计算:重新生成主图像。
保存:将主图像保存为文件,作为Windows位图。同时将参数保存到同名的XML文件中。
重置:将所有参数恢复为默认值。
复制:将主图像复制到剪贴板。
复制参数:将参数复制到剪贴板。
位图生成如下:
public System.Drawing.Bitmap GetBitmap(
int pImageWidth,
int pImageHeight,
double pXMin,
double pXMax,
double pYMin,
double pYMax,
int pMaxIterationCount)
{
try
{
int i = 0;
int j = 0;
int[][] lValues = new int[pImageHeight][];
for (i = 0; i < pImageHeight; i++)
{
lValues[i] = new int[pImageWidth];
}
CalculateLevels(
lValues,
pImageWidth,
pImageHeight,
pXMin,
pXMax,
pYMin,
pYMax,
pMaxIterationCount);
System.Drawing.Bitmap lBitmap = new System.Drawing.Bitmap(
pImageWidth, pImageHeight,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
byte lRed = 0;
byte lGreen = 0;
byte lBlue = 0;
int lPixelByteCount = 4;
int lAlphaPos = 3;
int lRedPos = 2;
int lGreenPos = 1;
int lBluePos = 0;
int lPixelCount = pImageHeight * pImageWidth;
int lPixelPos = 0;
m_ProgressBar.Minimum = 0;
m_ProgressBar.Maximum = lPixelCount;
m_ProgressBar.Value = 0;
System.Drawing.Imaging.BitmapData lBitmapData = new System.Drawing.Imaging.BitmapData();
lBitmap.LockBits(
new System.Drawing.Rectangle(0, 0, pImageWidth, pImageHeight),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb,
lBitmapData);
unsafe
{
System.Byte* lStartPtr = (System.Byte*)((void*)lBitmapData.Scan0);
int lEndToStart = lBitmapData.Stride -
pImageWidth * lPixelByteCount;
System.Byte* lPtr = lStartPtr;
for (j = 0; j < pImageHeight; j++)
{
for (i = 0; i < pImageWidth; i++)
{
GetColorFromLevel(
lValues[j][i],
pMaxIterationCount,
out lRed,
out lGreen,
out lBlue);
lPtr[lAlphaPos] = 255;
lPtr[lRedPos] = lRed;
lPtr[lGreenPos] = lGreen;
lPtr[lBluePos] = lBlue;
lPtr += lPixelByteCount;
lPixelPos++;
}
lPtr += lEndToStart;
m_ProgressBar.Value = lPixelPos;
System.Windows.Forms.Application.DoEvents();
}
}
lBitmap.UnlockBits(lBitmapData);
return lBitmap;
}
catch
{
return null;
}
}
这个函数获取一个描述曼德勃罗集视窗的值数组。然后创建一个适当大小的位图,锁定它并填充它,通过推断初始数组中的颜色。
这里使用了一个非常简单的算法。将潜力与最大可用值进行比较。然后将比率分成8个区间,如下进行:黑色到红色 - 红色到黄色 - 黄色到绿色 - 绿色到青色 - 青色到蓝色 - 蓝色到品红色 - 品红色到白色 - 白色到黑色。
<?xml version="1.0" encoding="utf-16"?>
<State xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<XMin>-0.040557444936069775</XMin>
<XMax>-0.040016368521333778</XMax>
<YMin>0.98423178672189038</YMin>
<YMax>0.98491968869265967</YMax>
<ImageWidth>1200</ImageWidth>
<ImageHeight>1526</ImageHeight>
<MaxIterationCount>100</MaxIterationCount>
</State>
示例图像是用这个软件计算的。注意:这些图像已经被缩小以满足大小要求。