// Path: src/main/java/me/bauer/BauerCam/Path/PolarCoordinates.java
// public final class PolarCoordinates {
// 
// 	public final float pitch;
// 	public final float yaw;
// 
// 	public PolarCoordinates(final float pitch, final float yaw) {
// 		this.pitch = pitch;
// 		this.yaw = yaw;
// 	}
// 
// }
// 
// Path: src/main/java/me/bauer/BauerCam/Path/Position.java
// public final class Position extends Vector3D {
// 
// 	public final float pitch;
// 	public final float yaw;
// 	public final float roll;
// 	public final float fov;
// 
// 	public Position(final double x, final double y, final double z, final float pitch, final float yaw,
// 			final float roll, final float fov) {
// 		super(x, y, z);
// 		this.pitch = pitch;
// 		this.yaw = yaw;
// 		this.roll = roll;
// 		this.fov = fov;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return super.toString() + padding + this.pitch + padding + this.yaw + padding + this.roll + padding + this.fov;
// 	}
// 
// 	public static Position fromString(final String input) {
// 		final String error = Main.positionCannotBeParsed + input;
// 
// 		final String[] parts = input.split(padding);
// 		if (parts.length != 7) {
// 			Utils.sendInformation(error);
// 			return null;
// 		}
// 
// 		try {
// 			final double x = Double.parseDouble(parts[0]);
// 			final double y = Double.parseDouble(parts[1]);
// 			final double z = Double.parseDouble(parts[2]);
// 			final float pitch = Float.parseFloat(parts[3]);
// 			final float yaw = Float.parseFloat(parts[4]);
// 			final float roll = Float.parseFloat(parts[5]);
// 			final float fov = Float.parseFloat(parts[6]);
// 
// 			return new Position(x, y, z, pitch, yaw, roll, fov);
// 		} catch (final NumberFormatException e) {
// 			Utils.sendInformation(error);
// 			return null;
// 		}
// 	}
// 
// }
// 
// Path: src/main/java/me/bauer/BauerCam/Path/Vector3D.java
// public class Vector3D {
// 
// 	protected static final String padding = "/";
// 
// 	public final double x;
// 	public final double y;
// 	public final double z;
// 
// 	public Vector3D(final double x, final double y, final double z) {
// 		this.x = x;
// 		this.y = y;
// 		this.z = z;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return this.x + padding + this.y + padding + this.z;
// 	}
// 
// 	public final double lengthSquared() {
// 		return this.x * this.x + this.y * this.y + this.z * this.z;
// 	}
// 
// 	public final double length() {
// 		return Math.sqrt(lengthSquared());
// 	}
// 
// 	public double distance(final Vector3D target) {
// 		return target.subtract(this).length();
// 	}
// 
// 	public Vector3D normalize() {
// 		final double length = length();
// 		return new Vector3D(this.x / length, this.y / length, this.z / length);
// 	}
// 
// 	public Vector3D subtract(final Vector3D other) {
// 		return new Vector3D(this.x - other.x, this.y - other.y, this.z - other.z);
// 	}
// 
// 	/**
// 	 * Used for camera entity location corrections
// 	 */
// 	public Vector3D addY(final double additionalY) {
// 		return new Vector3D(this.x, this.y + additionalY, this.z);
// 	}
// 
// 	public PolarCoordinates lookAt(final Vector3D target) {
// 		final Vector3D cartesianCoordinates = target.subtract(this).normalize();
// 
// 		double pitch = Math.asin(cartesianCoordinates.y);
// 		double yaw = Math.atan2(cartesianCoordinates.z, cartesianCoordinates.x);
// 
// 		// Into degrees
// 		pitch = Math.toDegrees(pitch);
// 		yaw = Math.toDegrees(yaw);
// 
// 		// Minecraft specific corrections
// 		pitch = -pitch;
// 		yaw -= 90;
// 
// 		return new PolarCoordinates((float) pitch, (float) yaw);
// 	}
// 
// }


import me.bauer.BauerCam.Path.PolarCoordinates;
import me.bauer.BauerCam.Path.Position;
import me.bauer.BauerCam.Path.Vector3D;
package me.bauer.BauerCam.Interpolation;


public final class CubicInterpolator
		implements IPositionInterpolator, IPolarCoordinatesInterpolator, IAdditionalAngleInterpolator {

	public static final CubicInterpolator instance = new CubicInterpolator();

	private CubicInterpolator() {
	}

	@Override
	public void interpolatePosition(final PositionBuilder builder, final Position y0, final Position y1,
			final Position y2, final Position y3, final double step) {
		builder.setPosition(new Vector3D(InterpolationUtils.cubic_catmull(y0.x, y1.x, y2.x, y3.x, step),
// Path: src/main/java/me/bauer/BauerCam/Path/PolarCoordinates.java
// public final class PolarCoordinates {
// 
// 	public final float pitch;
// 	public final float yaw;
// 
// 	public PolarCoordinates(final float pitch, final float yaw) {
// 		this.pitch = pitch;
// 		this.yaw = yaw;
// 	}
// 
// }
// 
// Path: src/main/java/me/bauer/BauerCam/Path/Position.java
// public final class Position extends Vector3D {
// 
// 	public final float pitch;
// 	public final float yaw;
// 	public final float roll;
// 	public final float fov;
// 
// 	public Position(final double x, final double y, final double z, final float pitch, final float yaw,
// 			final float roll, final float fov) {
// 		super(x, y, z);
// 		this.pitch = pitch;
// 		this.yaw = yaw;
// 		this.roll = roll;
// 		this.fov = fov;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return super.toString() + padding + this.pitch + padding + this.yaw + padding + this.roll + padding + this.fov;
// 	}
// 
// 	public static Position fromString(final String input) {
// 		final String error = Main.positionCannotBeParsed + input;
// 
// 		final String[] parts = input.split(padding);
// 		if (parts.length != 7) {
// 			Utils.sendInformation(error);
// 			return null;
// 		}
// 
// 		try {
// 			final double x = Double.parseDouble(parts[0]);
// 			final double y = Double.parseDouble(parts[1]);
// 			final double z = Double.parseDouble(parts[2]);
// 			final float pitch = Float.parseFloat(parts[3]);
// 			final float yaw = Float.parseFloat(parts[4]);
// 			final float roll = Float.parseFloat(parts[5]);
// 			final float fov = Float.parseFloat(parts[6]);
// 
// 			return new Position(x, y, z, pitch, yaw, roll, fov);
// 		} catch (final NumberFormatException e) {
// 			Utils.sendInformation(error);
// 			return null;
// 		}
// 	}
// 
// }
// 
// Path: src/main/java/me/bauer/BauerCam/Path/Vector3D.java
// public class Vector3D {
// 
// 	protected static final String padding = "/";
// 
// 	public final double x;
// 	public final double y;
// 	public final double z;
// 
// 	public Vector3D(final double x, final double y, final double z) {
// 		this.x = x;
// 		this.y = y;
// 		this.z = z;
// 	}
// 
// 	@Override
// 	public String toString() {
// 		return this.x + padding + this.y + padding + this.z;
// 	}
// 
// 	public final double lengthSquared() {
// 		return this.x * this.x + this.y * this.y + this.z * this.z;
// 	}
// 
// 	public final double length() {
// 		return Math.sqrt(lengthSquared());
// 	}
// 
// 	public double distance(final Vector3D target) {
// 		return target.subtract(this).length();
// 	}
// 
// 	public Vector3D normalize() {
// 		final double length = length();
// 		return new Vector3D(this.x / length, this.y / length, this.z / length);
// 	}
// 
// 	public Vector3D subtract(final Vector3D other) {
// 		return new Vector3D(this.x - other.x, this.y - other.y, this.z - other.z);
// 	}
// 
// 	/**
// 	 * Used for camera entity location corrections
// 	 */
// 	public Vector3D addY(final double additionalY) {
// 		return new Vector3D(this.x, this.y + additionalY, this.z);
// 	}
// 
// 	public PolarCoordinates lookAt(final Vector3D target) {
// 		final Vector3D cartesianCoordinates = target.subtract(this).normalize();
// 
// 		double pitch = Math.asin(cartesianCoordinates.y);
// 		double yaw = Math.atan2(cartesianCoordinates.z, cartesianCoordinates.x);
// 
// 		// Into degrees
// 		pitch = Math.toDegrees(pitch);
// 		yaw = Math.toDegrees(yaw);
// 
// 		// Minecraft specific corrections
// 		pitch = -pitch;
// 		yaw -= 90;
// 
// 		return new PolarCoordinates((float) pitch, (float) yaw);
// 	}
// 
// }


// Path: src/main/java/me/bauer/BauerCam/Interpolation/CubicInterpolator.java
import me.bauer.BauerCam.Path.PolarCoordinates;
import me.bauer.BauerCam.Path.Position;
import me.bauer.BauerCam.Path.Vector3D;

package me.bauer.BauerCam.Interpolation;


public final class CubicInterpolator
		implements IPositionInterpolator, IPolarCoordinatesInterpolator, IAdditionalAngleInterpolator {

	public static final CubicInterpolator instance = new CubicInterpolator();

	private CubicInterpolator() {
	}

	@Override
	public void interpolatePosition(final PositionBuilder builder, final Position y0, final Position y1,
			final Position y2, final Position y3, final double step) {
		builder.setPosition(new Vector3D(InterpolationUtils.cubic_catmull(y0.x, y1.x, y2.x, y3.x, step),
				InterpolationUtils.cubic_catmull(y0.y, y1.y, y2.y, y3.y, step),