| 1 | /// @ref gtx_pca |
| 2 | /// @file glm/gtx/pca.hpp |
| 3 | /// |
| 4 | /// @see core (dependence) |
| 5 | /// @see ext_scalar_relational (dependence) |
| 6 | /// |
| 7 | /// @defgroup gtx_pca GLM_GTX_pca |
| 8 | /// @ingroup gtx |
| 9 | /// |
| 10 | /// Include <glm/gtx/pca.hpp> to use the features of this extension. |
| 11 | /// |
| 12 | /// Implements functions required for fundamental 'princple component analysis' in 2D, 3D, and 4D: |
| 13 | /// 1) Computing a covariance matrics from a list of _relative_ position vectors |
| 14 | /// 2) Compute the eigenvalues and eigenvectors of the covariance matrics |
| 15 | /// This is useful, e.g., to compute an object-aligned bounding box from vertices of an object. |
| 16 | /// https://en.wikipedia.org/wiki/Principal_component_analysis |
| 17 | /// |
| 18 | /// Example: |
| 19 | /// ``` |
| 20 | /// std::vector<glm::dvec3> ptData; |
| 21 | /// // ... fill ptData with some point data, e.g. vertices |
| 22 | /// |
| 23 | /// glm::dvec3 center = computeCenter(ptData); |
| 24 | /// |
| 25 | /// glm::dmat3 covarMat = glm::computeCovarianceMatrix(ptData.data(), ptData.size(), center); |
| 26 | /// |
| 27 | /// glm::dvec3 evals; |
| 28 | /// glm::dmat3 evecs; |
| 29 | /// int evcnt = glm::findEigenvaluesSymReal(covarMat, evals, evecs); |
| 30 | /// |
| 31 | /// if(evcnt != 3) |
| 32 | /// // ... error handling |
| 33 | /// |
| 34 | /// glm::sortEigenvalues(evals, evecs); |
| 35 | /// |
| 36 | /// // ... now evecs[0] points in the direction (symmetric) of the largest spatial distribution within ptData |
| 37 | /// ``` |
| 38 | |
| 39 | #pragma once |
| 40 | |
| 41 | // Dependency: |
| 42 | #include "../glm.hpp" |
| 43 | #include "../ext/scalar_relational.hpp" |
| 44 | |
| 45 | #ifndef GLM_ENABLE_EXPERIMENTAL |
| 46 | # error "GLM: GLM_GTX_pca is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it." |
| 47 | #elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) |
| 48 | # pragma message("GLM: GLM_GTX_pca extension included") |
| 49 | #endif |
| 50 | |
| 51 | namespace glm { |
| 52 | /// @addtogroup gtx_pca |
| 53 | /// @{ |
| 54 | |
| 55 | /// Compute a covariance matrix form an array of relative coordinates `v` (e.g., relative to the center of gravity of the object) |
| 56 | /// @param v Points to a memory holding `n` times vectors |
| 57 | /// @param n Number of points in v |
| 58 | template<length_t D, typename T, qualifier Q> |
| 59 | GLM_INLINE mat<D, D, T, Q> computeCovarianceMatrix(vec<D, T, Q> const* v, size_t n); |
| 60 | |
| 61 | /// Compute a covariance matrix form an array of absolute coordinates `v` and a precomputed center of gravity `c` |
| 62 | /// @param v Points to a memory holding `n` times vectors |
| 63 | /// @param n Number of points in v |
| 64 | /// @param c Precomputed center of gravity |
| 65 | template<length_t D, typename T, qualifier Q> |
| 66 | GLM_INLINE mat<D, D, T, Q> computeCovarianceMatrix(vec<D, T, Q> const* v, size_t n, vec<D, T, Q> const& c); |
| 67 | |
| 68 | /// Compute a covariance matrix form a pair of iterators `b` (begin) and `e` (end) of a container with relative coordinates (e.g., relative to the center of gravity of the object) |
| 69 | /// Dereferencing an iterator of type I must yield a `vec<D, T, Q%gt;` |
| 70 | template<length_t D, typename T, qualifier Q, typename I> |
| 71 | GLM_FUNC_DECL mat<D, D, T, Q> computeCovarianceMatrix(I const& b, I const& e); |
| 72 | |
| 73 | /// Compute a covariance matrix form a pair of iterators `b` (begin) and `e` (end) of a container with absolute coordinates and a precomputed center of gravity `c` |
| 74 | /// Dereferencing an iterator of type I must yield a `vec<D, T, Q%gt;` |
| 75 | template<length_t D, typename T, qualifier Q, typename I> |
| 76 | GLM_FUNC_DECL mat<D, D, T, Q> computeCovarianceMatrix(I const& b, I const& e, vec<D, T, Q> const& c); |
| 77 | |
| 78 | /// Assuming the provided covariance matrix `covarMat` is symmetric and real-valued, this function find the `D` Eigenvalues of the matrix, and also provides the corresponding Eigenvectors. |
| 79 | /// Note: the data in `outEigenvalues` and `outEigenvectors` are in matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. |
| 80 | /// This is a numeric implementation to find the Eigenvalues, using 'QL decomposition` (variant of QR decomposition: https://en.wikipedia.org/wiki/QR_decomposition). |
| 81 | /// |
| 82 | /// @param[in] covarMat A symmetric, real-valued covariance matrix, e.g. computed from computeCovarianceMatrix |
| 83 | /// @param[out] outEigenvalues Vector to receive the found eigenvalues |
| 84 | /// @param[out] outEigenvectors Matrix to receive the found eigenvectors corresponding to the found eigenvalues, as column vectors |
| 85 | /// @return The number of eigenvalues found, usually D if the precondition of the covariance matrix is met. |
| 86 | template<length_t D, typename T, qualifier Q> |
| 87 | GLM_FUNC_DECL unsigned int findEigenvaluesSymReal |
| 88 | ( |
| 89 | mat<D, D, T, Q> const& covarMat, |
| 90 | vec<D, T, Q>& outEigenvalues, |
| 91 | mat<D, D, T, Q>& outEigenvectors |
| 92 | ); |
| 93 | |
| 94 | /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. |
| 95 | /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. |
| 96 | template<typename T, qualifier Q> |
| 97 | GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<2, T, Q>& eigenvalues, mat<2, 2, T, Q>& eigenvectors); |
| 98 | |
| 99 | /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. |
| 100 | /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. |
| 101 | template<typename T, qualifier Q> |
| 102 | GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<3, T, Q>& eigenvalues, mat<3, 3, T, Q>& eigenvectors); |
| 103 | |
| 104 | /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. |
| 105 | /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. |
| 106 | template<typename T, qualifier Q> |
| 107 | GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<4, T, Q>& eigenvalues, mat<4, 4, T, Q>& eigenvectors); |
| 108 | |
| 109 | /// @} |
| 110 | }//namespace glm |
| 111 | |
| 112 | #include "pca.inl" |