/***************************************************************************
     Copyright (C) 2009 by Pierre,,,
     pierre@pierre-laptop
 ***************************************************************************/
#ifndef DEFVECTEUR_3F_H
#define DEFVECTEUR_3F_H

#include <complex.h>
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <list>

#include "pointf.h"

class Matrice3f;

/** @brief classe permettant de manipuler des Vecteur3fs et une partie des calculs qui leur est associé sans avoir à se trimballer les 3 coordonnées en vrac*/

/**
libs utilisées dans cette library
@li complex.h : cette lib est utilisée pour calculer la rotation du Vecteur3f (mais n'est pas utiliser pour le moment)
@li math.h : indispensable pour les calculs qui nécessites des fonctions trigonomètriqes (sin, cos, tan, asin, acos...)
@li stdio.h : lib utile pour ouvrir un fichier et écrire dedans
@li iostream : utile pour utliliser la sortie standard de la console
*/


class Vecteur3f{
	public:
		//constructeur de Vecteur3f
		Vecteur3f(float vecX = 0, float vecY = 0, float vecZ = 0);
		//initialise un vecteur avec une chaîne
		Vecteur3f(const char * str);
		//Fonction qui permet d'initialiser un Vecteur3f avec un Point
		Vecteur3f(const Pointf & point);
		
		//constructeur de copie de Vecteur3f
		Vecteur3f(const Vecteur3f & vec);
		//destructeur de Vecteur3f
		virtual ~Vecteur3f();
		//sauvegarde des coordonnées du Vecteur3f dans un ficher ouvert en écriture
		void save(FILE* fp);
		void save2d(FILE* fp);
		//initialisation des coordonnées du Vecteur3f à partir d'un ficher ouvert en lecture
		void load(FILE* fp);
		//initialisation avec une chaine de caractères
		bool initString(const char * str);
		//redéfinition de l'opérateur =
		Vecteur3f & operator = (const Vecteur3f & vect);
		//redéfinition de l'opérateur +=
		Vecteur3f & operator += (const Vecteur3f & vect);
		//redéfinition de l'opérateur -=
		Vecteur3f & operator -= (const Vecteur3f & vect);
		//redéfinition de l'opérateur *=
		Vecteur3f & operator *= (float coef);    //redéfinition de l'opérateur *=
		//redéfinition de l'opérateur /=
		Vecteur3f & operator /= (float coef);
		//redéfinition de l'opérateur -
		Vecteur3f operator - ();
		//donne la norme euclidienne du Vecteur3f
		float taille() const;
		//donne la norme du vecteur en coordonnées de Leci-Civita
		float tailleLeviCivita() const;
		//fonction qui calcul et renvoie la norme au carré de *this
		float normeSQR() const;
		//Retourne un Veteur ayant pour composantes les valeurs absolues des composantes de this
		Vecteur3f abs() const;
		//renvoie un Vecteur3f qui a un x positif
		Vecteur3f absX() const;
		//renvoie un Vecteur3f qui a un y positif
		Vecteur3f absY() const;
		//renvoie un Vecteur3f qui a un z positif
		Vecteur3f absZ() const;
		///renvoie la composante x du Vecteur3f
		/** @return la composante x du Vecteur3f
		*/
		inline float getx() const{return x;}
		///renvoie la composante y du Vecteur3f
		/** @return la composante y du Vecteur3f
		*/
		inline float gety() const{return y;}
		///renvoie la composante z du Vecteur3f
		/** @return la composante z du Vecteur3f
		*/
		inline float getz() const{return z;}
		//donne un Vecteur3f de la composante x du Vecteur3f
		Vecteur3f getVectX() const;
		//donne un Vecteur3f de la composante y du Vecteur3f
		Vecteur3f getVectY() const;
		//donne un Vecteur3f de la composante z du Vecteur3f
		Vecteur3f getVectZ() const;
		//donne un Vecteur3f (x, y, 0)
		Vecteur3f getVectXY() const;
		//donne un Vecteur3f (0, y, z)
		Vecteur3f getVectYZ() const;
		//donne un Vecteur3f (x, 0, z)
		Vecteur3f getVectXZ() const;
		//donne le Vecteur3f unitaire correspondant au Vecteur3f courrant
		Vecteur3f getUnit() const;
		//fonction de calcul d'angle qui doit être plus rapide que le calcul avec des nombres complexes
		float getAngle(const Vecteur3f & normale) const;
		//Fonction qui converti un Vecteur3f en Point
		Pointf toPoint() const;
		//fonction qui transforme un vecteur en coordonnées de Leci-Civita (u, v) en un Vecteur3f normal (x, y, 0) en 2D en tout cas pour l'instant
		Vecteur3f leviCivitaToVecteur3f() const;
		//fonction qui initialise les composantes du Vecteur3f
		void setXYZ(float vecX, float vecY, float vecZ);
		//initialise les composantes x y z du Vecteur3f avec un Point
		void setXYZ(const Pointf & pt);
		//initialise la composantes x du Vecteur3f
		void setx(const float x);
		//initialise la composantes y du Vecteur3f
		void sety(const float y);
		//initialise la composantes z du Vecteur3f
		void setz(const float z);
		//ajoute une valeur à la composante en x du Vecteur3f
		void addx(float dx);
		//ajoute une valeur à la composante en y du Vecteur3f
		void addy(float dy);
		//ajoute une valeur à la composante en z du Vecteur3f
		void addz(float dz);
		//fonction qui initialise le vecteur avec des angles en coordonnées spériques
		void setRotation(float angleTeta, float anglePhi);
		void setSpheric(float rho, float angleTeta, float anglePhi);
		float getAngleTeta() const;
		//fonction qui calcul la rotation du vecteur avec les variations de ses angles en coordonnées spériques
		void rotation(const Vecteur3f & axe, float angle);            //change l'orientation du Vecteur3f
		void rotation(const Matrice3f & matriceRotation, const Vecteur3f & centreRotation = Vecteur3f(0.0,0.0,0.0));
		//fonction qui calcul le réflexion du Vecteur3f *this par rapport à un vecteur normal
		void reflexion(const Vecteur3f & normal);
		//addition
		friend Vecteur3f operator + (const Vecteur3f & vect1, const Vecteur3f & vect2);
		//soustraction
		friend Vecteur3f operator - (const Vecteur3f & vect1, const Vecteur3f & vect2);
		//Définition du produit scalaire entre deux Vecteur3f
		friend float operator * (const Vecteur3f & vect1, const Vecteur3f & vect2);
		//mutiplication par un scalaire à droite
		friend Vecteur3f operator * (const Vecteur3f & vect, float scal);
		//mutiplication par un scalaire à gauche
		friend Vecteur3f operator * (float scal, const Vecteur3f & vect);
		//division par un scalaire
		friend Vecteur3f operator / (const Vecteur3f & vect, float scal);
		//Définition  du produit vectoriel
		friend Vecteur3f operator ^ (const Vecteur3f & vect1, const Vecteur3f & vect2);
		//Définition de l'égalité entre deux Vecteur3f
		friend bool operator == (const Vecteur3f & vect1, const Vecteur3f & vect2);
		//Définition de l'inégalité entre deux Vecteur3f
		friend bool operator != (const Vecteur3f & vect1, const Vecteur3f & vect2);
		//permet l'affichage d'un vecteur dans la console
		friend std::ostream & operator << (std::ostream & out, const Vecteur3f & vecteur);
		//permet l'initialisation d'un Vecteur3f dans la console où avec un fichier de config
		friend std::istream & operator >> (std::istream & in, Vecteur3f & v);
		//initialise un Vecteur3f à partir d'une chaine de type (x,y,z)
		bool loadFromConfig(const char  * source);
	private:
		//initialisation de Vecteur3f
		void init(float vecX, float vecY, float vecZ);//initialisation de Vecteur3f
		
		///conposante sur l'axe des x
		float x;
		///conposante sur l'axe des y
		float y;
		///composante sur l'axe des z
		float z;

};

//Fonction qui converti un Point en Vecteur3f
Vecteur3f pointToVecteur3f(const Pointf & point);
//fonction qui indique comment initilialiser un Vecteur3f avec un fichier de config
void pConfig_load_obj(const char * source, Vecteur3f & v);

Vecteur3f initVecteur3f(float x = 0.0, float y = 0.0, float z = 0.0);

///definition d'un Vecteur3f NULL
extern const Vecteur3f VECT3F_NULL;
///définition de la constante de gravitation sur terre
extern const Vecteur3f GTerre3f;

typedef std::list<Vecteur3f> PListeVecteur3f;
bool loadPListeVecteur3f(const char * fileName, PListeVecteur3f & listeVecteur3f);
void savePlisteVecteur3f(const char * fileName, const PListeVecteur3f & listeVecteur3f);
void savePlisteVecteur3fX(const char * fileName, const PListeVecteur3f & listeVecteur3f);
void savePlisteVecteur3fY(const char * fileName, const PListeVecteur3f & listeVecteur3f);
void savePlisteVecteur3fZ(const char * fileName, const PListeVecteur3f & listeVecteur3f);

#endif


