00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00021 public class FractalFunction1D {
00022
00023
00024 final static int DOUBLE_TABLE_SIZE = 0x3fff+1;
00025 final static int INT_TABLE_SIZE = 0xff+1;
00026 private RanTable ranTable;
00027
00028
00029
00030 private int fractalDepth = 3;
00031 private int density = 1;
00032 private long index = 1;
00033 private UnitFunction1D unitFunction;
00034
00035
00036
00047 public FractalFunction1D (UnitFunction1D unitFunction, int fractalDepth, int density, long index) {
00048 this.unitFunction = unitFunction;
00049 this.fractalDepth = fractalDepth;
00050 this.density = density;
00051 this.index = index;
00052 ranTable = new RanTable(DOUBLE_TABLE_SIZE, INT_TABLE_SIZE, density, index);
00053 }
00054
00061 public FractalFunction1D (UnitFunction1D unitFunction, int density, long index) {
00062 this.unitFunction = unitFunction;
00063 this.density = density;
00064 this.index = index;
00065 }
00066
00072 public FractalFunction1D (UnitFunction1D unitFunction, long index) {
00073 this.unitFunction = unitFunction;
00074 this.index = index;
00075 }
00076
00082 public FractalFunction1D (UnitFunction1D unitFunction) {
00083 this.unitFunction = unitFunction;
00084 }
00085
00090 public FractalFunction1D () {
00091 this.unitFunction = new DoubleDip();
00092 }
00093
00094
00099 public void setIndex(long index) {
00100 this.index = index;
00101 ranTable.setSeed(index);
00102 }
00103
00104
00110 public double evaluate (double x) {
00111 x = x % 1;
00112
00113 if (x <= 0) x = x+1;
00114 if (fractalDepth<1) return 0;
00115 else return getDepthLocal (x, 1, index, 1);
00116 }
00117
00118
00119 private double getDepthLocal (double x, int recDepth, long seed, long span) {
00120 double depth = 0;
00121 double scale = 1.0/span;
00122 long square = (long) Math.ceil(x*span);
00123 long newSeed, square1;
00124 double x1;
00125
00126 for (int offset = -1; offset<2; offset++) {
00127 x1 = x;
00128 square1 = square + offset;
00129 if (square1 == 0) {
00130 square1 = span;
00131 x1 = x1 + 1;
00132 }
00133 else if (square1 > span) {
00134 square1 = 1;
00135 x1 = x1 - 1;
00136 }
00137 depth = depth + getDepthWRTSquare(x1, square1, recDepth, seed, span, scale);
00138 }
00139
00140 if (recDepth < fractalDepth) {
00141 newSeed = (span + seed) & (DOUBLE_TABLE_SIZE-1);
00142 long newSpan = span << 1;
00143 depth = depth + getDepthLocal(x,recDepth+1,newSeed,newSpan);
00144 }
00145 return depth;
00146 }
00147
00148
00149 private double getDepthWRTSquare (double x, long square, int recDepth, long seed, long span, double scale) {
00150 double depth = 0;
00151 long squareSeed = (square-1);
00152 long localSeed = (seed + squareSeed) & (DOUBLE_TABLE_SIZE-1);
00153 ranTable.setSeed(localSeed);
00154 int numUnits = ranTable.nextInteger();
00155 for (int i=1; i<=numUnits; i++) {
00156 double diameter = 1/(2 - ranTable.nextDouble()) * scale;
00157 double centre = (square - ranTable.nextDouble()) * scale;
00158 if ( (x-centre)*(x-centre) < diameter*diameter/4) {
00159 unitFunction.setCentre(centre);
00160 unitFunction.setScale(diameter);
00161 depth = depth+unitFunction.getValue(x);
00162 }
00163 }
00164 return depth;
00165 }
00166
00167 }