Family Day update
This commit is contained in:
parent
aac6731f2c
commit
9ad63ea473
2442 changed files with 39761 additions and 8255 deletions
232
Task/Mandelbrot-set/Java/mandelbrot-set-2.java
Normal file
232
Task/Mandelbrot-set/Java/mandelbrot-set-2.java
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
import static java.awt.Color.HSBtoRGB;
|
||||
import static java.awt.Color.black;
|
||||
import static java.awt.event.KeyEvent.VK_BACK_SLASH;
|
||||
import static java.awt.event.KeyEvent.VK_ESCAPE;
|
||||
import static java.awt.image.BufferedImage.TYPE_INT_RGB;
|
||||
import static java.lang.Math.abs;
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
import static java.lang.Math.signum;
|
||||
import static java.util.stream.Stream.of;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
/*
|
||||
* click: point to center
|
||||
* ctrl-click: point to origin
|
||||
* drag: point to mouse release point
|
||||
* ctrl-drag: point to origin + zoom
|
||||
* back-slash: back to previous point
|
||||
* esc: back to previous zoom point - zoom
|
||||
*/
|
||||
|
||||
public class Mandelbrot extends JFrame {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Insets insets;
|
||||
private int width, height;
|
||||
private double widthHeightRatio;
|
||||
private int minX, minY;
|
||||
private double Zoom;
|
||||
|
||||
private int mpX, mpY, mdX, mdY;
|
||||
private boolean isCtrlDown, ctrl;
|
||||
private Stack stack = new Stack();
|
||||
|
||||
private BufferedImage image;
|
||||
private boolean paint = true;
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Mandelbrot(800, 600); // (800, 600), (1024, 768), (1600, 900)
|
||||
}
|
||||
|
||||
public Mandelbrot(int width, int height) {
|
||||
super("Mandelbrot Set");
|
||||
setResizable(false);
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
Dimension screen = getToolkit().getScreenSize();
|
||||
setBounds(
|
||||
((int) screen.getWidth() - width) / 2,
|
||||
((int) screen.getHeight() - height) / 2,
|
||||
width,
|
||||
height
|
||||
);
|
||||
addMouseListener(mouseAdapter);
|
||||
addMouseMotionListener(mouseAdapter);
|
||||
addKeyListener(
|
||||
new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
isCtrlDown = e.isControlDown();
|
||||
}
|
||||
public void keyReleased(KeyEvent e) {
|
||||
isCtrlDown = e.isControlDown();
|
||||
}
|
||||
public void keyTyped(KeyEvent e) {
|
||||
char c = e.getKeyChar();
|
||||
boolean isEsc = c == VK_ESCAPE;
|
||||
if (!isEsc && c != VK_BACK_SLASH) return;
|
||||
if (stack.pop(isEsc)) {
|
||||
paint = true;
|
||||
printPoint();
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
);
|
||||
setVisible(true);
|
||||
insets = getInsets();
|
||||
this.width = width -= insets.left + insets.right;
|
||||
this.height = height -= insets.top + insets.bottom;
|
||||
widthHeightRatio = (double) width / height;
|
||||
minX = -width / 2 - 125;
|
||||
minY = -height / 2;
|
||||
Zoom = .005;
|
||||
paint = true;
|
||||
printPoint();
|
||||
}
|
||||
|
||||
private MouseAdapter mouseAdapter = new MouseAdapter() {
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
stack.push(false);
|
||||
if (!ctrl) {
|
||||
minX -= width / 2 ;
|
||||
minY -= height / 2;
|
||||
}
|
||||
minX += e.getX() - insets.left;
|
||||
minY += e.getY() - insets.top;
|
||||
ctrl = false;
|
||||
paint = true;
|
||||
printPoint();
|
||||
repaint();
|
||||
}
|
||||
public void mousePressed(MouseEvent e) {
|
||||
mpX = e.getX();
|
||||
mpY = e.getY();
|
||||
ctrl = isCtrlDown;
|
||||
}
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
if (!ctrl) return;
|
||||
setMdCoord(e);
|
||||
repaint();
|
||||
}
|
||||
private void setMdCoord(MouseEvent e) {
|
||||
int dx = e.getX() - mpX;
|
||||
int dy = e.getY() - mpY;
|
||||
mdX = (int) (mpX + max(abs(dx), abs(dy)*widthHeightRatio) * signum(dx));
|
||||
mdY = (int) (mpY + max(abs(dy), abs(dx)/widthHeightRatio) * signum(dy));
|
||||
acceptIf(insets.left, ge(mdX), setMdXY);
|
||||
acceptIf(insets.top, ge(mdY), setMdYX);
|
||||
acceptIf(insets.left+width-1, le(mdX), setMdXY);
|
||||
acceptIf(insets.top+height-1, le(mdY), setMdYX);
|
||||
}
|
||||
private void acceptIf(int value, Predicate<Integer> p, Consumer<Integer> c) { if (p.test(value)) c.accept(value); }
|
||||
private Predicate<Integer> ge(int md) { return v-> v >= md; }
|
||||
private Predicate<Integer> le(int md) { return v-> v <= md; }
|
||||
private Consumer<Integer> setMdXY = v-> mdY = (int) (mpY + abs((mdX=v)-mpX)/widthHeightRatio * signum(mdY-mpY));
|
||||
private Consumer<Integer> setMdYX = v-> mdX = (int) (mpX + abs((mdY=v)-mpY)*widthHeightRatio * signum(mdX-mpX));
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (e.getX() == mpX && e.getY() == mpY) return;
|
||||
stack.push(ctrl);
|
||||
if (!ctrl) {
|
||||
minX += mpX - (mdX = e.getX());
|
||||
minY += mpY - (mdY = e.getY());
|
||||
}
|
||||
else {
|
||||
setMdCoord(e);
|
||||
if (mdX < mpX) { int t=mpX; mpX=mdX; mdX=t; }
|
||||
if (mdY < mpY) { int t=mpY; mpY=mdY; mdY=t; }
|
||||
minX += mpX - insets.left;
|
||||
minY += mpY - insets.top;
|
||||
double rZoom = (double) width / abs(mdX - mpX);
|
||||
minX *= rZoom;
|
||||
minY *= rZoom;
|
||||
Zoom /= rZoom;
|
||||
}
|
||||
ctrl = false;
|
||||
paint = true;
|
||||
printPoint();
|
||||
repaint();
|
||||
}
|
||||
};
|
||||
|
||||
private void printPoint() {
|
||||
System.out.printf(
|
||||
"%.19e (%.19g%+.19gi) .. (%.19g%+.19gi) ", of(1, minX, minY, minX+width, minY+height).map(i->Zoom * i).toArray()
|
||||
);
|
||||
}
|
||||
|
||||
private class Stack extends java.util.Stack<Object[]> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public void push(boolean type) {
|
||||
push(new Object[] {type, minX, minY, Zoom});
|
||||
}
|
||||
public boolean pop(boolean type) {
|
||||
for (;;) {
|
||||
if (empty()) return false;
|
||||
Object[] d = super.pop();
|
||||
minX = (Integer) d[1];
|
||||
minY = (Integer) d[2];
|
||||
Zoom = (Double) d[3];
|
||||
if (!type || (Boolean) d[0]) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
if (paint) {
|
||||
image = newImage();
|
||||
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() {
|
||||
BufferedImage image = new BufferedImage(width, height, TYPE_INT_RGB);
|
||||
int maxX = minX + width;
|
||||
int maxY = minY + height;
|
||||
for (int x = minX; x < maxX; x+=1) {
|
||||
double r = Zoom * x;
|
||||
for (int y = minY; y < maxY; y+=1) {
|
||||
double i = Zoom * y;
|
||||
//System.out.printf("%+f%+fi\n", r, i);
|
||||
// 0f 1/6f 1/3f 1/2f 2/3f 5/6f
|
||||
//straight -> red yellow green cian blue magenta <- reverse
|
||||
image.setRGB(x-minX, y-minY, color(r, i, 360, false, 2/3f));
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
private int color(double r0, double i0, int max, boolean straight, float shift) {
|
||||
int n = -1;
|
||||
double r=0, i=0, r2=0, i2=0;
|
||||
do {
|
||||
i = r*(i+i) + i0;
|
||||
r = r2-i2 + r0;
|
||||
r2 = r*r;
|
||||
i2 = i*i;
|
||||
}
|
||||
while (++n < max && r2 + i2 < 4);
|
||||
return n == max
|
||||
? black.getRGB()
|
||||
: HSBtoRGB(shift + (float) (straight ? n : max-n) / max /* * 11/12f + (straight ? 0f : 1/12f) */, 1, 1)
|
||||
;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue