package tracer.geometry;

final public class Vector3d {
  private double x, y, z;

  public Vector3d(double a, double b, double c) {
    x = a;
    y = b;
    z = c;
  }

  public Vector3d(Vector3d a) {
    x = a.x;
    y = a.y;
    z = a.z;
  }

  public Vector3d() {
    x = 0.0;
    y = 0.0;
    z = 0.0;
  }

  public static Vector3d add(Vector3d a, Vector3d b) {
    return new Vector3d(a.x + b.x, a.y + b.y, a.z + b.z);
  }

  public static Vector3d adds(double s, Vector3d a, Vector3d b) {
    return new Vector3d(s * a.x + b.x, s * a.y + b.y, s * a.z + b.z);
  }

  public static Vector3d sub(Vector3d a, Vector3d b) {
    return new Vector3d(a.x - b.x, a.y - b.y, a.z - b.z);
  }

  public static Vector3d mult(Vector3d a, Vector3d b) {
    return new Vector3d(a.x * b.x, a.y * b.y, a.z * b.z);
  }

  public static Vector3d cross(Vector3d a, Vector3d b) {
    return
        new Vector3d(a.y * b.z - a.z * b.y,
                     a.z * b.x - a.x * b.z,
                     a.x * b.y - a.y * b.x);
  }

  public static double dot(Vector3d a, Vector3d b) {
    return a.x * b.x + a.y * b.y + a.z * b.z;
  }

  public static Vector3d comb(double a, Vector3d A, double b, Vector3d B) {
    return
        new Vector3d(a * A.x + b * B.x,
                     a * A.y + b * B.y,
                     a * A.z + b * B.z);
  }

  public void scale(double t) {
    x *= t;
    y *= t;
    z *= t;
  }

  public void negate() {
    x = -x;
    y = -y;
    z = -z;
  }

  public double normalize() {
    double len;
    len = Math.sqrt(x * x + y * y + z * z);
    if (len > 0.0) {
      x /= len;
      y /= len;
      z /= len;
    }
    return len;
  }

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

  public double getX() {
    return x;
  }

  public void setX(double x) {
    this.x = x;
  }

  public double getY() {
    return y;
  }

  public void setY(double y) {
    this.y = y;
  }

  public double getZ() {
    return z;
  }

  public void setZ(double z) {
    this.z = z;
  }
}