001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.pub.noise.perlin;
011
012import imagingbook.pub.noise.hashing.Hash32Shift;
013import imagingbook.pub.noise.hashing.HashFun;
014
015/**
016 * Gradient (Perlin) noise implementation.
017 * This is the super-class for all other Perlin noise
018 * generators (1D, 2D, N-dimensional).
019 */
020
021public abstract class PerlinNoiseGen {
022
023        final double f_min;
024        final double f_max;
025        final double persistence; // persistence (phi)
026        double[] F;             // frequencies f_i
027        double[] A;             // amplitudes a_i
028
029        HashFun hashFun;
030        public boolean VERBOSE = false; // for debugging only
031
032        PerlinNoiseGen(double f_min, double f_max, double persistence, HashFun hash) {
033                this.f_min = f_min;
034                this.f_max = f_max;
035                this.persistence = persistence;
036                this.hashFun = (hash != null) ? hash : new Hash32Shift();       // default
037                this.makeFrequencies(f_min, f_max, persistence);
038        }
039
040        /**
041         * Perlin's improved "fading" function s(x)
042         * @param x interpolation position in [0,1]
043         * @return s(x) = 10 x^3 - 15 x^4 + 6 x^5 
044         */
045        double s(double x) {
046                return x * x * x * (x * (x * 6 - 15) + 10); // s(x) = 10 x^3 - 15 x^4 + 6 x^5
047        }
048
049        void makeFrequencies(double fmin, double fmax, double persistence) {
050                int oct = getFrequencySteps(f_min, f_max);
051                if (oct < 1) {
052                        throw new IllegalArgumentException("f_max is smaller than f_min");
053                }
054                F = new double[oct];
055                A = new double[oct];
056                int n = 0;
057                double f = f_min;
058                double a = 1;
059                while (f <= f_max && n < oct) {
060                        F[n] = f;
061                        A[n] = a;
062                        n = n + 1;
063                        f = 2 * f;
064                        a = persistence * a;
065                }
066        }
067
068        // ----------------- UTILITY METHODS ----------------------------
069
070        /**
071         * The number of frequency steps, given fmin and fmax.
072         * 
073         * @param fmin min. frequency
074         * @param fmax max. frequency
075         * @return number of frequency steps
076         */
077        public int getFrequencySteps(double fmin, double fmax) {        // TODO: should not be public!
078                int i = 0;
079                double f = fmin;
080                while (f <= fmax) {
081                        i = i + 1;
082                        f = 2 * f;
083                }
084                return i;
085        }
086
087        /**
088         * @return An array with the frequencies f_i used for generating 
089         * the noise function.
090         */
091        public double[] getFrequencies() {
092                return F;
093        }
094
095        /**
096         * @return An array with the amplitudes a_i used for generating 
097         * the noise function.
098         */
099        public double[] getAmplitudes() {
100                return A;
101        }
102
103        /**
104         * Fast floor method (by Gustavson?)
105         * @param x argument
106         * @return floor(x), works for pos. and neg. x.
107         */
108        int ffloor(double x) {
109                int xint = (int) x;
110                return (xint < x) ? xint : xint - 1;
111        }
112        
113//      public static void main(String[] args) {        // TODO: delete
114//              double f_min = 0.01;
115//              double f_max = 0.015;
116//              int octaves = getFrequencySteps(f_min, f_max);
117//              System.out.format("fmin=%f fmax=%f octaves= %d", f_min, f_max, octaves);
118//      }
119
120}