#ifndef VECTEUR_H_INCLUDED
#define VECTEUR_H_INCLUDED

#include <cmath>

class Vecteur
{
    public:

    Vecteur() : m_x(0.0), m_y(0.0), m_z(0.0)
    {

    }
    Vecteur(float x, float y, float z = 0) : m_x(x), m_y(y), m_z(z)
    {

    }
    Vecteur(const Vecteur &vecteur) : m_x(vecteur.getX()), m_y(vecteur.getY()), m_z(vecteur.getZ())
    {

    }
    ~Vecteur()
    {

    }
    float getX() const
    {
        return m_x;
    }

    float getY() const
    {
        return m_y;
    }

    float getZ() const
    {
        return m_z;
    }


    // Setters

    void setVecteur(float x, float y, float z)
    {
        m_x = x;
        m_y = y;
        m_z = z;
    }

    void setX(float x)
    {
        m_x = x;
    }

    void setY(float y)
    {
        m_y = y;
    }

    void setZ(float z)
    {
        m_z = z;
    }
    void normaliser()
    {
        // La fonction sqrt() permet de trouver la racine carré d'un nombre

        float longueur (sqrt(m_x * m_x + m_y * m_y + m_z * m_z));


        // Normalisation du vecteur

        if(longueur != 0.0)
        {
            m_x /= longueur;
            m_y /= longueur;
            m_z /= longueur;
        }
    }
    Vecteur normalise()
    {
        // La fonction sqrt() permet de trouver la racine carré d'un nombre
        Vecteur resultat;
        float longueur (sqrt(m_x * m_x + m_y * m_y + m_z * m_z));


        // Normalisation du vecteur

        if(longueur != 0.0)
        {
            resultat.setX(m_x/longueur);
            resultat.setY(m_y/longueur);
            resultat.setZ(m_z/longueur);
        }
        return resultat;
    }
    Vecteur& operator=(const Vecteur &vecteur)
    {
        // Copie des valeurs

        m_x = vecteur.m_x;
        m_y = vecteur.m_y;
        m_z = vecteur.m_z;


        // Retour de l'objet

        return *this;
    }
    Vecteur operator+(const Vecteur &vecteur)
    {
        // Cr�ation d'un objet r�sultat

        Vecteur resultat;


        // Addition des coordonn�es

        resultat.m_x = m_x + vecteur.m_x;
        resultat.m_y = m_y + vecteur.m_y;
        resultat.m_z = m_z + vecteur.m_z;


        // Retour de r�sultat

        return resultat;
    }
    Vecteur operator-(const Vecteur &vecteur)
    {
        // Cr�ation d'un objet r�sultat

        Vecteur resultat;


        // Soustraction des coordonn�es

        resultat.m_x = m_x - vecteur.m_x;
        resultat.m_y = m_y - vecteur.m_y;
        resultat.m_z = m_z - vecteur.m_z;


        // Retour de r�sultat

        return resultat;
    }
    Vecteur operator*(float multiplicateur)
    {
        // Cr�ation d'un objet r�sultat

        Vecteur resultat;


        // Multiplication des coordonn�es

        resultat.m_x = m_x * multiplicateur;
        resultat.m_y = m_y * multiplicateur;
        resultat.m_z = m_z * multiplicateur;


        // Retour du r�sultat

        return resultat;
    }
    Vecteur operator/(float diviseur)
    {
        // Cr�ation d'un objet r�sultat

        Vecteur resultat;


        // Multiplication des coordonn�es

        resultat.m_x = m_x / diviseur;
        resultat.m_y = m_y / diviseur;
        resultat.m_z = m_z / diviseur;


        // Retour du r�sultat

        return resultat;
    }
    Vecteur operator*(const Vecteur &vecteur)
    {
        // Cr�ation d'un objet r�sultat

        Vecteur resultat;


        // Produit Vectoriel

        resultat.m_x = (m_y * vecteur.m_z) - (m_z * vecteur.m_y);
        resultat.m_y = (m_z * vecteur.m_x) - (m_x * vecteur.m_z);
        resultat.m_z = (m_x * vecteur.m_y) - (m_y * vecteur.m_x);


        // Retour de l'objet

        return resultat;
    }
    void operator*=(const Vecteur &vecteur)
    {
        *this = *this * vecteur;
    }
    void operator-=(const Vecteur &vecteur)
    {
        *this = *this - vecteur;
    }
    void operator+=(const Vecteur &vecteur)
    {
        *this = *this + vecteur;
    }
    void operator*=(float multiplicateur)
    {
        *this = *this * multiplicateur;
    }
    void operator/=(float multiplicateur)
    {
        *this = *this * multiplicateur;
    }
    float scalair(const Vecteur &vecteur)
    {
        Vecteur v1(*this), v2(vecteur);
        v1.normaliser();
        v2.normaliser();
        float produitScalair = v1.getX() * v2.getX() + v1.getY() * v2.getY() + v1.getZ() * v2.getZ();
        if(produitScalair>1)
            produitScalair = 1;
        return acos(produitScalair)*180/M_PI;
    }
    bool operator==(const Vecteur &vecteur)
    {
        if(m_x == vecteur.getX() && m_y == vecteur.getY() && m_z == vecteur.getZ())
            return true;
        else
            return false;
    }
    bool operator!=(const Vecteur &vecteur)
    {
        if(*this == vecteur)
            return false;
        else
            return true;
    }
    double norme()
    {
        return sqrt(m_x*m_x+m_y*m_y+m_z*m_z);
    }
    void rotate(float angle)
    {
        float _angle = angle*M_PI/180;
        float tmp = m_x;
        m_x = cos(_angle)*m_x-sin(_angle)*m_y;
        m_y = sin(_angle)*tmp+cos(_angle)*m_y;
    }

private:
    float m_x;
    float m_y;
    float m_z;
};

#endif // VECTEUR_H_INCLUDED