#include "StdAfx.h"
#include "Projection.h"
#include "BitVector.h"
#include <algorithm>

#define standardmapping 1

Projection::Projection()
{
	int x, y, z, d, counter = 0, no;

#ifdef standardmapping

	for(x = 0; x < xD; x++)
		for(y = 0; y < yD; y++)
			for(z = 0; z < zD; z++)
			{
				no = xD * yD * z + xD * y + x;
				mapping[x][y][z] = no;
				rxmapping[no] = x;
				rymapping[no] = y;
				rzmapping[no] = z;
			}

#else

	for(d = 0; d <= xD + yD + zD - 3; d++)
	{
		for(x = ::max(0, d - yD - zD + 2); x <= ::min(xD - 1, d); x++)
			for(y = ::max(0, d - x - zD + 1); y <= ::min(yD - 1, d - x); y++)
				for(z = ::max(0, d - x - y); z <= ::min(zD - 1, d - x - y); z++)
				{
					rxmapping[counter] = x;
					rymapping[counter] = y;
					rzmapping[counter] = z;
					mapping[x][y][z] = counter++;
				}
					
	}

#endif
	
}

Projection::~Projection(void)
{
}

int Projection::getIndex(int x, int y, int z)
{
#ifdef standardmapping
	return z * yD * xD + y * xD + x;
#else
	return mapping[x][y][z];
#endif
}

void Projection::getCoordinates(int index, int& x, int& y, int& z)
{
#ifdef standardmapping
	z = index / (yD * xD);
	y = (index % (yD * xD)) / xD;
	x = (index % xD);
#else
	x = rxmapping[index];
	y = rymapping[index];
	z = rzmapping[index];
#endif
}

__int64 Projection::projectAligned(bool space[maxExpansion][maxExpansion][maxExpansion])
{
	int x, y, z, minx = maxExpansion, miny = maxExpansion, minz = maxExpansion, maxx = 0, maxy = 0, maxz = 0;
	BitVector result = 0;

	for(x = 0; x < maxExpansion; x++)
		for(y = 0; y < maxExpansion; y++)
			for(z = 0; z < maxExpansion; z++)
				if(space[x][y][z])
				{
					minx = ::min(minx, x);
					miny = ::min(miny, y);
					minz = ::min(minz, z);
					maxx = ::max(maxx, x);
					maxy = ::max(maxy, y);
					maxz = ::max(maxz, z);
				}
	if((maxx - minx >= xD) || (maxy - miny >= yD) || (maxz - minz >= zD)) return 0;
	for(x = 0; x < maxExpansion; x++)
		for(y = 0; y < maxExpansion; y++)
			for(z = 0; z < maxExpansion; z++)
				if(space[x][y][z])
				{
					result.setBit(getIndex(x - minx, y - miny, z - minz));
				}
	return result;
}
