# Diamond-square algorithm not working (rewrite code from JS to JAVA)

I am trying rewrite code from JS to Java. The code is Diamond square algorithm.

I rewrite code, but my code not working...

My code in Java is:

public class MapGenerator {

public static void main(String[] args) {
MapGenerator mg = new MapGenerator(9);
mg.generate();
mg.printMap();
}

private int size, max;
double[] map;
int[][] matrix;

public MapGenerator(int detail) {
this.size = (int) Math.pow(2, detail) + 1;
this.max = this.size - 1;
this.map = new double[this.size * this.size];
}

private double get(int x, int y) {
if (x < 0 || x > this.max || y < 0 || y > this.max) {
return -1;
}
return this.map[x + this.size * y];
}

private void set(int x, int y, double val) {
this.map[x + this.size * y] = val;
}

public void generate() {
set(0, 0, max);
set(this.max, 0, max / 2);
set(this.max, this.max, 0);
set(0, this.max, max / 2);
divide(this.max);

buildMatrix();
saveTerrain(0, 0, 0, 0, matrix, "vystup.ter");
}

private void buildMatrix() {
matrix = new int[size][size];

for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
matrix[i][j] = (int) map[i + j];
}
}

}

private void divide(int size) {
//?
double roughness = 0.7;

int x, y, half = size / 2;
double scale = roughness * size;

if (half < 1) {
return;
}
for (y = half; y < max; y += size) {
for (x = half; x < max; x += size) {
square(x, y, half, Library.randInt(0, 100) * scale * 2 - scale);
}
}
for (y = 0; y <= max; y += half) {
for (x = (y + half) % size; x <= max; x += size) {
diamond(x, y, half, Library.randInt(0, 100) * scale * 2 - scale);
}
}
divide(size / 2);
}

private void square(int x, int y, int size, double offset) {

double tmp_1 = get(x, y - size);   // top
double tmp_2 = get(x + size, y);      // right
double tmp_3 = get(x, y + size);     // bottom
double tmp_4 = get(x - size, y);       // left

set(x, y, ((tmp_1 + tmp_2 + tmp_3 + tmp_4) / 4.0) + offset);
}

private void diamond(int x, int y, int size, double offset) {
double tmp_1 = get(x, y - size);      // top
double tmp_2 = get(x + size, y);      // right
double tmp_3 = get(x, y + size);      // bottom
double tmp_4 = get(x - size, y);      // left

set(x, y, ((tmp_1 + tmp_2 + tmp_3 + tmp_4) / 4.0) + offset);
}

public void printMap() {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println("");
}
}

public void saveTerrain(int canonX, int canonY, int targetX, int targetY,
int[][] terrain, String fName) {
int height = terrain.length;
int width = terrain[0].length;

DataOutputStream fout = null;
try {
// Samotný zápis dat
fout = new DataOutputStream(new FileOutputStream(fName));

fout.writeInt(width);
fout.writeInt(height);
fout.writeInt(canonX);
fout.writeInt(canonY);
fout.writeInt(targetX);
fout.writeInt(targetY);

for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
fout.writeInt(terrain[y][x]);
}
}
} /*
* Následuje pouze zav?ení souboru a ošetrení výjimek
*/ catch (FileNotFoundException e) {
System.err.println("Nepovedlo se otevrit vystupni soubor.");
} catch (IOException e) {
System.err.println("Nepovedlo se zapsat vystupni soubor.");
} finally {
try {
if (fout != null) {
fout.close();
}
} catch (IOException e) {
System.err.println("Nepovedlo se uzavrit vystupni soubor.");
}
}
}
}

Can anyone help me?

Output of algo is int[][] which i visualise using another program to image..

Visualise of output:

And this is how it should look

I am not getting error, but the output is wrong. Thanks for help.

I was coding this same thing yesterday (from the same source) and the recursive approach is really tricky due to square step overlaps of the subdivided areas and the irregularities in the same step. So I decided to do this from scratch the iterative way (which is much faster due to no heap/stack trashing in my programing environment) as you can see I am down from 130 lines to around 50 with comments.

This is how I do it (non recursively) in C++:

void diamond_square(int size)
{
picture pic;
int x,y,xx,yy,xs,ys,d,d2,r;
for (xs=1;xs<size;xs<<=1); xs>>=1; ys=xs;   // align  to power of 2
pic.resize(xs+1,ys+1); pic.pf=_pf_u;        // resize image to power of 2 +1
d=xs; d2=d>>1; r=128;                       // init step,half step and randomness
Randomize();
pic.p[ 0][ 0].dd=r;                         // set corners values (should be random but I want this)
pic.p[ 0][xs].dd=r;
pic.p[ys][ 0].dd=r;
pic.p[ys][xs].dd=r;
for (;d2;d=d2,d2>>=1)                       // subdivide step until full image is filled
{
// diamond
for (y=d2,yy=ys-d2;y<=yy;y+=d)
for (x=d2,xx=xs-d2;x<=xx;x+=d)
pic.p[y][x].dd=((pic.p[y-d2][x-d2].dd+pic.p[y-d2][x+d2].dd+pic.p[y+d2][x-d2].dd+pic.p[y+d2][x+d2].dd)>>2)+Random(r);
// square
for (y=d2,yy=ys-d2;y<=yy;y+=d)
for (x=d ,xx=xs-d ;x<=xx;x+=d)
pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y][x+d2].dd+pic.p[y-d2][x].dd+pic.p[y+d2][x].dd)>>2)+Random(r);
for (y=d ,yy=ys-d ;y<=yy;y+=d)
for (x=d2,xx=xs-d2;x<=xx;x+=d)
pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y][x+d2].dd+pic.p[y-d2][x].dd+pic.p[y+d2][x].dd)>>2)+Random(r);
for (x=d2,xx=xs-d2;x<=xx;x+=d)
{
y= 0; pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y][x+d2].dd+pic.p[y+d2][x].dd)/3)+Random(r);
y=ys; pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y][x+d2].dd+pic.p[y-d2][x].dd)/3)+Random(r);
}
for (y=d2,yy=ys-d2;y<=yy;y+=d)
{
x= 0; pic.p[y][x].dd=((pic.p[y][x+d2].dd+pic.p[y-d2][x].dd+pic.p[y+d2][x].dd)/3)+Random(r);
x=xs; pic.p[y][x].dd=((pic.p[y][x-d2].dd+pic.p[y-d2][x].dd+pic.p[y+d2][x].dd)/3)+Random(r);
}
r=(r*220)>>8; if (r<2) r=2;
}
// here pic holds the terrain map
}

I use my own picture class so here some members:

• resize(xs,ys) resize image to new resolution
• p[ys][xs].dd is pixel access in form of 32 unsigned ints DWORD
• pf is pixel format (you can ignore this)

This is the result for diamond_square(513);

You can play with the r randomnes initial and adjustment values to change behavior. Also you can change the initial corner values.

Beware the local int xs,ys variables in my program holds the power of 2 values not the power of 2 +1 !!!