```// Implementation of homogeneous vectors and matrices
import java.util.*;

// ALL get() functions return a value from a specified location
// ALL set() functions put a value into the specified location
// The different versions of the functions serve to convert different
// ways of saying the same thing into actually doing the same thing

// Geometric vectors of size N
public class VectorN {
private double v[];
VectorN(int n) { v = new double[n]; }
int size() { return v.length; }
double get(int j) { return v[j]; }
void set(int j, double f) { v[j] = f; }
void set(VectorN vec) { for (int j = 0 ; j < size() ; j++) set(j, vec.get(j)); }
//Converts the VectorN into a printable String
public String toString() {
String s = "{";
for (int j = 0 ; j < size() ; j++) s += (j == 0 ? "" : ",") + get(j);
return s + "}";
}
//changes the coordinate system for the matrix
void transform(MatrixN mat) {
VectorN tmp = new VectorN(size());
double f;
for (int i = 0 ; i < size() ; i++) {
f = 0.;
for (int j = 0 ; j < size() ; j++) f += mat.get(i,j) * get(j);
tmp.set(i, f);
}
set(tmp);
}
double distance(VectorN vec) {
double x, y, d = 0;
for (int i = 0 ; i < size() ; i++) {
x = vec.get(0) - get(0);
y = vec.get(1) - get(1);
d += x * x + y * y;
}
return Math.sqrt(d);
}
}

// N x N matrices
// Geometric matrices of size N x N
class MatrixN {
private VectorN v[];
MatrixN(int n) {
v = new VectorN[n];
for (int i = 0 ; i < n ; i++) v[i] = new VectorN(n);
}
int size() { return v.length; }
double get(int i, int j) { return get(i).get(j); }
void set(int i, int j, double f) { v[i].set(j,f); }
VectorN get(int i) { return v[i]; }
void set(int i, VectorN vec) { v[i].set(vec); }
void set(MatrixN mat) { for (int i = 0 ; i < size() ; i++) set(i, mat.get(i)); }
public String toString() {                   // print the values of the matrix
String s = "{";
for (int i = 0 ; i < size() ; i++) s += (i == 0 ? "" : ",") + get(i);
return s + "}";
}
void identity() {                // make this an N x N identity matrix
for (int j = 0 ; j < size() ; j++)
for (int i = 0 ; i < size() ; i++) set(i, j, (i == j ? 1 : 0));
}
void preMultiply(MatrixN mat) {     // mat * this
MatrixN tmp = new MatrixN(size());
double f;
for (int j = 0 ; j < size() ; j++)
for (int i = 0 ; i < size() ; i++) {
f = 0.;
for (int k = 0 ; k < size() ; k++) f += mat.get(i,k) * get(k,j);
tmp.set(i, j, f);
}
set(tmp);
}
void postMultiply(MatrixN mat) {    // this * mat
MatrixN tmp = new MatrixN(size());
double f;
for (int j = 0 ; j < size() ; j++)
for (int i = 0 ; i < size() ; i++) {
f = 0.;
for (int k = 0 ; k < size() ; k++) f += get(i,k) * mat.get(k,j);
tmp.set(i, j, f);
}
set(tmp);
}
}

// Homogeneous vectors in three dimensions
class Vector3D extends VectorN {
Vector3D() { super(4); }
void set(double x,double y,double z,double w){set(0,x);set(1,y);set(2,z);set(3,w);}
void set(double x, double y, double z) { set(x, y, z, 1); }
}

// Homogeneous matrices in three dimensions
class Matrix3D extends MatrixN {
Matrix3D() { super(4); identity(); }
//rotate the model in the given axes by the given angle
void rotateX(double theta) { rotate(0, theta); }
void rotateY(double theta) { rotate(1, theta); }
void rotateZ(double theta) { rotate(2, theta); }
void rotate(int axis, double theta) {
int i = (axis+1)%3;
int j = (axis+2)%3;
Matrix3D tmp = new Matrix3D();
double c = Math.cos(theta * Math.PI / 180);
double s = Math.sin(theta * Math.PI / 180);
tmp.set(i,i, c); tmp.set(i,j, s);
tmp.set(j,i,-s); tmp.set(j,j, c);
postMultiply(tmp);
}
//changes the coordinate system
void translate(double a, double b, double c) { // translate
Matrix3D tmp = new Matrix3D();
tmp.set(0,3, a);
tmp.set(1,3, b);
tmp.set(2,3, c);
postMultiply(tmp);
}
void scale(double s) { scale(s, s, s); }
void scale(double x, double y, double z) { // scale non-uniformly
Matrix3D tmp = new Matrix3D();
tmp.set(0,0,x);
tmp.set(1,1,y);
tmp.set(2,2,z);
postMultiply(tmp);
}
}

```