import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class MandelbrotVisualizer extends JPanel implements MouseWheelListener, MouseMotionListener, MouseListener { private static final int WIDTH = 800; private static final int HEIGHT = 800; private BufferedImage image; private double zoom = 200; private double offsetX = 0; private double offsetY = 0; private int lastX, lastY; private ExecutorService executor; public MandelbrotVisualizer() { image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); addMouseWheelListener(this); addMouseMotionListener(this); addMouseListener(this); executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); renderMandelbrot(); } /** * Renders the Mandelbrot set in the window. */ private void renderMandelbrot() { // Shutdown the existing executor and create a new one with the number of available processors. executor.shutdownNow(); executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); // Iterate through each pixel in the image. for (int x = 0; x < WIDTH; x++) { final int fx = x; // Submit a task to the executor for each row in the image. executor.submit(() -> { for (int y = 0; y < HEIGHT; y++) { double zx = (fx - WIDTH / 2) / zoom + offsetX; double zy = (y - HEIGHT / 2) / zoom + offsetY; // Calculate the complex number c. float c = mandelbrot(zx, zy); // Determine the color for the pixel based on the value of c. int color = Color.HSBtoRGB(0.7f + 10 * c, 0.7f, c > 0 ? 1 : 0); // Set the color of the pixel in the image. image.setRGB(fx, y, color); } // Repaint the window to display the updated image. repaint(); }); } // Shutdown the executor and wait for all tasks to complete. /** * Attempts to shut down the executor and wait for all tasks to complete. If an InterruptedException occurs, print the stack trace. */ try { executor.shutdown(); executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } /** * Calculates the number of iterations for a given point in the Mandelbrot set. * @param zx the real part of the complex number * @param zy the imaginary part of the complex number * @return the number of iterations, scaled between 0 and 1 */ private float mandelbrot(double zx, double zy) { double x = 0, y = 0; int maxIter = 1000; int iter; for (iter = 0; iter < maxIter && x * x + y * y < 4; iter++) { double temp = x * x - y * y + zx; y = 2 * x * y + zy; x = temp; } return iter < maxIter ? (float) iter / maxIter : 0; } /** * Paints the Mandelbrot set in the given Graphics object. * @param g the Graphics object to paint onto */ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); g.drawImage(image, 0, 0, null); } /** * Handles the mouse wheel event. Zooms in or out based on the scroll direction, and pans the view accordingly. Then repaints the window. * @param e the MouseWheelEvent that triggered this method call */ @Override public void mouseWheelMoved(MouseWheelEvent e) { int notches = e.getWheelRotation(); double mouseX = (e.getX() - WIDTH / 2.0) / zoom + offsetX; double mouseY = (e.getY() - HEIGHT / 2.0) / zoom + offsetY; if (notches < 0) { zoom *= 1.1; } else { zoom /= 1.1; } offsetX = mouseX - (e.getX() - WIDTH / 2.0) / zoom; offsetY = mouseY - (e.getY() - HEIGHT / 2.0) / zoom; renderMandelbrot(); } /** * Handles the mouse dragged event. Updates the offset values for zooming and panning, then repaints the window. */ @Override public void mouseDragged(MouseEvent e) { int dx = e.getX() - lastX; int dy = e.getY() - lastY; offsetX -= dx / zoom; offsetY -= dy / zoom; lastX = e.getX(); lastY = e.getY(); renderMandelbrot(); } @Override public void mousePressed(MouseEvent e) { lastX = e.getX(); lastY = e.getY(); } @Override public void mouseMoved(MouseEvent e) {} @Override public void mouseClicked(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) {} @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} /** * The main method that initializes and displays the Mandelbrot visualizer window. */ public static void main(String[] args) { // Create a JFrame to hold the MandelbrotVisualizer panel. JFrame frame = new JFrame("Mandelbrot Visualizer"); // Instantiate the MandelbrotVisualizer panel. MandelbrotVisualizer panel = new MandelbrotVisualizer(); // Add the panel to the frame. frame.add(panel); // Set the size of the frame. frame.setSize(WIDTH, HEIGHT); // Configure the frame's default close operation and center it on the screen. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationRelativeTo(null); // Make the frame visible. frame.setVisible(true); } }