如何使用 SWING/AWT 在 Java 中绘制 Mandelbrot 集?
How do you draw the Mandelbrot Set in Java using SWING/AWT?
我正在尝试绘制 Mandelbrot 集合,集合中的点为黑色,其他所有点为白色。在这个初始版本中,我不希望能够放大,而只是创建一个静态图像。
我创建了一个 ComplexNumber class,如下所示,用于一起处理复数的平方和相加。
public class ComplexNumber {
private double real;
private double imaginary;
public ComplexNumber(double real, double imaginary){
this.real = real;
this.imaginary = imaginary;
}
public ComplexNumber times(ComplexNumber number){
double a = this.real*number.real;
double b = this.imaginary*number.real;
double c = this.real*number.imaginary;
double d = this.imaginary*number.imaginary*-1;
double newReal = a+d;
double newImaginary = b+c;
ComplexNumber newComplexNumber = new ComplexNumber(newReal, newImaginary);
return newComplexNumber;
}
public ComplexNumber add(ComplexNumber number){
double newReal = this.real+number.real;
double newImaginary = this.imaginary+number.imaginary;
return new ComplexNumber(newReal, newImaginary);
}
public double abs(){
return Math.hypot(this.real, this.imaginary);
}
public double getReal() {
return real;
}
public double getImaginary() {
return imaginary;
}
}
这是我渲染 GUI 并实际计算 Mandelbrot 集中的点的代码。
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class MandelBrotSet extends JComponent {
public static final int WIDTH = 800;
public static final int HEIGHT = 800;
public static final int ITERATIONS = 100;
public static final double startX = -2;
public static final double width = 4;
public static final double startY = 2;
public static final double height = 4;
public static final double dx = width/(WIDTH-1);
public static final double dy = height/(HEIGHT-1);
private BufferedImage buffer;
public MandelBrotSet() {
buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
JFrame frame = new JFrame("Mandelbrot Set");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
frame.getContentPane().add(this);
frame.pack();
frame.setVisible(true);
}
@Override
public void addNotify() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
}
@Override
public void paint(Graphics g) {
g.drawImage(buffer, 0, 0, null);
}
public void render(){
for (int x=0; x<WIDTH; x++){
for (int y=0; y<HEIGHT; y++){
int color = calculatePoint(x, y);
buffer.setRGB(x, y, color);
}
}
}
public int calculatePoint(int x, int y){
ComplexNumber number = convertToComplex(x, y);
ComplexNumber z = number;
int i;
for (i=0; i<ITERATIONS; i++){
z = z.times(z).add(number);
if (z.abs()>2.0){
break;
}
}
if (i==ITERATIONS) {
return 0x00000000;
}
else {
return 0xFFFFFFFF;
}
}
public static ComplexNumber convertToComplex(int x, int y){
double real = startX + x*dx;
double imaginary = 2 - y*dy;
return new ComplexNumber(real, imaginary);
}
public static void main(String[] args) {
MandelBrotSet mandy = new MandelBrotSet();
mandy.render();
}
}
在 运行 这段代码之后,我得到了下面的图像。似乎可以瞥见 Mandelbrot 集,但随后被大量黑色遮挡。我做错了什么?
更新了下面的解决方案。感谢您的帮助。
您的图像渲染比显示 MandelBrotSet
-Object 花费的时间更长,并且之后永远不会更新。
您创建一个 MandelBrotSet
类型的对象,然后立即调用它的渲染方法。在创建该对象的过程中,您将其放入立即显示的 JFrame
中。显示框架时,渲染不完整,这就是为什么您的 ImageBuffer
尚未填充(构建 mandelbrot-form 需要更长的时间)。
要解决这个问题,您可以重新绘制涉及的组件和框架。我对 awt 的重绘功能的理解不足以告诉你如何正确地做它(也许其他人可以提供帮助),但是将它添加到你的渲染方法的末尾应该会有所帮助:
revalidate();
repaint();
可以省略 revalidate 或 repaint。
如果您使用已完成的图片更新您的问题,那就太好了:)
我正在尝试绘制 Mandelbrot 集合,集合中的点为黑色,其他所有点为白色。在这个初始版本中,我不希望能够放大,而只是创建一个静态图像。
我创建了一个 ComplexNumber class,如下所示,用于一起处理复数的平方和相加。
public class ComplexNumber {
private double real;
private double imaginary;
public ComplexNumber(double real, double imaginary){
this.real = real;
this.imaginary = imaginary;
}
public ComplexNumber times(ComplexNumber number){
double a = this.real*number.real;
double b = this.imaginary*number.real;
double c = this.real*number.imaginary;
double d = this.imaginary*number.imaginary*-1;
double newReal = a+d;
double newImaginary = b+c;
ComplexNumber newComplexNumber = new ComplexNumber(newReal, newImaginary);
return newComplexNumber;
}
public ComplexNumber add(ComplexNumber number){
double newReal = this.real+number.real;
double newImaginary = this.imaginary+number.imaginary;
return new ComplexNumber(newReal, newImaginary);
}
public double abs(){
return Math.hypot(this.real, this.imaginary);
}
public double getReal() {
return real;
}
public double getImaginary() {
return imaginary;
}
}
这是我渲染 GUI 并实际计算 Mandelbrot 集中的点的代码。
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class MandelBrotSet extends JComponent {
public static final int WIDTH = 800;
public static final int HEIGHT = 800;
public static final int ITERATIONS = 100;
public static final double startX = -2;
public static final double width = 4;
public static final double startY = 2;
public static final double height = 4;
public static final double dx = width/(WIDTH-1);
public static final double dy = height/(HEIGHT-1);
private BufferedImage buffer;
public MandelBrotSet() {
buffer = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
JFrame frame = new JFrame("Mandelbrot Set");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
frame.getContentPane().add(this);
frame.pack();
frame.setVisible(true);
}
@Override
public void addNotify() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
}
@Override
public void paint(Graphics g) {
g.drawImage(buffer, 0, 0, null);
}
public void render(){
for (int x=0; x<WIDTH; x++){
for (int y=0; y<HEIGHT; y++){
int color = calculatePoint(x, y);
buffer.setRGB(x, y, color);
}
}
}
public int calculatePoint(int x, int y){
ComplexNumber number = convertToComplex(x, y);
ComplexNumber z = number;
int i;
for (i=0; i<ITERATIONS; i++){
z = z.times(z).add(number);
if (z.abs()>2.0){
break;
}
}
if (i==ITERATIONS) {
return 0x00000000;
}
else {
return 0xFFFFFFFF;
}
}
public static ComplexNumber convertToComplex(int x, int y){
double real = startX + x*dx;
double imaginary = 2 - y*dy;
return new ComplexNumber(real, imaginary);
}
public static void main(String[] args) {
MandelBrotSet mandy = new MandelBrotSet();
mandy.render();
}
}
在 运行 这段代码之后,我得到了下面的图像。似乎可以瞥见 Mandelbrot 集,但随后被大量黑色遮挡。我做错了什么?
更新了下面的解决方案。感谢您的帮助。
您的图像渲染比显示 MandelBrotSet
-Object 花费的时间更长,并且之后永远不会更新。
您创建一个 MandelBrotSet
类型的对象,然后立即调用它的渲染方法。在创建该对象的过程中,您将其放入立即显示的 JFrame
中。显示框架时,渲染不完整,这就是为什么您的 ImageBuffer
尚未填充(构建 mandelbrot-form 需要更长的时间)。
要解决这个问题,您可以重新绘制涉及的组件和框架。我对 awt 的重绘功能的理解不足以告诉你如何正确地做它(也许其他人可以提供帮助),但是将它添加到你的渲染方法的末尾应该会有所帮助:
revalidate();
repaint();
可以省略 revalidate 或 repaint。
如果您使用已完成的图片更新您的问题,那就太好了:)