/*-------------------------------------------------------------*/
/* CVector3.h :   Fichier contenant la définition de la classe */
/*                CVector3 et également la surcharge des       */
/*                opérateurs sur les vecteurs.                 */
/*-------------------------------------------------------------*/

#ifndef CVECTOR3_H
#define CVECTOR3_H

#include <cmath>

class CVector3
{
 public:
  float x, y, z;

  // Constructeur par paramètres et par défaut
  inline CVector3(float a = 0, float b = 0, float c = 0)
    { x = a; y = b; z = c; }
  // Calcule et retourne la norme du vecteur
  inline float Norm() { return(sqrt(x*x + y*y + z*z)); }
  // Normalise le vecteur
  inline void Normalize() 
    { float Temp = sqrt(x*x + y*y + z*z); x /= Temp; y /= Temp; z /= Temp; }
};

// Addition de deux vecteurs
inline CVector3 operator + (const CVector3 &v1, const CVector3 &v2)
{
  return CVector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}

// Soustraction de deux vecteurs
inline CVector3 operator - (const CVector3 &v1, const CVector3 &v2)
{
  return CVector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}

// Produit scalaire de deux vecteurs
inline float operator * (const CVector3 &v1, const CVector3 &v2)
{
  return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z);
}

// Produit vectoriel de deux vecteurs
inline CVector3 operator ^ (const CVector3 &v1, const CVector3 &v2)
{
  return CVector3(v1.y*v2.z - v1.z*v2.y,
                  v1.z*v2.x - v1.x*v2.z,
                  v1.x*v2.y - v1.y*v2.x);
}

// Produit d'un vecteur par un scalaire
inline CVector3 operator * (const CVector3 &v, float k)
{
  return CVector3(k*v.x, k*v.y, k*v.z);
}

// Produit d'un scalaire par un vecteur
inline CVector3 operator * (float k, const CVector3 &v)
{
  return CVector3(k*v.x, k*v.y, k*v.z);
}

// Division d'un vecteur par un scalaire
inline CVector3 operator / (const CVector3 &v, float k)
{
  return CVector3(v.x/k, v.y/k, v.z/k);
}

// Projection d'un vecteur sur un autre vecteur
inline CVector3 operator >> (const CVector3 &v1, const CVector3 &v2)
{
  float Temp =
    (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z) /
    (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
  return CVector3(Temp*v2.x, Temp*v2.y, Temp*v2.z);
}


// Opposé d'un vecteur
inline CVector3 operator - (const CVector3 &v)
{
  return CVector3(-v.x, -v.y, -v.z);
}


// Opérateurs combinés à l'égalité
inline CVector3& operator += (CVector3 &v1, const CVector3 &v2)
{
  v1.x += v2.x;
  v1.y += v2.y;
  v1.z += v2.z;
  return v1;
}

inline CVector3& operator -= (CVector3 &v1, const CVector3 &v2)
{
  v1.x -= v2.x;
  v1.y -= v2.y;
  v1.z -= v2.z;
  return v1;
}

inline CVector3& operator ^= (CVector3 &v1, const CVector3 &v2)
{
  v1 = CVector3(v1.y*v2.z - v1.z*v2.y,
                v1.z*v2.x - v1.x*v2.z,
                v1.x*v2.y - v1.y*v2.x);
  return v1;
}

inline CVector3& operator *= (CVector3 &v, float k)
{
  v.x *= k;
  v.y *= k;
  v.z *= k;
  return v;
}

inline CVector3& operator /= (CVector3 &v, float k)
{
  v.x /= k;
  v.y /= k;
  v.z /= k;
  return v;
}

inline CVector3& operator >>= (CVector3 &v1, const CVector3 &v2)
{
  float Temp =
    (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z) /
    (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z);
  v1.x = v2.x * Temp;
  v1.y = v2.y * Temp;
  v1.z = v2.z * Temp;
  return v1;
}


#endif // CVECTOR3_H
