将颜色层添加到 mandelbrot 集
Posted
技术标签:
【中文标题】将颜色层添加到 mandelbrot 集【英文标题】:Adding color layers to the mandelbrot set 【发布时间】:2015-06-22 05:59:52 【问题描述】:我对分形非常感兴趣,但直到最近才有机会实施它们。我首先实现了一个黑白曼德布罗集,然后我尝试为其添加颜色。
这是我的 mandelbrot 的实现(我使用 org.apache.commons.math3.complex.Complex 来处理复数)
public class MyMandelbrot
public static int numberOfIterationsToCheck(Complex z0, int max)
Complex z = z0;
for (int t = 0; t < max; t++)
if (z.abs() > 2.0) return t;
z =z.multiply(z).add(z0);
return max;
public static void main(String[] args)
double xc = Double.parseDouble(args[0]);
double yc = Double.parseDouble(args[1]);
double size = Double.parseDouble(args[2]);
int N = 512;
int max = 255;
Viewer viewer = new Viewer(N, N);
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
double x0 = xc - size/2 + size*i/N;
double y0 = yc - size/2 + size*j/N;
Complex z0 = new Complex(x0, y0);
int gray = max - numberOfIterationsToCheck(z0, max);
Color color = new Color(gray, gray, gray);
if (z0.abs() > 2.0 )
color = new Color(gray, 128, gray);
else if (z0.abs() > 2.0 && numberOfIterationsToCheck(z0, max) > max/2)
color = new Color(255, gray, 255);
else if (z0.abs() > 2.0 && numberOfIterationsToCheck(z0, max) < max/2)
color = new Color(gray, 128,128);
else if (z0.abs() > 1.0 && numberOfIterationsToCheck(z0, max) < max/2 )
color = new Color(128, gray, 128);
else if (z0.abs() > 1.0)
color = new Color(128, gray, 128);
else if (z0.abs() <= 1.0)
color = new Color(gray, gray, 128);
viewer.set(i, N-1-j, color);
viewer.show();
在图像对象中绘制集合后,我正在使用自定义查看器类来查看集合。这是Viewer的set方法
public void set(int col, int row, Color color)
if (col < 0 || col >= width()) throw new IndexOutOfBoundsException("col must be between 0 and " + (width()-1));
if (row < 0 || row >= height()) throw new IndexOutOfBoundsException("row must be between 0 and " + (height()-1));
if (color == null) throw new NullPointerException("can't set Color to null");
if (isOriginUpperLeft) image.setRGB(col, row, color.getRGB());
else image.setRGB(col, height - row - 1, color.getRGB());
代码正在正确渲染集合,但我没有获得预期的结果。我想要的是能够产生类似于这些的彩色集
或者这个
但我找不到比这更好的彩色套装了。
我已经阅读了一些关于它的理论解释here 和here,但我在实践中显然做错了什么。我的着色方法有什么问题?我该如何解决?谢谢
【问题讨论】:
【参考方案1】:在您展示的示例中,颜色仅基于点转义之前的迭代次数,而不是基于初始复坐标 z0。一种方法是使用 getHSBColor() 使用 Hue-Saturation-Brightness 颜色值,并根据转义前的迭代次数更改色调,例如:
double x0 = xc - size/2 + size*i/N;
double y0 = yc - size/2 + size*j/N;
Complex z0 = new Complex(x0, y0);
int escapeIterations = numberOfIterationsToCheck(z0, max);
// set color varying hue based on escape iterations:
Color color = Color.getHSBColor((float)escapeIterations / (float)max, 1.0f, 1.0f);
viewer.set(i, N-1-j, color);
上面的代码不会改变饱和度或亮度(两者都设置为 1.0),但你也可以根据你想要的效果来改变它们。
您可以通过将色调值乘以一个常数来使颜色循环多次通过色调的色环,例如:
(float)escapeIterations * 2.0f / (float)max
您还可以添加一个常量,使其以特定颜色开始。
因为escapeIterations
是一个int,所以每次迭代颜色都会逐步跳跃。您可以通过从numberOfIterationsToCheck
返回一个浮点数来使颜色更平滑:
public static float numberOfIterationsToCheckSmooth(Complex z0, int max)
Complex z = z0;
for (int t = 0; t < max; t++)
double fAbs = z.abs();
if (fAbs > 2.0)
// based on the final value, add a fractional amount based on
// how much it escaped by (fAbs will be in the range of 2 to around 4):
return (float)t + (2.0f - (Math.log(fAbs) / Math.log(2.0)));
z =z.multiply(z).add(z0);
return (float)max;
最后,另一种可以最大程度地控制颜色的方法是使用颜色表,每次迭代最多使用一个颜色表,并可选择在它们之间进行插值。
【讨论】:
好的,让我在几分钟后应用这个,我会回来的 谢谢你的额外解释,我会玩的。以上是关于将颜色层添加到 mandelbrot 集的主要内容,如果未能解决你的问题,请参考以下文章