public class Point {
	public static Point ORIGIN = new Point(0, 0, 0, 1);

	private double x;
	private double y;
	private double z;
	private double h;

	private Point(double x, double y, double z, double h) {
		this.x = x;
		this.y = y;
		this.z = z;
		this.h = h;
	}

	public double getX() { return x; }
	public double getY() { return y; }
	public double getZ() { return z; }
	public double getHomogeneous() { return h; }

	public String toString() {
		return "(" + x + "," + y + "," + z + "," + h + ")";
	}

	public double getDistanceTo(Point other) {
		double oh = other.h;
		double dx = this.x / h - other.x / oh;
		double dy = this.y / h - other.y / oh;
		double dz = this.z / h - other.z / oh;
		return Math.sqrt(dx * dx + dy * dy + dz * dz);
	}

	public Vector subtract(Point other) {
		double oh = other.h;
		double dx = this.x / h - other.x / oh;
		double dy = this.y / h - other.y / oh;
		double dz = this.z / h - other.z / oh;
		return Vector.create(dx, dy, dz);
	}

	public Point addScaled(double scalar, Vector v) {
		scalar *= h;
		return Point.create(x + scalar * v.getX(), y + scalar * v.getY(), z + scalar * v.getZ(), h);
	}

	public Point add(Vector v) {
		return this.addScaled(1, v);
	}

	public static Point create(double x, double y, double z) {
		return new Point(x, y, z, 1);
	}
	public static Point create(double x, double y, double z, double h) {
		return new Point(x, y, z, h);
	}
}
