#include "noisegen.h"
#include <stdlib.h>
#include <algorithm>

NoiseGen::NoiseGen(int xsize, int ysize)
{
	m_noise = new float[xsize*ysize];
	m_xsize = xsize;
	m_ysize = ysize;
	newNoise();
}

void NoiseGen::newNoise()
{
	for(int i=0; i<m_xsize*m_ysize; ++i)
		m_noise[i] = rand()/float(RAND_MAX);
}

void NoiseGen::newNoise(int x, int y)
{
	if (x!=m_xsize || y!=m_ysize) {
		delete[] m_noise;
		m_noise = new float[x*y];
		m_xsize = x;
		m_ysize = y;
	}
	newNoise();
}

float NoiseGen::interpolate(float x, float y)
{
	using std::min;
	
	int ix = int(x), iy = int(y);
	float fx = x-ix, fy = y-iy;
	
	int ix2 = min(ix+1, m_xsize-1);
	int iy2 = min(iy+1, m_ysize-1);
	
	float f1 = getNoise(iy, ix);
	float f2 = getNoise(iy, ix2);
	float f3 = getNoise(iy2, ix);
	float f4 = getNoise(iy2, ix2);
	
	return f1*(1-fx)*(1-fy)
		+ f2*fx*(1-fy)
		+ f3*(1-fx)*fy
		+ f4*fx*fy;
}
float NoiseGen::interpolate(float x, float y, int maxX, int maxY)
{
	using std::min;
	
	int ix = int(x), iy = int(y);
	float fx = x-ix, fy = y-iy;

	int ix2 = ix+1, iy2 = iy+1;
	if (ix2 > maxX)
		ix2 = 0;
	if (iy2 > maxY)
		iy2 = 0;
	
	float f1 = getNoise(iy, ix);
	float f2 = getNoise(iy, ix2);
	float f3 = getNoise(iy2, ix);
	float f4 = getNoise(iy2, ix2);
	
	return f1*(1-fx)*(1-fy)
			+ f2*fx*(1-fy)
			+ f3*(1-fx)*fy
			+ f4*fx*fy;
}

float NoiseGen::turbulence(float x, float y, float a)
{
	float value=0;
	const float origA = a;
	while(a >= 1.0) {
		value += interpolate(y/a, x/a) * a;
		a *= 0.5f;
	}
	return value/origA;
}

float NoiseGen::tile(float x, float y, float a)
{
	int ia = int(a);
	int ix=int(x), iy=int(y);
	float value=0;
	const float origA = a;
	while(a >= 1.0) {
		value += interpolate(y/a, x/a, ix/ia, iy/ia) * a;
		a *= 0.5f;
		ia /= 2;
	}
	return value/origA;
}
