import java.awt.*;
import java.util.*;
import java.lang.Math;

public class Matrix3D
{
	static double MatrixTemp[][] = new double[4][4];
	public static void Translate(double Matrix[][], double a, double b, double c)
		//this method will translate a single point stored in a 3X3 matrix
		//translates point (x, y, z) to (x+a, y+b, z+c)
	{
		IdentityMatrix(MatrixTemp);
		MatrixTemp[0][3] = a;
		MatrixTemp[1][3] = b;
		MatrixTemp[2][3] = c;
		MultiplyMatrix(Matrix, MatrixTemp);
	}
	
	public static void Scale(double Matrix[][], double a, double b, double c)
		//this method will scale a single point stored in a 3X3 matrix
		//scales point (x, y, z) to (a*x, b*y, z*c)
	{
		IdentityMatrix(MatrixTemp);
		MatrixTemp[0][0] = a;
		MatrixTemp[1][1] = b;
		MatrixTemp[2][2] = c;
		MultiplyMatrix(Matrix, MatrixTemp);
	}
	
	public static void RotateX(double Matrix[][], double theta)
		//this method will rotate a single point about the X axis
		//it will rotate it by theta, which is in radians
		//must put in a radians converter
	{
		IdentityMatrix(MatrixTemp);
		MatrixTemp[1][1] = Math.cos(theta);
		MatrixTemp[1][2] = -(Math.sin(theta));
		MatrixTemp[2][1] = Math.sin(theta);
		MatrixTemp[2][2] = Math.cos(theta);
		MultiplyMatrix(Matrix, MatrixTemp);
	}
		
	public static void RotateY(double Matrix[][], double theta)
		//this method will rotate a single point about the Y axis
		//it will rotate it by theta, which is in radians
		//must put in a radians converter
	{
		IdentityMatrix(MatrixTemp);
		MatrixTemp[0][0] = Math.cos(theta);
		MatrixTemp[0][2] = Math.sin(theta);
		MatrixTemp[2][0] = -(Math.sin(theta));
		MatrixTemp[2][2] = Math.cos(theta);
		MultiplyMatrix(Matrix, MatrixTemp);
	}

	public static void RotateZ(double Matrix[][], double theta)
		//this method will rotate a single point about the Z Axis
		//it will rotate it by theta, which is in radians
		//must put in a radians converter
	{
		IdentityMatrix(MatrixTemp);
		MatrixTemp[0][0] = Math.cos(theta);
		MatrixTemp[0][1] = -(Math.sin(theta));
		MatrixTemp[1][0] = Math.sin(theta);
		MatrixTemp[1][1] = Math.cos(theta);
		MultiplyMatrix(Matrix, MatrixTemp);
	}

	public static void MultiplyMatrix(double MatrixA[][], double MatrixB[][])
		//this method will multiply two matrices together by doing
		//three dot products
	{
		double dTempMatrix[][] = new double[4][4];
		Copy(MatrixA, dTempMatrix);
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < 4; j++)
			{
				MatrixA[i][j] = dTempMatrix[i][0] * MatrixB[0][j] + 
								dTempMatrix[i][1] * MatrixB[1][j] +
								dTempMatrix[i][2] * MatrixB[2][j] +
								dTempMatrix[i][3] * MatrixB[3][j];
			}
		}
		
	}
	
	public static void Transform(double TransformationMatrix[][], double Coordinate[])
	//this method will take the matrix and coordinate vector passed in and multiply
	//the new transformed coordinate will be saved in the array Coordinate[]
	{
		double tempCoord[] = new double[4];
		for (int i=0; i<4; i++)
			tempCoord[i] = Coordinate[i];
			
		for (int j=0; j<4; j++)
		{			
			Coordinate[j] = (TransformationMatrix[j][0] * tempCoord[0] + 
							 TransformationMatrix[j][1] * tempCoord[1] + 
							 TransformationMatrix[j][2] * tempCoord[2] +
							 TransformationMatrix[j][3] * tempCoord[3] );
		}
	}
	
	public static void Copy(double Matrix[][], double dTempMatrix[][])
	//copies the values from one matrix to another temporary one
	//this method is assuming the matrices passed in are both
	//3x3 matrices, which is all we're dealing with in this assignment
	//For anything else, a more general method would have to be made
	{
		for (int i=0; i < 4; i++)
			for (int j=0; j < 4; j++)
				dTempMatrix[i][j] = Matrix[i][j];		
	}
	
	public static void IdentityMatrix(double Matrix[][])
	//makes any matrix passed into the identity matrix
	//this assumes the matrix is a square matrix
	{
		int len = Matrix.length;
		for (int i=0; i<len; i++)
			for (int j=0; j<len; j++)
			{
				if (i == j)
					Matrix[i][j] = 1;
				else
					Matrix[i][j] = 0;
			}
	}		
}