Skip to content
Snippets Groups Projects
Select Git revision
  • daf3602c64b2d7d6a57ac8292f517252ce1bab08
  • main default protected
  • variant
3 results

module-info.class.uniqueId0

Blame
  • Forked from COUETOUX Basile / FirefighterStarter
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    Mandelbrot.java 3.93 KiB
    package mandelbrot;
    
    import java.util.function.Function;
    
    /**
     * A class to compute how fast a parameterized polynomial sequence diverges.
     * This is used to compute the colors of point in the Mandelbrot fractal.
     */
    public class Mandelbrot {
    
        /**
         * If a complex has modulus above <code>RADIUS</code>, we know that
         * the sequence diverges. <code>RADIUS</code> should be at least 2 for
         * the usual Mandelbrot sequence.
         */
        private static final double RADIUS = 10;
    
        /**
         * The square of <code>RADIUS</code>, used in computations.
         */
        private static final double RADIUS2 = RADIUS * RADIUS;
    
    
        /**
         * How many iterations of the sequence do we compute before concluding
         * that it probably converges. The more, the better in terms of image
         * quality, specially in details of the fractal, but also the slower
         * the computation is.
         */
        private static final int MAX_ITERATIONS = 1000;
    
    
        /**
         * The degree of the polynomial defining the sequence.
         */
        private static final int DEGREE = 2;
    
        /**
         * Compute how divergent is the sequence generated by <code>z -&gt; z ** 2 + c</code>
         *
         * @param c A complex parameter, defining the polynomial to use.
         * @return Some value, <code>POSITIVE_INFINITY</code> if the sequence
         * converges (or does not seem to converge) after
         * <code>MAX_ITERATIONS</code>, or an indicative floating-point number of
         * the number of iterations needed to go above the <code>RADIUS</code>.
         */
        public double divergence(Complex c) {
            if (isConvergent(c)) return Double.POSITIVE_INFINITY;
            Function<Complex, Complex> f = z -> z.pow(DEGREE).add(c);
            Sequence seq = new Sequence(c, f);
            int countIterations = 0;
            for (Complex z : seq) {
                if (isDiverging(z))
                    return smoothIterationCount(countIterations, z);
                if (countIterations >= MAX_ITERATIONS)
                    return Double.POSITIVE_INFINITY;
                countIterations++;
            }
            return 0.;
        }
    
        /**
         * This method is used to smooth the number of iterations until
         * getting out of the <code>RADIUS</code>, so that we get a
         * floating-point value and thus smooth coloring.
         *
         * @param countIterations the iteration on which <code>RADIUS</code> is beaten.
         * @param z               the first complex of the sequence whose modulus is above <code>RADIUS</code>
         * @return a double close to <code>countIterations</code>.
         */
        private double smoothIterationCount(int countIterations, Complex z) {
            double x = Math.log(z.modulus()) / Math.log(RADIUS);
            return (double) countIterations - Math.log(x) / Math.log(DEGREE);
    
        }
    
    
        /**
         * Checks whether a term of the sequence is out of the given
         * <code>RADIUS</code>, which guarantees that the sequence diverges.
         *
         * @param z a term of the sequence
         * @return <code>true</code> if we are sure that the sequence diverges.
         */
        private boolean isDiverging(Complex z) {
            return z.squaredModulus() > RADIUS2;
        }
    
    
        /**
         * Checks whether the parameter of the sequence is in some region
         * that guarantees that the sequence is convergent. This does not
         * capture all convergent parameters.
         *
         * @param c the parameter for the polynomial
         * @return <code>true</code> if we are sure that the sequence converges.
         */
        private boolean isConvergent(Complex c) {
            return isIn2Bulb(c) || isInCardioid(c);
        }
    
        /* The cardioid black shape of the fractal */
        private boolean isInCardioid(Complex z) {
            double m = z.squaredModulus();
            return Helpers.doubleCompare(m * (8 * m - 3), 3. / 32. - z.getReal()) <= 0;
        }
    
        /* The main black disc of the fractal */
        private boolean isIn2Bulb(Complex z) {
            Complex zMinusOne = z.subtract(new Complex(-1, 0));
            return Helpers.doubleCompare(zMinusOne.squaredModulus(), 1. / 16.) < 0;
        }
    
    
    }