Mandelbrot set: Difference between revisions

Content added Content deleted
Line 4,263: Line 4,263:


public class Mandelbrot extends JFrame {
public class Mandelbrot extends JFrame {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
private Insets insets;
private Insets insets;
private int width, height;
private int width, height;
private double widthHeightRatio;
private double widthHeightRatio;
private int minX, minY;
private int minX, minY;
private double Zoom;
private double Zoom;
private int mpX, mpY, mdX, mdY;
private int mpX, mpY, mdX, mdY;
private boolean isCtrlDown, ctrl;
private boolean isCtrlDown, ctrl;
private Stack stack = new Stack();
private Stack stack = new Stack();
private BufferedImage image;
private BufferedImage image;
boolean paint = true;
public static void main(String[] args) {
public static void main(String[] args) {
new Mandelbrot(800, 600); // (800, 600), (1024, 768), (1600, 900)
new Mandelbrot(800, 600); // (800, 600), (1024, 768), (1600, 900)
}
}
public Mandelbrot(int width, int height) {
super("Mandelbrot Set");
public Mandelbrot(int width, int height) {
super("Mandelbrot Set");
setResizable(false);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Dimension screen = getToolkit().getScreenSize();
Dimension screen = getToolkit().getScreenSize();
setBounds(
setBounds(
((int) screen.getWidth() - width) / 2,
((int) screen.getHeight() - height) / 2,
((int) screen.getWidth() - width) / 2,
((int) screen.getHeight() - height) / 2,
width,
width,
height
height
);
);
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
addMouseListener(mouseAdapter);
addMouseMotionListener(mouseAdapter);
addKeyListener(
addKeyListener(
new KeyAdapter() {
new KeyAdapter() {
public void keyPressed(KeyEvent e) {
public void keyPressed(KeyEvent e) {
isCtrlDown = e.isControlDown();
isCtrlDown = e.isControlDown();
}
}
public void keyReleased(KeyEvent e) {
public void keyReleased(KeyEvent e) {
isCtrlDown = e.isControlDown();
isCtrlDown = e.isControlDown();
}
}
public void keyTyped(KeyEvent e) {
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
char c = e.getKeyChar();
boolean isEsc = c == KeyEvent.VK_ESCAPE;
if (!isEsc && c != KeyEvent.VK_BACK_SLASH) return;
boolean isEsc = c == KeyEvent.VK_ESCAPE;
if (!isEsc && c != KeyEvent.VK_BACK_SLASH) return;
stack.pop(isEsc);
stack.pop(isEsc);
repaint();
paint = true;
}
printPoint();
}
repaint();
);
}
setVisible(true);
}
insets = getInsets();
);
this.width = width -= insets.left + insets.right;
setVisible(true);
this.height = height -= insets.top + insets.bottom;
insets = getInsets();
widthHeightRatio = (double) width / height;
minX = -width / 2 - 125;
this.width = width -= insets.left + insets.right;
this.height = height -= insets.top + insets.bottom;
minY = -height / 2;
widthHeightRatio = (double) width / height;
Zoom = .005;
minX = -width / 2 - 125;
System.out.println(Zoom);
minY = -height / 2;
}
Zoom = .005;
paint = true;
private MouseAdapter mouseAdapter = new MouseAdapter() {
printPoint();
public void mouseClicked(MouseEvent e) {
}
stack.push(false);
if (!ctrl) {
private MouseAdapter mouseAdapter = new MouseAdapter() {
minX -= (double) width / 2 ;
public void mouseClicked(MouseEvent e) {
minY -= (double) height / 2;
stack.push(false);
}
if (!ctrl) {
minX += e.getX() - insets.left;
minX -= (double) width / 2 ;
minY += e.getY() - insets.top;
minY -= (double) height / 2;
ctrl = false;
}
repaint();
minX += e.getX() - insets.left;
}
minY += e.getY() - insets.top;
public void mousePressed(MouseEvent e) {
ctrl = false;
mpX = e.getX();
paint = true;
mpY = e.getY();
printPoint();
ctrl = isCtrlDown;
repaint();
}
}
public void mouseDragged(MouseEvent e) {
public void mousePressed(MouseEvent e) {
if (!ctrl) return;
mpX = e.getX();
setMdCoord(e);
mpY = e.getY();
repaint();
ctrl = isCtrlDown;
}
}
private void setMdCoord(MouseEvent e) {
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - mpX;
if (!ctrl) return;
int dy = e.getY() - mpY;
setMdCoord(e);
mdX = (int) (mpX + max(abs(dx), abs(dy)*widthHeightRatio) * signum(dx));
repaint();
mdY = (int) (mpY + max(abs(dy), abs(dx)/widthHeightRatio) * signum(dy));
}
acceptIf(insets.left, ge(mdX), setMdXY);
private void setMdCoord(MouseEvent e) {
acceptIf(insets.top, ge(mdY), setMdYX);
int dx = e.getX() - mpX;
acceptIf(insets.left+width-1, le(mdX), setMdXY);
int dy = e.getY() - mpY;
acceptIf(insets.top+height-1, le(mdY), setMdYX);
mdX = (int) (mpX + max(abs(dx), abs(dy)*widthHeightRatio) * signum(dx));
}
mdY = (int) (mpY + max(abs(dy), abs(dx)/widthHeightRatio) * signum(dy));
private void acceptIf(int value, Predicate<Integer> p, Consumer<Integer> c) { if (p.test(value)) c.accept(value); }
acceptIf(insets.left, ge(mdX), setMdXY);
private Predicate<Integer> ge(int md) { return v-> v >= md; }
acceptIf(insets.top, ge(mdY), setMdYX);
private Predicate<Integer> le(int md) { return v-> v <= md; }
acceptIf(insets.left+width-1, le(mdX), setMdXY);
private Consumer<Integer> setMdXY = v-> mdY = (int) (mpY + abs((mdX=v)-mpX)/widthHeightRatio * signum(mdY-mpY));
acceptIf(insets.top+height-1, le(mdY), setMdYX);
private Consumer<Integer> setMdYX = v-> mdX = (int) (mpX + abs((mdY=v)-mpY)*widthHeightRatio * signum(mdX-mpX));
}
public void mouseReleased(MouseEvent e) {
private void acceptIf(int value, Predicate<Integer> p, Consumer<Integer> c) { if (p.test(value)) c.accept(value); }
if (e.getX() == mpX && e.getY() == mpY) return;
private Predicate<Integer> ge(int md) { return v-> v >= md; }
stack.push(ctrl);
private Predicate<Integer> le(int md) { return v-> v <= md; }
if (!ctrl) {
private Consumer<Integer> setMdXY = v-> mdY = (int) (mpY + abs((mdX=v)-mpX)/widthHeightRatio * signum(mdY-mpY));
minX += mpX - (mdX = e.getX());
private Consumer<Integer> setMdYX = v-> mdX = (int) (mpX + abs((mdY=v)-mpY)*widthHeightRatio * signum(mdX-mpX));
minY += mpY - (mdY = e.getY());
public void mouseReleased(MouseEvent e) {
}
if (e.getX() == mpX && e.getY() == mpY) return;
else {
stack.push(ctrl);
setMdCoord(e);
if (!ctrl) {
if (mdX < mpX) {int t=mpX; mpX=mdX; mdX=t; }
minX += mpX - (mdX = e.getX());
if (mdY < mpY) {int t=mpY; mpY=mdY; mdY=t; }
minY += mpY - (mdY = e.getY());
minX += mpX - insets.left;
}
minY += mpY - insets.top;
else {
double rZoom = (double) width / abs(mdX - mpX);
setMdCoord(e);
minX *= rZoom;
if (mdX < mpX) {int t=mpX; mpX=mdX; mdX=t; }
minY *= rZoom;
if (mdY < mpY) {int t=mpY; mpY=mdY; mdY=t; }
Zoom /= rZoom;
minX += mpX - insets.left;
System.out.println(Zoom);
minY += mpY - insets.top;
}
double rZoom = (double) width / abs(mdX - mpX);
ctrl = false;
minX *= rZoom;
repaint();
minY *= rZoom;
}
Zoom /= rZoom;
};
}
ctrl = false;
private class Stack extends java.util.Stack<Object[]> {
paint = true;
private static final long serialVersionUID = 1L;
printPoint();
public void push(boolean type) {
repaint();
push(new Object[] {type, minX, minY, Zoom});
}
}
};
public synchronized void pop(boolean type) {
for (;;) {
private void printPoint() {
if (empty()) return;
System.out.printf("%g %g%+gi .. %g%+gi ", Zoom, Zoom*minX, Zoom*minY, Zoom*(minX+width), Zoom*(minY+height));
Object[] d = super.pop();
}
minX = (Integer) d[1];
minY = (Integer) d[2];
private class Stack extends java.util.Stack<Object[]> {
Zoom = (Double) d[3];
private static final long serialVersionUID = 1L;
if (!type || (Boolean) d[0]) return;
public void push(boolean type) {
}
push(new Object[] {type, minX, minY, Zoom});
}
}
}
public synchronized void pop(boolean type) {
for (;;) {
@Override
if (empty()) return;
public void paint(Graphics g) {
Object[] d = super.pop();
if (!ctrl) image = newImage();
minX = (Integer) d[1];
g.drawImage(image, insets.left, insets.top, this);
minY = (Integer) d[2];
//g.setColor(Color.lightGray);
Zoom = (Double) d[3];
//g.fillRect(7, height + insets.top - 22, 426, 15);
if (!type || (Boolean) d[0]) return;
//g.setColor(Color.black);
}
//g.drawString(String.format("%e %e %e %e %e",minX*Zoom,minY*Zoom,maxX*Zoom,maxY*Zoom,Zoom),10,height+insets.top-10);
}
//g.drawLine(insets.left+width/2, insets.top+0, insets.left+width/2, insets.top+height);
}
//g.drawLine(insets.left+0, insets.top+height/2, insets.left+width, insets.top+height/2);
if (!ctrl) return;
@Override
g.drawRect(min(mpX, mdX), min(mpY, mdY), abs(mpX - mdX), abs(mpY - mdY));
public void paint(Graphics g) {
}
if (paint) try {
newImage();
}
finally {
paint = false;
System.out.println("done!");
}
g.drawImage(image, insets.left, insets.top, this);
//g.drawLine(insets.left+width/2, insets.top+0, insets.left+width/2, insets.top+height);
//g.drawLine(insets.left+0, insets.top+height/2, insets.left+width, insets.top+height/2);
if (!ctrl) return;
g.drawRect(min(mpX, mdX), min(mpY, mdY), abs(mpX - mdX), abs(mpY - mdY));
}


private BufferedImage newImage() {
private BufferedImage newImage() {
int maxX = minX + width;
int maxX = minX + width;
int maxY = minY + height;
int maxY = minY + height;
BufferedImage image = new BufferedImage(width, height, TYPE_INT_RGB);
image = new BufferedImage(width, height, TYPE_INT_RGB);
for (int x = minX; x < maxX; x+=1) {
for (int x = minX; x < maxX; x+=1) {
double r = x * Zoom;
double r = x * Zoom;
for (int y = minY; y < maxY; y+=1) {
for (int y = minY; y < maxY; y+=1) {
double i = y * Zoom;
double i = y * Zoom;
//System.out.println(xz + " " + yz);
//System.out.printf("%+f%+fi\n", r, i);
// 0f 1/6f 1/3f 1/2f 2/3f 5/6f
// 0f 1/6f 1/3f 1/2f 2/3f 5/6f
//straight -> red yellow green cian blue magenta <- reverse
//straight -> red yellow green cian blue magenta <- reverse
image.setRGB(x-minX, y-minY, color(r, i, 360, false, 2/3f));
image.setRGB(x-minX, y-minY, color(r, i, 360, false, 2/3f));
}
}
}
}
return image;
return image;
}
}
private int color(double r0, double i0, int max, boolean straight, float shift) {
private int color(double r0, double i0, int max, boolean straight, float shift) {
int n = -1;
int n = -1;
double r=0, i=0, r2=0, i2=0;
double r=0, i=0, r2=0, i2=0;
do {
do {
i = r*(i+i) + i0;
i = r*(i+i) + i0;
r = r2-i2 + r0;
r = r2-i2 + r0;
r2 = r*r;
r2 = r*r;
i2 = i*i;
i2 = i*i;
}
}
while (++n < max && r2 + i2 < 4);
while (++n < max && r2 + i2 < 4);
return n == max ? 0 : HSBtoRGB(shift + (float) (straight ? n : max-n) / max /* * 11/12f + (straight?0:1)/12f*/, 1, 1);
return n == max ? 0 : HSBtoRGB(shift + (float) (straight ? n : max-n) / max /* * 11/12f + (straight?0:1)/12f*/, 1, 1);
}
}
}</lang>
}</lang>