#include "plotter.h"

double Plotter::getSteps(double min, double max, double iterations) {
	return ((max-min)/iterations);
}

double Plotter::convert(double min, double max, double current,
		double destmin, double destmax) {

	// converts a number in the range [min..max] to a number in the range
	// [destmin..destmax]
	return (destmin+((current-min)/(max-min)*(destmax-destmin)));
}

// abstraction abstraction abstraction.

void Plotter::setSourceBoundaries (double minX, double minY, double maxX, 
		double maxY) {
	MinSourceX = minX;
	MinSourceY = minY;
	
	MaxSourceX = maxX;
	MaxSourceY = maxY;
}

void Plotter::setTargetBoundaries (double minX, double minY, double maxX, 
		double maxY) {
	MinDestX = minX;
	MinDestY = minY;

	MaxDestX = maxX;
	MaxDestY = maxY;
}

void Plotter::setTargetArray(double * t_array) {
	target = t_array;
}

int Plotter::getPlotPosition(double x, double y) {
	if ( (x < MinSourceX) || (x > MaxSourceX)) return(-1);
	if ( (y < MinSourceY) || (y > MaxSourceY)) return(-1);
	
	int realX = (int)rint(convert(MinSourceX, MaxSourceX, x, MinDestX, 
				MaxDestX));
	int realY = (int)rint(convert(MinSourceY, MaxSourceY, y, MinDestY, 
				MaxDestY));

	int linearC = (realY*(int)rint(MaxDestX)) + realX;

	// must be done because of double rounding errors (e.g 0.494999999999)
	if (linearC > (int)rint(MaxDestX)*(int)rint(MaxDestY)) return(-1);

	return(linearC);
}

bool Plotter::plot(double x, double y, double value) {
	int linear = getPlotPosition(x, y);
	if (linear == -1) return(false);

	target[linear] = value;
	return(true);
}

double Plotter::getStepsX(double iterations) {
	return getSteps(MinSourceX, MaxSourceX, iterations);
}

double Plotter::getStepsY(double iterations) {
	return getSteps(MinSourceY, MaxSourceY, iterations);
}

double Plotter::getPixelArea() {
	// gets area of the rectangle corresponding to a single output value.
	double x_length_per_pixel = (MaxSourceX-MinSourceX)/MaxDestX;
	double y_length_per_pixel = (MaxSourceY-MinSourceY)/MaxDestY;
	return (x_length_per_pixel*y_length_per_pixel);
}


// Compute box-counting dimension
double Plotter::computeBDimension(double value) {
	// will only return a technically accurate value if the plot is square.
	// first calculate the length of a square with area equal to the "box" 
	// (rectangle  corresponding to a pixel), then count the number of 
	// pixels that is initialized to another value than "value". When done,
	// perform the calculation of the dimension.

	// assumes mindestx,y is 0.

	int total_pixels = (int)rint(MaxDestX*MaxDestY);
	double side_length = sqrt(getPixelArea());
	int covered_pixels = 0;

	for (int ycounter = 0; ycounter < (int)rint(MaxDestY); ycounter++) {
		for (int xcounter = 0; xcounter < (int)rint(MaxDestX); 
				xcounter++) {
			int linear = (ycounter*(int)rint(MaxDestX)) + xcounter;
			if(target[linear] != value) covered_pixels++;
		}
	}

	// calculate dimension
	return (log(covered_pixels)/log(1/side_length));
}
