我应该怎么做才能在图像中看到复平面的一般矩形区域?
What should I do to allow a general rectangular region of the complex plane to be viewed in the image?
我希望每个人都过得很好:)
我有一个显示图像的 Java 程序,我需要修改它以允许在图像中查看复平面的一般矩形区域。用户可以通过鼠标拖动select矩形。
任何人都可以帮我做吗?
这是代码:
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
public class Mandelbrot extends JApplet {
public static void main(String s[]) {
JFrame frame = new JFrame();
frame.setTitle("Mandelbrot set");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JApplet applet = new Mandelbrot();
applet.init();
frame.getContentPane().add(applet);
frame.pack();
frame.setVisible(true);
}
public void init() {
JPanel panel = new MandelbrotPanel();
getContentPane().add(panel);
}
}
class MandelbrotPanel extends JPanel{
BufferedImage bi;
public MandelbrotPanel() {
int w = 500;
int h = 500;
setPreferredSize(new Dimension(w, h));
setBackground(Color.white);
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
WritableRaster raster = bi.getRaster();
int[] rgb = new int[3];
float xmin = -2;
float ymin = -2;
float xscale = 4f/w;
float yscale = 4f/h;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
float cr = xmin + j * xscale;
float ci = ymin + i * yscale;
int count = iterCount(cr, ci);
rgb[0] = (count & 0x07) << 5;
rgb[1] = ((count >> 3) & 0x07) << 5;
rgb[2] = ((count >> 6) & 0x07) << 5;
raster.setPixel(j, i, rgb);
}
}
}
private int iterCount(float cr, float ci) {
int max = 512;
float zr = 0;
float zi = 0;
float lengthsq = 0;
int count = 0;
while ((lengthsq < 4.0) && (count < max)) {
float temp = zr * zr - zi * zi + cr;
zi = 2 * zr * zi + ci;
zr = temp;
lengthsq = zr * zr + zi * zi;
count++;
}
return max-count;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bi, 0, 0, this);
}
}
提前谢谢你:)
您需要跟踪显示给用户的复平面的矩形。为此,您可以使用 java.awt.geom 中的 Rectangle2D.Double
class。初始矩形的左上角为 -2+2i,宽度和高度为 4:
Rectangle2D.Double viewRect = new Rectangle2D.Double(-2, 2, 4, 4);
您需要将绘图代码移到构造函数之外,以便它可以 运行 不止一次,并调整它以考虑当前的 viewRect
:
float xmin = viewRect.x;
float ymin = viewRect.y;
float xscale = viewRect.width/w;
float yscale = viewRect.height/h;
当您添加获取鼠标拖动通知的方法时,您将需要计算新的 viewRect。左上角对应于拖动开始处的复数。由于Java中没有复数class,我们暂时用Point2D.Double
:
Point2D.Double dragStartComplex = new Point2D.Double(
viewRect.x + viewRect.width * dragStart.x/w,
viewRect.y - viewRect.height * dragStart.y/h);
同样你可以算出拖动结束于哪个复数:
Point2D.Double dragEndComplex = new Point2D.Double(
viewRect.x + viewRect.width * dragEnd.x/w,
viewRect.y - viewRect.height * dragEnd.y/h);
有了角之后,就可以计算新的视图矩形了。之后你会重新粉刷。
viewRect.setRect(dragStartPoint.x, dragStartPoint.y,
dragEndPoint.x-dragStartPoint.x, dragEndPoint.y-dragStartPoint.y);
这有点过于简单化了,因为没有任何东西可以保证用户总是从左到右和从上到下拖动。要支持其他拖动方向,您必须调整坐标,以便 (viewRect.x,viewRect.y) 始终位于左上角。
我希望每个人都过得很好:) 我有一个显示图像的 Java 程序,我需要修改它以允许在图像中查看复平面的一般矩形区域。用户可以通过鼠标拖动select矩形。 任何人都可以帮我做吗? 这是代码:
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
public class Mandelbrot extends JApplet {
public static void main(String s[]) {
JFrame frame = new JFrame();
frame.setTitle("Mandelbrot set");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JApplet applet = new Mandelbrot();
applet.init();
frame.getContentPane().add(applet);
frame.pack();
frame.setVisible(true);
}
public void init() {
JPanel panel = new MandelbrotPanel();
getContentPane().add(panel);
}
}
class MandelbrotPanel extends JPanel{
BufferedImage bi;
public MandelbrotPanel() {
int w = 500;
int h = 500;
setPreferredSize(new Dimension(w, h));
setBackground(Color.white);
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
WritableRaster raster = bi.getRaster();
int[] rgb = new int[3];
float xmin = -2;
float ymin = -2;
float xscale = 4f/w;
float yscale = 4f/h;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
float cr = xmin + j * xscale;
float ci = ymin + i * yscale;
int count = iterCount(cr, ci);
rgb[0] = (count & 0x07) << 5;
rgb[1] = ((count >> 3) & 0x07) << 5;
rgb[2] = ((count >> 6) & 0x07) << 5;
raster.setPixel(j, i, rgb);
}
}
}
private int iterCount(float cr, float ci) {
int max = 512;
float zr = 0;
float zi = 0;
float lengthsq = 0;
int count = 0;
while ((lengthsq < 4.0) && (count < max)) {
float temp = zr * zr - zi * zi + cr;
zi = 2 * zr * zi + ci;
zr = temp;
lengthsq = zr * zr + zi * zi;
count++;
}
return max-count;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bi, 0, 0, this);
}
}
提前谢谢你:)
您需要跟踪显示给用户的复平面的矩形。为此,您可以使用 java.awt.geom 中的 Rectangle2D.Double
class。初始矩形的左上角为 -2+2i,宽度和高度为 4:
Rectangle2D.Double viewRect = new Rectangle2D.Double(-2, 2, 4, 4);
您需要将绘图代码移到构造函数之外,以便它可以 运行 不止一次,并调整它以考虑当前的 viewRect
:
float xmin = viewRect.x;
float ymin = viewRect.y;
float xscale = viewRect.width/w;
float yscale = viewRect.height/h;
当您添加获取鼠标拖动通知的方法时,您将需要计算新的 viewRect。左上角对应于拖动开始处的复数。由于Java中没有复数class,我们暂时用Point2D.Double
:
Point2D.Double dragStartComplex = new Point2D.Double(
viewRect.x + viewRect.width * dragStart.x/w,
viewRect.y - viewRect.height * dragStart.y/h);
同样你可以算出拖动结束于哪个复数:
Point2D.Double dragEndComplex = new Point2D.Double(
viewRect.x + viewRect.width * dragEnd.x/w,
viewRect.y - viewRect.height * dragEnd.y/h);
有了角之后,就可以计算新的视图矩形了。之后你会重新粉刷。
viewRect.setRect(dragStartPoint.x, dragStartPoint.y,
dragEndPoint.x-dragStartPoint.x, dragEndPoint.y-dragStartPoint.y);
这有点过于简单化了,因为没有任何东西可以保证用户总是从左到右和从上到下拖动。要支持其他拖动方向,您必须调整坐标,以便 (viewRect.x,viewRect.y) 始终位于左上角。