// hotelling.cc - Classe Hotelling // robert - Programme du robot APBteam // Copyright (C) 2005 Olivier Gaillard /// @file hotelling.cc Detecte l'orientation principale d'une masse de données #include #include #include "hotelling.hh" /// Constructeur Hotelling::Hotelling (const std::vector &dataList) { oconfig_ = OConfig::getInstance (); dataSize_ = dataList.size (); if (dataSize_ == 0) meanX_ = meanY_ = 0; else { // Calcul de la moyenne mean (dataList); // Initialisation des données data_ = new Hpoint[dataSize_]; // Changement de repère des données int i = 0; for (std::vector::const_iterator iter = dataList.begin (); iter != dataList.end (); ++iter) { data_[i].set ((*iter)[0] - meanX_, (*iter)[1] - meanY_); ++i; } } } /// Destructeur Hotelling::~Hotelling (void) { delete [] data_; } /// Covariance double Hotelling::cov (const unsigned i, const unsigned j) { double c = 0; for (unsigned k = 0; k < dataSize_; ++k) c += data_[k][i] * data_[k][j]; c /= (dataSize_-1); return c; } /// Calcul de la matrice de covariance void Hotelling::covMatrix () { /// Calcul de la covariance covMatrix_[0][0] = cov (0, 0); covMatrix_[0][1] = cov (0, 1); covMatrix_[1][0] = covMatrix_[0][1]; covMatrix_[1][1] = cov (1, 1); } /// Calcul de la moyenne des deux composantes void Hotelling::mean (const std::vector &dataList) { meanX_ = meanY_ = 0; for (std::vector::const_iterator iter = dataList.begin (); iter != dataList.end (); ++iter) { meanX_ += (*iter)[0]; meanY_ += (*iter)[1]; } meanX_ /= dataSize_; meanY_ /= dataSize_; } /// Calcul des eigenvalues void Hotelling::eigenValues () { double apd = covMatrix_[0][0] + covMatrix_[1][1]; double sqrtdelta = sqrt (apd*apd - 4* (covMatrix_[0][0]*covMatrix_[1][1] - covMatrix_[1][0]*covMatrix_[1][0])); val1_ = (apd - sqrtdelta)/(2); val2_ = (apd + sqrtdelta)/(2); } /// Calcul des eigenvectors void Hotelling::eigenVectors () { covMatrix (); eigenValues (); // Calcul des vecteurs e2_.set (1, covMatrix_[1][0] / (val2_ - covMatrix_[1][1])); e1_.set (1, covMatrix_[1][0] / (val1_ - covMatrix_[1][1])); // Normalisation e1_.norm (); e2_.norm (); } /// Accessors void Hotelling::getPC (Hpoint &pca) { if (val1_>val2_) pca = e1_; else pca = e2_; } void Hotelling::getPC (double &x, double &y) { Hpoint h; getPC (h); x = h[0]; y = h[1]; } /// Affiche la matrice de covariance void Hotelling::showCovMatrix () const { std::cout << "Matrice de covariance :\n" << "\t" << covMatrix_[0][0] << "\n" << "\t" << covMatrix_[0][1] << "\n" << "\t" << covMatrix_[1][0] << "\n" << "\t" << covMatrix_[1][1] << std::endl; } /// Affiche les eigenvectors void Hotelling::show () const { std::cout << "EigenValues :\n" << "\t" << val1_ << ", " << val2_ << "\n"; std::cout << "EigenVectors :\n" << "\t" << e1_[0] << ", " << e1_[1] << "\n" << "\t" << e2_[0] << ", " << e2_[1] << std::endl; } void Hotelling::get (double &x, double &y, double &x2, double &y2) { if (val1_>val2_) { x = e1_[0]; y = e1_[1]; x2 = e2_[0]; y2 = e2_[1]; } else { x = e2_[0]; y = e2_[1]; x2 = e1_[0]; y2 = e1_[1]; } }