【问题标题】:Java Mandelbrot visualization questions on zooming and coloringJava Mandelbrot 关于缩放和着色的可视化问题
【发布时间】:2018-11-19 19:25:40
【问题描述】:

我正在尝试为 Java 中的 Mandelbrot 集编写可视化程序,并且有几件事我正在努力编程。我意识到围绕这个主题的问题被问了很多,网上有很多文档,但是很多事情看起来很复杂,而且我对编程还比较陌生。

第一期

我遇到的第一个问题是放大分形。我的目标是在分形上进行“无限”缩放(当然不是无限的,只要普通计算机允许计算时间和精度)。我目前正在采用的方法是计时器上的以下内容:

  • 在实轴范围 (-2, 2) 和虚轴范围 (2, 2) 上使用一定次数的迭代绘制集合。
  • 更改这些范围以放大。
  • 根据迭代次数重新绘制集合的该部分。

这是我挣扎的第二步。这是我当前的代码:

for (int Py = beginY; Py < endY; Py++) {
        for (int Px = beginX; Px < endX; Px++) {
            double x0 = map(Px, 0, height,-2, 2);
            double y0 = map(Py, 0, width, -2, 2);

Px 和 Py 是图像中像素的坐标。图像为 1000x1000。 map 函数接受一个范围为 (0, 1000) 的数字,在本例中为 Px 或 Py,并将其平均分配在 (-2, 2) 范围内,因此它返回该范围内的相应值。

我认为为了放大,我必须通过某种方式在计时器中更改 -2 和 2 值,但无论我尝试什么,它似乎都不起作用。缩放总是会在一段时间后变慢,或者最终会放大集合中的一部分,而不是边界。我尝试在每个计时器滴答声中将它们乘以某个比例因子,但这并不能真正产生我想要的结果。

现在我有两个关于这个问题的问题。

  1. 这是对集合进行可视化和放大(绘制、更改范围、重绘)的正确方法吗?
  2. 如果是,我如何正确放大有趣的区域,并且即使在运行一分钟后仍能正常放大?

第二期

当然,在可视化某些东西时,您需要获得一些实际的视觉效果。在这种情况下,我想以类似于您在此处看到的方式为集合着色:(https://upload.wikimedia.org/wikipedia/commons/f/fc/Mandel_zoom_08_satellite_antenna.jpg)。

我的猜测是,您已经使用了一个像素在跳出循环之前所经历的迭代量来赋予它一些颜色值。但是,我只知道如何使用黑白配色方案来做到这一点。我尝试制作一个颜色数组,它包含与最大迭代量相同数量的不同灰色颜色,从黑色开始,以白色结束。这是我的代码:

Color[] colors = new Color[maxIterations + 2];
    for (int i = 0; i < colors.length; i++) {
        colors[i] = new Color((int)map(i, 0, maxIterations + 2, 0, 255), 
        (int)map(i, 0, maxIterations + 2, 0, 255), 
        (int)map(i, 0, maxIterations + 2, 0, 255));
    }

然后我只是在数组中填充了迭代次数并将该颜色分配给像素。我对此有两个问题:

  1. 当我们以前面描述的方式放大分形时,这是否也有效?
  2. 如何添加我自己的配色方案,如图所示?我已经阅读了一些有关“线性插值”的内容,但我并不真正了解它是什么以及它可以以何种方式帮助我。

【问题讨论】:

  • 在计算机上无法进行无限缩放,但您可以缩放直到失去精度。 64 位 IEEE 浮点数为您提供 18 位精度。
  • @duffymo 是的,你是对的。我的目标只是进行缩放,直到由于这些或类似的限制而无法再缩放。我会在帖子中澄清这一点。
  • 我已经用 Java 完成了,但我无法访问我在工作中保存的 BitBucket 存储库。我会尽量记住稍后发布。

标签: java mandelbrot


【解决方案1】:

听起来你已经有了一个好的开始。

关于第一个问题:我相信有一些方法可以自动选择场景中“有趣”的部分进行放大,但我不知道它们是什么。而且我很确定它涉及的不仅仅是将一些线性函数应用于您当前的边界矩形,这听起来就像您正在做的那样。

因此,您可以尝试找出这些方法是什么(可能在数学上变得复杂),但如果您是编程新手,您可能会发现让用户选择缩放位置更容易。这在开始时也更有趣,因为您可以反复运行您的程序并每次探索集合的新部分。

一种简单的方法是让用户在图像上绘制一个矩形,并使用您的map 函数将绘制矩形的像素坐标转换为缩放区域的新实坐标和虚坐标。

您也可以将这两种方法结合起来:通过手动选择缩放区域找到感兴趣的地方后,您可以将其设置为“最终目的地”,并让代码逐渐平滑地放大它,以创建不错的电影。

不过,随着您开始使用越来越精确的坐标,它总是会逐渐变慢,直到您使用double 达到精度极限,它就会变成一个像素化的混乱。从那里开始,如果您想进一步放大,则必须使用BigDecimal 研究任意精度的算术 - 它会越来越慢。

关于第二个问题:首先为每个像素计算 numIterations / maxIterations 的值(即介于 0 和 1 之间)是正确的想法(我认为这基本上就是您正在做的事情)。

从那里开始,有各种方法可以将此值转换为颜色,是时候发挥创意了!

一个简单的方法是拥有一组非常不同的颜色。例如。如果您有白色 (0.0)、红色 (0.25)、绿色 (0.5)、蓝色 (0.75)、黑色 (1.0),那么如果您计算的数字恰好是列出的数字之一,您将使用相应的颜色。如果介于两者之间,则混合颜色,例如0.3 你会拿:

((0.5-0.3)*red + (0.3-0.25)*green) / (0.5 - 0.25)
= 0.8*red + 0.2*green

取两种颜色的加权平均值作为练习我会留下来;) (提示:分别取 r、g 和 b 值的平均值。使用 alpha 值也可能有效)。

另一个,如果你想得到更多的数学,是拿一个equation for a spiral并用它来计算HSB colour space平面上的一个点(你可以将亮度保持在某个固定值,比如1)。事实上,如果您将坐标解释为某个颜色空间中的点,那么您知道如何将任何 2D 或 3D 曲线写为一个实变量的方程,都可以通过这种方式为您提供平滑变化的颜色。

希望这足以让您继续前进!如果不清楚,请告诉我。

【讨论】:

  • 感谢您的回复。我肯定会仔细研究放大有趣部分的方法。在您的推荐之后,我尝试了用户输入的缩放方式,它可以工作。这已经是一个不错的选择,但是,我仍然希望有某种自动缩放。你说我可以让程序放大保存的位置,但那是我真的不知道该怎么做的事情。要么图像被拉伸,缩放速度减慢,要么我放大到场景的“白色”部分,在那里你什么都看不到。 (...)
  • 对于第二期,我不太明白如何使用螺旋方程来分配颜色。我假设我使用迭代/maxIterations 的比率作为角度或其他什么?但是我如何使用这些信息来获得颜色呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-26
相关资源
最近更新 更多