/* * The MIT License (MIT) * * Copyright (c) 2015 Camil Staps * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package com.camilstaps.mandelbrot; import java.util.HashMap; import java.util.Map; /** * Class for calculating Mandelbrot numbers * By remembering seen numbers, we can significantly decrease calculation time * * @author Camil Staps */ public class MandelbrotFractal { /** * Storage for previously calculated numbers */ private static final Map mandelNumbers = new HashMap<>(); /** * Calculate the Mandelbrot number for a specific point up to some maximum * @param x the x coordinate of the point * @param y the y coordinate of the point * @param repetitions the maximum * @return the mandelbrot number */ public synchronized static int mandelNumber(double x, double y, int repetitions) { Point p = new Point(x, y); return mandelNumber(p, repetitions); } /** * Calculate the Mandelbrot number for a specific point up to some maximum * @param p the point * @param repetitions the maximum * @return the mandelbrot number */ public synchronized static int mandelNumber(Point p, int repetitions) { if (mandelNumbers.containsKey(p)) { Result result = mandelNumbers.get(p); if (repetitions < result.repetitions || result.mandelNumber < result.repetitions) { return result.mandelNumber; } else { calculateMandelNumber(p, repetitions, result); return result.mandelNumber; } } else { Result result = calculateMandelNumber(p, repetitions); mandelNumbers.put(p, result); return result.mandelNumber; } } /** * Calculate the Mandelbrot number for a specifc point up to some maximum * @param p the point * @param repetitions the maximum * @return the result */ protected synchronized static Result calculateMandelNumber(Point p, int repetitions) { Result start = new Result(); start.x = p.x; start.y = p.y; calculateMandelNumber(p, repetitions, start); return start; } /** * Calculate the Mandelbrot number for a specific point up to some maximum, * starting from an earlier result * @param p the point * @param repetitions the maximum * @param start the earlier result; will be updated with the new result */ protected synchronized static void calculateMandelNumber(Point p, int repetitions, Result start) { int n = start.repetitions; while (start.x * start.x + start.y * start.y <= 4 && n < repetitions) { double new_x = start.x * start.x - start.y * start.y + p.x; start.y = 2 * start.x * start.y + p.y; start.x = new_x; n++; } start.mandelNumber = n; } /** * A point on a coordinate system */ public static class Point { double x, y; public Point(double x, double y) { this.x = x; this.y = y; } @Override public boolean equals(Object another) { if (another == null || another.getClass() != Point.class) { return false; } Point that = (Point) another; return that.x == x && that.y == y; } @Override public int hashCode() { int hash = 7; hash = 97 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); hash = 97 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); return hash; } @Override public String toString() { return String.format("(%f,%f)", x, y); } } /** * A Mandelbrot result consists of a point, the mandelbrot number and the * maximum with which we calculated that result. */ protected static class Result { int mandelNumber = -1, repetitions = 0; double x, y; } }