/* Auteur : Pierre Aubert Mail : aubertp7@gmail.com Licence : lgpl */ #include "matrice3f.h" const Matrice3f MAT3F_NULL(VECT3F_NULL, VECT3F_NULL, VECT3F_NULL); const Matrice3f MAT3F_ID(1.0,0.0,0.0 , 0.0,1.0,0.0 , 0.0,0.0,1.0); ///converti un angle en radian en degré /** @param rad : angle en radian @return angle en degré */ float radToDegF(float rad){return rad*180.0/M_PI;} ///converti un angle en degré en radian /** @param deg : angle en degré @return angle en radian */ float degToRadF(float deg){return deg*M_PI/180.0;} using namespace std; ///constructeur de Matrice3f /** @param v1 : Vecteur3f de la premiere colonne * @param v2 : Vecteur3f de la deuxième colonne * @param v3 : Vecteur3f de la troisième colonne */ Matrice3f::Matrice3f(const Vecteur3f& v1, const Vecteur3f& v2, const Vecteur3f& v3){ this->initialisation(v1, v2, v3); } ///constructeur de Matrice3f /** @param x1 : coeficient en (0,0) * @param y1 : coeficient en (0,1) * @param z1 : coeficient en (0,2) * @param x2 : coeficient en (1,0) * @param y2 : coeficient en (1,1) * @param z2 : coeficient en (1,2) * @param x3 : coeficient en (2,0) * @param y3 : coeficient en (2,1) * @param z3 : coeficient en (2,2) */ Matrice3f::Matrice3f(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3){ this->initialisation(Vecteur3f(x1, y1, z1), Vecteur3f(x2, y2, z2), Vecteur3f(x3, y3, z3)); } ///constructeur de copie de Matrice3f /** @param matrice : Matrice3f à copier */ Matrice3f::Matrice3f(const Matrice3f & matrice){ this->copyMatrice3f(matrice); } ///destructeur de Matrice3f Matrice3f::~Matrice3f(){ delete [] this->p_mat; } ///initialise les Vecteur3fs colonnes de la Matrice3f /** @param v1 : Vecteur3f de la premiere colonne * @param v2 : Vecteur3f de la deuxième colonne * @param v3 : Vecteur3f de la troisième colonne */ void Matrice3f::setVecteur3f(const Vecteur3f& v1, const Vecteur3f& v2, const Vecteur3f& v3){ this->initialisation(v1, v2, v3); } ///remplace toute les valeurs de la matrice par une seule /** @param val : nouvelle valeur des "cases" de la Matrice3f */ void Matrice3f::fill(float val){ for(unsigned int i = 0; i < 9; i++){ this->p_mat[i] = val; } } ///transforme la matrice en matrice de rotation avec un axe de rotation et un angle angleRad en radians /** @param axe : axe de rotation (pas forcément unitaire) * @param angleRad : angle de rotation autour de l'axe Ox en radians */ void Matrice3f::setRotRad(const Vecteur3f& axe, float angleRad){ Vecteur3f axeUnit(axe.getUnit()); if(axeUnit == VECT3F_NULL) return; float x(axeUnit.getx()); float y(axeUnit.gety()); float z(axeUnit.getz()); Vecteur3f colonne1(x*x + (1 - x*x)*cos(angleRad), x*y*(1 - cos(angleRad)) + z*sin(angleRad), x*z*(1 - cos(angleRad)) - y*sin(angleRad)); Vecteur3f colonne2(x*y*(1 - cos(angleRad)) - z*sin(angleRad), y*y + (1 - y*y)*cos(angleRad), y*z*(1- cos(angleRad)) + x*sin(angleRad)); Vecteur3f colonne3(x*z*(1 - cos(angleRad)) + y*sin(angleRad), y*z*(1 - cos(angleRad)) - x*sin(angleRad), z*z + (1 - z*z)*cos(angleRad)); this->setVecteur3f(colonne1, colonne2, colonne3); } ///transforme la matrice en matrice de rotation avec des angles en radians /** @param rotX : rotation suivant Ox * @param rotY : rotation suivant Oy * @param rotZ : rotation suivant Oz */ void Matrice3f::setRotRad(float rotX, float rotY, float rotZ){ Matrice3f matRotX; matRotX.setRotXRad(rotX); Matrice3f matRotY; matRotY.setRotYRad(rotY); Matrice3f matRotZ; matRotZ.setRotZRad(rotZ); this->copyMatrice3f(matRotX*matRotY*matRotZ); } ///transforme la matrice en matrice de rotation d'axe Ox et d'angle angleRad en radians /** @param angleRad : angle de rotation autour de l'axe Ox en radians */ void Matrice3f::setRotXRad(float angleRad){ Vecteur3f colonne1(1.0, 0.0, 0.0); Vecteur3f colonne2(0.0, cos(angleRad), sin(angleRad)); Vecteur3f colonne3(0.0, -sin(angleRad), cos(angleRad)); this->setVecteur3f(colonne1, colonne2, colonne3); } ///transforme la matrice en matrice de rotation d'axe Oy et d'angle angleRad en radians /** @param angleRad : angle de rotation autour de l'axe Oy en radians */ void Matrice3f::setRotYRad(float angleRad){ Vecteur3f colonne1(cos(angleRad), 0.0, -sin(angleRad)); Vecteur3f colonne2(0.0, 1.0, 0.0); Vecteur3f colonne3(sin(angleRad), 0.0, cos(angleRad)); this->setVecteur3f(colonne1, colonne2, colonne3); } ///transforme la matrice en matrice de rotation d'axe Oz et d'angle angleRad en radians /** @param angleRad : angle de rotation autour de l'axe Oz en radians */ void Matrice3f::setRotZRad(float angleRad){ Vecteur3f colonne1(cos(angleRad), sin(angleRad), 0.0); Vecteur3f colonne2(-sin(angleRad), cos(angleRad), 0.0); Vecteur3f colonne3(0.0, 0.0, 1.0); this->setVecteur3f(colonne1, colonne2, colonne3); } ///transforme la matrice en matrice de rotation avec un axe de angleDeg et un angle angleRad en degrés /** @param axe : axe de rotation (pas forcément unitaire) * @param angleDeg : angle de rotation autour de l'axe Ox en degrés */ void Matrice3f::setRotDeg(const Vecteur3f& axe, float angleDeg){ this->setRotRad(axe, degToRadF(angleDeg)); } ///transforme la matrice en matrice de rotation avec des angles en dégrés /** @param rotX : rotation suivant Ox * @param rotY : rotation suivant Oy * @param rotZ : rotation suivant Oz */ void Matrice3f::setRotDeg(float rotX, float rotY, float rotZ){ setRotRad(degToRadF(rotX), degToRadF(rotY), degToRadF(rotZ)); } ///transforme la matrice en matrice de rotation d'axe Ox et d'angle angleDeg en degrés /** @param angleDeg : angle de rotation autour de l'axe Ox en degrés */ void Matrice3f::setRotXDeg(float angleDeg){ setRotXRad(degToRadF(angleDeg)); } ///transforme la matrice en matrice de rotation d'axe Oy et d'angle angleDeg en degrés /** @param angleDeg : angle de rotation autour de l'axe Oy en degrés */ void Matrice3f::setRotYDeg(float angleDeg){ setRotYRad(degToRadF(angleDeg)); } ///transforme la matrice en matrice de rotation d'axe Oz et d'angle angleDeg en degrés /** @param angleDeg : angle de rotation autour de l'axe Oz en degrés */ void Matrice3f::setRotZDeg(float angleDeg){ setRotZRad(degToRadF(angleDeg)); } ///calcul de déterminant de la Matrice3f /** @return déterminant de la Matrice3f */ float Matrice3f::determinant(){ return (this->p_mat[0]*(this->p_mat[4]*this->p_mat[8] - this->p_mat[7]*this->p_mat[5]) - this->p_mat[3]*(this->p_mat[1]*this->p_mat[8] - this->p_mat[7]*this->p_mat[2]) + this->p_mat[6]*(this->p_mat[1]*this->p_mat[5] - this->p_mat[4]*this->p_mat[2])); } ///calcul et renvoie la matrice transposée /** @return matrice transposée */ Matrice3f Matrice3f::transposed(){ Matrice3f matrice(*this); float tmp; tmp = matrice.p_mat[1]; matrice.p_mat[1] = matrice.p_mat[3]; matrice.p_mat[3] = tmp; tmp = matrice.p_mat[2]; matrice.p_mat[2] = matrice.p_mat[6]; matrice.p_mat[6] = tmp; tmp = matrice.p_mat[5]; matrice.p_mat[5] = matrice.p_mat[7]; matrice.p_mat[7] = tmp; return matrice; } ///calcul et renvoie la comatrice /** @return comatrice */ Matrice3f Matrice3f::comatrice(){ Matrice3f matrice; matrice.p_mat[0] = this->p_mat[4]*this->p_mat[8] - this->p_mat[7]*this->p_mat[5]; matrice.p_mat[1] = this->p_mat[5]*this->p_mat[6] - this->p_mat[3]*this->p_mat[8]; matrice.p_mat[2] = this->p_mat[4]*this->p_mat[7] - this->p_mat[5]*this->p_mat[6]; matrice.p_mat[3] = this->p_mat[2]*this->p_mat[7] - this->p_mat[1]*this->p_mat[8]; matrice.p_mat[4] = this->p_mat[0]*this->p_mat[8] - this->p_mat[2]*this->p_mat[6]; matrice.p_mat[5] = this->p_mat[1]*this->p_mat[6] - this->p_mat[0]*this->p_mat[7]; matrice.p_mat[6] = this->p_mat[1]*this->p_mat[5] - this->p_mat[2]*this->p_mat[4]; matrice.p_mat[7] = this->p_mat[2]*this->p_mat[3] - this->p_mat[0]*this->p_mat[5]; matrice.p_mat[8] = this->p_mat[0]*this->p_mat[4] - this->p_mat[1]*this->p_mat[3]; return matrice; } ///calcul et renvoie la comatrice transposée /** @return comatrice transposée */ Matrice3f Matrice3f::comatriceTranposed(){ Matrice3f matrice; matrice.p_mat[0] = this->p_mat[4]*this->p_mat[8] - this->p_mat[7]*this->p_mat[5]; matrice.p_mat[4] = this->p_mat[0]*this->p_mat[8] - this->p_mat[2]*this->p_mat[6]; matrice.p_mat[8] = this->p_mat[0]*this->p_mat[4] - this->p_mat[1]*this->p_mat[3]; matrice.p_mat[3] = this->p_mat[5]*this->p_mat[6] - this->p_mat[3]*this->p_mat[8]; matrice.p_mat[6] = this->p_mat[4]*this->p_mat[7] - this->p_mat[5]*this->p_mat[6]; matrice.p_mat[7] = this->p_mat[1]*this->p_mat[6] - this->p_mat[0]*this->p_mat[7]; matrice.p_mat[1] = this->p_mat[2]*this->p_mat[7] - this->p_mat[1]*this->p_mat[8]; matrice.p_mat[2] = this->p_mat[1]*this->p_mat[5] - this->p_mat[2]*this->p_mat[4]; matrice.p_mat[5] = this->p_mat[2]*this->p_mat[3] - this->p_mat[0]*this->p_mat[5]; return matrice; } ///calcul et renvoie la matrice inverse de la Matrice3f /** @return matrice inverse de la Matrice3f, où matrice NULLE si elle n'existe pas (det = 0.0) */ Matrice3f Matrice3f::invert(){ Matrice3f matrice = this->comatriceTranposed(); float det = this->determinant(); if(det != 0.0){ matrice /= det; }else{ matrice.fill(0.0); } return matrice; } ///définition de l'operateur = /** @param matrice : Matrice3f à copier * @return Matrice3f copiée */ Matrice3f & Matrice3f::operator = (const Matrice3f & matrice){ this->copyMatrice3f(matrice); return *this; } ///définition de l'operateur += /** @param matrice : Matrice3f à additioner * @return résultat de l'addition */ Matrice3f & Matrice3f::operator += (const Matrice3f & matrice){ for(unsigned int i = 0; i < 9; i++){ this->p_mat[i] += matrice.p_mat[i]; } return *this; } ///définition de l'operateur *= /** @param matrice : Matrice3f à multiplier * @return résultat de la multiplication */ Matrice3f & Matrice3f::operator *= (const Matrice3f & matrice){ Matrice3f buffer; for(unsigned int j = 0; j < 3; j++){ for(unsigned int i = 0; i < 3; i++){ float calcul = 0; for(unsigned int k = 0; k < 3; k++){ calcul += this->p_mat[3*j + k]*matrice.p_mat[3*k + j]; } buffer.p_mat[3*j + i] = calcul; } } *this = buffer; return *this; } ///définition de l'operateur *= /** @param scal : scalaire multipliant la matrice * @return résultat de la multiplication */ Matrice3f & Matrice3f::operator *= (float scal){ for(unsigned int i = 0; i < 9; i++){ this->p_mat[i] *= scal; } return *this; } ///définition de l'operateur /= /** @param scal : scalaire divisant la matrice * @return résultat de la division */ Matrice3f & Matrice3f::operator /= (float scal){ for(unsigned int i = 0; i < 9; i++){ this->p_mat[i] /= scal; } return *this; } ///opérateur - sur une Matrice3f /** @return opposé de la Matrice3f */ Matrice3f & Matrice3f::operator - (){ for(unsigned int i = 0; i < 9; i++){ this->p_mat[i] = -this->p_mat[i]; } return *this; } ///renvoie un nombre de la Matrice /** @param i : position du nombre dans la Matrice3f * @return nombre à la position i dans la Matrice3f */ float Matrice3f::operator [] (unsigned int i) const{ if(i < 9){return this->p_mat[i];} else {return 0.0;} } ////////////////////////////////////////////////////////////////////////// // Fonctions amies de la classe Matrice3f // ////////////////////////////////////////////////////////////////////////// ///définition de l'opérateur + /** @param matrice1 : Matrice3f * @param matrice2 : Matrice3f * @return addition matrice1 + matrice2 */ Matrice3f operator + (const Matrice3f & matrice1, const Matrice3f & matrice2){ Matrice3f matrice; for(unsigned int i = 0; i < 9; i++){ matrice.p_mat[i] = matrice1.p_mat[i] + matrice2.p_mat[i]; } return matrice; } ///définition de l'opérateur - /** @param matrice1 : Matrice3f * @param matrice2 : Matrice3f * @return soustraction matrice1 + matrice2 */ Matrice3f operator - (const Matrice3f & matrice1, const Matrice3f & matrice2){ Matrice3f matrice; for(unsigned int i = 0; i < 9; i++){ matrice.p_mat[i] = matrice1.p_mat[i] - matrice2.p_mat[i]; } return matrice; } ///définition de l'opérateur - /** @param matrice1 : Matrice3f * @param scal : scalaire * @return division de matrice1 par scal */ Matrice3f operator / (const Matrice3f & matrice1, float scal){ Matrice3f matrice; for(unsigned int i = 0; i < 9; i++){ matrice.p_mat[i] = matrice1.p_mat[i]/scal; } return matrice; } ///définition de l'opérateur * (multiplication à droite par un scalaire) /** @param matrice1 : Matrice3f * @param scal : scalaire * @return multiplication de matrice1 par scal */ Matrice3f operator * (const Matrice3f & matrice1, float scal){ Matrice3f matrice; for(unsigned int i = 0; i < 9; i++){ matrice.p_mat[i] = matrice1.p_mat[i]*scal; } return matrice; } ///définition de l'opérateur * (multiplication à gauche par un scalaire) /** @param scal : scalaire * @param matrice2 : Matrice3f * @return multiplication de matrice1 par scal */ Matrice3f operator * (float scal, const Matrice3f & matrice2){ Matrice3f matrice; for(unsigned int i = 0; i < 9; i++){ matrice.p_mat[i] = matrice2.p_mat[i]*scal; } return matrice; } ///définition de l'opérateur * /** @param matrice1 : Matrice3f * @param matrice2 : Matrice3f * @return multiplication de matrice1 par matrice2 */ Matrice3f operator * (const Matrice3f & matrice1, const Matrice3f & matrice2){ Matrice3f matrice; for(unsigned int j = 0; j < 3; j++){ for(unsigned int i = 0; i < 3; i++){ float calcul = 0; for(unsigned int k = 0; k < 3; k++){ calcul += matrice1.p_mat[3*j + k]*matrice2.p_mat[3*k + i]; } matrice.p_mat[3*j + i] = calcul; } } return matrice; } ///définition de l'opérateur * (multiplication à gauche par un Vecteur3f /** @param matrice1 : Matrice3f * @param vecteur : Vecteur3f * @return multiplication de matrice1 par matrice2 */ Vecteur3f operator * (const Matrice3f & matrice1, const Vecteur3f & vecteur){ Vecteur3f vect(matrice1.p_mat[0]*vecteur.getx() + matrice1.p_mat[1]*vecteur.gety() + matrice1.p_mat[2]*vecteur.getz(), matrice1.p_mat[3]*vecteur.getx() + matrice1.p_mat[4]*vecteur.gety() + matrice1.p_mat[5]*vecteur.getz(), matrice1.p_mat[6]*vecteur.getx() + matrice1.p_mat[7]*vecteur.gety() + matrice1.p_mat[8]*vecteur.getz()); return vect; } ///opérateur d'égalité /** @param matrice1 : Matrice3f * @param matrice2 : Matrice3f * @return true si matrice1 = matrice2, false sinon */ bool operator == (const Matrice3f & matrice1, const Matrice3f & matrice2){ bool pareil = true; unsigned int i = 0; while(pareil && i < 9){ pareil = pareil && (matrice1.p_mat[i] == matrice2.p_mat[i]); i++; } return pareil; } ///opérateur d'inégalité /** @param matrice1 : Matrice3f * @param matrice2 : Matrice3f * @return false si matrice1 = matrice2, true sinon */ bool operator != (const Matrice3f & matrice1, const Matrice3f & matrice2){ bool different = true; unsigned int i = 0; while(different && i < 9){ different = different && (matrice1.p_mat[i] != matrice2.p_mat[i]); i++; } return different; } ///opérateur de flux pour afficher la Matrice3f /** @param out : flux de sortie * @param matrice : matrice à afficher * @return flux de sortie comprenant la Matrice3f à afficher */ std::ostream & operator << (std::ostream & out, const Matrice3f & matrice){ out << matrice.p_mat[0] << " " << matrice.p_mat[1] << " " << matrice.p_mat[2] << endl; out << matrice.p_mat[3] << " " << matrice.p_mat[4] << " " << matrice.p_mat[5] << endl; out << matrice.p_mat[6] << " " << matrice.p_mat[7] << " " << matrice.p_mat[8] << endl; return out; } ///initialise la Matrice3f /** @param v1 : Vecteur3f de la premiere colonne * @param v2 : Vecteur3f de la deuxième colonne * @param v3 : Vecteur3f de la troisième colonne */ void Matrice3f::initialisation(const Vecteur3f& v1, const Vecteur3f& v2, const Vecteur3f& v3){ this->p_mat = new float[9]; this->p_mat[0] = v1.getx(); this->p_mat[3] = v1.gety(); this->p_mat[6] = v1.getz(); this->p_mat[1] = v2.getx(); this->p_mat[4] = v2.gety(); this->p_mat[7] = v2.getz(); this->p_mat[2] = v3.getx(); this->p_mat[5] = v3.gety(); this->p_mat[8] = v3.getz(); } ///fonction de copie de la Matrice3f /** @param matrice : Matrice3f à copier */ void Matrice3f::copyMatrice3f(const Matrice3f & matrice){ this->p_mat = new float[9]; for(unsigned int i = 0; i < 9; i++){ this->p_mat[i] = matrice.p_mat[i]; } } ///fonction qui ne sert manifestement à rien (mais bon si elle est là c'est peut être pour une raison, mais la question est de savoir laquelle) /** @param i : entrée * @return déterminant de la matrice 2×2 qui reste (enfin je croix */ float Matrice3f::det2(unsigned int i){ if(i < 4){ return this->p_mat[i]*this->p_mat[i + 4] - this->p_mat[i + 1]*this->p_mat[i + 3]; } return 0.0; }