Mandelbrot 集的视觉表示
Visual representation of the Mandelbrot set
我想使用 Java 生成 Mandelbrot 集的 PNG 照片,应该可以在 google 图片搜索中轻松找到输出。
集合定义为以下序列:
z_n+1 = z_n^2 + c
其中 c
和 z
是复数,z
的模数总是小于 2。
我首先为复数定义了一个class,其中还包含了所需的基本复数运算。
public class ComplexNumber {
private double real;
private double imaginary;
public ComplexNumber(double real, double imaginary) {
this.real = real;
this.imaginary = imaginary;
}
public ComplexNumber add(ComplexNumber z1, ComplexNumber z2) {
ComplexNumber sum = new ComplexNumber(0, 0);
sum.real = z1.real + z2.real;
sum.imaginary = z1.imaginary + z2.imaginary;
return sum;
}
public ComplexNumber square(ComplexNumber z) {
ComplexNumber squared = new ComplexNumber(0, 0);
squared.real = Math.pow(z.real, 2) - Math.pow(z.imaginary, 2);
squared.imaginary = 2 * z.real * z.imaginary;
return squared;
}
public double abs() {
double absolute = Math.sqrt(Math.pow(this.real, 2) + Math.pow(this.imaginary, 2));
return absolute;
}
}
然后我定义了 Mandelbrot class,它获取一些复数 c(基于像素)使用 mandelbrot 方法检查这些数字是否在 mandelbrot 集中,并传输此输出要显示的颜色的方法。
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Mandelbrot {
public static int mandelbrot(ComplexNumber c, ComplexNumber z, int i, int n) {
if (i < n) {
if (c.abs() > 2.0) {
return i;
} else
return 0;
}
return mandelbrot(c, z.square(z).add(z, c), i, n);
}
// Create the Mandelbrot image, fill it and save it as PNG file.
public static void createMandelbrotImage(int tileSize, int maxRecurse) throws IOException {
int height = 2 * tileSize;
int width = 3 * tileSize;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
ComplexNumber z0 = new ComplexNumber(0, 0);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Construct a complex number from the pixel coordinates
float xPos = (x + 0.5f - 2 * tileSize) / tileSize;
float yPos = (y + 0.5f - tileSize) / tileSize;
ComplexNumber c = new ComplexNumber(xPos, yPos);
// Check the Mandelbrot condition for this complex number
int mb = mandelbrot(c, z0, 0, maxRecurse);
// Translate the result to number in a reasonable range and use it as color.
double mbl = mb > 0 ? Math.log(mb) / Math.log(maxRecurse) : 0;
image.setRGB(x, y, (int) (mbl * 255));
}
}
// Save the image as PNG
String OS = System.getProperty("os.name").toLowerCase(); // different for win and unix
String filePath = System.getProperty("user.dir") + (OS.indexOf("win") >= 0 ? "\" : "/") + "mandelbrot.png";
System.out.println("Writing mandelbrot image to: " + filePath);
ImageIO.write(image, "png", new File(filePath));
}
public static void main(String[] args) throws IOException {
createMandelbrotImage(500, 2 ^ 24);
}
}
问题是这段代码总是输出黑色的空图,我好像没发现错误。
您的递归 mandelbrot 函数似乎有不正确的终止条件。
您希望 mandelbrot 函数 return,当
- z的绝对值超过2或
- 已达到最大递归深度。
此外,您永远不会递增 i。
所以更新后的函数看起来像:
public static int mandelbrot(ComplexNumber c, ComplexNumber z, int i, int n) {
if (i >= n) {
// mandelbrot function does not diverge after n iterations.
// Returning -1 as a magic value to indicate that the point c is in the mandelbrot set.
// Values may already be outside of the mandelbrot set in the 0th iteration, so returning -1 makes more sense.
return -1;
} else if (z.abs() >= 2.0) {
// mandelbrot function is diverging after i iterations.
return i;
} else {
// recursively call mandelbrot function with an updated z and an incremented i.
return mandelbrot(c, z.squared().add(c), i + 1, n);
}
}
最后,如果您选择 return -1 对于 mandelbrot 集中的一个点,您必须更新您的颜色计算以将这些点设置为黑色。
int mb = mandelbrot(c, z0, 0, maxRecurse);
if (mb == -1) {
image.setRGB(x, y, 0);
} else {
// set the color of your image as usual
}
我想使用 Java 生成 Mandelbrot 集的 PNG 照片,应该可以在 google 图片搜索中轻松找到输出。
集合定义为以下序列:
z_n+1 = z_n^2 + c
其中 c
和 z
是复数,z
的模数总是小于 2。
我首先为复数定义了一个class,其中还包含了所需的基本复数运算。
public class ComplexNumber {
private double real;
private double imaginary;
public ComplexNumber(double real, double imaginary) {
this.real = real;
this.imaginary = imaginary;
}
public ComplexNumber add(ComplexNumber z1, ComplexNumber z2) {
ComplexNumber sum = new ComplexNumber(0, 0);
sum.real = z1.real + z2.real;
sum.imaginary = z1.imaginary + z2.imaginary;
return sum;
}
public ComplexNumber square(ComplexNumber z) {
ComplexNumber squared = new ComplexNumber(0, 0);
squared.real = Math.pow(z.real, 2) - Math.pow(z.imaginary, 2);
squared.imaginary = 2 * z.real * z.imaginary;
return squared;
}
public double abs() {
double absolute = Math.sqrt(Math.pow(this.real, 2) + Math.pow(this.imaginary, 2));
return absolute;
}
}
然后我定义了 Mandelbrot class,它获取一些复数 c(基于像素)使用 mandelbrot 方法检查这些数字是否在 mandelbrot 集中,并传输此输出要显示的颜色的方法。
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Mandelbrot {
public static int mandelbrot(ComplexNumber c, ComplexNumber z, int i, int n) {
if (i < n) {
if (c.abs() > 2.0) {
return i;
} else
return 0;
}
return mandelbrot(c, z.square(z).add(z, c), i, n);
}
// Create the Mandelbrot image, fill it and save it as PNG file.
public static void createMandelbrotImage(int tileSize, int maxRecurse) throws IOException {
int height = 2 * tileSize;
int width = 3 * tileSize;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
ComplexNumber z0 = new ComplexNumber(0, 0);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// Construct a complex number from the pixel coordinates
float xPos = (x + 0.5f - 2 * tileSize) / tileSize;
float yPos = (y + 0.5f - tileSize) / tileSize;
ComplexNumber c = new ComplexNumber(xPos, yPos);
// Check the Mandelbrot condition for this complex number
int mb = mandelbrot(c, z0, 0, maxRecurse);
// Translate the result to number in a reasonable range and use it as color.
double mbl = mb > 0 ? Math.log(mb) / Math.log(maxRecurse) : 0;
image.setRGB(x, y, (int) (mbl * 255));
}
}
// Save the image as PNG
String OS = System.getProperty("os.name").toLowerCase(); // different for win and unix
String filePath = System.getProperty("user.dir") + (OS.indexOf("win") >= 0 ? "\" : "/") + "mandelbrot.png";
System.out.println("Writing mandelbrot image to: " + filePath);
ImageIO.write(image, "png", new File(filePath));
}
public static void main(String[] args) throws IOException {
createMandelbrotImage(500, 2 ^ 24);
}
}
问题是这段代码总是输出黑色的空图,我好像没发现错误。
您的递归 mandelbrot 函数似乎有不正确的终止条件。
您希望 mandelbrot 函数 return,当
- z的绝对值超过2或
- 已达到最大递归深度。
此外,您永远不会递增 i。
所以更新后的函数看起来像:
public static int mandelbrot(ComplexNumber c, ComplexNumber z, int i, int n) {
if (i >= n) {
// mandelbrot function does not diverge after n iterations.
// Returning -1 as a magic value to indicate that the point c is in the mandelbrot set.
// Values may already be outside of the mandelbrot set in the 0th iteration, so returning -1 makes more sense.
return -1;
} else if (z.abs() >= 2.0) {
// mandelbrot function is diverging after i iterations.
return i;
} else {
// recursively call mandelbrot function with an updated z and an incremented i.
return mandelbrot(c, z.squared().add(c), i + 1, n);
}
}
最后,如果您选择 return -1 对于 mandelbrot 集中的一个点,您必须更新您的颜色计算以将这些点设置为黑色。
int mb = mandelbrot(c, z0, 0, maxRecurse);
if (mb == -1) {
image.setRGB(x, y, 0);
} else {
// set the color of your image as usual
}