探索生物形态生成算法

在80年代末,研究人员克利福德·皮克沃(Clifford Pickover)开发了一种算法,用于生成一系列类似生物形态的图形,这些图形看起来像是微生物,或者可能是抽象画。这个过程非常简单,从一个复杂的变量函数F(z)开始,比如Sin(z) + z^2 + c,其中c是一个常数。然后,使用朱利亚集的标准收敛性研究,递归地处理这个函数,直到发现函数发散,即模值大于给定值。

关键在于皮克沃修改了算法,增加了一个关于结果实部和虚部大小的最终条件,但他在混淆了OR和AND运算符时犯了一个错误,正是这个错误让能够获得如此惊人的结果。

这个项目是用C#编写的,使用的是Visual Studio 2015。这个演示应用程序实际上只是一个幻灯片,展示了使用随机选择的函数生成的图像,这些函数来自一组十个函数中。常数c是随机选择的,这是获得许多不同形状的关键,即使使用相同的函数和相同的复平面子集。

首先,为这十个函数中的每一个定义了限制xmin, xmax, ymin, ymax,这些限制存储在一个名为_limits的数组中:

private double[,] _limits = new double[10, 4] { { 2, 4, -5, -3 }, { -2, 2, -2, 2 }, { -1.7, 1.7, -1.7, 1.7 }, { -3, 3, -3, 3 }, { -5, 5, -5, 5 }, { -10, 10, -10, 10 }, { -3, 3, -3, 3 }, { -1.5, 1.5, -1.5, 1.5 }, { -1.2, 1.2, -1.2, 1.2 }, { -8, 8, -8, 8 } };

为了处理复数,选择了System.Numerics命名空间中的Complex结构。Fz方法实现了选择的十个函数。实际上,不需要考虑太多来定义这些函数。写的几乎所有东西都会很好地工作:

private Complex Fz(Complex z, Complex c, int f) { switch(f) { case 0: return Complex.Sin(z) + Complex.Pow(z, 2) + c; case 1: return Complex.Pow(z, 2) + Complex.Pow(z, 6) + c; case 2: return Complex.Pow(z, 2) + Complex.Pow(z, 5) + c; case 3: return Complex.Pow(z, 3) + c; case 4: return Complex.Sin(z) + Complex.Pow(z, 5) + c; case 5: return Complex.Sin(z) - Complex.Cos(z) + Complex.Pow(z, 2) + c; case 6: return Complex.Pow(z, 3) - Complex.Cos(z) + Complex.Pow(z, 2) + c; case 7: return Complex.Pow(z, 6) - Complex.Pow(z, 4) + Complex.Sinh(z) + c; case 8: return Complex.Pow(z, 10) - Complex.Sinh(z) + c; default: return Complex.Cos(z) + Complex.Pow(z, 4) + c; } }

这是进行计算并绘制结果的方法。选择了使用async / await异步编程,以便在显示图片时让应用程序保持响应。

没有使用Bitmap类的SetPixel方法,而是通过使用包含像素颜色的整数数组的优化方式。在过程结束时,这些数据通过一次操作复制到Bitmap中。

private Task<Bitmap> BiomorphAsync(Complex c, int f) { return Task.Run(() => { int[] bmpbits = new int[640 * 480]; for (int ix = 0; ix < bmpbits.Length; ix++) { bmpbits[ix] = Color.White.ToArgb(); } double xmin = _limits[f, 0]; double xmax = _limits[f, 1]; double ymin = _limits[f, 2]; double ymax = _limits[f, 3]; double px = (xmax - xmin) / 639; double py = (ymax - ymin) / 479; for (int p = 0; p < 640; p++) { for (int q = 0; q < 480; q++) { Complex z = new Complex(xmin + p * px, ymin + q * py); for (int k = 1; k < 50; k++) { z = Fz(z, c, f); if (z.Magnitude > 100) { break; } } if (Math.Abs(z.Real) < 100 || Math.Abs(z.Imaginary) < 100) { bmpbits[p + 640 * (479 - q)] = Color.Black.ToArgb(); } } } Bitmap bmp = new Bitmap(640, 480); BitmapData bd = bmp.LockBits(new Rectangle(0, 0, 640, 480), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb); Marshal.Copy(bmpbits, 0, bd.Scan0, bmpbits.Length); bmp.UnlockBits(bd); return bmp; }); }

这个过程是在表单的Load事件中启动的,并循环直到FormClosing事件被触发。常数c是随机创建的,函数也是以同样的方式选择的。

private async void frmBio_Load(object sender, EventArgs e) { _stopBio = false; Random rnd = new Random(); while (!_stopBio) { pbImage.Image = await BiomorphAsync(new Complex(rnd.NextDouble() * (rnd.Next(3) + 1), rnd.NextDouble() * (rnd.Next(3) + 1)), rnd.Next(9)); await WaitmsAsync(1000); } } private void frmBio_FormClosing(object sender, FormClosingEventArgs e) { _stopBio = true; }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485