
AXIS_X = 0
AXIS_Y = 1
AXIS_Z = 2

function toPolar(x, y)
	return math.sqrt(x*x + y*y), math.atan2(y, x)
end

function toCartesian(r, theta)
	return r*math.cos(theta), r*math.sin(theta)
end

function fixAngleRad(a)
	local twopi = 2*math.pi
	while a >= twopi do
		a = a - twopi
	end
	while a < 0 do
		a = a + twopi
	end
	return a
end

function round(a)
	return math.floor(a + 0.499)
end

function prov(origProvider, axis, rotateDegrees)
	local getNewCoords
	local rotateRad = math.rad(rotateDegrees)
	if axis == AXIS_X then
		getNewCoords = function(x, y, z, mult)
			local r, theta = toPolar(y, z)
			y, z = toCartesian(r, fixAngleRad(theta - rotateRad * mult))
			return x, y, z
		end
	elseif axis == AXIS_Y then
		getNewCoords = function(x, y, z, mult)
			local r, theta = toPolar(x, z)
			x, z = toCartesian(r, fixAngleRad(theta - rotateRad * mult))
			return x, y, z
		end
	elseif axis == AXIS_Z then
		getNewCoords = function(x, y, z, mult)
			local r, theta = toPolar(x, y)
			x, y = toCartesian(r, fixAngleRad(theta - rotateRad * mult))
			return x, y, z
		end
	else
		print("Invalid axis specified to pcons rotate")
	end
	local origCorners = {
		{ origProvider.startX, origProvider.startY, origProvider.startZ },
		{ origProvider.startX, origProvider.startY, origProvider.startZ + origProvider.sizeZ - 1 },
		{ origProvider.startX, origProvider.startY + origProvider.sizeY - 1, origProvider.startZ },
		{ origProvider.startX + origProvider.sizeX - 1, origProvider.startY, origProvider.startZ },
		{ origProvider.startX, origProvider.startY + origProvider.sizeY - 1, origProvider.startZ + origProvider.sizeZ - 1 },
		{ origProvider.startX + origProvider.sizeX - 1, origProvider.startY, origProvider.startZ + origProvider.sizeZ - 1 },
		{ origProvider.startX + origProvider.sizeX - 1, origProvider.startY + origProvider.sizeY - 1, origProvider.startZ },
		{ origProvider.startX + origProvider.sizeX - 1, origProvider.startY + origProvider.sizeY - 1, origProvider.startZ + origProvider.sizeZ - 1 }
	}
	local minX, minY, minZ, maxX, maxY, maxZ = nil, nil, nil, nil, nil, nil
	for cornerIdx, corner in ipairs(origCorners) do
		local nx, ny, nz = getNewCoords(corner[1], corner[2], corner[3], -1)
		nx, ny, nz = round(nx), round(ny), round(nz)
		if minX == nil or nx < minX then minX = nx end
		if minY == nil or ny < minY then minY = ny end
		if minZ == nil or nz < minZ then minZ = nz end
		if maxX == nil or nx > maxX then maxX = nx end
		if maxY == nil or ny > maxY then maxY = ny end
		if maxZ == nil or nz > maxZ then maxZ = nz end
	end
	local getBlockAt = function(x, y, z)
		local fromX, fromY, fromZ = getNewCoords(x, y, z, 1)
		local nx, ny, nz = round(fromX), round(fromY), round(fromZ)
		if nx < origProvider.startX or nx >= origProvider.startX + origProvider.sizeX
			or ny < origProvider.startY or ny >= origProvider.startY + origProvider.sizeY
			or nz < origProvider.startZ or nz >= origProvider.startZ + origProvider.sizeZ
		then
			return nil
		end
		local fromMat = origProvider.getBlockAt(nx, ny, nz)
		return fromMat
	end
	return {
		["startX"] = minX,
		["startY"] = minY,
		["startZ"] = minZ,
		["sizeX"] = maxX - minX + 1,
		["sizeY"] = maxY - minY + 1,
		["sizeZ"] = maxZ - minZ + 1,
		["numMaterials"] = origProvider.numMaterials,
		["getBlockAt"] = getBlockAt
	}
end


