```/*
* MogensenSolidNoiseGenerator.java  1.0  98/06/03  Carl Burke
*
* Encapsulates Mogensen's method for solid noise generation.
*
* Copyright (c) 1998 Carl Burke.
*
* Derived from code in planet.c Copyright 1998 Torben AE. Mogensen
*/

public class MogensenSolidNoiseGenerator implements SolidNoiseGenerator
{
private double log2(double x)
{
return(Math.log(x)/Math.log(2.0));
}

///** SUBDIVISION CONSTANTS ***

public static final double Dda0 = .13; // initial altitude variation (suggest 0.15)
public static final double Ddda = .9;  // rate of decrease of altitude variation (suggest .9)

public static final double M  = -.015;  // initial altitude (slightly below sea level) (suggest -.015)

///** SUBDIVISION VARIABLES ***

int Depth; // depth of subdivisions

///*** VALUES CONTROLLING WORLD CHARACTERISTICS ***

public static final double Da0 = 2.0; 	 // initial scale (size of box)

double t1,t2,t3;

public MogensenSolidNoiseGenerator()
{
latic = false;
land = 0;
water = 0;
t1 = Math.exp(Math.log(2.)/3.);	   // dimension of box = (scale,t1*scale,t2*scale)
t2 = Math.exp(2.*Math.log(2.)/3.); // so halving will keep the same relative scale
t3 = t2/2.;		   // like A4 paper (but in 3 dimensions)
}

///** RANDOM NUMBER INITIALIZATION AND GENERATION ***

private double rseed;
private double r1;
private double r2;
private double r3;
private double r4;
private double r5;
private double r6;
private double r7;
private double r8;

// random number generator taking two seeds
// rand2(p,q) = rand2(q,p) is important
private double rand2(double p, double q)
{
double r = (p+3.14159265)*(q+3.14159265);
return(2.*(r-(int)r)-1.);
}
public void setSeed(double s)
{
r1 = rseed = s;

r1 = rand2(r1,r1);
r2 = rand2(r1,r1);
r3 = rand2(r1,r2);
r4 = rand2(r2,r3);
r5 = rand2(r4,r3);
r6 = rand2(r4,r5);
r7 = rand2(r6,r5);
r8 = rand2(r6,r7);
}
public double getSeed() {return rseed;}

///** FRACTAL PLANET CALCULATION ROUTINES ***

private double ta,tb,tc,td,te,tf,tg,th;
private double tas,tbs,tcs,tds,tes,tfs,tgs,ths;
private double tax,tay,taz, tscale, tdalt;

private double planet(
// altitudes of the eight corners
double a, double b, double c, double d,
double e, double f, double g, double h,
// seeds for the eight corners
double as, double bs, double cs, double ds,
double es, double fs, double gs, double hs,
// bottom left closest corner
double ax, double ay, double az,
// goal point, scale, and variance
double x, double y, double z,
int level, double scale, double dalt)
{
double ae,bf,cg,dh,aes,bfs,cgs,dhs,tmp;

while (level>0)
{
if (level == 12)
{ // save information for shortcut
ta=a; tb=b; tc=c; td=d; te=e; tf=f; tg=g; th=h;
tas=as; tbs=bs; tcs=cs; tds=ds; tes=es; tfs=fs; tgs=gs; ths=hs;
tax=ax; tay=ay; taz=az; tscale=scale; tdalt=dalt;
}

// subdivide over longest axis
aes = rand2(as,es); bfs = rand2(bs,fs); // find seeds for new points
cgs = rand2(cs,gs); dhs = rand2(ds,hs);
ae = (a+e+dalt*aes)/2.; bf = (b+f+dalt*bfs)/2.; // find altitudes
cg = (c+g+dalt*cgs)/2.; dh = (d+h+dalt*dhs)/2.; // as mean+variation
// find which halfbox goal point is in and continue in that
if (az+scale*t3 >= z)
{
h=c; g=cg; f=dh; e=d; d=b; c=bf; b=ae;
hs=cs; gs=cgs; fs=dhs; es=ds; ds=bs; cs=bfs; bs=aes;
tmp = ax; ax=az; az=ay; ay=tmp;
}
else
{
a=ae; b=e; c=f; d=bf; e=dh; f=h; h=cg;
as=aes; bs=es; cs=fs; ds=bfs; es=dhs; fs=hs; hs=cgs;
tmp = ax; ax=az+scale*t3; az=ay; ay=tmp;
}
tmp = x; x=z; z=y; y=tmp;
scale=scale*t3; dalt=dalt*Ddda;

// subdivide over longest axis
aes = rand2(as,es); bfs = rand2(bs,fs); // find seeds for new points
cgs = rand2(cs,gs); dhs = rand2(ds,hs);
ae = (a+e+dalt*aes)/2.; bf = (b+f+dalt*bfs)/2.; // find altitudes
cg = (c+g+dalt*cgs)/2.; dh = (d+h+dalt*dhs)/2.; // as mean+variation
// find which halfbox goal point is in and continue in that
if (az+scale*t3 >= z)
{
h=c; g=cg; f=dh; e=d; d=b; c=bf; b=ae;
hs=cs; gs=cgs; fs=dhs; es=ds; ds=bs; cs=bfs; bs=aes;
tmp = ax; ax=az; az=ay; ay=tmp;
}
else
{
a=ae; b=e; c=f; d=bf; e=dh; f=h; h=cg;
as=aes; bs=es; cs=fs; ds=bfs; es=dhs; fs=hs; hs=cgs;
tmp = ax; ax=az+scale*t3; az=ay; ay=tmp;
}
tmp = x; x=z; z=y; y=tmp;
scale=scale*t3; dalt=dalt*Ddda;

// subdivide over longest axis
aes = rand2(as,es); bfs = rand2(bs,fs); // find seeds for new points
cgs = rand2(cs,gs); dhs = rand2(ds,hs);
ae = (a+e+dalt*aes)/2.; bf = (b+f+dalt*bfs)/2.; // find altitudes
cg = (c+g+dalt*cgs)/2.; dh = (d+h+dalt*dhs)/2.; // as mean+variation
// find which halfbox goal point is in and continue in that
if (az+scale*t3 >= z)
{
h=c; g=cg; f=dh; e=d; d=b; c=bf; b=ae;
hs=cs; gs=cgs; fs=dhs; es=ds; ds=bs; cs=bfs; bs=aes;
tmp = ax; ax=az; az=ay; ay=tmp;
}
else
{
a=ae; b=e; c=f; d=bf; e=dh; f=h; h=cg;
as=aes; bs=es; cs=fs; ds=bfs; es=dhs; fs=hs; hs=cgs;
tmp = ax; ax=az+scale*t3; az=ay; ay=tmp;
}
tmp = x; x=z; z=y; y=tmp;
scale=scale*t3; dalt=dalt*Ddda;

level = level-3;
}
return((a+b+c+d+e+f+g+h)/8);
}

///** COLOR INDEX CONSTANTS ***

public static final int BLACK = 0;
public static final int BLUE0 = 1;
public static final int BLUE1 = 9;
public static final int LAND0 = 10;
public static final int LAND1 = 18;
public static final int WHITE = 19;

static int[] rtable =
{0,   0,	 0,  0,	 0,  0,	 0,  0,	 0,  0,	  0, 16, 32,
48, 64, 80, 96,112,128, 255};
static int[] gtable =
{0,   0, 16, 32, 48, 64, 80, 96,112,128, 255,240,224,208,192,
176,160,144,128, 255};
static int[] btable =
{0, 255,255,255,255,255,255,255,255,255,	  0,  4,  8,
12, 16, 20, 24, 28, 32, 255};

public boolean latic; // flag for latitude based colour

public double land;	// percentage of surface covered by land
public double water;// percentage of surface covered by water

///*** ROUTINES REQUIRED BY INTERFACE ***

public void setScaling(double M, double W, double H)
{
Depth = 3*((int)(log2(M*H)))+3;
}
public double value(double x, double y, double z)
{
if (tax= 0.98)
{	// white if close to poles
colour = WHITE;
}
else
{	// blue scale otherwise
colour = BLUE1+(int)((BLUE1-BLUE0+1)*(10*alt));
if (colour= 0.1)
{	// if high then white
colour = WHITE;
}
else
{	// else green to brown scale
colour = LAND0+(int)((LAND1-LAND0+1)*(10*alt));
}
}
return(255<<24 | rtable[colour]<<16 | gtable[colour]<<8 | btable[colour]);
}

public int background()
{
return 0xFF000000;
}
}
```