#include "Vector3D.h"
#include <cmath>

Vector3D::Vector3D() : x(0), y(0), z(0)
{
}

Vector3D::Vector3D(float ix, float iy, float iz) : x(ix), y(iy), z(iz)
{
}

Vector3D::Vector3D(const Vector3D& orig)
{
    x = orig.x;
    y = orig.y;
    z = orig.z;
}

Vector3D::~Vector3D()
{
}

float Vector3D::getX() const
{
    return x;
}

float Vector3D::getY() const
{
    return y;
}

float Vector3D::getZ() const
{
    return z;
}

void Vector3D::setX(float ix)
{
    x = ix;
}

void Vector3D::setY(float iy)
{
    y = iy;
}

void Vector3D::setZ(float iz)
{
    z = iz;
}

void Vector3D::set(float ix, float iy, float iz)
{
    x = ix;
    y = iy;
    z = iz;
}

void Vector3D::set(const Vector3D& v)
{
    x = v.x;
    y = v.y;
    z = v.z;
}

void Vector3D::setInverse(const Vector3D& v)
{
    x = -v.x;
    y = -v.y;
    z = -v.z;
}

void Vector3D::setMul(const Vector3D& v, float f)
{
    x = v.x * f;
    y = v.y * f;
    z = v.z * f;
}

void Vector3D::setAngles(float lengthAngle, float widthAngle)
{
    lengthAngle = lengthAngle * M_PI / 180.0f;
    widthAngle = widthAngle * M_PI / 180.0f;
    x = cosf(widthAngle) * sinf(lengthAngle);
    y = sinf(widthAngle);
    z = cosf(widthAngle) * cosf(lengthAngle); 
}


void Vector3D::add(const Vector3D& v)
{
    x += v.x;
    y += v.y;
    z += v.z;
}

void Vector3D::sub(const Vector3D& v)
{
    x -= v.x;
    y -= v.y;
    z -= v.z;
}

void Vector3D::mul(float f)
{
    x *= f;
    y *= f;
    z *= f;
}

void Vector3D::addMul(const Vector3D& v, float f)
{
    x += v.x * f;
    y += v.y * f;
    z += v.z * f;
}


void Vector3D::cross(float ix, float iy, float iz)
{
    set(y * iz - z * iy, z * ix - x * iz, x * iy - y * ix);
}

void Vector3D::cross(const Vector3D& v)
{
    set(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
}


void Vector3D::normalize()
{
    float f = length();
    x /= f;
    y /= f;
    z /= f;
}

float Vector3D::length() const
{
    return sqrtf(x * x + y * y + z * z);
}

float Vector3D::dot(const Vector3D& v) const
{
    return x * v.x + y * v.y + z * v.z;
}

float Vector3D::dotInverse(const Vector3D& v) const
{
    return x * (-v.x) + y * (-v.y) + z * (-v.z);
}

std::ostream& operator<<(std::ostream& os, const Vector3D& v)
{
    return os << "Vector3D(x = " << v.getX() << ", y = " << v.getY() << ", z = " << v.getZ() << ")";
}