001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019/*
020*
021
022Licensed under the Apache License, Version 2.0 (the "License");
023you may not use this file except in compliance with the License.
024You may obtain a copy of the License at
025
026   http://www.apache.org/licenses/LICENSE-2.0
027
028Unless required by applicable law or agreed to in writing, software
029distributed under the License is distributed on an "AS IS" BASIS,
030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
031See the License for the specific language governing permissions and
032limitations under the License.
033*/
034
035package lucee.runtime.img.math;
036
037public class FBM implements Function2D {
038
039        protected float[] exponents;
040        protected float H;
041        protected float lacunarity;
042        protected float octaves;
043        protected Function2D basis;
044
045        public FBM(float H, float lacunarity, float octaves) {
046                this(H, lacunarity, octaves, new Noise());
047        }
048        
049        public FBM(float H, float lacunarity, float octaves, Function2D basis) {
050                this.H = H;
051                this.lacunarity = lacunarity;
052                this.octaves = octaves;
053                this.basis = basis;
054
055                exponents = new float[(int)octaves+1];
056                float frequency = 1.0f;
057                for (int i = 0; i <= (int)octaves; i++) {
058                        exponents[i] = (float)Math.pow(frequency, -H);
059                        frequency *= lacunarity;
060                }
061        }
062
063        public void setBasis(Function2D basis) {
064                this.basis = basis;
065        }
066
067        public Function2D getBasisType() {
068                return basis;
069        }
070
071        public float evaluate(float x, float y) {
072                float value = 0.0f;
073                float remainder;
074                int i;
075                
076                // to prevent "cascading" effects
077                x += 371;
078                y += 529;
079                
080                for (i = 0; i < (int)octaves; i++) {
081                        value += basis.evaluate(x, y) * exponents[i];
082                        x *= lacunarity;
083                        y *= lacunarity;
084                }
085
086                remainder = octaves - (int)octaves;
087                if (remainder != 0)
088                        value += remainder * basis.evaluate(x, y) * exponents[i];
089
090                return value;
091        }
092
093}