Init
This commit is contained in:
commit
d2076b8226
|
@ -0,0 +1,47 @@
|
||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
project(GTI320-labos)
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Add google test and setup build
|
||||||
|
#--------------------------------------------------
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
googletest
|
||||||
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||||
|
GIT_TAG release-1.11.0
|
||||||
|
)
|
||||||
|
|
||||||
|
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||||
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
# No need for GMock
|
||||||
|
set( BUILD_GMOCK OFF CACHE BOOL "" FORCE)
|
||||||
|
set( INSTALL_GTEST OFF CACHE BOOL "" FORCE)
|
||||||
|
set( GTEST_FORCE_SHARED_CRT ON CACHE BOOL "" FORCE)
|
||||||
|
set( GTEST_DISABLE_PTHREADS ON CACHE BOOL "" FORCE)
|
||||||
|
FetchContent_MakeAvailable(googletest)
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Add nanogui
|
||||||
|
#--------------------------------------------------
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
nanogui
|
||||||
|
GIT_REPOSITORY https://github.com/mitsuba-renderer/nanogui.git
|
||||||
|
GIT_PROGRESS TRUE
|
||||||
|
)
|
||||||
|
set( NANOGUI_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||||
|
set( NANOGUI_BUILD_SHARED OFF CACHE BOOL "" FORCE)
|
||||||
|
set( NANOGUI_BUILD_PYTHON OFF CACHE BOOL "" FORCE)
|
||||||
|
set( NANOGUI_USE_OPENGL ON CACHE BOOL "" FORCE)
|
||||||
|
FetchContent_MakeAvailable(nanogui)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/labo01/src ${COMMON_INCLUDES})
|
||||||
|
add_subdirectory(labo01)
|
||||||
|
add_subdirectory(labo_ik)
|
||||||
|
|
||||||
|
if( MSVC )
|
||||||
|
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT labo_ik)
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
|
project(labo01)
|
||||||
|
|
||||||
|
# Setup language requirements
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Add .cpp and .h files
|
||||||
|
file(GLOB_RECURSE TESTS_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" CONFIGURE_DEPENDS "tests/*.cpp")
|
||||||
|
file(GLOB_RECURSE MAIN_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" CONFIGURE_DEPENDS "src/*.h")
|
||||||
|
add_executable(labo01 main.cpp ${MAIN_SOURCES} ${TESTS_SOURCES})
|
||||||
|
|
||||||
|
# Add linking information for Google Test
|
||||||
|
target_link_libraries(labo01 gtest)
|
||||||
|
|
||||||
|
|
||||||
|
# Set labo01 as the startup project for Visual Studio
|
||||||
|
if( MSVC )
|
||||||
|
set_property(TARGET labo01 PROPERTY VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/labo01)
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* @file main.cpp
|
||||||
|
*
|
||||||
|
* @brief Execute unit tests for a simple linear algebra library.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
// Executer tous les tests unitaires.
|
||||||
|
//
|
||||||
|
// Les tests sont écrites dans les fichiers:
|
||||||
|
// tests/Tests1a.cpp
|
||||||
|
// tests/Tests1b.cpp
|
||||||
|
// tests/TestsSupplementaire1a.cpp
|
||||||
|
// tests/TestsSupplementaire1b.cpp
|
||||||
|
//
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
const int ret = RUN_ALL_TESTS();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,220 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file DenseStorage.h
|
||||||
|
*
|
||||||
|
* @brief Stockage dense pour des données à taille fixe ou dynamique.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace gti320
|
||||||
|
{
|
||||||
|
enum SizeType { Dynamic = -1 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stockage à taille fixe.
|
||||||
|
*
|
||||||
|
* Le nombre de données à stocker est connu au moment de la compilation.
|
||||||
|
* Ce nombre est donné par le paramètre de patron : _Size
|
||||||
|
*
|
||||||
|
* Un tampon (tableau) de taille `_Size_` est alloué sur la pile d'exécution.
|
||||||
|
*/
|
||||||
|
template<typename _Scalar, int _Size>
|
||||||
|
class DenseStorage
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
// TODO déclarer une variable m_data et allouer la mémoire pour y stocker _Size éléments
|
||||||
|
_Scalar* m_data; // <-- Ceci n'est pas bon, à modifier
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
DenseStorage() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
DenseStorage(const DenseStorage& other)
|
||||||
|
{
|
||||||
|
memcpy(m_data, other.m_data, sizeof(m_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur avec taille spécifiée.
|
||||||
|
* Doit être la même que la taille spécifiée dans le patron
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
explicit DenseStorage(int _size)
|
||||||
|
{
|
||||||
|
assert(_size > 0 && _size == _Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur avec taille (_size) et données initiales (_data).
|
||||||
|
*/
|
||||||
|
explicit DenseStorage(const _Scalar* _data, int _size)
|
||||||
|
{
|
||||||
|
assert(_size >= 0 && _size == _Size);
|
||||||
|
memcpy(m_data, _data, sizeof(_Scalar) * _size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie
|
||||||
|
*/
|
||||||
|
DenseStorage& operator=(const DenseStorage& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
assert(other.size() == _Size);
|
||||||
|
memcpy(m_data, other.m_data, sizeof(m_data));
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int size() { return _Size; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redimensionne le stockage pour qu'il contienne `size` élément.
|
||||||
|
*/
|
||||||
|
void resize(int size)
|
||||||
|
{
|
||||||
|
// Ne rien faire. Invalide pour les matrices à taille fixe.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mets tous les éléments à zéro.
|
||||||
|
*/
|
||||||
|
void setZero()
|
||||||
|
{
|
||||||
|
memset(m_data, 0, sizeof(_Scalar) * _Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès au tampon de données (en lecteur seulement)
|
||||||
|
*/
|
||||||
|
const _Scalar* data() const
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès au tampon de données (pour lecture et écriture)
|
||||||
|
*/
|
||||||
|
_Scalar* data()
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stockage à taille dynamique.
|
||||||
|
*
|
||||||
|
* Le nombre de données à stocker est déterminé à l'exécution.
|
||||||
|
* Un tampon de la taille demandée doit être alloué sur le tas via
|
||||||
|
* l'opérateur `new []` et la mémoire doit être libérée avec `delete[]`
|
||||||
|
*/
|
||||||
|
template<typename _Scalar>
|
||||||
|
class DenseStorage<_Scalar, Dynamic>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
_Scalar* m_data;
|
||||||
|
int m_size;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
DenseStorage() : m_data(nullptr), m_size(0) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur avec taille spécifiée
|
||||||
|
*/
|
||||||
|
explicit DenseStorage(int _size) : m_data(nullptr), m_size(_size)
|
||||||
|
{
|
||||||
|
// TODO allouer un tampon pour stocker _size éléments de type _Scalar.
|
||||||
|
|
||||||
|
// TODO initialiser ce tampon à zéro.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
DenseStorage(const DenseStorage& other)
|
||||||
|
: m_data(nullptr)
|
||||||
|
, m_size(other.m_size)
|
||||||
|
{
|
||||||
|
// TODO allouer un tampon pour stocker _size éléments de type _Scalar.
|
||||||
|
|
||||||
|
// TODO copier other.m_data dans m_data.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie
|
||||||
|
*/
|
||||||
|
DenseStorage& operator=(const DenseStorage& other)
|
||||||
|
{
|
||||||
|
// TODO implémenter !
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~DenseStorage()
|
||||||
|
{
|
||||||
|
// TODO libérer la mémoire allouée
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la taille du tampon
|
||||||
|
*/
|
||||||
|
inline int size() const { return m_size; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redimensionne le tampon alloué pour le stockage.
|
||||||
|
* La mémoire qui n'est plus utilisée doit être libérée.
|
||||||
|
*
|
||||||
|
* Note : Toutes opérations de redimensionnement entraînent une réallocation de mémoire.
|
||||||
|
* Il n’est pas pertinent de copier les données car le résultat serait de toute façon incohérent.
|
||||||
|
*/
|
||||||
|
void resize(int _size)
|
||||||
|
{
|
||||||
|
// TODO redimensionner la mémoire allouée
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Met tous les éléments à zéro.
|
||||||
|
*/
|
||||||
|
void setZero()
|
||||||
|
{
|
||||||
|
// TODO implémenter !
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès au tampon de données (en lecteur seulement)
|
||||||
|
*/
|
||||||
|
const _Scalar* data() const { return m_data; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès au tampon de données (pour lecture et écriture)
|
||||||
|
*/
|
||||||
|
_Scalar* data() { return m_data; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file Math3D.h
|
||||||
|
*
|
||||||
|
* @brief Fonctions pour l'intinialisation et la manipulation de matrices de
|
||||||
|
* rotation, des matrices de transformations en coordonnées homogènes et les
|
||||||
|
* vecteurs 3D.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Matrix.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
#include "Operators.h"
|
||||||
|
|
||||||
|
#ifndef _USE_MATH_DEFINES
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace gti320 {
|
||||||
|
|
||||||
|
// Deux types de vecteurs 3D considérés ici
|
||||||
|
typedef Vector<double, 3> Vector3d;
|
||||||
|
typedef Vector<float, 3> Vector3f;
|
||||||
|
|
||||||
|
// Dans le cadre de ce projet, nous considérons seulement deux
|
||||||
|
// cas :
|
||||||
|
//
|
||||||
|
// - les rotations
|
||||||
|
// - les translations
|
||||||
|
//
|
||||||
|
// Deux types de matrices en coordonnées homogèes :
|
||||||
|
typedef Matrix<double, 4, 4, ColumnStorage> Matrix4d;
|
||||||
|
typedef Matrix<float, 4, 4, ColumnStorage> Matrix4f;
|
||||||
|
//
|
||||||
|
// Deux types de matrices pour les rotations
|
||||||
|
typedef Matrix<double, 3, 3, ColumnStorage> Matrix3d;
|
||||||
|
typedef Matrix<float, 3, 3, ColumnStorage> Matrix3f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise et retourne la matrice identité
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
inline void Matrix4d::setIdentity()
|
||||||
|
{
|
||||||
|
// TODO affecter la valeur 0.0 partout, sauf sur la diagonale principale où c'est 1.0.
|
||||||
|
// Note: ceci est une redéfinition d'une fonction membre!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcul de la matrice inverse, SPÉCIALISÉ pour le cas d'une matrice de
|
||||||
|
* transformation en coordonnées homogènes.
|
||||||
|
*
|
||||||
|
* TODO (vous pouvez supposer qu'il s'agit d'une matrice de transformation
|
||||||
|
* en coordonnées homogènes)
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
inline Matrix4d Matrix4d::inverse() const
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix4d(); // Pas bon, à changer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcul de la matrice inverse, SPÉCIALISÉ pour le cas d'une matrice de rotation.
|
||||||
|
*
|
||||||
|
* (vous pouvez supposer qu'il s'agit d'une matrice de rotation)
|
||||||
|
*/
|
||||||
|
template<>
|
||||||
|
inline Matrix3d Matrix3d::inverse() const
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix3d();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication d'une matrice 4x4 avec un vecteur 3D où la matrice
|
||||||
|
* représente une transformation en coordonnées homogène.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar>
|
||||||
|
Vector<_Scalar, 3> operator*(const Matrix<_Scalar, 4, 4, ColumnStorage>& A, const Vector<_Scalar, 3>& v)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Vector<_Scalar, 3>(); // pas bon, à changer
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise et retourne la matrice de rotation définie par les angles
|
||||||
|
* d'Euler XYZ exprimés en radians.
|
||||||
|
*
|
||||||
|
* La matrice doit correspondre au produit : Rz*Ry*Rx.
|
||||||
|
*/
|
||||||
|
template<typename _Scalar>
|
||||||
|
static Matrix<_Scalar, 3, 3> makeRotation(_Scalar x, _Scalar y, _Scalar z)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
|
||||||
|
return Matrix<_Scalar, 3, 3>(); // pas bon, à changer
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,350 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file Matrix.h
|
||||||
|
*
|
||||||
|
* @brief Implémentation de matrices simples.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MatrixBase.h"
|
||||||
|
|
||||||
|
namespace gti320
|
||||||
|
{
|
||||||
|
enum StorageType
|
||||||
|
{
|
||||||
|
ColumnStorage = 0,
|
||||||
|
RowStorage = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Déclaration avancée
|
||||||
|
template <typename _Scalar, int _RowsAtCompile, int _ColsAtCompile, int _StorageType> class SubMatrix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe Matrix spécialisé pour le cas générique. (defaut par colonne)
|
||||||
|
*
|
||||||
|
* (le cas d'un stockage par ligne fait l'objet d'une spécialisation de patron, voir plus bas)
|
||||||
|
*/
|
||||||
|
template <typename _Scalar = double, int _RowsAtCompile = Dynamic, int _ColsAtCompile = Dynamic, int _StorageType = ColumnStorage>
|
||||||
|
class Matrix : public MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile> {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
Matrix() : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
Matrix(const Matrix& other) : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>(other) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur avec spécification du nombre de ligne et de colonnes
|
||||||
|
*/
|
||||||
|
explicit Matrix(int _rows, int _cols) : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>(_rows, _cols) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~Matrix() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie à partir d'une sous-matrice.
|
||||||
|
*
|
||||||
|
* Exemple :
|
||||||
|
* Matrix<...> A(...);
|
||||||
|
* Matrix<...> B(...);
|
||||||
|
* B = A.block(i,j,m,n);
|
||||||
|
|
||||||
|
*/
|
||||||
|
template<typename _OtherScalar, int OtherRows, int _OtherCols, int _OtherStorage>
|
||||||
|
Matrix& operator= (const SubMatrix<_OtherScalar, OtherRows, _OtherCols, _OtherStorage>& submatrix)
|
||||||
|
{
|
||||||
|
// TODO copier les données de la sous-matrice.
|
||||||
|
// Note : si les dimensions ne correspondent pas, la matrice doit être redimensionnée.
|
||||||
|
// Vous pouvez présumer qu'il s'agit d'un stockage par colonnes.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur à une entrée de la matrice (lecture seule)
|
||||||
|
*/
|
||||||
|
_Scalar operator()(int i, int j) const
|
||||||
|
{
|
||||||
|
// TODO implementer
|
||||||
|
return (double)(i + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur à une entrée de la matrice (lecture ou écriture)
|
||||||
|
*/
|
||||||
|
_Scalar& operator()(int i, int j)
|
||||||
|
{
|
||||||
|
// TODO implementer
|
||||||
|
// Indice : l'implémentation est identique à celle de la fonction précédente.
|
||||||
|
_Scalar x = (double)(i + j);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une sous-matrice pour un block de taille (rows, cols) à partir de l'index (i,j).
|
||||||
|
*/
|
||||||
|
SubMatrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType> block(int i, int j, int rows, int cols) const
|
||||||
|
{
|
||||||
|
return SubMatrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>(*this, i, j, rows, cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcule l'inverse de la matrice
|
||||||
|
*/
|
||||||
|
Matrix inverse() const
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la transposée de la matrice
|
||||||
|
*/
|
||||||
|
template<typename _OtherScalar, int _OtherRows, int _OtherCols, int _OtherStorage>
|
||||||
|
Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const
|
||||||
|
{
|
||||||
|
// TODO calcule et retourne la transposée de la matrice.
|
||||||
|
|
||||||
|
return Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(); // pas bon, à changer
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affecte l'identité à la matrice
|
||||||
|
*/
|
||||||
|
inline void setIdentity()
|
||||||
|
{
|
||||||
|
// TODO affecter la valeur 0.0 partour, sauf sur la diagonale principale où c'est 1.0..
|
||||||
|
// Votre implémentation devrait aussi fonctionner pour des matrices qui ne sont pas carrées.
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe Matrix spécialisée pour un stockage par lignes
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _RowsAtCompile, int _ColsAtCompile>
|
||||||
|
class Matrix< _Scalar, _RowsAtCompile, _ColsAtCompile, RowStorage> : public MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
Matrix() : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
Matrix(const Matrix& other) : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>(other) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur avec spécification du nombre de ligne et de colonnes
|
||||||
|
*/
|
||||||
|
explicit Matrix(int rows, int cols) : MatrixBase<_Scalar, _RowsAtCompile, _ColsAtCompile>(rows, cols) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~Matrix() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie à partir d'une sous-matrice.
|
||||||
|
*
|
||||||
|
* Exemple :
|
||||||
|
* Matrix<...> A(...);
|
||||||
|
* Matrix<...> B(...);
|
||||||
|
* B = A.block(i,j,m,n);
|
||||||
|
*/
|
||||||
|
template<typename _OtherScalar, int OtherRows, int _OtherCols, int _OtherStorage>
|
||||||
|
Matrix& operator= (const SubMatrix<_OtherScalar, OtherRows, _OtherCols, _OtherStorage>& submatrix)
|
||||||
|
{
|
||||||
|
// TODO copier les données de la sous-matrice.
|
||||||
|
// Note : si les dimensions ne correspondent pas, la matrice doit être redimensionnée.
|
||||||
|
// Vous pouvez présumer qu'il s'agit d'un stockage par lignes.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur à une entrée de la matrice (lecture seule)
|
||||||
|
*/
|
||||||
|
_Scalar operator()(int i, int j) const
|
||||||
|
{
|
||||||
|
// TODO implementer
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur à une entrée de la matrice (lecture ou écriture)
|
||||||
|
*/
|
||||||
|
_Scalar& operator()(int i, int j)
|
||||||
|
{
|
||||||
|
// TODO implementer
|
||||||
|
_Scalar x = 0.0;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crée une sous-matrice pour un block de taille (rows, cols) à partir de l'index (i,j).
|
||||||
|
*/
|
||||||
|
SubMatrix<_Scalar, _RowsAtCompile, _ColsAtCompile, RowStorage> block(int i, int j, int rows, int cols) const {
|
||||||
|
return SubMatrix<_Scalar, _RowsAtCompile, _ColsAtCompile, RowStorage>(*this, i, j, rows, cols);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcule l'inverse de la matrice
|
||||||
|
*/
|
||||||
|
Matrix inverse() const
|
||||||
|
{
|
||||||
|
// Do nothing.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la transposée de la matrice
|
||||||
|
*/
|
||||||
|
Matrix<_Scalar, _ColsAtCompile, _RowsAtCompile, ColumnStorage> transpose() const
|
||||||
|
{
|
||||||
|
// TODO calcule et retourne la transposée de la matrice.
|
||||||
|
// Optimisez cette fonction en tenant compte du type de stockage utilisé.
|
||||||
|
|
||||||
|
return Matrix<_Scalar, _ColsAtCompile, _RowsAtCompile, ColumnStorage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affecte l'identité à la matrice
|
||||||
|
*/
|
||||||
|
inline void setIdentity()
|
||||||
|
{
|
||||||
|
// TODO affecter la valeur 0.0 partour, sauf sur la diagonale principale où c'est 1.0..
|
||||||
|
// Votre implémentation devrait aussi fonctionner pour des matrices qui ne sont pas carrées.
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe pour accéder à une sous-matrice.
|
||||||
|
*
|
||||||
|
* Un sous-matrice ne copie pas les données. Au lieu de cela, elle conserve une
|
||||||
|
* référence à la matrice originale.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _RowsAtCompile, int _ColsAtCompile, int _StorageType>
|
||||||
|
class SubMatrix
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// Référence à la matrice originale
|
||||||
|
Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>& m_matrix;
|
||||||
|
|
||||||
|
// Constructeur par défaut (privé)
|
||||||
|
SubMatrix() {}
|
||||||
|
|
||||||
|
// (i,j) est le coin supérieur gauche de la sous-matrice
|
||||||
|
int m_i; // Décalage en ligne
|
||||||
|
int m_j; // Décalage en colonne
|
||||||
|
|
||||||
|
// la sous-matrice est de dimension : m_rows x m_cols
|
||||||
|
int m_rows; // Hauteur de la sous-matrice (nombre de lignes)
|
||||||
|
int m_cols; // Largeur de la sous-matrice (nombre de colonnes)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur à partir d'une référence en lecture seule à une matrice.
|
||||||
|
*/
|
||||||
|
SubMatrix(const Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>& _matrix, int _i, int _j, int _rows, int _cols) :
|
||||||
|
m_matrix(const_cast<Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>&>(_matrix)),
|
||||||
|
m_i(_i), m_j(_j), m_rows(_rows), m_cols(_cols)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur à partir d'une référence en lecture et écriture à une matrice.
|
||||||
|
*/
|
||||||
|
explicit SubMatrix(Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, _StorageType>& _matrix, int _i, int _j, int _rows, int _cols) :
|
||||||
|
m_matrix(_matrix),
|
||||||
|
m_i(_i), m_j(_j), m_rows(_rows), m_cols(_cols)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
SubMatrix(const SubMatrix& other) :
|
||||||
|
m_matrix(other.m_matrix),
|
||||||
|
m_i(other.m_i), m_j(other.m_j), m_rows(other.m_rows), m_cols(other.m_cols)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~SubMatrix() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie (à partir d'une matrice)
|
||||||
|
*
|
||||||
|
* Copies toutes les entrées de la matrice dans la sous-matrice.
|
||||||
|
*
|
||||||
|
* Note : la taille de la matrice doit correspondre à la taille de la
|
||||||
|
* sous-matrice.
|
||||||
|
*/
|
||||||
|
template<typename _OtherScalar, int _OtherRows, int _OtherCols, int _OtherStorage>
|
||||||
|
SubMatrix& operator= (const Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>& matrix)
|
||||||
|
{
|
||||||
|
// TODO Cpopie les valeurs de la matrice dans la sous-matrice.
|
||||||
|
// Note les dimensions de la matrice doivent correspondre à celle de
|
||||||
|
// la sous-matrice.
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur aux entrées de la sous-matrice (lecture seule)
|
||||||
|
*
|
||||||
|
* Note : il faut s'assurer que les indices respectent la taille de la
|
||||||
|
* sous-matrice
|
||||||
|
*/
|
||||||
|
_Scalar operator()(int i, int j) const
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur aux entrées de la sous-matrice (lecture et écriture)
|
||||||
|
*
|
||||||
|
* Note : il faut s'assurer que les indices respectent la taille de la
|
||||||
|
* sous-matrice
|
||||||
|
*/
|
||||||
|
_Scalar& operator()(int i, int j)
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
_Scalar x = 0.0;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la transposée de la sous-matrice sous la forme d'une matrice.
|
||||||
|
*/
|
||||||
|
template<typename _OtherScalar, int _OtherRows, int _OtherCols, int _OtherStorage>
|
||||||
|
Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
return Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int rows() const { return m_rows; }
|
||||||
|
inline int cols() const { return m_cols; }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,357 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file MatrixBase.h
|
||||||
|
*
|
||||||
|
* @brief Classe contenant les éléments de base des matrices et des vecteurs.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "DenseStorage.h"
|
||||||
|
|
||||||
|
namespace gti320
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe de base pour les matrices et vecteurs à taille fixe.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _Rows, int _Cols>
|
||||||
|
class MatrixBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
DenseStorage<_Scalar, _Rows* _Cols> m_storage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef _Scalar Scalar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
MatrixBase() : m_storage() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
MatrixBase(const MatrixBase& other) : m_storage(other.m_storage) { }
|
||||||
|
|
||||||
|
explicit MatrixBase(int _rows, int _cols) : m_storage() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~MatrixBase() { }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redimensionne la matrice
|
||||||
|
*/
|
||||||
|
void resize(int _rows, int _cols)
|
||||||
|
{
|
||||||
|
// Ne rien faire.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie
|
||||||
|
*/
|
||||||
|
MatrixBase& operator=(const MatrixBase& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
m_storage = other.m_storage;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setZero() { m_storage.setZero(); }
|
||||||
|
static inline int cols() { return _Cols; }
|
||||||
|
static inline int rows() { return _Rows; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès à la donnée membre de stockage (en lecture seule)
|
||||||
|
*/
|
||||||
|
const DenseStorage<_Scalar, _Rows* _Cols>& storage() const
|
||||||
|
{
|
||||||
|
return m_storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nombre d'éléments stockés dans le tampon.
|
||||||
|
*/
|
||||||
|
inline int size() const
|
||||||
|
{
|
||||||
|
return m_storage.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès au tampon de données ((lecture seule))
|
||||||
|
*/
|
||||||
|
const _Scalar* data() const
|
||||||
|
{
|
||||||
|
return m_storage.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe de base pour les matrices avec un nombre de lignes dynamique et un
|
||||||
|
* nombre fixe de colonnes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _Cols>
|
||||||
|
class MatrixBase<_Scalar, Dynamic, _Cols>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
DenseStorage<_Scalar, Dynamic> m_storage;
|
||||||
|
int m_rows;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef _Scalar Scalar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
MatrixBase() : m_storage(), m_rows(0) { }
|
||||||
|
|
||||||
|
explicit MatrixBase(int _rows, int _cols) : m_storage(_rows* _Cols), m_rows(_rows) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
MatrixBase(const MatrixBase& other) : m_storage(other.m_storage), m_rows(other.m_rows) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~MatrixBase() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie
|
||||||
|
*/
|
||||||
|
MatrixBase& operator=(const MatrixBase& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
m_storage = other.m_storage;
|
||||||
|
m_rows = other.m_rows;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redimensionne la matrice
|
||||||
|
*/
|
||||||
|
void resize(int _rows, int _cols)
|
||||||
|
{
|
||||||
|
assert(_cols == _Cols);
|
||||||
|
m_storage.resize(_rows * _Cols);
|
||||||
|
m_rows = _rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setZero() { m_storage.setZero(); }
|
||||||
|
|
||||||
|
static inline int cols() { return _Cols; }
|
||||||
|
inline int rows() const { return m_rows; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès à la donnée membre de stockage (en lecture seule)
|
||||||
|
*/
|
||||||
|
const DenseStorage<_Scalar, Dynamic>& storage() const
|
||||||
|
{
|
||||||
|
return m_storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nombre d'éléments stockés dans le tampon.
|
||||||
|
*/
|
||||||
|
inline int size() const
|
||||||
|
{
|
||||||
|
return m_storage.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès au tampon de données ((lecture seule))
|
||||||
|
*/
|
||||||
|
const _Scalar* data() const
|
||||||
|
{
|
||||||
|
return m_storage.data();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe de base pour les matrices avec un nombre fixe de lignes et un
|
||||||
|
* nombre de colonnes dynamique.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _Rows>
|
||||||
|
class MatrixBase<_Scalar, _Rows, Dynamic>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
DenseStorage<_Scalar, Dynamic> m_storage;
|
||||||
|
int m_cols;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef _Scalar Scalar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
MatrixBase() : m_storage() { }
|
||||||
|
|
||||||
|
explicit MatrixBase(int _rows, int _cols) : m_storage(_rows* _cols), m_cols(_cols) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
MatrixBase(const MatrixBase& other) : m_storage(other.m_storage), m_cols(other.m_cols) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~MatrixBase() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie
|
||||||
|
*/
|
||||||
|
MatrixBase& operator=(const MatrixBase& other)
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
m_storage = other.m_storage;
|
||||||
|
m_cols = other.m_cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redimensionne la matrice
|
||||||
|
*/
|
||||||
|
void resize(int _rows, int _cols)
|
||||||
|
{
|
||||||
|
assert(_rows == _Rows);
|
||||||
|
m_storage.resize(_Rows * _cols);
|
||||||
|
m_cols = _cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setZero() { m_storage.setZero(); }
|
||||||
|
|
||||||
|
inline int cols() const { return m_cols; }
|
||||||
|
static inline int rows() { return _Rows; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès à la donnée membre de stockage (en lecture seule)
|
||||||
|
*/
|
||||||
|
const DenseStorage<_Scalar, Dynamic>& storage() const
|
||||||
|
{
|
||||||
|
return m_storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nombre d'éléments stockés dans le tampon.
|
||||||
|
*/
|
||||||
|
inline int size() const
|
||||||
|
{
|
||||||
|
return m_storage.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès au tampon de données ((lecture seule))
|
||||||
|
*/
|
||||||
|
const _Scalar* data() const
|
||||||
|
{
|
||||||
|
return m_storage.data();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe de base pour les matrices avec un nombre de lignes et de colonnes
|
||||||
|
* dynamiques.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar>
|
||||||
|
class MatrixBase<_Scalar, Dynamic, Dynamic>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
DenseStorage<_Scalar, Dynamic> m_storage;
|
||||||
|
int m_cols;
|
||||||
|
int m_rows;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef _Scalar Scalar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
MatrixBase() : m_storage(), m_rows(0), m_cols(0) { }
|
||||||
|
|
||||||
|
explicit MatrixBase(int _rows, int _cols) : m_storage(_rows* _cols), m_rows(_rows), m_cols(_cols) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
MatrixBase(const MatrixBase& other) : m_storage(other.m_storage), m_rows(other.m_rows), m_cols(other.m_cols) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~MatrixBase() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie
|
||||||
|
*/
|
||||||
|
MatrixBase& operator=(const MatrixBase& other)
|
||||||
|
{
|
||||||
|
if (this != &other)
|
||||||
|
{
|
||||||
|
resize(other.m_rows, other.m_cols);
|
||||||
|
m_storage = other.m_storage;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redimensionne la matrice
|
||||||
|
*/
|
||||||
|
void resize(int _rows, int _cols)
|
||||||
|
{
|
||||||
|
m_storage.resize(_rows * _cols);
|
||||||
|
m_rows = _rows;
|
||||||
|
m_cols = _cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setZero() { m_storage.setZero(); }
|
||||||
|
|
||||||
|
inline int cols() const { return m_cols; }
|
||||||
|
inline int rows() const { return m_rows; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès à la donnée membre de stockage (en lecture seule)
|
||||||
|
*/
|
||||||
|
const DenseStorage<_Scalar, Dynamic>& storage() const
|
||||||
|
{
|
||||||
|
return m_storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nombre d'éléments stockés dans le tampon.
|
||||||
|
*/
|
||||||
|
inline int size() const
|
||||||
|
{
|
||||||
|
return m_storage.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accès au tampon de données ((lecture seule))
|
||||||
|
*/
|
||||||
|
const _Scalar* data() const
|
||||||
|
{
|
||||||
|
return m_storage.data();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file Operators.h
|
||||||
|
*
|
||||||
|
* @brief Opérateurs arithmétiques pour les matrices et les vecteurs.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Matrix.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implémentation de divers opérateurs arithmétiques pour les matrices et les vecteurs.
|
||||||
|
*/
|
||||||
|
namespace gti320 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication : Matrice * Matrice (générique)
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int RowsA, int ColsA, int StorageA, int RowsB, int ColsB, int StorageB>
|
||||||
|
Matrix<_Scalar, RowsA, ColsB> operator*(const Matrix<_Scalar, RowsA, ColsA, StorageA>& A, const Matrix<_Scalar, RowsB, ColsB, StorageB>& B)
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
return Matrix<_Scalar, RowsA, ColsB>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication : Matrice (colonne) * Matrice (ligne)
|
||||||
|
*
|
||||||
|
* Spécialisation de l'opérateur de multiplication pour le cas où les matrices
|
||||||
|
* ont un stockage à taille dynamique et où la matrice de gauche utilise un
|
||||||
|
* stockage par colonnes et celle de droite un stockage par lignes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar>
|
||||||
|
Matrix<_Scalar, Dynamic, Dynamic> operator*(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, RowStorage>& B)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix<_Scalar, Dynamic, Dynamic>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication : Matrice (ligne) * Matrice (colonne)
|
||||||
|
*
|
||||||
|
* Spécialisation de l'opérateur de multiplication pour le cas où les matrices
|
||||||
|
* ont un stockage à taille dynamique et où la matrice de gauche utilise un
|
||||||
|
* stockage par lignes et celle de droite un stockage par colonnes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar>
|
||||||
|
Matrix<_Scalar, Dynamic, Dynamic> operator*(const Matrix<_Scalar, Dynamic, Dynamic, RowStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& B)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix<_Scalar, Dynamic, Dynamic>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addition : Matrice + Matrice (générique)
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int Rows, int Cols, int StorageA, int StorageB>
|
||||||
|
Matrix<_Scalar, Rows, Cols> operator+(const Matrix<_Scalar, Rows, Cols, StorageA>& A, const Matrix<_Scalar, Rows, Cols, StorageB>& B)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix<_Scalar, Rows, Cols>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addition : Matrice (colonne) + Matrice (colonne)
|
||||||
|
*
|
||||||
|
* Spécialisation de l'opérateur d'addition pour le cas où les deux matrices
|
||||||
|
* sont stockées par colonnes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar>
|
||||||
|
Matrix<_Scalar, Dynamic, Dynamic> operator+(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& B)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix<_Scalar, Dynamic, Dynamic>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addition : Matrice (ligne) + Matrice (ligne)
|
||||||
|
*
|
||||||
|
* Spécialisation de l'opérateur d'addition pour le cas où les deux matrices
|
||||||
|
* sont stockées par lignes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar>
|
||||||
|
Matrix<_Scalar, Dynamic, Dynamic, RowStorage> operator+(const Matrix<_Scalar, Dynamic, Dynamic, RowStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, RowStorage>& B)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix<_Scalar, Dynamic, Dynamic, RowStorage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication : Scalaire * Matrice (colonne)
|
||||||
|
*
|
||||||
|
* Spécialisation de l'opérateur de multiplication par un scalaire pour le
|
||||||
|
* cas d'une matrice stockée par colonnes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _Rows, int _Cols>
|
||||||
|
Matrix<_Scalar, _Rows, _Cols, ColumnStorage> operator*(const _Scalar& a, const Matrix<_Scalar, _Rows, _Cols, ColumnStorage>& A)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix<_Scalar, Dynamic, Dynamic>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication : Scalaire * Matrice (ligne)
|
||||||
|
*
|
||||||
|
* Spécialisation de l'opérateur de multiplication par un scalaire pour le
|
||||||
|
* cas d'une matrice stockée par lignes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _Rows, int _Cols>
|
||||||
|
Matrix<_Scalar, _Rows, _Cols, RowStorage> operator*(const _Scalar& a, const Matrix<_Scalar, _Rows, _Cols, RowStorage>& A)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Matrix<_Scalar, Dynamic, Dynamic, RowStorage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication : Matrice (ligne) * Vecteur
|
||||||
|
*
|
||||||
|
* Spécialisation de l'opérateur de multiplication matrice*vecteur pour le
|
||||||
|
* cas où la matrice est représentée par lignes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _Rows, int _Cols>
|
||||||
|
Vector<_Scalar, _Rows> operator*(const Matrix<_Scalar, _Rows, _Cols, RowStorage>& A, const Vector<_Scalar, _Cols>& v)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Vector<_Scalar, _Rows>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication : Matrice (colonne) * Vecteur
|
||||||
|
*
|
||||||
|
* Spécialisation de l'opérateur de multiplication matrice*vecteur pour le
|
||||||
|
* cas où la matrice est représentée par colonnes.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _Rows, int _Cols>
|
||||||
|
Vector<_Scalar, _Rows> operator*(const Matrix<_Scalar, _Rows, _Cols, ColumnStorage>& A, const Vector<_Scalar, _Cols>& v)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Vector<_Scalar, _Rows>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication : Scalaire * Vecteur
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _Rows>
|
||||||
|
Vector<_Scalar, _Rows> operator*(const _Scalar& a, const Vector<_Scalar, _Rows>& v)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Vector<_Scalar, _Rows>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addition : Vecteur + Vecteur
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _RowsA, int _RowsB>
|
||||||
|
Vector<_Scalar, _RowsA> operator+(const Vector<_Scalar, _RowsA>& a, const Vector<_Scalar, _RowsB>& b)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Vector<_Scalar, _RowsA>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Soustraction : Vecteur - Vecteur
|
||||||
|
*/
|
||||||
|
template <typename _Scalar, int _RowsA, int _RowsB>
|
||||||
|
Vector<_Scalar, _RowsA> operator-(const Vector<_Scalar, _RowsA>& a, const Vector<_Scalar, _RowsB>& b)
|
||||||
|
{
|
||||||
|
// TODO : implémenter
|
||||||
|
return Vector<_Scalar, _RowsA>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,104 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file Vector.h
|
||||||
|
*
|
||||||
|
* @brief Implémentation de vecteurs simples
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include "MatrixBase.h"
|
||||||
|
|
||||||
|
namespace gti320 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe vecteur générique.
|
||||||
|
*
|
||||||
|
* Cette classe réutilise la classe `MatrixBase` et ses spécialisations de
|
||||||
|
* templates pour les manipulation bas niveau.
|
||||||
|
*/
|
||||||
|
template <typename _Scalar = double, int _Rows = Dynamic>
|
||||||
|
class Vector : public MatrixBase<_Scalar, _Rows, 1> {
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur par défaut
|
||||||
|
*/
|
||||||
|
Vector() : MatrixBase<_Scalar, _Rows, 1>() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contructeur à partir d'un taille (rows).
|
||||||
|
*/
|
||||||
|
explicit Vector(int rows) : MatrixBase<_Scalar, _Rows, 1>(rows, 1) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur de copie
|
||||||
|
*/
|
||||||
|
Vector(const Vector& other) : MatrixBase<_Scalar, _Rows, 1>(other) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur
|
||||||
|
*/
|
||||||
|
~Vector() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateur de copie
|
||||||
|
*/
|
||||||
|
Vector& operator=(const Vector& other)
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
this->m_storage = other.m_storage;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur à une entrée du vecteur (lecture seule)
|
||||||
|
*/
|
||||||
|
_Scalar operator()(int i) const
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
return (double)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accesseur à une entrée du vecteur (lecture et écriture)
|
||||||
|
*/
|
||||||
|
_Scalar& operator()(int i)
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
_Scalar x = (double)i;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifie le nombre de lignes du vecteur
|
||||||
|
*/
|
||||||
|
void resize(int _rows)
|
||||||
|
{
|
||||||
|
MatrixBase<_Scalar, _Rows, 1>::resize(_rows, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produit scalaire de *this et other.
|
||||||
|
*/
|
||||||
|
inline _Scalar dot(const Vector& other) const
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne la norme euclidienne du vecteur
|
||||||
|
*/
|
||||||
|
inline _Scalar norm() const
|
||||||
|
{
|
||||||
|
// TODO implémenter
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,398 @@
|
||||||
|
/**
|
||||||
|
* @file Tests1a.cpp
|
||||||
|
*
|
||||||
|
* @brief Tests unitaires de la partie 1b
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Matrix.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
using namespace gti320;
|
||||||
|
|
||||||
|
TEST(TestLabo1a, DotAndNorm) {
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 81.74804972455644; u(1) = -74.09304417781078; u(2) = -91.38202093790602;
|
||||||
|
Vector<double,3> v; v(0) = 81.1462118959985; v(1) = 29.763442976156085; v(2) = 39.00787276684184;
|
||||||
|
EXPECT_NEAR(u.dot(v), 863.662223794679, 1e-4) << "(u=(81.74804972455644, -74.09304417781078, -91.38202093790602), v= (81.1462118959985, 29.763442976156085, 39.00787276684184))";
|
||||||
|
EXPECT_NEAR(u.norm(), 143.25919370148452, 1e-4) << "(u=(81.74804972455644, -74.09304417781078, -91.38202093790602))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 94.82712892764025, 1e-4) << "u=(81.74804972455644, -74.09304417781078, -91.38202093790602)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 13.087936541928485; u(1) = -26.541934227528046; u(2) = -48.13859302157102;
|
||||||
|
Vector<double,3> v; v(0) = -66.28108277028942; v(1) = 11.919000480625243; v(2) = -96.21367167640467;
|
||||||
|
EXPECT_NEAR(u.dot(v), 3447.7548518990116, 1e-4) << "(u=(13.087936541928485, -26.541934227528046, -48.13859302157102), v= (-66.28108277028942, 11.919000480625243, -96.21367167640467))";
|
||||||
|
EXPECT_NEAR(u.norm(), 56.50745520336602, 1e-4) << "(u=(13.087936541928485, -26.541934227528046, -48.13859302157102))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 117.44068768154457, 1e-4) << "u=(13.087936541928485, -26.541934227528046, -48.13859302157102)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = -79.56972852806103; u(1) = -64.04761691711548; u(2) = 75.76398532227091;
|
||||||
|
Vector<double,3> v; v(0) = 68.1521534060019; v(1) = -38.02548546805114; v(2) = 44.66242384133133;
|
||||||
|
EXPECT_NEAR(u.dot(v), 396.3966055984092, 1e-4) << "(u=(-79.56972852806103, -64.04761691711548, 75.76398532227091), v= (68.1521534060019, -38.02548546805114, 44.66242384133133))";
|
||||||
|
EXPECT_NEAR(u.norm(), 127.17554954748255, 1e-4) << "(u=(-79.56972852806103, -64.04761691711548, 75.76398532227091))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 89.91877258025103, 1e-4) << "u=(-79.56972852806103, -64.04761691711548, 75.76398532227091)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = -27.829925590795995; u(1) = 97.52374799957443; u(2) = -71.29949583706774;
|
||||||
|
Vector<double,3> v; v(0) = 15.413123773966177; v(1) = -25.9678191712148; v(2) = -70.46329734352945;
|
||||||
|
EXPECT_NEAR(u.dot(v), 2062.5724349077673, 1e-4) << "(u=(-27.829925590795995, 97.52374799957443, -71.29949583706774), v= (15.413123773966177, -25.9678191712148, -70.46329734352945))";
|
||||||
|
EXPECT_NEAR(u.norm(), 123.97178827819569, 1e-4) << "(u=(-27.829925590795995, 97.52374799957443, -71.29949583706774))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 76.66138721353245, 1e-4) << "u=(-27.829925590795995, 97.52374799957443, -71.29949583706774)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 46.94969707999718; u(1) = 92.7292896206543; u(2) = 61.3890905084975;
|
||||||
|
Vector<double,3> v; v(0) = 91.40236621394195; v(1) = -23.911909695536067; v(2) = -66.18706904017846;
|
||||||
|
EXPECT_NEAR(u.dot(v), -1989.1849652004407, 1e-4) << "(u=(46.94969707999718, 92.7292896206543, 61.3890905084975), v= (91.40236621394195, -23.911909695536067, -66.18706904017846))";
|
||||||
|
EXPECT_NEAR(u.norm(), 120.71294728783312, 1e-4) << "(u=(46.94969707999718, 92.7292896206543, 61.3890905084975))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 115.3555377211011, 1e-4) << "u=(46.94969707999718, 92.7292896206543, 61.3890905084975)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 9.836648455487577; u(1) = 27.373779624683323; u(2) = 33.47163213808042;
|
||||||
|
Vector<double,3> v; v(0) = -17.904556153169437; v(1) = -10.39159035574184; v(2) = 36.045191146582226;
|
||||||
|
EXPECT_NEAR(u.dot(v), 745.913449426867, 1e-4) << "(u=(9.836648455487577, 27.373779624683323, 33.47163213808042), v= (-17.904556153169437, -10.39159035574184, 36.045191146582226))";
|
||||||
|
EXPECT_NEAR(u.norm(), 44.344488065198725, 1e-4) << "(u=(9.836648455487577, 27.373779624683323, 33.47163213808042))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 41.566983123113395, 1e-4) << "u=(9.836648455487577, 27.373779624683323, 33.47163213808042)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 77.34524968701723; u(1) = -86.53838659054598; u(2) = 52.511893628372974;
|
||||||
|
Vector<double,3> v; v(0) = 39.390038592378005; v(1) = -53.13512176642368; v(2) = 60.23922457130902;
|
||||||
|
EXPECT_NEAR(u.dot(v), 10808.13583201148, 1e-4) << "(u=(77.34524968701723, -86.53838659054598, 52.511893628372974), v= (39.390038592378005, -53.13512176642368, 60.23922457130902))";
|
||||||
|
EXPECT_NEAR(u.norm(), 127.39183245121873, 1e-4) << "(u=(77.34524968701723, -86.53838659054598, 52.511893628372974))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 89.4632912562147, 1e-4) << "u=(77.34524968701723, -86.53838659054598, 52.511893628372974)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 72.58764125601218; u(1) = 13.004884623782146; u(2) = 6.688195585248067;
|
||||||
|
Vector<double,3> v; v(0) = -41.68110389567836; v(1) = 65.83906651972734; v(2) = 64.45916748876758;
|
||||||
|
EXPECT_NEAR(u.dot(v), -1738.1880334803595, 1e-4) << "(u=(72.58764125601218, 13.004884623782146, 6.688195585248067), v= (-41.68110389567836, 65.83906651972734, 64.45916748876758))";
|
||||||
|
EXPECT_NEAR(u.norm(), 74.04609812391155, 1e-4) << "(u=(72.58764125601218, 13.004884623782146, 6.688195585248067))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 101.12903329655835, 1e-4) << "u=(72.58764125601218, 13.004884623782146, 6.688195585248067)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 44.123038783178856; u(1) = 59.032307289173275; u(2) = -96.45920641599031;
|
||||||
|
Vector<double,3> v; v(0) = -23.433056105942327; v(1) = -95.82287577132844; v(2) = -87.71884659805113;
|
||||||
|
EXPECT_NEAR(u.dot(v), 1770.7072393377675, 1e-4) << "(u=(44.123038783178856, 59.032307289173275, -96.45920641599031), v= (-23.433056105942327, -95.82287577132844, -87.71884659805113))";
|
||||||
|
EXPECT_NEAR(u.norm(), 121.39206875965131, 1e-4) << "(u=(44.123038783178856, 59.032307289173275, -96.45920641599031))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 132.006544110677, 1e-4) << "u=(44.123038783178856, 59.032307289173275, -96.45920641599031)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = -7.594864170286073; u(1) = -92.12702535387345; u(2) = 10.61833019724412;
|
||||||
|
Vector<double,3> v; v(0) = -57.88532008253067; v(1) = -61.95047768934079; v(2) = -50.9801175870505;
|
||||||
|
EXPECT_NEAR(u.dot(v), 5605.620650217189, 1e-4) << "(u=(-7.594864170286073, -92.12702535387345, 10.61833019724412), v= (-57.88532008253067, -61.95047768934079, -50.9801175870505))";
|
||||||
|
EXPECT_NEAR(u.norm(), 93.04740565161417, 1e-4) << "(u=(-7.594864170286073, -92.12702535387345, 10.61833019724412))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 98.9320188623685, 1e-4) << "u=(-7.594864170286073, -92.12702535387345, 10.61833019724412)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 28.01623276831728; u(1) = -35.47111447521442; u(2) = -80.09707278049716;
|
||||||
|
Vector<double,3> v; v(0) = 62.23810927998369; v(1) = -69.45561657190204; v(2) = -17.998932897185853;
|
||||||
|
EXPECT_NEAR(u.dot(v), 5649.007321253708, 1e-4) << "(u=(28.01623276831728, -35.47111447521442, -80.09707278049716), v= (62.23810927998369, -69.45561657190204, -17.998932897185853))";
|
||||||
|
EXPECT_NEAR(u.norm(), 91.97092110361056, 1e-4) << "(u=(28.01623276831728, -35.47111447521442, -80.09707278049716))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 94.98224310663369, 1e-4) << "u=(28.01623276831728, -35.47111447521442, -80.09707278049716)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 17.056114318144637; u(1) = -47.87236586884536; u(2) = -66.233990996889;
|
||||||
|
Vector<double,3> v; v(0) = -16.5274983107699; v(1) = -61.98159750757431; v(2) = -95.73085862430288;
|
||||||
|
EXPECT_NEAR(u.dot(v), 9025.947640683207, 1e-4) << "(u=(17.056114318144637, -47.87236586884536, -66.233990996889), v= (-16.5274983107699, -61.98159750757431, -95.73085862430288))";
|
||||||
|
EXPECT_NEAR(u.norm(), 83.48422613218729, 1e-4) << "(u=(17.056114318144637, -47.87236586884536, -66.233990996889))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 115.23573197124973, 1e-4) << "u=(17.056114318144637, -47.87236586884536, -66.233990996889)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 53.68514451573557; u(1) = 40.487633535881685; u(2) = -34.39102876903675;
|
||||||
|
Vector<double,3> v; v(0) = 5.723467714467617; v(1) = -11.984939376053532; v(2) = 71.57117734380691;
|
||||||
|
EXPECT_NEAR(u.dot(v), -2639.3830610897676, 1e-4) << "(u=(53.68514451573557, 40.487633535881685, -34.39102876903675), v= (5.723467714467617, -11.984939376053532, 71.57117734380691))";
|
||||||
|
EXPECT_NEAR(u.norm(), 75.52540016977055, 1e-4) << "(u=(53.68514451573557, 40.487633535881685, -34.39102876903675))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 72.79306478576713, 1e-4) << "u=(53.68514451573557, 40.487633535881685, -34.39102876903675)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = -19.41880304735801; u(1) = 80.15388147841654; u(2) = 18.762371448279836;
|
||||||
|
Vector<double,3> v; v(0) = 56.544323419883455; v(1) = 37.75922627098413; v(2) = -45.767718603712495;
|
||||||
|
EXPECT_NEAR(u.dot(v), 1069.8145305211428, 1e-4) << "(u=(-19.41880304735801, 80.15388147841654, 18.762371448279836), v= (56.544323419883455, 37.75922627098413, -45.767718603712495))";
|
||||||
|
EXPECT_NEAR(u.norm(), 84.57991020455952, 1e-4) << "(u=(-19.41880304735801, 80.15388147841654, 18.762371448279836))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 81.96159921441485, 1e-4) << "u=(-19.41880304735801, 80.15388147841654, 18.762371448279836)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 14.53101118226931; u(1) = -87.12123268098249; u(2) = -12.733552633138217;
|
||||||
|
Vector<double,3> v; v(0) = -96.36370344463752; v(1) = -81.8797705320039; v(2) = -25.593956628649764;
|
||||||
|
EXPECT_NEAR(u.dot(v), 6059.106481886422, 1e-4) << "(u=(14.53101118226931, -87.12123268098249, -12.733552633138217), v= (-96.36370344463752, -81.8797705320039, -25.593956628649764))";
|
||||||
|
EXPECT_NEAR(u.norm(), 89.23790020217884, 1e-4) << "(u=(14.53101118226931, -87.12123268098249, -12.733552633138217))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 129.01670736710366, 1e-4) << "u=(14.53101118226931, -87.12123268098249, -12.733552633138217)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = -68.15128360202914; u(1) = -35.22142681790423; u(2) = -80.20820520692742;
|
||||||
|
Vector<double,3> v; v(0) = -71.59083714955358; v(1) = -22.11220916087268; v(2) = -41.412146034892785;
|
||||||
|
EXPECT_NEAR(u.dot(v), 8979.424909853704, 1e-4) << "(u=(-68.15128360202914, -35.22142681790423, -80.20820520692742), v= (-71.59083714955358, -22.11220916087268, -41.412146034892785))";
|
||||||
|
EXPECT_NEAR(u.norm(), 110.98874963801407, 1e-4) << "(u=(-68.15128360202914, -35.22142681790423, -80.20820520692742))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 85.61053438078382, 1e-4) << "u=(-68.15128360202914, -35.22142681790423, -80.20820520692742)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 32.15880264107108; u(1) = -27.044272757999167; u(2) = -21.93384224298498;
|
||||||
|
Vector<double,3> v; v(0) = 94.98651607465004; v(1) = 96.25601423462368; v(2) = -4.364871517549744;
|
||||||
|
EXPECT_NEAR(u.dot(v), 547.2171237254174, 1e-4) << "(u=(32.15880264107108, -27.044272757999167, -21.93384224298498), v= (94.98651607465004, 96.25601423462368, -4.364871517549744))";
|
||||||
|
EXPECT_NEAR(u.norm(), 47.399100327501664, 1e-4) << "(u=(32.15880264107108, -27.044272757999167, -21.93384224298498))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 135.3022934606082, 1e-4) << "u=(32.15880264107108, -27.044272757999167, -21.93384224298498)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = -38.55884639660741; u(1) = -32.44768663392304; u(2) = -86.51014461651837;
|
||||||
|
Vector<double,3> v; v(0) = -32.975270310868936; v(1) = -48.59524328395069; v(2) = -92.16520328196806;
|
||||||
|
EXPECT_NEAR(u.dot(v), 10821.51667331416, 1e-4) << "(u=(-38.55884639660741, -32.44768663392304, -86.51014461651837), v= (-32.975270310868936, -48.59524328395069, -92.16520328196806))";
|
||||||
|
EXPECT_NEAR(u.norm(), 100.1181408382185, 1e-4) << "(u=(-38.55884639660741, -32.44768663392304, -86.51014461651837))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 109.2853641523316, 1e-4) << "u=(-38.55884639660741, -32.44768663392304, -86.51014461651837)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = -93.94403064987613; u(1) = -22.806019440495206; u(2) = -6.186803379242534;
|
||||||
|
Vector<double,3> v; v(0) = 99.58719003758503; v(1) = 11.426147026760503; v(2) = 89.17338366240898;
|
||||||
|
EXPECT_NEAR(u.dot(v), -10167.905155829267, 1e-4) << "(u=(-93.94403064987613, -22.806019440495206, -6.186803379242534), v= (99.58719003758503, 11.426147026760503, 89.17338366240898))";
|
||||||
|
EXPECT_NEAR(u.norm(), 96.87038739221866, 1e-4) << "(u=(-93.94403064987613, -22.806019440495206, -6.186803379242534))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 134.1642933468604, 1e-4) << "u=(-93.94403064987613, -22.806019440495206, -6.186803379242534)";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double,3> u; u(0) = 49.70172009239852; u(1) = 35.23095832735339; u(2) = -95.645812626239;
|
||||||
|
Vector<double,3> v; v(0) = -26.17330847186834; v(1) = -13.328976428902024; v(2) = 43.288466758804674;
|
||||||
|
EXPECT_NEAR(u.dot(v), -5910.811645163534, 1e-4) << "(u=(49.70172009239852, 35.23095832735339, -95.645812626239), v= (-26.17330847186834, -13.328976428902024, 43.288466758804674))";
|
||||||
|
EXPECT_NEAR(u.norm(), 113.40018905513546, 1e-4) << "(u=(49.70172009239852, 35.23095832735339, -95.645812626239))";
|
||||||
|
u = v;
|
||||||
|
EXPECT_NEAR(u.norm(), 52.31247502588592, 1e-4) << "u=(49.70172009239852, 35.23095832735339, -95.645812626239)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test les matrice avec redimensionnement dynamique
|
||||||
|
TEST(TestLabo1a, StaticMatrixTests)
|
||||||
|
{
|
||||||
|
// Crée une matrice ŕ taille fixe
|
||||||
|
Matrix<double, 3, 5> M;
|
||||||
|
EXPECT_EQ(M.cols(), 5);
|
||||||
|
EXPECT_EQ(M.rows(), 3);
|
||||||
|
|
||||||
|
// Redimensionne la matrice (la taille ne doit pas changer).
|
||||||
|
M.resize(100, 1000);
|
||||||
|
EXPECT_EQ(M.cols(), 5);
|
||||||
|
EXPECT_EQ(M.rows(), 3);
|
||||||
|
|
||||||
|
// Test - stockage par colonnes
|
||||||
|
Matrix<double, 100, 99, ColumnStorage> ColM;
|
||||||
|
ColM.setZero();
|
||||||
|
ColM(0, 0) = 1.0;
|
||||||
|
ColM(90, 17) = 99.0;
|
||||||
|
ColM(10, 33) = 7.2;
|
||||||
|
EXPECT_EQ(ColM(0, 0), 1.0);
|
||||||
|
EXPECT_EQ(ColM(90, 17), 99.0);
|
||||||
|
EXPECT_EQ(ColM(10, 33), 7.2);
|
||||||
|
|
||||||
|
// Test - stockage par lignes
|
||||||
|
Matrix<double, 5, 4, RowStorage> RowM;
|
||||||
|
RowM.setZero();
|
||||||
|
RowM(0, 0) = 2.1;
|
||||||
|
RowM(3, 3) = -0.2;
|
||||||
|
RowM(4, 3) = 1.2;
|
||||||
|
EXPECT_EQ(RowM.rows(), 5);
|
||||||
|
EXPECT_EQ(RowM.cols(), 4);
|
||||||
|
EXPECT_DOUBLE_EQ(RowM(0, 0), 2.1);
|
||||||
|
EXPECT_DOUBLE_EQ(RowM(3, 3), -0.2);
|
||||||
|
EXPECT_DOUBLE_EQ(RowM(4, 3), 1.2);
|
||||||
|
EXPECT_DOUBLE_EQ(RowM(3, 2), 0.0);
|
||||||
|
|
||||||
|
// Transposée
|
||||||
|
const auto RowMT = RowM.transpose();
|
||||||
|
EXPECT_EQ(RowMT.rows(), 4);
|
||||||
|
EXPECT_EQ(RowMT.cols(), 5);
|
||||||
|
EXPECT_DOUBLE_EQ(RowMT(0, 0), 2.1);
|
||||||
|
EXPECT_DOUBLE_EQ(RowMT(3, 3), -0.2);
|
||||||
|
EXPECT_DOUBLE_EQ(RowMT(3, 4), 1.2);
|
||||||
|
EXPECT_DOUBLE_EQ(RowMT(2, 3), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Test les matrice avec redimensionnement dynamique
|
||||||
|
TEST(TestLabo1a, DynamicMatrixTests)
|
||||||
|
{
|
||||||
|
// Crée une matrice ŕ taille dynamique
|
||||||
|
// (note : les valeurs par défaut du patron de la classe `Matrix` mettent le
|
||||||
|
// le nombre de ligne et de colonnes ŕ `Dynamic`)
|
||||||
|
Matrix<double> M(3, 5);
|
||||||
|
EXPECT_EQ(M.cols(), 5);
|
||||||
|
EXPECT_EQ(M.rows(), 3);
|
||||||
|
|
||||||
|
// Redimensionne la matrice
|
||||||
|
M.resize(100, 1000);
|
||||||
|
EXPECT_EQ(M.cols(), 1000);
|
||||||
|
EXPECT_EQ(M.rows(), 100);
|
||||||
|
|
||||||
|
// Test - stockage par colonnes
|
||||||
|
Matrix<double, Dynamic, Dynamic, ColumnStorage> ColM(100, 100);
|
||||||
|
ColM.setZero();
|
||||||
|
ColM(0, 0) = 1.0;
|
||||||
|
ColM(99, 99) = 99.0;
|
||||||
|
ColM(10, 33) = 5.0;
|
||||||
|
EXPECT_EQ(ColM(0, 0), 1.0);
|
||||||
|
EXPECT_EQ(ColM(10, 33), 5.0);
|
||||||
|
EXPECT_EQ(ColM(99, 99), 99.0);
|
||||||
|
|
||||||
|
// Test - stockage par lignes
|
||||||
|
Matrix<double, Dynamic, Dynamic, RowStorage> RowM(5, 4);
|
||||||
|
RowM.setZero();
|
||||||
|
RowM(0, 0) = 2.1;
|
||||||
|
RowM(3, 3) = -0.2;
|
||||||
|
RowM(4, 3) = 1.2;
|
||||||
|
EXPECT_EQ(RowM.rows(), 5);
|
||||||
|
EXPECT_EQ(RowM.cols(), 4);
|
||||||
|
EXPECT_DOUBLE_EQ(RowM(0, 0), 2.1);
|
||||||
|
EXPECT_DOUBLE_EQ(RowM(3, 3), -0.2);
|
||||||
|
EXPECT_DOUBLE_EQ(RowM(4, 3), 1.2);
|
||||||
|
EXPECT_DOUBLE_EQ(RowM(3, 2), 0.0);
|
||||||
|
|
||||||
|
// Transposée
|
||||||
|
const auto RowMT = RowM.transpose();
|
||||||
|
EXPECT_EQ(RowMT.rows(), 4);
|
||||||
|
EXPECT_EQ(RowMT.cols(), 5);
|
||||||
|
EXPECT_DOUBLE_EQ(RowMT(0, 0), 2.1);
|
||||||
|
EXPECT_DOUBLE_EQ(RowMT(3, 3), -0.2);
|
||||||
|
EXPECT_DOUBLE_EQ(RowMT(3, 4), 1.2);
|
||||||
|
EXPECT_DOUBLE_EQ(RowMT(2, 3), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test pour les vecteurs ŕ taille dynamique
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1a, DynamicVectorSizeTest)
|
||||||
|
{
|
||||||
|
Vector<double> v(5);
|
||||||
|
v.setZero();
|
||||||
|
|
||||||
|
EXPECT_EQ(v.rows(), 5);
|
||||||
|
|
||||||
|
v.resize(3);
|
||||||
|
EXPECT_EQ(v.rows(), 3);
|
||||||
|
|
||||||
|
v(0) = 1.0;
|
||||||
|
v(1) = 2.0;
|
||||||
|
v(2) = 3.0;
|
||||||
|
|
||||||
|
EXPECT_DOUBLE_EQ(v.norm(), 3.7416573867739413855837487323165);
|
||||||
|
|
||||||
|
Vector<double, Dynamic> v2(3);
|
||||||
|
v2.setZero();
|
||||||
|
v2(1) = 2.0;
|
||||||
|
|
||||||
|
EXPECT_DOUBLE_EQ(v2.dot(v), 4.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v2(0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v2(1), 2.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v2(2), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestLabo1a, Transpose) {
|
||||||
|
{
|
||||||
|
Matrix<double, 3, -1, ColumnStorage> m; m.resize(3, 2);
|
||||||
|
m(0, 0) = 96.65562704596559; m(0, 1) = -5.374125981819006; m(1, 0) = 64.81364389648456; m(1, 1) = -69.97868420900502; m(2, 0) = -48.298014749653696; m(2, 1) = 81.5535983882881;
|
||||||
|
Matrix<double, -1, 3, RowStorage> mtr = m.transpose<double, -1, 3, RowStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtr(0, 0), 96.65562704596559); EXPECT_DOUBLE_EQ(mtr(0, 1), 64.81364389648456); EXPECT_DOUBLE_EQ(mtr(0, 2), -48.298014749653696); EXPECT_DOUBLE_EQ(mtr(1, 0), -5.374125981819006); EXPECT_DOUBLE_EQ(mtr(1, 1), -69.97868420900502); EXPECT_DOUBLE_EQ(mtr(1, 2), 81.5535983882881);
|
||||||
|
Matrix<double, -1, 3, ColumnStorage> mtc = m.transpose<double, -1, 3, ColumnStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtc(0, 0), 96.65562704596559); EXPECT_DOUBLE_EQ(mtc(0, 1), 64.81364389648456); EXPECT_DOUBLE_EQ(mtc(0, 2), -48.298014749653696); EXPECT_DOUBLE_EQ(mtc(1, 0), -5.374125981819006); EXPECT_DOUBLE_EQ(mtc(1, 1), -69.97868420900502); EXPECT_DOUBLE_EQ(mtc(1, 2), 81.5535983882881);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 3, -1, ColumnStorage> m; m.resize(3, 11);
|
||||||
|
m(0, 0) = -93.11774348806081; m(0, 1) = -98.38480859022877; m(0, 2) = -70.06261616604155; m(0, 3) = 84.87535684986423; m(0, 4) = -99.9818642210925; m(0, 5) = -25.11185567441916; m(0, 6) = 8.85590979917103; m(0, 7) = 32.717509759851936; m(0, 8) = 12.677927494307738; m(0, 9) = -76.92757015087707; m(0, 10) = -80.99502606313347; m(1, 0) = -14.108330840223957; m(1, 1) = -94.81883611699344; m(1, 2) = -45.060719301725285; m(1, 3) = -41.383939879963094; m(1, 4) = 80.36741308691853; m(1, 5) = -87.50961508738959; m(1, 6) = -32.65290161505921; m(1, 7) = 18.529868291798238; m(1, 8) = -46.169755352790595; m(1, 9) = 83.67078184672366; m(1, 10) = -30.02053885691531; m(2, 0) = 5.8022044043901815; m(2, 1) = -39.507965223996266; m(2, 2) = 38.099939917456425; m(2, 3) = -11.891042873050296; m(2, 4) = 53.89070563872062; m(2, 5) = 23.280098882479578; m(2, 6) = -5.0318917624474295; m(2, 7) = 31.50255873280196; m(2, 8) = 22.629046207699318; m(2, 9) = 3.5102931218199416; m(2, 10) = -95.03021938861154;
|
||||||
|
Matrix<double, -1, 3, RowStorage> mtr = m.transpose<double, -1, 3, RowStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtr(0, 0), -93.11774348806081); EXPECT_DOUBLE_EQ(mtr(0, 1), -14.108330840223957); EXPECT_DOUBLE_EQ(mtr(0, 2), 5.8022044043901815); EXPECT_DOUBLE_EQ(mtr(1, 0), -98.38480859022877); EXPECT_DOUBLE_EQ(mtr(1, 1), -94.81883611699344); EXPECT_DOUBLE_EQ(mtr(1, 2), -39.507965223996266); EXPECT_DOUBLE_EQ(mtr(2, 0), -70.06261616604155); EXPECT_DOUBLE_EQ(mtr(2, 1), -45.060719301725285); EXPECT_DOUBLE_EQ(mtr(2, 2), 38.099939917456425); EXPECT_DOUBLE_EQ(mtr(3, 0), 84.87535684986423); EXPECT_DOUBLE_EQ(mtr(3, 1), -41.383939879963094); EXPECT_DOUBLE_EQ(mtr(3, 2), -11.891042873050296); EXPECT_DOUBLE_EQ(mtr(4, 0), -99.9818642210925); EXPECT_DOUBLE_EQ(mtr(4, 1), 80.36741308691853); EXPECT_DOUBLE_EQ(mtr(4, 2), 53.89070563872062); EXPECT_DOUBLE_EQ(mtr(5, 0), -25.11185567441916); EXPECT_DOUBLE_EQ(mtr(5, 1), -87.50961508738959); EXPECT_DOUBLE_EQ(mtr(5, 2), 23.280098882479578); EXPECT_DOUBLE_EQ(mtr(6, 0), 8.85590979917103); EXPECT_DOUBLE_EQ(mtr(6, 1), -32.65290161505921); EXPECT_DOUBLE_EQ(mtr(6, 2), -5.0318917624474295); EXPECT_DOUBLE_EQ(mtr(7, 0), 32.717509759851936); EXPECT_DOUBLE_EQ(mtr(7, 1), 18.529868291798238); EXPECT_DOUBLE_EQ(mtr(7, 2), 31.50255873280196); EXPECT_DOUBLE_EQ(mtr(8, 0), 12.677927494307738); EXPECT_DOUBLE_EQ(mtr(8, 1), -46.169755352790595); EXPECT_DOUBLE_EQ(mtr(8, 2), 22.629046207699318); EXPECT_DOUBLE_EQ(mtr(9, 0), -76.92757015087707); EXPECT_DOUBLE_EQ(mtr(9, 1), 83.67078184672366); EXPECT_DOUBLE_EQ(mtr(9, 2), 3.5102931218199416); EXPECT_DOUBLE_EQ(mtr(10, 0), -80.99502606313347); EXPECT_DOUBLE_EQ(mtr(10, 1), -30.02053885691531); EXPECT_DOUBLE_EQ(mtr(10, 2), -95.03021938861154);
|
||||||
|
Matrix<double, -1, 3, ColumnStorage> mtc = m.transpose<double, -1, 3, ColumnStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtc(0, 0), -93.11774348806081); EXPECT_DOUBLE_EQ(mtc(0, 1), -14.108330840223957); EXPECT_DOUBLE_EQ(mtc(0, 2), 5.8022044043901815); EXPECT_DOUBLE_EQ(mtc(1, 0), -98.38480859022877); EXPECT_DOUBLE_EQ(mtc(1, 1), -94.81883611699344); EXPECT_DOUBLE_EQ(mtc(1, 2), -39.507965223996266); EXPECT_DOUBLE_EQ(mtc(2, 0), -70.06261616604155); EXPECT_DOUBLE_EQ(mtc(2, 1), -45.060719301725285); EXPECT_DOUBLE_EQ(mtc(2, 2), 38.099939917456425); EXPECT_DOUBLE_EQ(mtc(3, 0), 84.87535684986423); EXPECT_DOUBLE_EQ(mtc(3, 1), -41.383939879963094); EXPECT_DOUBLE_EQ(mtc(3, 2), -11.891042873050296); EXPECT_DOUBLE_EQ(mtc(4, 0), -99.9818642210925); EXPECT_DOUBLE_EQ(mtc(4, 1), 80.36741308691853); EXPECT_DOUBLE_EQ(mtc(4, 2), 53.89070563872062); EXPECT_DOUBLE_EQ(mtc(5, 0), -25.11185567441916); EXPECT_DOUBLE_EQ(mtc(5, 1), -87.50961508738959); EXPECT_DOUBLE_EQ(mtc(5, 2), 23.280098882479578); EXPECT_DOUBLE_EQ(mtc(6, 0), 8.85590979917103); EXPECT_DOUBLE_EQ(mtc(6, 1), -32.65290161505921); EXPECT_DOUBLE_EQ(mtc(6, 2), -5.0318917624474295); EXPECT_DOUBLE_EQ(mtc(7, 0), 32.717509759851936); EXPECT_DOUBLE_EQ(mtc(7, 1), 18.529868291798238); EXPECT_DOUBLE_EQ(mtc(7, 2), 31.50255873280196); EXPECT_DOUBLE_EQ(mtc(8, 0), 12.677927494307738); EXPECT_DOUBLE_EQ(mtc(8, 1), -46.169755352790595); EXPECT_DOUBLE_EQ(mtc(8, 2), 22.629046207699318); EXPECT_DOUBLE_EQ(mtc(9, 0), -76.92757015087707); EXPECT_DOUBLE_EQ(mtc(9, 1), 83.67078184672366); EXPECT_DOUBLE_EQ(mtc(9, 2), 3.5102931218199416); EXPECT_DOUBLE_EQ(mtc(10, 0), -80.99502606313347); EXPECT_DOUBLE_EQ(mtc(10, 1), -30.02053885691531); EXPECT_DOUBLE_EQ(mtc(10, 2), -95.03021938861154);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 3, -1, ColumnStorage> m; m.resize(3, 19);
|
||||||
|
m(0, 0) = 50.864090811708934; m(0, 1) = 86.72545584739655; m(0, 2) = -59.41096188367827; m(0, 3) = -81.01855448213378; m(0, 4) = -44.75527142333435; m(0, 5) = 6.881484559867502; m(0, 6) = 75.66386662485408; m(0, 7) = -56.002568995946575; m(0, 8) = -44.600865729883445; m(0, 9) = -18.413408652944696; m(0, 10) = -97.11569037525811; m(0, 11) = 53.19666636708692; m(0, 12) = -64.58909530248837; m(0, 13) = -13.336152508799714; m(0, 14) = -69.12350514623267; m(0, 15) = 56.52730125536351; m(0, 16) = 89.92552663330136; m(0, 17) = 94.33106257780301; m(0, 18) = 76.55814809986282; m(1, 0) = 14.747374583026797; m(1, 1) = -12.087041962746213; m(1, 2) = -63.3966872965287; m(1, 3) = -11.386504830855642; m(1, 4) = -76.29669292020178; m(1, 5) = -66.38097797841678; m(1, 6) = -20.191218640024687; m(1, 7) = -48.05245125934678; m(1, 8) = -83.87380388512868; m(1, 9) = -21.25569067138788; m(1, 10) = 4.889708648539596; m(1, 11) = -85.80217867074691; m(1, 12) = -85.26796006798745; m(1, 13) = 3.8169098134350605; m(1, 14) = 73.4920467291056; m(1, 15) = 98.24187210950205; m(1, 16) = -9.878913280704495; m(1, 17) = -63.027946780158196; m(1, 18) = 55.64310458734482; m(2, 0) = -75.20410363410058; m(2, 1) = 45.30781974344674; m(2, 2) = -43.85391331821933; m(2, 3) = 67.45134132003074; m(2, 4) = 55.35009554124747; m(2, 5) = -24.1599830304106; m(2, 6) = 89.85022708733555; m(2, 7) = 63.770995127367826; m(2, 8) = -7.388429976036122; m(2, 9) = 8.073425560498507; m(2, 10) = 76.76129649290999; m(2, 11) = -50.19697292034915; m(2, 12) = -25.310526646715076; m(2, 13) = 14.496228473119118; m(2, 14) = 46.35572803496012; m(2, 15) = -43.2905212948518; m(2, 16) = 72.28250601709692; m(2, 17) = 59.72857548888601; m(2, 18) = 39.776820197984875;
|
||||||
|
Matrix<double, -1, 3, RowStorage> mtr = m.transpose<double, -1, 3, RowStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtr(0, 0), 50.864090811708934); EXPECT_DOUBLE_EQ(mtr(0, 1), 14.747374583026797); EXPECT_DOUBLE_EQ(mtr(0, 2), -75.20410363410058); EXPECT_DOUBLE_EQ(mtr(1, 0), 86.72545584739655); EXPECT_DOUBLE_EQ(mtr(1, 1), -12.087041962746213); EXPECT_DOUBLE_EQ(mtr(1, 2), 45.30781974344674); EXPECT_DOUBLE_EQ(mtr(2, 0), -59.41096188367827); EXPECT_DOUBLE_EQ(mtr(2, 1), -63.3966872965287); EXPECT_DOUBLE_EQ(mtr(2, 2), -43.85391331821933); EXPECT_DOUBLE_EQ(mtr(3, 0), -81.01855448213378); EXPECT_DOUBLE_EQ(mtr(3, 1), -11.386504830855642); EXPECT_DOUBLE_EQ(mtr(3, 2), 67.45134132003074); EXPECT_DOUBLE_EQ(mtr(4, 0), -44.75527142333435); EXPECT_DOUBLE_EQ(mtr(4, 1), -76.29669292020178); EXPECT_DOUBLE_EQ(mtr(4, 2), 55.35009554124747); EXPECT_DOUBLE_EQ(mtr(5, 0), 6.881484559867502); EXPECT_DOUBLE_EQ(mtr(5, 1), -66.38097797841678); EXPECT_DOUBLE_EQ(mtr(5, 2), -24.1599830304106); EXPECT_DOUBLE_EQ(mtr(6, 0), 75.66386662485408); EXPECT_DOUBLE_EQ(mtr(6, 1), -20.191218640024687); EXPECT_DOUBLE_EQ(mtr(6, 2), 89.85022708733555); EXPECT_DOUBLE_EQ(mtr(7, 0), -56.002568995946575); EXPECT_DOUBLE_EQ(mtr(7, 1), -48.05245125934678); EXPECT_DOUBLE_EQ(mtr(7, 2), 63.770995127367826); EXPECT_DOUBLE_EQ(mtr(8, 0), -44.600865729883445); EXPECT_DOUBLE_EQ(mtr(8, 1), -83.87380388512868); EXPECT_DOUBLE_EQ(mtr(8, 2), -7.388429976036122); EXPECT_DOUBLE_EQ(mtr(9, 0), -18.413408652944696); EXPECT_DOUBLE_EQ(mtr(9, 1), -21.25569067138788); EXPECT_DOUBLE_EQ(mtr(9, 2), 8.073425560498507); EXPECT_DOUBLE_EQ(mtr(10, 0), -97.11569037525811); EXPECT_DOUBLE_EQ(mtr(10, 1), 4.889708648539596); EXPECT_DOUBLE_EQ(mtr(10, 2), 76.76129649290999); EXPECT_DOUBLE_EQ(mtr(11, 0), 53.19666636708692); EXPECT_DOUBLE_EQ(mtr(11, 1), -85.80217867074691); EXPECT_DOUBLE_EQ(mtr(11, 2), -50.19697292034915); EXPECT_DOUBLE_EQ(mtr(12, 0), -64.58909530248837); EXPECT_DOUBLE_EQ(mtr(12, 1), -85.26796006798745); EXPECT_DOUBLE_EQ(mtr(12, 2), -25.310526646715076); EXPECT_DOUBLE_EQ(mtr(13, 0), -13.336152508799714); EXPECT_DOUBLE_EQ(mtr(13, 1), 3.8169098134350605); EXPECT_DOUBLE_EQ(mtr(13, 2), 14.496228473119118); EXPECT_DOUBLE_EQ(mtr(14, 0), -69.12350514623267); EXPECT_DOUBLE_EQ(mtr(14, 1), 73.4920467291056); EXPECT_DOUBLE_EQ(mtr(14, 2), 46.35572803496012); EXPECT_DOUBLE_EQ(mtr(15, 0), 56.52730125536351); EXPECT_DOUBLE_EQ(mtr(15, 1), 98.24187210950205); EXPECT_DOUBLE_EQ(mtr(15, 2), -43.2905212948518); EXPECT_DOUBLE_EQ(mtr(16, 0), 89.92552663330136); EXPECT_DOUBLE_EQ(mtr(16, 1), -9.878913280704495); EXPECT_DOUBLE_EQ(mtr(16, 2), 72.28250601709692); EXPECT_DOUBLE_EQ(mtr(17, 0), 94.33106257780301); EXPECT_DOUBLE_EQ(mtr(17, 1), -63.027946780158196); EXPECT_DOUBLE_EQ(mtr(17, 2), 59.72857548888601); EXPECT_DOUBLE_EQ(mtr(18, 0), 76.55814809986282); EXPECT_DOUBLE_EQ(mtr(18, 1), 55.64310458734482); EXPECT_DOUBLE_EQ(mtr(18, 2), 39.776820197984875);
|
||||||
|
Matrix<double, -1, 3, ColumnStorage> mtc = m.transpose<double, -1, 3, ColumnStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtc(0, 0), 50.864090811708934); EXPECT_DOUBLE_EQ(mtc(0, 1), 14.747374583026797); EXPECT_DOUBLE_EQ(mtc(0, 2), -75.20410363410058); EXPECT_DOUBLE_EQ(mtc(1, 0), 86.72545584739655); EXPECT_DOUBLE_EQ(mtc(1, 1), -12.087041962746213); EXPECT_DOUBLE_EQ(mtc(1, 2), 45.30781974344674); EXPECT_DOUBLE_EQ(mtc(2, 0), -59.41096188367827); EXPECT_DOUBLE_EQ(mtc(2, 1), -63.3966872965287); EXPECT_DOUBLE_EQ(mtc(2, 2), -43.85391331821933); EXPECT_DOUBLE_EQ(mtc(3, 0), -81.01855448213378); EXPECT_DOUBLE_EQ(mtc(3, 1), -11.386504830855642); EXPECT_DOUBLE_EQ(mtc(3, 2), 67.45134132003074); EXPECT_DOUBLE_EQ(mtc(4, 0), -44.75527142333435); EXPECT_DOUBLE_EQ(mtc(4, 1), -76.29669292020178); EXPECT_DOUBLE_EQ(mtc(4, 2), 55.35009554124747); EXPECT_DOUBLE_EQ(mtc(5, 0), 6.881484559867502); EXPECT_DOUBLE_EQ(mtc(5, 1), -66.38097797841678); EXPECT_DOUBLE_EQ(mtc(5, 2), -24.1599830304106); EXPECT_DOUBLE_EQ(mtc(6, 0), 75.66386662485408); EXPECT_DOUBLE_EQ(mtc(6, 1), -20.191218640024687); EXPECT_DOUBLE_EQ(mtc(6, 2), 89.85022708733555); EXPECT_DOUBLE_EQ(mtc(7, 0), -56.002568995946575); EXPECT_DOUBLE_EQ(mtc(7, 1), -48.05245125934678); EXPECT_DOUBLE_EQ(mtc(7, 2), 63.770995127367826); EXPECT_DOUBLE_EQ(mtc(8, 0), -44.600865729883445); EXPECT_DOUBLE_EQ(mtc(8, 1), -83.87380388512868); EXPECT_DOUBLE_EQ(mtc(8, 2), -7.388429976036122); EXPECT_DOUBLE_EQ(mtc(9, 0), -18.413408652944696); EXPECT_DOUBLE_EQ(mtc(9, 1), -21.25569067138788); EXPECT_DOUBLE_EQ(mtc(9, 2), 8.073425560498507); EXPECT_DOUBLE_EQ(mtc(10, 0), -97.11569037525811); EXPECT_DOUBLE_EQ(mtc(10, 1), 4.889708648539596); EXPECT_DOUBLE_EQ(mtc(10, 2), 76.76129649290999); EXPECT_DOUBLE_EQ(mtc(11, 0), 53.19666636708692); EXPECT_DOUBLE_EQ(mtc(11, 1), -85.80217867074691); EXPECT_DOUBLE_EQ(mtc(11, 2), -50.19697292034915); EXPECT_DOUBLE_EQ(mtc(12, 0), -64.58909530248837); EXPECT_DOUBLE_EQ(mtc(12, 1), -85.26796006798745); EXPECT_DOUBLE_EQ(mtc(12, 2), -25.310526646715076); EXPECT_DOUBLE_EQ(mtc(13, 0), -13.336152508799714); EXPECT_DOUBLE_EQ(mtc(13, 1), 3.8169098134350605); EXPECT_DOUBLE_EQ(mtc(13, 2), 14.496228473119118); EXPECT_DOUBLE_EQ(mtc(14, 0), -69.12350514623267); EXPECT_DOUBLE_EQ(mtc(14, 1), 73.4920467291056); EXPECT_DOUBLE_EQ(mtc(14, 2), 46.35572803496012); EXPECT_DOUBLE_EQ(mtc(15, 0), 56.52730125536351); EXPECT_DOUBLE_EQ(mtc(15, 1), 98.24187210950205); EXPECT_DOUBLE_EQ(mtc(15, 2), -43.2905212948518); EXPECT_DOUBLE_EQ(mtc(16, 0), 89.92552663330136); EXPECT_DOUBLE_EQ(mtc(16, 1), -9.878913280704495); EXPECT_DOUBLE_EQ(mtc(16, 2), 72.28250601709692); EXPECT_DOUBLE_EQ(mtc(17, 0), 94.33106257780301); EXPECT_DOUBLE_EQ(mtc(17, 1), -63.027946780158196); EXPECT_DOUBLE_EQ(mtc(17, 2), 59.72857548888601); EXPECT_DOUBLE_EQ(mtc(18, 0), 76.55814809986282); EXPECT_DOUBLE_EQ(mtc(18, 1), 55.64310458734482); EXPECT_DOUBLE_EQ(mtc(18, 2), 39.776820197984875);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 3, -1, ColumnStorage> m; m.resize(3, 12);
|
||||||
|
m(0, 0) = -32.75375661346618; m(0, 1) = -13.6098421772042; m(0, 2) = -46.86521220477553; m(0, 3) = 59.00702831249865; m(0, 4) = -4.564740481250126; m(0, 5) = 16.232920948792312; m(0, 6) = -65.0828541930055; m(0, 7) = -57.88248367433246; m(0, 8) = -81.72734394349992; m(0, 9) = 28.080964462881383; m(0, 10) = 36.6937632974539; m(0, 11) = 41.35837714070166; m(1, 0) = -47.68004182743719; m(1, 1) = -64.19046526329765; m(1, 2) = -75.66374889412242; m(1, 3) = -82.35155489863575; m(1, 4) = -75.40948179339736; m(1, 5) = -21.839837867220055; m(1, 6) = -7.047883213897393; m(1, 7) = -28.576424866142986; m(1, 8) = 36.45450614900494; m(1, 9) = -9.122226758045997; m(1, 10) = 39.94779111587877; m(1, 11) = 9.684112064820866; m(2, 0) = 34.000255287178476; m(2, 1) = 64.99966038549962; m(2, 2) = -11.973673265362649; m(2, 3) = 80.2812674443403; m(2, 4) = 95.91223898270886; m(2, 5) = -27.634369350449873; m(2, 6) = -75.21066302899243; m(2, 7) = -20.700089950120855; m(2, 8) = 86.68513293601455; m(2, 9) = 75.43854998281424; m(2, 10) = -88.06922362937304; m(2, 11) = -92.34886576586136;
|
||||||
|
Matrix<double, -1, 3, RowStorage> mtr = m.transpose<double, -1, 3, RowStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtr(0, 0), -32.75375661346618); EXPECT_DOUBLE_EQ(mtr(0, 1), -47.68004182743719); EXPECT_DOUBLE_EQ(mtr(0, 2), 34.000255287178476); EXPECT_DOUBLE_EQ(mtr(1, 0), -13.6098421772042); EXPECT_DOUBLE_EQ(mtr(1, 1), -64.19046526329765); EXPECT_DOUBLE_EQ(mtr(1, 2), 64.99966038549962); EXPECT_DOUBLE_EQ(mtr(2, 0), -46.86521220477553); EXPECT_DOUBLE_EQ(mtr(2, 1), -75.66374889412242); EXPECT_DOUBLE_EQ(mtr(2, 2), -11.973673265362649); EXPECT_DOUBLE_EQ(mtr(3, 0), 59.00702831249865); EXPECT_DOUBLE_EQ(mtr(3, 1), -82.35155489863575); EXPECT_DOUBLE_EQ(mtr(3, 2), 80.2812674443403); EXPECT_DOUBLE_EQ(mtr(4, 0), -4.564740481250126); EXPECT_DOUBLE_EQ(mtr(4, 1), -75.40948179339736); EXPECT_DOUBLE_EQ(mtr(4, 2), 95.91223898270886); EXPECT_DOUBLE_EQ(mtr(5, 0), 16.232920948792312); EXPECT_DOUBLE_EQ(mtr(5, 1), -21.839837867220055); EXPECT_DOUBLE_EQ(mtr(5, 2), -27.634369350449873); EXPECT_DOUBLE_EQ(mtr(6, 0), -65.0828541930055); EXPECT_DOUBLE_EQ(mtr(6, 1), -7.047883213897393); EXPECT_DOUBLE_EQ(mtr(6, 2), -75.21066302899243); EXPECT_DOUBLE_EQ(mtr(7, 0), -57.88248367433246); EXPECT_DOUBLE_EQ(mtr(7, 1), -28.576424866142986); EXPECT_DOUBLE_EQ(mtr(7, 2), -20.700089950120855); EXPECT_DOUBLE_EQ(mtr(8, 0), -81.72734394349992); EXPECT_DOUBLE_EQ(mtr(8, 1), 36.45450614900494); EXPECT_DOUBLE_EQ(mtr(8, 2), 86.68513293601455); EXPECT_DOUBLE_EQ(mtr(9, 0), 28.080964462881383); EXPECT_DOUBLE_EQ(mtr(9, 1), -9.122226758045997); EXPECT_DOUBLE_EQ(mtr(9, 2), 75.43854998281424); EXPECT_DOUBLE_EQ(mtr(10, 0), 36.6937632974539); EXPECT_DOUBLE_EQ(mtr(10, 1), 39.94779111587877); EXPECT_DOUBLE_EQ(mtr(10, 2), -88.06922362937304); EXPECT_DOUBLE_EQ(mtr(11, 0), 41.35837714070166); EXPECT_DOUBLE_EQ(mtr(11, 1), 9.684112064820866); EXPECT_DOUBLE_EQ(mtr(11, 2), -92.34886576586136);
|
||||||
|
Matrix<double, -1, 3, ColumnStorage> mtc = m.transpose<double, -1, 3, ColumnStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtc(0, 0), -32.75375661346618); EXPECT_DOUBLE_EQ(mtc(0, 1), -47.68004182743719); EXPECT_DOUBLE_EQ(mtc(0, 2), 34.000255287178476); EXPECT_DOUBLE_EQ(mtc(1, 0), -13.6098421772042); EXPECT_DOUBLE_EQ(mtc(1, 1), -64.19046526329765); EXPECT_DOUBLE_EQ(mtc(1, 2), 64.99966038549962); EXPECT_DOUBLE_EQ(mtc(2, 0), -46.86521220477553); EXPECT_DOUBLE_EQ(mtc(2, 1), -75.66374889412242); EXPECT_DOUBLE_EQ(mtc(2, 2), -11.973673265362649); EXPECT_DOUBLE_EQ(mtc(3, 0), 59.00702831249865); EXPECT_DOUBLE_EQ(mtc(3, 1), -82.35155489863575); EXPECT_DOUBLE_EQ(mtc(3, 2), 80.2812674443403); EXPECT_DOUBLE_EQ(mtc(4, 0), -4.564740481250126); EXPECT_DOUBLE_EQ(mtc(4, 1), -75.40948179339736); EXPECT_DOUBLE_EQ(mtc(4, 2), 95.91223898270886); EXPECT_DOUBLE_EQ(mtc(5, 0), 16.232920948792312); EXPECT_DOUBLE_EQ(mtc(5, 1), -21.839837867220055); EXPECT_DOUBLE_EQ(mtc(5, 2), -27.634369350449873); EXPECT_DOUBLE_EQ(mtc(6, 0), -65.0828541930055); EXPECT_DOUBLE_EQ(mtc(6, 1), -7.047883213897393); EXPECT_DOUBLE_EQ(mtc(6, 2), -75.21066302899243); EXPECT_DOUBLE_EQ(mtc(7, 0), -57.88248367433246); EXPECT_DOUBLE_EQ(mtc(7, 1), -28.576424866142986); EXPECT_DOUBLE_EQ(mtc(7, 2), -20.700089950120855); EXPECT_DOUBLE_EQ(mtc(8, 0), -81.72734394349992); EXPECT_DOUBLE_EQ(mtc(8, 1), 36.45450614900494); EXPECT_DOUBLE_EQ(mtc(8, 2), 86.68513293601455); EXPECT_DOUBLE_EQ(mtc(9, 0), 28.080964462881383); EXPECT_DOUBLE_EQ(mtc(9, 1), -9.122226758045997); EXPECT_DOUBLE_EQ(mtc(9, 2), 75.43854998281424); EXPECT_DOUBLE_EQ(mtc(10, 0), 36.6937632974539); EXPECT_DOUBLE_EQ(mtc(10, 1), 39.94779111587877); EXPECT_DOUBLE_EQ(mtc(10, 2), -88.06922362937304); EXPECT_DOUBLE_EQ(mtc(11, 0), 41.35837714070166); EXPECT_DOUBLE_EQ(mtc(11, 1), 9.684112064820866); EXPECT_DOUBLE_EQ(mtc(11, 2), -92.34886576586136);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 3, -1, ColumnStorage> m; m.resize(3, 17);
|
||||||
|
m(0, 0) = 41.19222807334356; m(0, 1) = -9.647827035990119; m(0, 2) = 79.08578232010518; m(0, 3) = -81.30050511004372; m(0, 4) = 5.2008331502779725; m(0, 5) = -94.16930980955891; m(0, 6) = -13.738166181380976; m(0, 7) = 31.708028058804274; m(0, 8) = -98.07812519655093; m(0, 9) = -51.718134217817926; m(0, 10) = -81.49405897174573; m(0, 11) = 86.09136014594006; m(0, 12) = -23.14506976740256; m(0, 13) = 76.3616884219812; m(0, 14) = 60.28344358729666; m(0, 15) = -35.34123633864937; m(0, 16) = -87.33936780992902; m(1, 0) = 25.563530352835954; m(1, 1) = -43.62388501728416; m(1, 2) = 0.5379451108277209; m(1, 3) = 40.11963964000961; m(1, 4) = -63.945471933511236; m(1, 5) = 25.47334071885645; m(1, 6) = 20.998951793092573; m(1, 7) = 23.964236092014318; m(1, 8) = -53.69611952912465; m(1, 9) = -48.45849352784126; m(1, 10) = 0.03386109792266723; m(1, 11) = -43.90344163766924; m(1, 12) = -6.698621092523396; m(1, 13) = -99.37831178796779; m(1, 14) = -9.64088536276411; m(1, 15) = 3.118955974716698; m(1, 16) = -81.5481380106742; m(2, 0) = 62.07279507925867; m(2, 1) = 90.29145840318458; m(2, 2) = -25.71415288702252; m(2, 3) = 74.7395459171091; m(2, 4) = 24.394997421168824; m(2, 5) = -58.2301634354434; m(2, 6) = -4.768291835922895; m(2, 7) = 49.704487303266575; m(2, 8) = 18.65157355854312; m(2, 9) = 98.9073219636636; m(2, 10) = -45.19000115648366; m(2, 11) = -45.249286237965315; m(2, 12) = 97.09143831741096; m(2, 13) = -31.80834068260583; m(2, 14) = -78.03982967131924; m(2, 15) = -14.844621355572116; m(2, 16) = -66.64707457523824;
|
||||||
|
Matrix<double, -1, 3, RowStorage> mtr = m.transpose<double, -1, 3, RowStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtr(0, 0), 41.19222807334356); EXPECT_DOUBLE_EQ(mtr(0, 1), 25.563530352835954); EXPECT_DOUBLE_EQ(mtr(0, 2), 62.07279507925867); EXPECT_DOUBLE_EQ(mtr(1, 0), -9.647827035990119); EXPECT_DOUBLE_EQ(mtr(1, 1), -43.62388501728416); EXPECT_DOUBLE_EQ(mtr(1, 2), 90.29145840318458); EXPECT_DOUBLE_EQ(mtr(2, 0), 79.08578232010518); EXPECT_DOUBLE_EQ(mtr(2, 1), 0.5379451108277209); EXPECT_DOUBLE_EQ(mtr(2, 2), -25.71415288702252); EXPECT_DOUBLE_EQ(mtr(3, 0), -81.30050511004372); EXPECT_DOUBLE_EQ(mtr(3, 1), 40.11963964000961); EXPECT_DOUBLE_EQ(mtr(3, 2), 74.7395459171091); EXPECT_DOUBLE_EQ(mtr(4, 0), 5.2008331502779725); EXPECT_DOUBLE_EQ(mtr(4, 1), -63.945471933511236); EXPECT_DOUBLE_EQ(mtr(4, 2), 24.394997421168824); EXPECT_DOUBLE_EQ(mtr(5, 0), -94.16930980955891); EXPECT_DOUBLE_EQ(mtr(5, 1), 25.47334071885645); EXPECT_DOUBLE_EQ(mtr(5, 2), -58.2301634354434); EXPECT_DOUBLE_EQ(mtr(6, 0), -13.738166181380976); EXPECT_DOUBLE_EQ(mtr(6, 1), 20.998951793092573); EXPECT_DOUBLE_EQ(mtr(6, 2), -4.768291835922895); EXPECT_DOUBLE_EQ(mtr(7, 0), 31.708028058804274); EXPECT_DOUBLE_EQ(mtr(7, 1), 23.964236092014318); EXPECT_DOUBLE_EQ(mtr(7, 2), 49.704487303266575); EXPECT_DOUBLE_EQ(mtr(8, 0), -98.07812519655093); EXPECT_DOUBLE_EQ(mtr(8, 1), -53.69611952912465); EXPECT_DOUBLE_EQ(mtr(8, 2), 18.65157355854312); EXPECT_DOUBLE_EQ(mtr(9, 0), -51.718134217817926); EXPECT_DOUBLE_EQ(mtr(9, 1), -48.45849352784126); EXPECT_DOUBLE_EQ(mtr(9, 2), 98.9073219636636); EXPECT_DOUBLE_EQ(mtr(10, 0), -81.49405897174573); EXPECT_DOUBLE_EQ(mtr(10, 1), 0.03386109792266723); EXPECT_DOUBLE_EQ(mtr(10, 2), -45.19000115648366); EXPECT_DOUBLE_EQ(mtr(11, 0), 86.09136014594006); EXPECT_DOUBLE_EQ(mtr(11, 1), -43.90344163766924); EXPECT_DOUBLE_EQ(mtr(11, 2), -45.249286237965315); EXPECT_DOUBLE_EQ(mtr(12, 0), -23.14506976740256); EXPECT_DOUBLE_EQ(mtr(12, 1), -6.698621092523396); EXPECT_DOUBLE_EQ(mtr(12, 2), 97.09143831741096); EXPECT_DOUBLE_EQ(mtr(13, 0), 76.3616884219812); EXPECT_DOUBLE_EQ(mtr(13, 1), -99.37831178796779); EXPECT_DOUBLE_EQ(mtr(13, 2), -31.80834068260583); EXPECT_DOUBLE_EQ(mtr(14, 0), 60.28344358729666); EXPECT_DOUBLE_EQ(mtr(14, 1), -9.64088536276411); EXPECT_DOUBLE_EQ(mtr(14, 2), -78.03982967131924); EXPECT_DOUBLE_EQ(mtr(15, 0), -35.34123633864937); EXPECT_DOUBLE_EQ(mtr(15, 1), 3.118955974716698); EXPECT_DOUBLE_EQ(mtr(15, 2), -14.844621355572116); EXPECT_DOUBLE_EQ(mtr(16, 0), -87.33936780992902); EXPECT_DOUBLE_EQ(mtr(16, 1), -81.5481380106742); EXPECT_DOUBLE_EQ(mtr(16, 2), -66.64707457523824);
|
||||||
|
Matrix<double, -1, 3, ColumnStorage> mtc = m.transpose<double, -1, 3, ColumnStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtc(0, 0), 41.19222807334356); EXPECT_DOUBLE_EQ(mtc(0, 1), 25.563530352835954); EXPECT_DOUBLE_EQ(mtc(0, 2), 62.07279507925867); EXPECT_DOUBLE_EQ(mtc(1, 0), -9.647827035990119); EXPECT_DOUBLE_EQ(mtc(1, 1), -43.62388501728416); EXPECT_DOUBLE_EQ(mtc(1, 2), 90.29145840318458); EXPECT_DOUBLE_EQ(mtc(2, 0), 79.08578232010518); EXPECT_DOUBLE_EQ(mtc(2, 1), 0.5379451108277209); EXPECT_DOUBLE_EQ(mtc(2, 2), -25.71415288702252); EXPECT_DOUBLE_EQ(mtc(3, 0), -81.30050511004372); EXPECT_DOUBLE_EQ(mtc(3, 1), 40.11963964000961); EXPECT_DOUBLE_EQ(mtc(3, 2), 74.7395459171091); EXPECT_DOUBLE_EQ(mtc(4, 0), 5.2008331502779725); EXPECT_DOUBLE_EQ(mtc(4, 1), -63.945471933511236); EXPECT_DOUBLE_EQ(mtc(4, 2), 24.394997421168824); EXPECT_DOUBLE_EQ(mtc(5, 0), -94.16930980955891); EXPECT_DOUBLE_EQ(mtc(5, 1), 25.47334071885645); EXPECT_DOUBLE_EQ(mtc(5, 2), -58.2301634354434); EXPECT_DOUBLE_EQ(mtc(6, 0), -13.738166181380976); EXPECT_DOUBLE_EQ(mtc(6, 1), 20.998951793092573); EXPECT_DOUBLE_EQ(mtc(6, 2), -4.768291835922895); EXPECT_DOUBLE_EQ(mtc(7, 0), 31.708028058804274); EXPECT_DOUBLE_EQ(mtc(7, 1), 23.964236092014318); EXPECT_DOUBLE_EQ(mtc(7, 2), 49.704487303266575); EXPECT_DOUBLE_EQ(mtc(8, 0), -98.07812519655093); EXPECT_DOUBLE_EQ(mtc(8, 1), -53.69611952912465); EXPECT_DOUBLE_EQ(mtc(8, 2), 18.65157355854312); EXPECT_DOUBLE_EQ(mtc(9, 0), -51.718134217817926); EXPECT_DOUBLE_EQ(mtc(9, 1), -48.45849352784126); EXPECT_DOUBLE_EQ(mtc(9, 2), 98.9073219636636); EXPECT_DOUBLE_EQ(mtc(10, 0), -81.49405897174573); EXPECT_DOUBLE_EQ(mtc(10, 1), 0.03386109792266723); EXPECT_DOUBLE_EQ(mtc(10, 2), -45.19000115648366); EXPECT_DOUBLE_EQ(mtc(11, 0), 86.09136014594006); EXPECT_DOUBLE_EQ(mtc(11, 1), -43.90344163766924); EXPECT_DOUBLE_EQ(mtc(11, 2), -45.249286237965315); EXPECT_DOUBLE_EQ(mtc(12, 0), -23.14506976740256); EXPECT_DOUBLE_EQ(mtc(12, 1), -6.698621092523396); EXPECT_DOUBLE_EQ(mtc(12, 2), 97.09143831741096); EXPECT_DOUBLE_EQ(mtc(13, 0), 76.3616884219812); EXPECT_DOUBLE_EQ(mtc(13, 1), -99.37831178796779); EXPECT_DOUBLE_EQ(mtc(13, 2), -31.80834068260583); EXPECT_DOUBLE_EQ(mtc(14, 0), 60.28344358729666); EXPECT_DOUBLE_EQ(mtc(14, 1), -9.64088536276411); EXPECT_DOUBLE_EQ(mtc(14, 2), -78.03982967131924); EXPECT_DOUBLE_EQ(mtc(15, 0), -35.34123633864937); EXPECT_DOUBLE_EQ(mtc(15, 1), 3.118955974716698); EXPECT_DOUBLE_EQ(mtc(15, 2), -14.844621355572116); EXPECT_DOUBLE_EQ(mtc(16, 0), -87.33936780992902); EXPECT_DOUBLE_EQ(mtc(16, 1), -81.5481380106742); EXPECT_DOUBLE_EQ(mtc(16, 2), -66.64707457523824);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 3, -1, ColumnStorage> m; m.resize(3, 11);
|
||||||
|
m(0, 0) = -44.385915446696366; m(0, 1) = 28.793505461441015; m(0, 2) = 71.2114986465838; m(0, 3) = 51.14773880111491; m(0, 4) = -7.958682467368476; m(0, 5) = -83.09905041318346; m(0, 6) = -22.191719125506793; m(0, 7) = -2.2844026553076873; m(0, 8) = -85.89049887253955; m(0, 9) = 7.359151344016439; m(0, 10) = -12.836173824817394; m(1, 0) = 60.864624834962456; m(1, 1) = 55.31797716120735; m(1, 2) = 54.86505134841502; m(1, 3) = 1.2088001265842365; m(1, 4) = 51.71783583087824; m(1, 5) = -97.7984372019131; m(1, 6) = -21.276052450577225; m(1, 7) = -38.9853136735308; m(1, 8) = -83.47696130822689; m(1, 9) = 3.197398523431062; m(1, 10) = -81.03476411018644; m(2, 0) = 78.17495315633076; m(2, 1) = -81.81693970564498; m(2, 2) = -30.34183030075195; m(2, 3) = -15.609525205781651; m(2, 4) = -27.0093291175411; m(2, 5) = 42.95413233280735; m(2, 6) = -72.61359152573652; m(2, 7) = 78.95917814822454; m(2, 8) = -83.12124753315223; m(2, 9) = 74.1286028999458; m(2, 10) = -87.09605709830836;
|
||||||
|
Matrix<double, -1, 3, RowStorage> mtr = m.transpose<double, -1, 3, RowStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtr(0, 0), -44.385915446696366); EXPECT_DOUBLE_EQ(mtr(0, 1), 60.864624834962456); EXPECT_DOUBLE_EQ(mtr(0, 2), 78.17495315633076); EXPECT_DOUBLE_EQ(mtr(1, 0), 28.793505461441015); EXPECT_DOUBLE_EQ(mtr(1, 1), 55.31797716120735); EXPECT_DOUBLE_EQ(mtr(1, 2), -81.81693970564498); EXPECT_DOUBLE_EQ(mtr(2, 0), 71.2114986465838); EXPECT_DOUBLE_EQ(mtr(2, 1), 54.86505134841502); EXPECT_DOUBLE_EQ(mtr(2, 2), -30.34183030075195); EXPECT_DOUBLE_EQ(mtr(3, 0), 51.14773880111491); EXPECT_DOUBLE_EQ(mtr(3, 1), 1.2088001265842365); EXPECT_DOUBLE_EQ(mtr(3, 2), -15.609525205781651); EXPECT_DOUBLE_EQ(mtr(4, 0), -7.958682467368476); EXPECT_DOUBLE_EQ(mtr(4, 1), 51.71783583087824); EXPECT_DOUBLE_EQ(mtr(4, 2), -27.0093291175411); EXPECT_DOUBLE_EQ(mtr(5, 0), -83.09905041318346); EXPECT_DOUBLE_EQ(mtr(5, 1), -97.7984372019131); EXPECT_DOUBLE_EQ(mtr(5, 2), 42.95413233280735); EXPECT_DOUBLE_EQ(mtr(6, 0), -22.191719125506793); EXPECT_DOUBLE_EQ(mtr(6, 1), -21.276052450577225); EXPECT_DOUBLE_EQ(mtr(6, 2), -72.61359152573652); EXPECT_DOUBLE_EQ(mtr(7, 0), -2.2844026553076873); EXPECT_DOUBLE_EQ(mtr(7, 1), -38.9853136735308); EXPECT_DOUBLE_EQ(mtr(7, 2), 78.95917814822454); EXPECT_DOUBLE_EQ(mtr(8, 0), -85.89049887253955); EXPECT_DOUBLE_EQ(mtr(8, 1), -83.47696130822689); EXPECT_DOUBLE_EQ(mtr(8, 2), -83.12124753315223); EXPECT_DOUBLE_EQ(mtr(9, 0), 7.359151344016439); EXPECT_DOUBLE_EQ(mtr(9, 1), 3.197398523431062); EXPECT_DOUBLE_EQ(mtr(9, 2), 74.1286028999458); EXPECT_DOUBLE_EQ(mtr(10, 0), -12.836173824817394); EXPECT_DOUBLE_EQ(mtr(10, 1), -81.03476411018644); EXPECT_DOUBLE_EQ(mtr(10, 2), -87.09605709830836);
|
||||||
|
Matrix<double, -1, 3, ColumnStorage> mtc = m.transpose<double, -1, 3, ColumnStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(mtc(0, 0), -44.385915446696366); EXPECT_DOUBLE_EQ(mtc(0, 1), 60.864624834962456); EXPECT_DOUBLE_EQ(mtc(0, 2), 78.17495315633076); EXPECT_DOUBLE_EQ(mtc(1, 0), 28.793505461441015); EXPECT_DOUBLE_EQ(mtc(1, 1), 55.31797716120735); EXPECT_DOUBLE_EQ(mtc(1, 2), -81.81693970564498); EXPECT_DOUBLE_EQ(mtc(2, 0), 71.2114986465838); EXPECT_DOUBLE_EQ(mtc(2, 1), 54.86505134841502); EXPECT_DOUBLE_EQ(mtc(2, 2), -30.34183030075195); EXPECT_DOUBLE_EQ(mtc(3, 0), 51.14773880111491); EXPECT_DOUBLE_EQ(mtc(3, 1), 1.2088001265842365); EXPECT_DOUBLE_EQ(mtc(3, 2), -15.609525205781651); EXPECT_DOUBLE_EQ(mtc(4, 0), -7.958682467368476); EXPECT_DOUBLE_EQ(mtc(4, 1), 51.71783583087824); EXPECT_DOUBLE_EQ(mtc(4, 2), -27.0093291175411); EXPECT_DOUBLE_EQ(mtc(5, 0), -83.09905041318346); EXPECT_DOUBLE_EQ(mtc(5, 1), -97.7984372019131); EXPECT_DOUBLE_EQ(mtc(5, 2), 42.95413233280735); EXPECT_DOUBLE_EQ(mtc(6, 0), -22.191719125506793); EXPECT_DOUBLE_EQ(mtc(6, 1), -21.276052450577225); EXPECT_DOUBLE_EQ(mtc(6, 2), -72.61359152573652); EXPECT_DOUBLE_EQ(mtc(7, 0), -2.2844026553076873); EXPECT_DOUBLE_EQ(mtc(7, 1), -38.9853136735308); EXPECT_DOUBLE_EQ(mtc(7, 2), 78.95917814822454); EXPECT_DOUBLE_EQ(mtc(8, 0), -85.89049887253955); EXPECT_DOUBLE_EQ(mtc(8, 1), -83.47696130822689); EXPECT_DOUBLE_EQ(mtc(8, 2), -83.12124753315223); EXPECT_DOUBLE_EQ(mtc(9, 0), 7.359151344016439); EXPECT_DOUBLE_EQ(mtc(9, 1), 3.197398523431062); EXPECT_DOUBLE_EQ(mtc(9, 2), 74.1286028999458); EXPECT_DOUBLE_EQ(mtc(10, 0), -12.836173824817394); EXPECT_DOUBLE_EQ(mtc(10, 1), -81.03476411018644); EXPECT_DOUBLE_EQ(mtc(10, 2), -87.09605709830836);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestLabo1a, AffectationBySubMatrix)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m.setIdentity();
|
||||||
|
EXPECT_DOUBLE_EQ(m(0, 0), 1); EXPECT_DOUBLE_EQ(m(0, 1), 0); EXPECT_DOUBLE_EQ(m(0, 2), 0); EXPECT_DOUBLE_EQ(m(0, 3), 0); EXPECT_DOUBLE_EQ(m(1, 0), 0); EXPECT_DOUBLE_EQ(m(1, 1), 1); EXPECT_DOUBLE_EQ(m(1, 2), 0); EXPECT_DOUBLE_EQ(m(1, 3), 0); EXPECT_DOUBLE_EQ(m(2, 0), 0); EXPECT_DOUBLE_EQ(m(2, 1), 0); EXPECT_DOUBLE_EQ(m(2, 2), 1); EXPECT_DOUBLE_EQ(m(2, 3), 0); EXPECT_DOUBLE_EQ(m(3, 0), 0); EXPECT_DOUBLE_EQ(m(3, 1), 0); EXPECT_DOUBLE_EQ(m(3, 2), 0); EXPECT_DOUBLE_EQ(m(3, 3), 1);
|
||||||
|
Matrix<double, 4, 1, RowStorage> c;
|
||||||
|
c(0, 0) = 1.0; c(1, 0) = 2.0; c(2, 0) = 3.0; c(3, 0) = 4.0;
|
||||||
|
m.block(0, 0, 4, 1) = c;
|
||||||
|
m.block(0, 1, 4, 1) = c;
|
||||||
|
m.block(0, 2, 4, 1) = c;
|
||||||
|
m.block(0, 3, 4, 1) = c;
|
||||||
|
EXPECT_DOUBLE_EQ(m(0, 0), 1); EXPECT_DOUBLE_EQ(m(0, 1), 1); EXPECT_DOUBLE_EQ(m(0, 2), 1); EXPECT_DOUBLE_EQ(m(0, 3), 1); EXPECT_DOUBLE_EQ(m(1, 0), 2); EXPECT_DOUBLE_EQ(m(1, 1), 2); EXPECT_DOUBLE_EQ(m(1, 2), 2); EXPECT_DOUBLE_EQ(m(1, 3), 2); EXPECT_DOUBLE_EQ(m(2, 0), 3); EXPECT_DOUBLE_EQ(m(2, 1), 3); EXPECT_DOUBLE_EQ(m(2, 2), 3); EXPECT_DOUBLE_EQ(m(2, 3), 3); EXPECT_DOUBLE_EQ(m(3, 0), 4); EXPECT_DOUBLE_EQ(m(3, 1), 4); EXPECT_DOUBLE_EQ(m(3, 2), 4); EXPECT_DOUBLE_EQ(m(3, 3), 4);
|
||||||
|
Matrix<double, 2, 2, ColumnStorage> b;
|
||||||
|
b(0, 0) = 0.0; b(1, 0) = 1.0; b(0, 1) = 2.0; b(1, 1) = 3.0;
|
||||||
|
m.block(0, 0, 2, 2) = b;
|
||||||
|
m.block(2, 0, 2, 2) = b;
|
||||||
|
m.block(0, 2, 2, 2) = b;
|
||||||
|
m.block(2, 2, 2, 2) = b;
|
||||||
|
EXPECT_DOUBLE_EQ(m(0, 0), 0); EXPECT_DOUBLE_EQ(m(0, 1), 2); EXPECT_DOUBLE_EQ(m(0, 2), 0); EXPECT_DOUBLE_EQ(m(0, 3), 2); EXPECT_DOUBLE_EQ(m(1, 0), 1); EXPECT_DOUBLE_EQ(m(1, 1), 3); EXPECT_DOUBLE_EQ(m(1, 2), 1); EXPECT_DOUBLE_EQ(m(1, 3), 3); EXPECT_DOUBLE_EQ(m(2, 0), 0); EXPECT_DOUBLE_EQ(m(2, 1), 2); EXPECT_DOUBLE_EQ(m(2, 2), 0); EXPECT_DOUBLE_EQ(m(2, 3), 2); EXPECT_DOUBLE_EQ(m(3, 0), 1); EXPECT_DOUBLE_EQ(m(3, 1), 3); EXPECT_DOUBLE_EQ(m(3, 2), 1); EXPECT_DOUBLE_EQ(m(3, 3), 3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, RowStorage> m;
|
||||||
|
m.setIdentity();
|
||||||
|
EXPECT_DOUBLE_EQ(m(0, 0), 1); EXPECT_DOUBLE_EQ(m(0, 1), 0); EXPECT_DOUBLE_EQ(m(0, 2), 0); EXPECT_DOUBLE_EQ(m(0, 3), 0); EXPECT_DOUBLE_EQ(m(1, 0), 0); EXPECT_DOUBLE_EQ(m(1, 1), 1); EXPECT_DOUBLE_EQ(m(1, 2), 0); EXPECT_DOUBLE_EQ(m(1, 3), 0); EXPECT_DOUBLE_EQ(m(2, 0), 0); EXPECT_DOUBLE_EQ(m(2, 1), 0); EXPECT_DOUBLE_EQ(m(2, 2), 1); EXPECT_DOUBLE_EQ(m(2, 3), 0); EXPECT_DOUBLE_EQ(m(3, 0), 0); EXPECT_DOUBLE_EQ(m(3, 1), 0); EXPECT_DOUBLE_EQ(m(3, 2), 0); EXPECT_DOUBLE_EQ(m(3, 3), 1);
|
||||||
|
Matrix<double, 4, 1, RowStorage> c;
|
||||||
|
c(0, 0) = 1.0; c(1, 0) = 2.0; c(2, 0) = 3.0; c(3, 0) = 4.0;
|
||||||
|
m.block(0, 0, 4, 1) = c;
|
||||||
|
m.block(0, 1, 4, 1) = c;
|
||||||
|
m.block(0, 2, 4, 1) = c;
|
||||||
|
m.block(0, 3, 4, 1) = c;
|
||||||
|
EXPECT_DOUBLE_EQ(m(0, 0), 1); EXPECT_DOUBLE_EQ(m(0, 1), 1); EXPECT_DOUBLE_EQ(m(0, 2), 1); EXPECT_DOUBLE_EQ(m(0, 3), 1); EXPECT_DOUBLE_EQ(m(1, 0), 2); EXPECT_DOUBLE_EQ(m(1, 1), 2); EXPECT_DOUBLE_EQ(m(1, 2), 2); EXPECT_DOUBLE_EQ(m(1, 3), 2); EXPECT_DOUBLE_EQ(m(2, 0), 3); EXPECT_DOUBLE_EQ(m(2, 1), 3); EXPECT_DOUBLE_EQ(m(2, 2), 3); EXPECT_DOUBLE_EQ(m(2, 3), 3); EXPECT_DOUBLE_EQ(m(3, 0), 4); EXPECT_DOUBLE_EQ(m(3, 1), 4); EXPECT_DOUBLE_EQ(m(3, 2), 4); EXPECT_DOUBLE_EQ(m(3, 3), 4);
|
||||||
|
Matrix<double, 2, 2, ColumnStorage> b;
|
||||||
|
b(0, 0) = 0.0; b(1, 0) = 1.0; b(0, 1) = 2.0; b(1, 1) = 3.0;
|
||||||
|
m.block(0, 0, 2, 2) = b;
|
||||||
|
m.block(2, 0, 2, 2) = b;
|
||||||
|
m.block(0, 2, 2, 2) = b;
|
||||||
|
m.block(2, 2, 2, 2) = b;
|
||||||
|
EXPECT_DOUBLE_EQ(m(0, 0), 0); EXPECT_DOUBLE_EQ(m(0, 1), 2); EXPECT_DOUBLE_EQ(m(0, 2), 0); EXPECT_DOUBLE_EQ(m(0, 3), 2); EXPECT_DOUBLE_EQ(m(1, 0), 1); EXPECT_DOUBLE_EQ(m(1, 1), 3); EXPECT_DOUBLE_EQ(m(1, 2), 1); EXPECT_DOUBLE_EQ(m(1, 3), 3); EXPECT_DOUBLE_EQ(m(2, 0), 0); EXPECT_DOUBLE_EQ(m(2, 1), 2); EXPECT_DOUBLE_EQ(m(2, 2), 0); EXPECT_DOUBLE_EQ(m(2, 3), 2); EXPECT_DOUBLE_EQ(m(3, 0), 1); EXPECT_DOUBLE_EQ(m(3, 1), 3); EXPECT_DOUBLE_EQ(m(3, 2), 1); EXPECT_DOUBLE_EQ(m(3, 3), 3);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,801 @@
|
||||||
|
/**
|
||||||
|
* @file Tests1b.cpp
|
||||||
|
*
|
||||||
|
* @brief Tests unitaires de la partie 1b
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Matrix.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
#include "Math3D.h"
|
||||||
|
#include "Operators.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
using namespace gti320;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Multiplication matrice * vecteur, utilisant une implémentation naive
|
||||||
|
*/
|
||||||
|
template<typename _Scalar>
|
||||||
|
static inline Vector<_Scalar, Dynamic> naiveMatrixMult(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Vector<_Scalar, Dynamic>& v)
|
||||||
|
{
|
||||||
|
assert(A.cols() == v.rows());
|
||||||
|
|
||||||
|
Vector<_Scalar, Dynamic> b(A.rows());
|
||||||
|
assert(b.rows() == A.rows());
|
||||||
|
|
||||||
|
for (int i = 0; i < A.rows(); ++i) {
|
||||||
|
b(i) = 0.0;
|
||||||
|
for (int j = 0; j < A.cols(); ++j) {
|
||||||
|
b(i) += A(i, j) * v(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addition matrice + matrice, utilisant une implémentation naive
|
||||||
|
*/
|
||||||
|
template<typename _Scalar>
|
||||||
|
static inline Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> naiveMatrixAddition(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& B)
|
||||||
|
{
|
||||||
|
assert(A.cols() == B.cols() && A.rows() == B.rows());
|
||||||
|
|
||||||
|
Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> C(A.rows(), A.cols());
|
||||||
|
assert(C.rows() == A.rows() && C.cols() == A.cols());
|
||||||
|
for (int i = 0; i < C.rows(); ++i) {
|
||||||
|
for (int j = 0; j < C.cols(); ++j) {
|
||||||
|
C(i, j) = A(i, j) + B(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multiplication matrice * matrice, utilisant une implémentation naive.
|
||||||
|
*/
|
||||||
|
template<typename _Scalar, int _Storage>
|
||||||
|
static inline Matrix<_Scalar, Dynamic, Dynamic, _Storage> naiveMatrixMult(const Matrix<_Scalar, Dynamic, Dynamic, _Storage>& A, const Matrix<_Scalar, Dynamic, Dynamic, _Storage>& B)
|
||||||
|
{
|
||||||
|
assert(A.cols() == B.rows());
|
||||||
|
Matrix<_Scalar, Dynamic, Dynamic> product(A.rows(), B.cols());
|
||||||
|
for (int i = 0; i < A.rows(); ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < B.cols(); ++j)
|
||||||
|
{
|
||||||
|
for (int k = 0; k < A.cols(); ++k)
|
||||||
|
{
|
||||||
|
product(i, j) += A(i, k) * B(k, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test pour les opérateurs d'arithmétique matricielle.
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1b, MatrixMatrixOperators)
|
||||||
|
{
|
||||||
|
// Opérations arithmétiques avec matrices à taille dynamique
|
||||||
|
{
|
||||||
|
// Test : matrice identité
|
||||||
|
Matrix<double> A(6, 6);
|
||||||
|
A.setIdentity();
|
||||||
|
EXPECT_DOUBLE_EQ(A(0, 0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(A(1, 1), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(A(2, 2), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(A(3, 3), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(A(4, 4), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(A(5, 5), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(A(0, 1), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(A(1, 0), 0.0);
|
||||||
|
|
||||||
|
// Test : produit scalaire * matrice
|
||||||
|
const double alpha = 2.5;
|
||||||
|
Matrix<double> B = alpha * A;
|
||||||
|
EXPECT_DOUBLE_EQ(B(0, 0), alpha);
|
||||||
|
EXPECT_DOUBLE_EQ(B(1, 1), alpha);
|
||||||
|
EXPECT_DOUBLE_EQ(B(2, 2), alpha);
|
||||||
|
EXPECT_DOUBLE_EQ(B(3, 3), alpha);
|
||||||
|
EXPECT_DOUBLE_EQ(B(4, 4), alpha);
|
||||||
|
EXPECT_DOUBLE_EQ(B(5, 5), alpha);
|
||||||
|
EXPECT_DOUBLE_EQ(B(0, 1), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(B(1, 0), 0.0);
|
||||||
|
|
||||||
|
// Test : produit matrice * matrice
|
||||||
|
Matrix<double> C = A * B;
|
||||||
|
EXPECT_DOUBLE_EQ(C(0, 0), A(0, 0) * B(0, 0));
|
||||||
|
EXPECT_DOUBLE_EQ(C(1, 1), A(1, 1) * B(1, 1));
|
||||||
|
EXPECT_DOUBLE_EQ(C(2, 2), A(2, 2) * B(2, 2));
|
||||||
|
EXPECT_DOUBLE_EQ(C(3, 3), A(3, 3) * B(3, 3));
|
||||||
|
EXPECT_DOUBLE_EQ(C(4, 4), A(4, 4) * B(4, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(C(5, 5), A(5, 5) * B(5, 5));
|
||||||
|
EXPECT_DOUBLE_EQ(C(0, 1), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(C(2, 3), 0.0);
|
||||||
|
|
||||||
|
// Test : addition matrice * matrice
|
||||||
|
Matrix<double> A_plus_B = A + B;
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_B(0, 0), A(0, 0) + B(0, 0));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_B(1, 1), A(1, 1) + B(1, 1));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_B(2, 2), A(2, 2) + B(2, 2));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_B(3, 3), A(3, 3) + B(3, 3));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_B(4, 4), A(4, 4) + B(4, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_B(5, 5), A(5, 5) + B(5, 5));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_B(0, 1), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_B(2, 3), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opérations arithmétique avec matrices à stockage par lignes et par
|
||||||
|
// colonnes.
|
||||||
|
{
|
||||||
|
// Création d'un matrice à stockage par lignes
|
||||||
|
Matrix<double, Dynamic, Dynamic, RowStorage> A(5, 5);
|
||||||
|
A(0, 0) = 0.8147; A(0, 1) = 0.0975; A(0, 2) = 0.1576; A(0, 3) = 0.1419; A(0, 4) = 0.6557;
|
||||||
|
A(1, 0) = 0.9058; A(1, 1) = 0.2785; A(1, 2) = 0.9706; A(1, 3) = 0.4218; A(1, 4) = 0.0357;
|
||||||
|
A(2, 0) = 0.1270; A(2, 1) = 0.5469; A(2, 2) = 0.9572; A(2, 3) = 0.9157; A(2, 4) = 0.8491;
|
||||||
|
A(3, 0) = 0.9134; A(3, 1) = 0.9575; A(3, 2) = 0.4854; A(3, 3) = 0.7922; A(3, 4) = 0.9340;
|
||||||
|
A(4, 0) = 0.6324; A(4, 1) = 0.9649; A(4, 2) = 0.8003; A(4, 3) = 0.9595; A(4, 4) = 0.6787;
|
||||||
|
|
||||||
|
// Test : transposée (le résultat est une matrice à stockage par
|
||||||
|
// colonnes)
|
||||||
|
Matrix<double, Dynamic, Dynamic, ColumnStorage> B = A.transpose();
|
||||||
|
|
||||||
|
// Test : multiplication matrix(ligne) * matrice(colonne)
|
||||||
|
// Note : teste seulement la première et la dernière colonne
|
||||||
|
const auto C = A * B;
|
||||||
|
EXPECT_NEAR(C(0, 0), 1.14815820000000, 1e-3); EXPECT_NEAR(C(0, 4), 1.31659795000000, 1e-3);
|
||||||
|
EXPECT_NEAR(C(1, 0), 1.00133748000000, 1e-3); EXPECT_NEAR(C(1, 4), 2.04727044000000, 1e-3);
|
||||||
|
EXPECT_NEAR(C(2, 0), 0.99433707000000, 1e-3); EXPECT_NEAR(C(2, 4), 2.82896409000000, 1e-3);
|
||||||
|
EXPECT_NEAR(C(3, 0), 1.63883925000000, 1e-3); EXPECT_NEAR(C(3, 4), 3.28401323000000, 1e-3);
|
||||||
|
EXPECT_NEAR(C(4, 0), 1.31659795000000, 1e-3); EXPECT_NEAR(C(4, 4), 3.35271580000000, 1e-3);
|
||||||
|
|
||||||
|
|
||||||
|
// Test : multiplication matrice(colonne) * matrice(ligne)
|
||||||
|
// Note : teste seulement la première et la dernière colonne
|
||||||
|
const auto C2 = B * A;
|
||||||
|
EXPECT_NEAR(C2(0, 0), 2.73456805000000, 1e-3); EXPECT_NEAR(C2(0, 4), 1.95669703000000, 1e-3);
|
||||||
|
EXPECT_NEAR(C2(1, 0), 1.88593811000000, 1e-3); EXPECT_NEAR(C2(1, 4), 2.08742862000000, 1e-3);
|
||||||
|
EXPECT_NEAR(C2(2, 0), 2.07860468000000, 1e-3); EXPECT_NEAR(C2(2, 4), 1.94727447000000, 1e-3);
|
||||||
|
EXPECT_NEAR(C2(3, 0), 1.94434955000000, 1e-3); EXPECT_NEAR(C2(3, 4), 2.27675041000000, 1e-3);
|
||||||
|
EXPECT_NEAR(C2(4, 0), 1.95669703000000, 1e-3); EXPECT_NEAR(C2(4, 4), 2.48517748000000, 1e-3);
|
||||||
|
|
||||||
|
// Test : addition matrice(ligne) + matrice(ligne)
|
||||||
|
// Note : teste seulement la première et la dernière colonne
|
||||||
|
const auto A_plus_A = A + A;
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_A(0, 0), A(0, 0) + A(0, 0)); EXPECT_DOUBLE_EQ(A_plus_A(0, 4), A(0, 4) + A(0, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_A(1, 0), A(1, 0) + A(1, 0)); EXPECT_DOUBLE_EQ(A_plus_A(1, 4), A(1, 4) + A(1, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_A(2, 0), A(2, 0) + A(2, 0)); EXPECT_DOUBLE_EQ(A_plus_A(2, 4), A(2, 4) + A(2, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_A(3, 0), A(3, 0) + A(3, 0)); EXPECT_DOUBLE_EQ(A_plus_A(3, 4), A(3, 4) + A(3, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(A_plus_A(4, 0), A(4, 0) + A(4, 0)); EXPECT_DOUBLE_EQ(A_plus_A(4, 4), A(4, 4) + A(4, 4));
|
||||||
|
|
||||||
|
// Test : addition matrice(colonne) + matrice(colonne)
|
||||||
|
// Note : teste seulement la première et la dernière colonne
|
||||||
|
const auto B_plus_B = B + B;
|
||||||
|
EXPECT_DOUBLE_EQ(B_plus_B(0, 0), B(0, 0) + B(0, 0)); EXPECT_DOUBLE_EQ(B_plus_B(0, 4), B(0, 4) + B(0, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(B_plus_B(1, 0), B(1, 0) + B(1, 0)); EXPECT_DOUBLE_EQ(B_plus_B(1, 4), B(1, 4) + B(1, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(B_plus_B(2, 0), B(2, 0) + B(2, 0)); EXPECT_DOUBLE_EQ(B_plus_B(2, 4), B(2, 4) + B(2, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(B_plus_B(3, 0), B(3, 0) + B(3, 0)); EXPECT_DOUBLE_EQ(B_plus_B(3, 4), B(3, 4) + B(3, 4));
|
||||||
|
EXPECT_DOUBLE_EQ(B_plus_B(4, 0), B(4, 0) + B(4, 0)); EXPECT_DOUBLE_EQ(B_plus_B(4, 4), B(4, 4) + B(4, 4));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test pour la multiplication matrice * vecteur
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1b, MatrixVectorOperators)
|
||||||
|
{
|
||||||
|
// Vecteur à taille dynamique
|
||||||
|
Vector<double> v(5);
|
||||||
|
v(0) = 1.0;
|
||||||
|
v(1) = 2.0;
|
||||||
|
v(2) = 4.0;
|
||||||
|
v(3) = 8.0;
|
||||||
|
v(4) = 16.0;
|
||||||
|
|
||||||
|
// Test : multiplication par la matrice identité
|
||||||
|
{
|
||||||
|
Matrix<double> M(5, 5);
|
||||||
|
M.setIdentity();
|
||||||
|
|
||||||
|
const auto b = M * v;
|
||||||
|
EXPECT_DOUBLE_EQ(b(0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b(1), 2.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b(2), 4.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b(3), 8.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b(4), 16.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test : multiplication par une matrice à taille dynamique avec stockage par ligne.
|
||||||
|
{
|
||||||
|
Matrix<double, Dynamic, Dynamic, RowStorage> M(5, 5);
|
||||||
|
M.setIdentity();
|
||||||
|
M = 2.0 * M;
|
||||||
|
|
||||||
|
Vector<double> b2 = M * v;
|
||||||
|
EXPECT_DOUBLE_EQ(b2(0), 2.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b2(1), 4.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b2(2), 8.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b2(3), 16.0);
|
||||||
|
EXPECT_DOUBLE_EQ(b2(4), 32.0);
|
||||||
|
}
|
||||||
|
// Test : autres
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = 89.63885274026418; u(1) = 33.98267508829284; u(2) = 58.18085749457168;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = -37.761291293282206; m33(0, 1) = -58.77833883088219; m33(0, 2) = -80.31292383738193; m33(1, 0) = 82.42200051847567; m33(1, 1) = -21.616077216647483; m33(1, 2) = -81.41765352024458; m33(2, 0) = -1.826095889555674; m33(2, 1) = -72.65845670305742; m33(2, 2) = -68.43559055076148;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = -0.6810804556978075; m44(0, 1) = -0.3717461369121619; m44(0, 2) = -0.6308202775413543; m44(0, 3) = 65.25663257716863; m44(1, 0) = -0.7322085856273928; m44(1, 1) = 0.3457881173505905; m44(1, 2) = 0.5867718168356992; m44(1, 3) = -72.82746334890318; m44(2, 0) = 0.0; m44(2, 1) = 0.8615308396047228; m44(2, 2) = -0.5077052416609282; m44(2, 3) = -50.951590508183095; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), -10054.998796995307, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), 1916.692541293076, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), -6614.459208480986, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), -45.129230953732865, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), -92.57210823264782, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), -51.21319422167322, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = 21.26102327359945; u(1) = -63.632003812151375; u(2) = 21.749676556807557;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = -72.46587508929531; m33(0, 1) = 26.74413795088728; m33(0, 2) = 66.40155978725781; m33(1, 0) = 30.554539344667063; m33(1, 1) = 34.707428553000256; m33(1, 2) = -78.73225643210714; m33(2, 0) = 29.88002386285075; m33(2, 1) = 84.40743250651678; m33(2, 2) = 89.33116036637102;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = -0.8156253236747055; m44(0, 1) = 0.0; m44(0, 2) = 0.5785804450381398; m44(0, 3) = -36.44550865077372; m44(1, 0) = -0.4886547783002762; m44(1, 1) = 0.5354367269787551; m44(1, 2) = -0.6888570381774334; m44(1, 3) = 26.24571159164249; m44(2, 0) = -0.3097932197851331; m44(2, 1) = -0.8445753438280554; m44(2, 2) = -0.43671575374937205; m44(2, 3) = 58.09911341828064; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), -1798.269296618443, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), -3271.2835658593685, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), -2792.8103398519333, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), -41.2026000982854, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), -33.19691864907287, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), 95.75618766923024, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = 60.89920397428068; u(1) = 41.99263628824008; u(2) = 2.8397811977043403;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = 37.756340946034896; m33(0, 1) = 34.695096214807364; m33(0, 2) = 71.82563147437446; m33(1, 0) = 74.91874228380777; m33(1, 1) = 11.371524438829937; m33(1, 2) = 22.662878030996694; m33(2, 0) = -33.183135422386044; m33(2, 1) = -48.81237469926953; m33(2, 2) = 77.28631280104915;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = 0.09071108841607319; m44(0, 1) = 0.15875989354807826; m44(0, 2) = -0.9831412892555038; m44(0, 3) = -20.28034322391565; m44(1, 0) = 0.8682639927927074; m44(1, 1) = -0.49610244790735053; m44(1, 2) = 0.0; m44(1, 3) = -65.91591665493024; m44(2, 0) = -0.487738800238444; m44(2, 1) = -0.8536261812883538; m44(2, 2) = -0.18284749208295362; m44(2, 3) = -28.08938117342305; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), 3960.2387427031354, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), 5104.369672559086, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), -3851.1106117734685, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), -10.881269828726621, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), -33.87198031100272, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), -94.15754648234068, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = 5.188467455547638; u(1) = 18.80451508110363; u(2) = -21.656727889135595;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = 87.9457818703861; m33(0, 1) = 73.05874068692381; m33(0, 2) = 39.940251688233246; m33(1, 0) = 75.10237717805055; m33(1, 1) = 72.18489393198146; m33(1, 2) = 99.55423077694917; m33(2, 0) = -23.406607601688265; m33(2, 1) = 36.642344803461384; m33(2, 2) = 59.655570064408465;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = 0.17067228277067772; m44(0, 1) = -0.6737686724718157; m44(0, 2) = -0.7189622715340582; m44(0, 3) = -18.335201879756795; m44(1, 0) = -0.9693828421385298; m44(1, 1) = -0.24555428191629253; m44(1, 2) = 0.0; m44(1, 3) = 29.845708309352148; m44(2, 0) = -0.1765442643114522; m44(2, 1) = 0.6969496901700587; m44(2, 2) = -0.6950491005034012; m44(2, 3) = -31.894796135192152; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), 965.1628555052321, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), -408.9507197542059, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), -724.347344278602, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), -14.549197180540624, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), 20.198567783425617, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), -4.652500106271733, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = 37.47349664672282; u(1) = -60.74514266373965; u(2) = -40.46471876369226;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = -18.595918421354753; m33(0, 1) = -63.34971612297557; m33(0, 2) = 51.78315639657973; m33(1, 0) = 60.68830258069576; m33(1, 1) = -63.44130757420927; m33(1, 2) = 0.1227343978225548; m33(2, 0) = 69.14823593166864; m33(2, 1) = 49.45675635266332; m33(2, 2) = 81.76280170074256;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = -0.250151688477416; m44(0, 1) = -0.2581347286114716; m44(0, 2) = -0.9331616122819132; m44(0, 3) = 15.902624286413442; m44(1, 0) = -0.7181238873483027; m44(1, 1) = 0.6959152839389017; m44(1, 2) = 0.0; m44(1, 3) = -12.358184768214258; m44(2, 0) = 0.6494014283720508; m44(2, 1) = 0.6701256445360971; m44(2, 2) = -0.3594570980846258; m44(2, 3) = -95.12313555065694; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), 1055.9425967082998, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), 6122.987769732011, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), -3721.5403091682488, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), 59.969118945113756, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), -81.54227105743792, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), -96.94934080054827, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = -18.242981648343232; u(1) = 56.21809486615007; u(2) = 68.42388784251386;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = 72.32617531563085; m33(0, 1) = 16.921578626504015; m33(0, 2) = -27.34080821434577; m33(1, 0) = 75.31926937290174; m33(1, 1) = -81.4337114340538; m33(1, 2) = 49.516021610363254; m33(2, 0) = 40.651084247784695; m33(2, 1) = -19.615350275581747; m33(2, 2) = 96.61096468197644;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = 0.8628144975844739; m44(0, 1) = -0.39604187777629973; m44(0, 2) = 0.3141687027784186; m44(0, 3) = -15.592609294116613; m44(1, 0) = -0.5055206650158348; m44(1, 1) = -0.6759578736217757; m44(1, 2) = 0.5362180622943203; m44(1, 3) = 10.857285613068584; m44(2, 0) = 0.0; m44(2, 1) = -0.6214754895699024; m44(2, 2) = -0.7834336065448367; m44(2, 3) = -95.09026591014809; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), -2238.9105712501655, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), -2564.0174545638056, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), 4766.163205213616, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), -32.1009941127323, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), 18.768550516577342, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), -183.634007166056, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = -59.27939726364973; u(1) = 96.57872437189005; u(2) = -50.71931054476342;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = -53.51188145034156; m33(0, 1) = -39.773533094835024; m33(0, 2) = -81.91533947789623; m33(1, 0) = -48.98656664587613; m33(1, 1) = -30.35481126192778; m33(1, 2) = -24.41812181189411; m33(2, 0) = 50.987332445586844; m33(2, 1) = -15.614790715203753; m33(2, 2) = 1.953005394977339;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = -0.9781360701985449; m44(0, 1) = 0.0; m44(0, 2) = -0.20796593032645286; m44(0, 3) = 31.079492180635583; m44(1, 0) = 0.17988007252338098; m44(1, 1) = 0.5018585333987298; m44(1, 2) = -0.846038516832336; m44(1, 3) = 89.95140758767585; m44(2, 0) = 0.10436947679053606; m44(2, 1) = -0.8649497167205016; m44(2, 2) = -0.4908859336542387; m44(2, 3) = -66.61272043333199; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), 3485.5645301169448, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), 1210.7354976539962, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), -4629.6099911875845, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), 99.6106974667983, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), 170.66757254759543, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), -131.4380242858257, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = -33.64679408120854; u(1) = 57.74585710730173; u(2) = -38.78100535372986;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = -48.76215910463826; m33(0, 1) = -17.88064937607517; m33(0, 2) = -10.666843689761578; m33(1, 0) = 54.129177432133815; m33(1, 1) = -50.3409670888066; m33(1, 2) = 67.92880818886752; m33(2, 0) = -36.14536761608753; m33(2, 1) = 92.53432169416001; m33(2, 2) = 68.69365938680332;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = 0.4751126538005149; m44(0, 1) = 0.5241078534879362; m44(0, 2) = -0.7068089728568109; m44(0, 3) = 7.21266115268952; m44(1, 0) = -0.7408885299063788; m44(1, 1) = 0.671628011813954; m44(1, 2) = 0.0; m44(1, 3) = -99.71424185587028; m44(2, 0) = 0.4747127051720829; m44(2, 1) = 0.5236666608245202; m44(2, 2) = 0.7074044641427562; m44(2, 3) = -11.057694172067542; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), 1021.8278247323343, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), -7362.603053042772, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), 3895.640286793221, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), 48.90246330164035, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), -36.001982853511294, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), -24.22453095406812, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = 15.282052878141911; u(1) = -2.259998336973041; u(2) = 91.08586195638563;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = -88.39582865245377; m33(0, 1) = -64.58071224128338; m33(0, 2) = -4.675696828923634; m33(1, 0) = -86.1584474938788; m33(1, 1) = -34.543435043656444; m33(1, 2) = -62.495745585883625; m33(2, 0) = -59.183456388092395; m33(2, 1) = -57.14307430989349; m33(2, 2) = 44.41751022537625;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = 0.44386855289227883; m44(0, 1) = 0.5950916475208161; m44(0, 2) = 0.6699601770286612; m44(0, 3) = -72.72024311218823; m44(1, 0) = -0.8960919080949868; m44(1, 1) = 0.29477162558569525; m44(1, 2) = 0.33185686823727545; m44(1, 3) = 15.476209050615353; m44(2, 0) = 0.0; m44(2, 1) = -0.7476467212531113; m44(2, 2) = 0.6640966648007446; m44(2, 3) = 99.8824543736142; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), -1630.8073013173835, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), -6931.088700045262, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), 3270.5057477108207, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), -6.258026348579378, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), 31.343370633361097, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), 162.0619518560263, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Vector<double, 3> u; u(0) = -45.53190350588168; u(1) = 98.18869916536156; u(2) = 82.67567746788419;
|
||||||
|
Matrix<double, 3, 3, ColumnStorage> m33;
|
||||||
|
m33(0, 0) = -51.297389589304785; m33(0, 1) = -66.59459838930371; m33(0, 2) = 27.56805306675247; m33(1, 0) = 96.48690448918092; m33(1, 1) = 9.10079699500524; m33(1, 2) = 83.88487605323621; m33(2, 0) = 41.570057963368356; m33(2, 1) = 24.52264689542079; m33(2, 2) = -76.44940699537474;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m44;
|
||||||
|
m44(0, 0) = 0.774965095070908; m44(0, 1) = 0.0; m44(0, 2) = 0.6320040359220331; m44(0, 3) = -94.78257020280037; m44(1, 0) = -0.5539089538751407; m44(1, 1) = 0.4815245168438749; m44(1, 2) = 0.6792046896887713; m44(1, 3) = 63.87247725975902; m44(2, 0) = -0.3043254380407359; m44(2, 1) = -0.8764326212997054; m44(2, 2) = 0.3731646929748866; m44(2, 3) = -95.85244653326883; m44(3, 0) = 0.0; m44(3, 1) = 0.0; m44(3, 2) = 0.0; m44(3, 3) = 1.0;
|
||||||
|
Vector<double, 3> v = m33 * u;
|
||||||
|
EXPECT_NEAR(v(0), -1923.9617306372265, 1e-3);
|
||||||
|
EXPECT_NEAR(v(1), 3435.6019505357876, 1e-3);
|
||||||
|
EXPECT_NEAR(v(2), -5805.423584529748, 1e-3);
|
||||||
|
Vector<double, 3> w = m44 * u;
|
||||||
|
EXPECT_NEAR(w(0), -77.81684429970429, 1e-3);
|
||||||
|
EXPECT_NEAR(w(1), 192.52698008315832, 1e-3);
|
||||||
|
EXPECT_NEAR(w(2), -137.20006524672516, 1e-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opérateurs d'arithmétique vectorielle
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1b, VectorOperators)
|
||||||
|
{
|
||||||
|
Vector<double> v(5);
|
||||||
|
v(0) = 0.1;
|
||||||
|
v(1) = 0.2;
|
||||||
|
v(2) = 0.4;
|
||||||
|
v(3) = 0.8;
|
||||||
|
v(4) = 1.6;
|
||||||
|
|
||||||
|
// Test : multiplication scalaire * vecteur
|
||||||
|
const double alpha = 4.0;
|
||||||
|
const auto v2 = alpha * v;
|
||||||
|
EXPECT_DOUBLE_EQ(v2(0), alpha * v(0));
|
||||||
|
EXPECT_DOUBLE_EQ(v2(1), alpha * v(1));
|
||||||
|
EXPECT_DOUBLE_EQ(v2(2), alpha * v(2));
|
||||||
|
EXPECT_DOUBLE_EQ(v2(3), alpha * v(3));
|
||||||
|
EXPECT_DOUBLE_EQ(v2(4), alpha * v(4));
|
||||||
|
|
||||||
|
// Test : addition vecteur + vecteur
|
||||||
|
const auto v3 = v + v2;
|
||||||
|
EXPECT_DOUBLE_EQ(v3(0), v(0) + v2(0));
|
||||||
|
EXPECT_DOUBLE_EQ(v3(1), v(1) + v2(1));
|
||||||
|
EXPECT_DOUBLE_EQ(v3(2), v(2) + v2(2));
|
||||||
|
EXPECT_DOUBLE_EQ(v3(3), v(3) + v2(3));
|
||||||
|
EXPECT_DOUBLE_EQ(v3(4), v(4) + v2(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mathématiques 3D
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1b, Math3D)
|
||||||
|
{
|
||||||
|
// Test : norme d'un vecteur de dimension 3
|
||||||
|
Vector3d v;
|
||||||
|
v.setZero();
|
||||||
|
v(1) = 2.0;
|
||||||
|
EXPECT_EQ(v.rows(), 3);
|
||||||
|
EXPECT_EQ(v.cols(), 1);
|
||||||
|
EXPECT_DOUBLE_EQ(v(0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v(1), 2.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v(2), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v.norm(), 2.0);
|
||||||
|
|
||||||
|
// Test : calcul de la norme d'un deuxième vecteur 3D
|
||||||
|
Vector3d v2;
|
||||||
|
v2(0) = 4.0;
|
||||||
|
v2(1) = 2.0;
|
||||||
|
v2(2) = 5.0;
|
||||||
|
EXPECT_EQ(v2.rows(), 3);
|
||||||
|
EXPECT_EQ(v2.cols(), 1);
|
||||||
|
EXPECT_DOUBLE_EQ(v2(0), 4.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v2(1), 2.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v2(2), 5.0);
|
||||||
|
EXPECT_DOUBLE_EQ(v2.norm(), 6.7082039324993690892275210061938);
|
||||||
|
|
||||||
|
// Test : produit scalaire
|
||||||
|
EXPECT_DOUBLE_EQ(v.dot(v2), 4.0);
|
||||||
|
|
||||||
|
// Test : matrice identité 4x4
|
||||||
|
Matrix4d M;
|
||||||
|
M.setIdentity();
|
||||||
|
EXPECT_DOUBLE_EQ(M(0, 0), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(M(0, 1), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(M(0, 2), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(M(1, 1), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(M(1, 0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(M(1, 2), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(M(2, 0), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(M(2, 1), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(M(2, 2), 1.0);
|
||||||
|
|
||||||
|
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des x
|
||||||
|
const auto Rx = makeRotation<double>(M_PI / 4.0, 0, 0);
|
||||||
|
EXPECT_NEAR(Rx(0, 0), 1, 1e-3); EXPECT_NEAR(Rx(0, 1), 0, 1e-3); EXPECT_NEAR(Rx(0, 2), 0, 1e-3);
|
||||||
|
EXPECT_NEAR(Rx(1, 0), 0, 1e-3); EXPECT_NEAR(Rx(1, 1), 0.7071, 1e-3); EXPECT_NEAR(Rx(1, 2), -0.7071, 1e-3);
|
||||||
|
EXPECT_NEAR(Rx(2, 0), 0, 1e-3); EXPECT_NEAR(Rx(2, 1), 0.7071, 1e-3); EXPECT_NEAR(Rx(2, 2), 0.7071, 1e-3);
|
||||||
|
|
||||||
|
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des y
|
||||||
|
const auto Ry = makeRotation<double>(0, M_PI / 4.0, 0);
|
||||||
|
EXPECT_NEAR(Ry(0, 0), 0.7071, 1e-3); EXPECT_NEAR(Ry(0, 1), 0, 1e-3); EXPECT_NEAR(Ry(0, 2), 0.7071, 1e-3);
|
||||||
|
EXPECT_NEAR(Ry(1, 0), 0, 1e-3); EXPECT_NEAR(Ry(1, 1), 1, 1e-3); EXPECT_NEAR(Ry(1, 2), 0, 1e-3);
|
||||||
|
EXPECT_NEAR(Ry(2, 0), -0.7071, 1e-3); EXPECT_NEAR(Ry(2, 1), 0, 1e-3); EXPECT_NEAR(Ry(2, 2), 0.7071, 1e-3);
|
||||||
|
|
||||||
|
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des z
|
||||||
|
const auto Rz = makeRotation<double>(0, 0, M_PI / 4.0);
|
||||||
|
EXPECT_NEAR(Rz(0, 0), 0.7071, 1e-3); EXPECT_NEAR(Rz(0, 1), -0.7071, 1e-3); EXPECT_NEAR(Rz(0, 2), 0, 1e-3);
|
||||||
|
EXPECT_NEAR(Rz(1, 0), 0.7071, 1e-3); EXPECT_NEAR(Rz(1, 1), 0.7071, 1e-3); EXPECT_NEAR(Rz(1, 2), 0, 1e-3);
|
||||||
|
EXPECT_NEAR(Rz(2, 0), 0, 1e-3); EXPECT_NEAR(Rz(2, 1), 0, 1e-3); EXPECT_NEAR(Rz(2, 2), 1, 1e-3);
|
||||||
|
|
||||||
|
// Test : création d'une matrice de rotation quelconque.
|
||||||
|
const auto Rxyz = makeRotation<double>(M_PI / 3.0, -M_PI / 6.0, M_PI / 4.0);
|
||||||
|
EXPECT_NEAR(Rxyz(0, 0), 0.6124, 1e-3); EXPECT_NEAR(Rxyz(0, 1), -0.6597, 1e-3); EXPECT_NEAR(Rxyz(0, 2), 0.4356, 1e-3);
|
||||||
|
EXPECT_NEAR(Rxyz(1, 0), 0.6124, 1e-3); EXPECT_NEAR(Rxyz(1, 1), 0.0474, 1e-3); EXPECT_NEAR(Rxyz(1, 2), -0.7891, 1e-3);
|
||||||
|
EXPECT_NEAR(Rxyz(2, 0), 0.5, 1e-3); EXPECT_NEAR(Rxyz(2, 1), 0.75, 1e-3); EXPECT_NEAR(Rxyz(2, 2), 0.4330, 1e-3);
|
||||||
|
|
||||||
|
// Test : création d'une transformation homogène via la sous-matrice 3x3 en
|
||||||
|
// utilisant la fonction `block`
|
||||||
|
M.block(0, 0, 3, 3) = Rxyz;
|
||||||
|
M(0, 3) = -0.1;
|
||||||
|
M(1, 3) = 1.0;
|
||||||
|
M(2, 3) = 2.1;
|
||||||
|
|
||||||
|
// Test : calcule l'inverse de la matrice M et vérifie que M^(-1) * M * v = v
|
||||||
|
const Matrix4d Minv = M.inverse();
|
||||||
|
const Vector3d v3 = Minv * (M * v2);
|
||||||
|
EXPECT_DOUBLE_EQ(v3(0), v2(0));
|
||||||
|
EXPECT_DOUBLE_EQ(v3(1), v2(1));
|
||||||
|
EXPECT_DOUBLE_EQ(v3(2), v2(2));
|
||||||
|
|
||||||
|
// Test : translation d'un vecteur 3D effectuée avec une matrice 4x4 en coordonnées homogènes
|
||||||
|
Matrix4d T;
|
||||||
|
T.setIdentity();
|
||||||
|
T(0, 3) = 1.2;
|
||||||
|
T(1, 3) = 2.5;
|
||||||
|
T(2, 3) = -4.0;
|
||||||
|
const Vector3d t = T * v3;
|
||||||
|
EXPECT_DOUBLE_EQ(t(0), v3(0) + 1.2);
|
||||||
|
EXPECT_DOUBLE_EQ(t(1), v3(1) + 2.5);
|
||||||
|
EXPECT_DOUBLE_EQ(t(2), v3(2) - 4.0);
|
||||||
|
|
||||||
|
// Test : inverse d'un matrice de rotation
|
||||||
|
const Matrix3d Rinv = Rxyz.inverse();
|
||||||
|
const Matrix3d RT = Rxyz.transpose<double, 3, 3, ColumnStorage>();
|
||||||
|
EXPECT_DOUBLE_EQ(Rinv(0, 0), RT(0, 0));
|
||||||
|
EXPECT_DOUBLE_EQ(Rinv(1, 1), RT(1, 1));
|
||||||
|
EXPECT_DOUBLE_EQ(Rinv(0, 2), RT(0, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TestLabo1b, RigidTransformInverse) {
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = -0.7899179842354741; m(0, 1) = 0.5558875173441905; m(0, 2) = 0.2588795979645317; m(0, 3) = 63.53646575655944; m(1, 0) = -0.6132125065435026; m(1, 1) = -0.7160740240561843; m(1, 2) = -0.3334792555626483; m(1, 3) = 46.40415080808421; m(2, 0) = 0.0; m(2, 1) = -0.4221694684991984; m(2, 2) = 0.9065169275127214; m(2, 3) = 37.91755407005138; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), -0.7899179842354742, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), -0.6132125065435026, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), 5.0321798256853854e-17, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), 78.64420258691568, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), 0.5558875173441905, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), -0.7160740240561843, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), -0.42216946849919834, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), 13.917312440360101, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), 0.25887959796453164, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), -0.33347925556264824, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), 0.9065169275127212, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), -35.34637765902901, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = 0.6589112893907124; m(0, 1) = -0.32720889915223983; m(0, 2) = 0.6773258071482646; m(0, 3) = -47.579657162583366; m(1, 0) = -0.7522206542720485; m(1, 1) = -0.2866202043457096; m(1, 2) = 0.5933067888937011; m(1, 3) = 30.029355381737275; m(2, 0) = 0.0; m(2, 1) = -0.9004350030826229; m(2, 2) = -0.4349905806147956; m(2, 3) = 80.66547089822612; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), 0.6589112893907124, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), -0.7522206542720486, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), 5.551115123125783e-17, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), 53.939474602384124, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), -0.3272088991522398, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), -0.28662020434570956, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), -0.9004350030826228, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), 65.67254627057903, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), 0.6773258071482645, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), 0.5933067888937011, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), -0.43499058061479545, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), 49.49902929898342, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = -0.12921677297502387; m(0, 1) = 0.0; m(0, 2) = -0.9916163701663668; m(0, 3) = -85.67624239250289; m(1, 0) = 0.5536164401240612; m(1, 1) = -0.8296411663169171; m(1, 2) = -0.07214133611645579; m(1, 3) = -80.61895745285052; m(2, 0) = -0.8226857618837724; m(2, 1) = -0.5582969954713223; m(2, 2) = 0.1072035542387071; m(2, 3) = -59.16846832515195; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), -0.12921677297502387, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), 0.5536164401240611, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), -0.8226857618837723, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), -15.115883774598393, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), -0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), -0.829641166316917, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), -0.5582969954713222, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), -99.91838398100924, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), -0.991616370166367, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), -0.07214133611645579, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), 0.10720355423870709, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), -84.43085369439521, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = 0.6178488588834932; m(0, 1) = 0.656563779114608; m(0, 2) = 0.4326508887441579; m(0, 3) = -3.573389719025613; m(1, 0) = -0.7862968825935693; m(1, 1) = 0.5159084191865928; m(1, 2) = 0.33996428553015007; m(1, 3) = 9.98340634305292; m(2, 0) = 0.0; m(2, 1) = -0.5502385909468138; m(2, 2) = 0.8350074808244923; m(2, 3) = 57.03623931292819; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), 0.6178488588834931, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), -0.7862968825935694, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), -0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), 10.057736045453359, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), 0.656563779114608, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), 0.5159084191865929, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), -0.5502385909468138, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), 28.57917482608178, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), 0.4326508887441579, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), 0.33996428553015007, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), 0.8350074808244924, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), -49.473657871198526, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = -0.30532791727234754; m(0, 1) = 0.42993321248800975; m(0, 2) = -0.8496659906892062; m(0, 3) = -4.900019523419871; m(1, 0) = -0.9522472698486095; m(1, 1) = -0.13785349298616878; m(1, 2) = 0.272436325656807; m(1, 3) = 61.254180348498465; m(2, 0) = 0.0; m(2, 1) = 0.8922745358191345; m(2, 2) = 0.45149324771113447; m(2, 3) = 41.98722428204593; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), -0.3053279172723474, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), -0.9522472698486094, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), 56.83301324799237, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), 0.42993321248800975, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), -0.13785349298616878, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), 0.8922745358191346, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), -26.91334720059331, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), -0.8496659906892063, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), 0.27243632565680703, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), 0.4514932477111345, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), -39.80819202150404, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = -0.8426665329724763; m(0, 1) = -0.13329457405486883; m(0, 2) = 0.5216758291656588; m(0, 3) = 54.75958681320196; m(1, 0) = -0.5384358032376251; m(1, 1) = 0.20860959822407732; m(1, 2) = -0.81643672217793; m(1, 3) = 91.96965943681118; m(2, 0) = 0.0; m(2, 1) = -0.9688728461755547; m(2, 2) = -0.24755889792871488; m(2, 3) = 99.00199341303772; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), -0.8426665329724762, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), -0.5384358032376252, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), -2.7755575615628914e-17, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), 95.66382861923651, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), -0.13329457405486886, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), 0.20860959822407737, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), -0.9688728461755547, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), 84.03374523091135, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), 0.5216758291656588, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), -0.8164367221779302, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), -0.2475588979287149, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), 71.02947881694217, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = -0.7135830808790772; m(0, 1) = 0.0; m(0, 2) = -0.7005706150582712; m(0, 3) = 46.98894352455778; m(1, 0) = 0.5815768734392242; m(1, 1) = 0.5575439866421585; m(1, 2) = -0.5923791380862643; m(1, 3) = -32.31315706340996; m(2, 0) = 0.39059893364393755; m(2, 1) = -0.8301473983330724; m(2, 2) = -0.39785395571371457; m(2, 3) = 7.702713412699751; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), -0.7135830808790772, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), 0.581576873439224, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), 0.39059893364393744, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), 49.314428298230084, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), -5.551115123125783e-17, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), 0.5575439866421584, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), -0.8301473983330723, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), 24.41039390978577, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), -0.7005706150582711, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), -0.5923791380862641, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), -0.3978539557137144, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), 16.841987936840617, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = 0.655199358191179; m(0, 1) = -0.7015590749923188; m(0, 2) = 0.2802296653136303; m(0, 3) = -24.378695814492147; m(1, 0) = -0.7554560219005917; m(1, 1) = -0.6084550818878111; m(1, 2) = 0.24304035117451178; m(1, 3) = 36.943036725120294; m(2, 0) = 0.0; m(2, 1) = -0.3709410702804682; m(2, 2) = -0.928656407063011; m(2, 3) = -32.64950630748629; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), 0.6551993581911789, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), -0.7554560219005915, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), 5.1550786254351327e-17, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), 43.88174541248007, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), -0.7015590749923187, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), -0.6084550818878111, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), -0.37094107028046824, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), -6.735959663194609, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), 0.28022966531363025, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), 0.24304035117451175, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), -0.9286564070630109, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), -32.467188070139514, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = -0.12316316348384228; m(0, 1) = 0.47851608243384774; m(0, 2) = -0.8693981792095123; m(0, 3) = -97.68194268706864; m(1, 0) = -0.9684362001788849; m(1, 1) = -0.24926156178416892; m(1, 2) = 0.0; m(1, 3) = -93.30408292578261; m(2, 0) = -0.2167075479620758; m(2, 1) = 0.8419566691161013; m(2, 2) = 0.4941121390809829; m(2, 3) = -48.17348057895294; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), -0.12316316348384225, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), -0.9684362001788847, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), -0.2167075479620758, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), -112.82942545947078, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), 0.47851608243384763, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), -0.2492615617841688, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), 0.8419566691161011, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), 64.04524235620795, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), -0.8693981792095123, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), 0.49411213908098284, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), -61.12140157794279, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> m;
|
||||||
|
m(0, 0) = -0.8820615884895145; m(0, 1) = -0.11346792289034995; m(0, 2) = -0.45726620757093356; m(0, 3) = -48.8253349197771; m(1, 0) = -0.12758811649101956; m(1, 1) = 0.9918272392560481; m(1, 2) = 0.0; m(1, 3) = 50.033634014775515; m(2, 0) = 0.4535290802601621; m(2, 1) = 0.058341734158967; m(2, 2) = -0.8893298687290875; m(2, 3) = 92.22065810812657; m(3, 0) = 0.0; m(3, 1) = 0.0; m(3, 2) = 0.0; m(3, 3) = 1.0;
|
||||||
|
Matrix<double, 4, 4, ColumnStorage> mi = m.inverse();
|
||||||
|
EXPECT_NEAR(mi(0, 0), -0.8820615884895142, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 1), -0.12758811649101953, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 2), 0.453529080260162, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(0, 3), -78.50800560549041, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 0), -0.11346792289034992, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 1), 0.991827239256048, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 2), 0.05834173415896697, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(1, 3), -60.545143551904374, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 0), -0.45726620757093345, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 1), 6.120531779240618e-18, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 2), -0.8893298687290875, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(2, 3), 59.68841003726312, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 0), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 1), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 2), 0.0, 1e-3);
|
||||||
|
EXPECT_NEAR(mi(3, 3), 1.0, 1e-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test des performance de la multiplication matrice * vecteur
|
||||||
|
* pour de grandes dimensions.
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1b, PerformanceMatrixVector)
|
||||||
|
{
|
||||||
|
Matrix<double> A(16384, 16384); // grande matrice avec stockage colonne
|
||||||
|
Vector<double> v(16384); // grand vecteur
|
||||||
|
|
||||||
|
using namespace std::chrono;
|
||||||
|
// Test : multiplication avec l'algorithme naif.
|
||||||
|
high_resolution_clock::time_point t = high_resolution_clock::now();
|
||||||
|
naiveMatrixMult(A, v);
|
||||||
|
const duration<double> naive_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
|
||||||
|
|
||||||
|
// Test : multiplication avec l'implémentation spécifique pour les matrices avec
|
||||||
|
// stockage par colonnes.
|
||||||
|
t = high_resolution_clock::now();
|
||||||
|
A* v;
|
||||||
|
const duration<double> optimal_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
|
||||||
|
|
||||||
|
EXPECT_TRUE(optimal_t < 0.4 * naive_t)
|
||||||
|
<< "Naive time: " << duration_cast<std::chrono::milliseconds>(naive_t).count() << " ms, "
|
||||||
|
<< "optimized time: " << duration_cast<std::chrono::milliseconds>(optimal_t).count() << " ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test des performances de l'addition matrice + matrice
|
||||||
|
* pour de grandes dimensions.
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1b, PerformanceLargeMatrixMatrix)
|
||||||
|
{
|
||||||
|
// deux grandes matrices à stockage par colonnes
|
||||||
|
Matrix<double> A(16384, 16384);
|
||||||
|
Matrix<double> B(16384, 16384);
|
||||||
|
|
||||||
|
using namespace std::chrono;
|
||||||
|
high_resolution_clock::time_point t = high_resolution_clock::now();
|
||||||
|
// Test : addition avec l'algorithme naif
|
||||||
|
naiveMatrixAddition(A, B);
|
||||||
|
const duration<double> naive_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
|
||||||
|
|
||||||
|
// Test : addition avec l'implémentation spécifique pour les matrices à
|
||||||
|
// stockage par colonnes.
|
||||||
|
t = high_resolution_clock::now();
|
||||||
|
A + B;
|
||||||
|
const duration<double> optimal_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
|
||||||
|
|
||||||
|
EXPECT_TRUE(optimal_t < 0.4 * naive_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test pour la matrice à taille fixe 4D
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1b, Matrix4x4SizeTest)
|
||||||
|
{
|
||||||
|
Matrix4d M;
|
||||||
|
|
||||||
|
EXPECT_EQ(M.cols(), 4);
|
||||||
|
EXPECT_EQ(M.rows(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test pour la matrice à taille fixe 3D
|
||||||
|
*/
|
||||||
|
TEST(TestLabo1b, Matrix3x3SizeTest)
|
||||||
|
{
|
||||||
|
Matrix3d M;
|
||||||
|
|
||||||
|
EXPECT_EQ(M.cols(), 3);
|
||||||
|
EXPECT_EQ(M.rows(), 3);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* @file TestsSupplementaire1a.cpp
|
||||||
|
*
|
||||||
|
* @brief Tests unitaires supplémentaires de la partie 1a
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Matrix.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace gti320;
|
||||||
|
|
||||||
|
TEST(TestLabo1a, Supplementaires)
|
||||||
|
{
|
||||||
|
// TODO vos propres tests ici
|
||||||
|
|
||||||
|
// TEST 1
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 2
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 3
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 4
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 5
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 6
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 7
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 8
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 9
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 10
|
||||||
|
//
|
||||||
|
|
||||||
|
EXPECT_TRUE(false);
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/**
|
||||||
|
* @file TestsSupplementaire1b.cpp
|
||||||
|
*
|
||||||
|
* @brief Tests unitaires supplémentaires de la partie 1b
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Matrix.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
#include "Math3D.h"
|
||||||
|
#include "Operators.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
using namespace gti320;
|
||||||
|
|
||||||
|
TEST(TestLabo1b, Supplementaires)
|
||||||
|
{
|
||||||
|
// TODO vos propres tests ici
|
||||||
|
|
||||||
|
// TEST 1
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 2
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 3
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 4
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 5
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 6
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 7
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 8
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 9
|
||||||
|
//
|
||||||
|
|
||||||
|
// TEST 10
|
||||||
|
//
|
||||||
|
|
||||||
|
EXPECT_TRUE(false);
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Armature.h"
|
||||||
|
|
||||||
|
using namespace gti320;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
//
|
||||||
|
Link::Link(Link* _parent, const Vector3f& _eulerAng, const Vector3f& _trans) :
|
||||||
|
parent(_parent), eulerAng(_eulerAng), trans(_trans)
|
||||||
|
{
|
||||||
|
if (parent != nullptr)
|
||||||
|
{
|
||||||
|
parent->enfants.push_back(this);
|
||||||
|
}
|
||||||
|
M.setIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Link::forward()
|
||||||
|
{
|
||||||
|
// TODO Create a rotation matrix from the Euler angles
|
||||||
|
// of the current link.
|
||||||
|
|
||||||
|
// TODO Create a local 4D rigid transformation matrix from the
|
||||||
|
// 3D rotation matrix and translation of the current link.
|
||||||
|
|
||||||
|
// TODO Update the global transformation for the link using the
|
||||||
|
// parent's rigid transformation matrix and the local transformation.
|
||||||
|
// Hint : the parent matrix should be post-multiplied.
|
||||||
|
// Hint : the root does not have a parent. You must consider this case.
|
||||||
|
|
||||||
|
// TODO Update the transformation of child links
|
||||||
|
// by recursion.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Armature::Armature() : links(), root(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Armature::~Armature()
|
||||||
|
{
|
||||||
|
for (Link* l : links)
|
||||||
|
{
|
||||||
|
delete l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Armature::updateKinematics()
|
||||||
|
{
|
||||||
|
assert(root != nullptr);
|
||||||
|
root->forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Armature::pack(Vector<float, Dynamic>& theta)
|
||||||
|
{
|
||||||
|
// TODO Collect the Euler angles of each link and put them
|
||||||
|
// into the dense vector @a theta
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Armature::unpack(const Vector<float, Dynamic>& theta)
|
||||||
|
{
|
||||||
|
const int numLinks = links.size();
|
||||||
|
assert(theta.size() == 3 * numLinks);
|
||||||
|
|
||||||
|
// TODO Extract the Euler angles contained in the
|
||||||
|
// dense vector @a theta and update the angles
|
||||||
|
// for each link in the armature.
|
||||||
|
//
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math3D.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace gti320
|
||||||
|
{
|
||||||
|
class Link
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor.
|
||||||
|
// @a _parent = the parent link
|
||||||
|
// @a _eulerAng = the initial rotation
|
||||||
|
// @a _trans = the position relative to the parent
|
||||||
|
//
|
||||||
|
Link(Link* _parent, const Vector3f& _eulerAng, const Vector3f& _trans);
|
||||||
|
|
||||||
|
// Return true if this link is the root, false otherwise.
|
||||||
|
//
|
||||||
|
inline bool isRoot() const { return (parent == nullptr); }
|
||||||
|
|
||||||
|
// Return true if this link is an endEffector, false otherwise.
|
||||||
|
//
|
||||||
|
inline bool isEndEffector() const { return (enfants.size() == 0); }
|
||||||
|
|
||||||
|
// Compute the forward kinematics.
|
||||||
|
//
|
||||||
|
void forward();
|
||||||
|
|
||||||
|
Vector3f eulerAng; // Euler angles giving rotation relative to the parent.
|
||||||
|
Vector3f trans; // Translation giving position relative to the parent.
|
||||||
|
Matrix4f M; // Global rigid transformation of the link, computed in forward().
|
||||||
|
Link* parent; // Parent of this link (if the root, nullptr)
|
||||||
|
std::vector<Link*> enfants; // Child links.
|
||||||
|
};
|
||||||
|
|
||||||
|
class Armature
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor.
|
||||||
|
//
|
||||||
|
Armature();
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
//
|
||||||
|
~Armature();
|
||||||
|
|
||||||
|
// Forward kinematics to update the global transforms of all links.
|
||||||
|
//
|
||||||
|
void updateKinematics();
|
||||||
|
|
||||||
|
// Extract the Euler angles of all links and put them in the dense vector @a theta.
|
||||||
|
//
|
||||||
|
void pack(Vector<float, Dynamic>& theta);
|
||||||
|
|
||||||
|
// Update the Euler angles of all links on the armature from the vector @a theta.
|
||||||
|
//
|
||||||
|
void unpack(const Vector<float, Dynamic>& theta);
|
||||||
|
|
||||||
|
std::vector<Link*> links; // All of the articulated links that make-up the armature.
|
||||||
|
Link* root; // The root link.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
|
project(labo_ik)
|
||||||
|
|
||||||
|
# Setup language requirements
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
#--------------------------------------------------
|
||||||
|
# Sous MAC, OpenGL est Deprecated, mais toujours
|
||||||
|
# fonctionnel, on veut éviter tous les warnings
|
||||||
|
# durant la compilation.
|
||||||
|
#--------------------------------------------------
|
||||||
|
if (APPLE)
|
||||||
|
add_definitions( -DGL_SILENCE_DEPRECATION )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(${NANOGUI_EXTRA_DEFS})
|
||||||
|
include_directories(${nanogui_SRC_DIR}/include)
|
||||||
|
include_directories(${NANOGUI_EXTRA_INCS})
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/../labo01/src ${COMMON_INCLUDES})
|
||||||
|
|
||||||
|
find_package(OpenGL REQUIRED)
|
||||||
|
|
||||||
|
# Add .cpp and .h files
|
||||||
|
set(HEADERS IKApplication.h IKGLCanvas.h LinkUI.h TargetUI.h Armature.h IKSolver.h SVD.h)
|
||||||
|
set(SOURCE main.cpp IKApplication.cpp IKGLCanvas.cpp LinkUI.cpp TargetUI.cpp Armature.cpp IKSolver.cpp)
|
||||||
|
add_executable(labo_ik ${SOURCE} ${HEADERS})
|
||||||
|
|
||||||
|
target_link_libraries(labo_ik nanogui opengl32 ${NANOGUI_EXTRA_LIBS})
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
set_property(TARGET labo_ik PROPERTY VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/labo_ik)
|
||||||
|
endif()
|
|
@ -0,0 +1,189 @@
|
||||||
|
#include "IKApplication.h"
|
||||||
|
#include "IKGLCanvas.h"
|
||||||
|
|
||||||
|
#include <nanogui/window.h>
|
||||||
|
#include <nanogui/formhelper.h>
|
||||||
|
#include <nanogui/layout.h>
|
||||||
|
#include <nanogui/label.h>
|
||||||
|
#include <nanogui/checkbox.h>
|
||||||
|
#include <nanogui/button.h>
|
||||||
|
#include <nanogui/toolbutton.h>
|
||||||
|
#include <nanogui/popupbutton.h>
|
||||||
|
#include <nanogui/combobox.h>
|
||||||
|
#include <nanogui/textbox.h>
|
||||||
|
#include <nanogui/slider.h>
|
||||||
|
#include <nanogui/vscrollpanel.h>
|
||||||
|
#include <nanogui/graph.h>
|
||||||
|
#include <nanogui/tabwidget.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "IKSolver.h"
|
||||||
|
|
||||||
|
using namespace nanogui;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// Random number generator.
|
||||||
|
// Returns a random value such that _min <= val <= _max
|
||||||
|
//
|
||||||
|
template<typename _Scalar>
|
||||||
|
static inline _Scalar rand(_Scalar _min, _Scalar _max)
|
||||||
|
{
|
||||||
|
static std::random_device rdev;
|
||||||
|
static std::default_random_engine re(rdev());
|
||||||
|
|
||||||
|
// Using uniform distribution (recommended since C++11)
|
||||||
|
typedef typename std::conditional<
|
||||||
|
std::is_floating_point<_Scalar>::value,
|
||||||
|
std::uniform_real_distribution<_Scalar>,
|
||||||
|
std::uniform_int_distribution<_Scalar>>::type dist_type;
|
||||||
|
dist_type uni(_min, _max);
|
||||||
|
return static_cast<_Scalar>(uni(re));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
IKApplication::IKApplication() : Screen(Vector2i(1280, 720), "GTI320 Labo sur la cinematique inverse"),
|
||||||
|
m_targetPos()
|
||||||
|
{
|
||||||
|
m_armature = std::make_unique<gti320::Armature>();
|
||||||
|
m_ikSolver = std::make_unique<gti320::IKSolver>(m_armature.get(), m_targetPos);
|
||||||
|
|
||||||
|
initializeTarget();
|
||||||
|
initializeArmature();
|
||||||
|
|
||||||
|
m_window = new Window(this, "Cinematique inverse");
|
||||||
|
m_window->set_position(Vector2i(8, 8));
|
||||||
|
m_window->set_layout(new GroupLayout());
|
||||||
|
|
||||||
|
m_canvas = std::make_unique<IKGLCanvas>(this);
|
||||||
|
m_canvas->set_background_color({ 255, 255, 255, 255 });
|
||||||
|
m_canvas->set_size({ 1080, 600 });
|
||||||
|
|
||||||
|
Window* controls = new Window(this, "Controls");
|
||||||
|
controls->set_position(Vector2i(1020, 10));
|
||||||
|
controls->set_layout(new GroupLayout());
|
||||||
|
|
||||||
|
Widget* tools = new Widget(controls);
|
||||||
|
tools->set_layout(new BoxLayout(Orientation::Vertical, Alignment::Middle, 0, 5));
|
||||||
|
|
||||||
|
m_targetUI = std::make_unique<TargetUI>(tools, m_targetPos);
|
||||||
|
|
||||||
|
const int numLinks = m_armature->links.size();
|
||||||
|
for (int i = 0; i < numLinks; ++i)
|
||||||
|
{
|
||||||
|
gti320::Link* link = m_armature->links[i];
|
||||||
|
if (!link->isEndEffector())
|
||||||
|
{
|
||||||
|
m_linkUIArr.push_back(new LinkUI(m_armature->links[i], i, tools));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button* solveButton = new Button(tools, "IK solve");
|
||||||
|
solveButton->set_callback([this]
|
||||||
|
{
|
||||||
|
ikSolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
Button* resetButton = new Button(tools, "Reset");
|
||||||
|
resetButton->set_callback([this]
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
perform_layout();
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IKApplication::keyboard_event(int key, int scancode, int action, int modifiers)
|
||||||
|
{
|
||||||
|
if (Screen::keyboard_event(key, scancode, action, modifiers))
|
||||||
|
return true;
|
||||||
|
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
|
||||||
|
set_visible(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKApplication::draw(NVGcontext* ctx)
|
||||||
|
{
|
||||||
|
assert(m_armature->root != nullptr);
|
||||||
|
|
||||||
|
m_armature->updateKinematics();
|
||||||
|
|
||||||
|
// Draw the user interface
|
||||||
|
Screen::draw(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKApplication::reset()
|
||||||
|
{
|
||||||
|
// Reset all joints to zero angle
|
||||||
|
//
|
||||||
|
for (gti320::Link* l : m_armature->links)
|
||||||
|
{
|
||||||
|
l->eulerAng.setZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the armature
|
||||||
|
//
|
||||||
|
m_armature->updateKinematics();
|
||||||
|
|
||||||
|
// Update UI
|
||||||
|
//
|
||||||
|
for (LinkUI* ui : m_linkUIArr)
|
||||||
|
{
|
||||||
|
ui->onArmatureChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKApplication::ikSolve()
|
||||||
|
{
|
||||||
|
m_ikSolver->solve();
|
||||||
|
for (LinkUI* ui : m_linkUIArr)
|
||||||
|
{
|
||||||
|
ui->onArmatureChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKApplication::initializeArmature()
|
||||||
|
{
|
||||||
|
// Initialize the armature
|
||||||
|
//
|
||||||
|
gti320::Vector3f angs;
|
||||||
|
angs.setZero();
|
||||||
|
gti320::Vector3f t;
|
||||||
|
|
||||||
|
// Root
|
||||||
|
t.setZero();
|
||||||
|
gti320::Link* link0 = new gti320::Link(nullptr, angs, t);
|
||||||
|
|
||||||
|
// First joint
|
||||||
|
t(1) = 1.5f;
|
||||||
|
gti320::Link* link1 = new gti320::Link(link0, angs, t);
|
||||||
|
|
||||||
|
// Second joint
|
||||||
|
t(1) = 0.75f;
|
||||||
|
gti320::Link* link2 = new gti320::Link(link1, angs, t);
|
||||||
|
|
||||||
|
// End-effector
|
||||||
|
t(1) = 0.25f;
|
||||||
|
gti320::Link* link3 = new gti320::Link(link2, angs, t);
|
||||||
|
|
||||||
|
m_armature->links.push_back(link0);
|
||||||
|
m_armature->links.push_back(link1);
|
||||||
|
m_armature->links.push_back(link2);
|
||||||
|
m_armature->links.push_back(link3);
|
||||||
|
m_armature->root = link0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKApplication::initializeTarget()
|
||||||
|
{
|
||||||
|
m_targetPos(0) = 1.0f;
|
||||||
|
m_targetPos(1) = 1.0f;
|
||||||
|
m_targetPos(2) = 0.0f;
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file IKApplication.h
|
||||||
|
*
|
||||||
|
* @brief Application class for labo 2.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <nanogui/window.h>
|
||||||
|
#include <nanogui/textbox.h>
|
||||||
|
#include <nanogui/label.h>
|
||||||
|
#include <nanogui/layout.h>
|
||||||
|
#include <nanogui/slider.h>
|
||||||
|
#include <nanogui/screen.h>
|
||||||
|
#include <nanogui/vscrollpanel.h>
|
||||||
|
|
||||||
|
#include "Armature.h"
|
||||||
|
#include "LinkUI.h"
|
||||||
|
#include "TargetUI.h"
|
||||||
|
#include "IKSolver.h"
|
||||||
|
#include "Math3D.h"
|
||||||
|
|
||||||
|
class IKGLCanvas;
|
||||||
|
|
||||||
|
// Iterative closest point algorithm
|
||||||
|
//
|
||||||
|
class IKApplication : public nanogui::Screen
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IKApplication();
|
||||||
|
|
||||||
|
virtual bool keyboard_event(int key, int scancode, int action, int modifiers) override;
|
||||||
|
|
||||||
|
virtual void draw(NVGcontext *ctx) override;
|
||||||
|
|
||||||
|
nanogui::Window* getWindow() { return m_window.get(); }
|
||||||
|
|
||||||
|
gti320::Armature* getArmature() const { return m_armature.get(); }
|
||||||
|
|
||||||
|
const gti320::Vector3f& getTargetPos() const { return m_targetPos; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Reset the source transform and the initial transform.
|
||||||
|
//
|
||||||
|
void reset();
|
||||||
|
void ikSolve();
|
||||||
|
void initializeArmature();
|
||||||
|
void initializeTarget();
|
||||||
|
|
||||||
|
std::unique_ptr<gti320::IKSolver> m_ikSolver;
|
||||||
|
std::unique_ptr<IKGLCanvas> m_canvas;
|
||||||
|
nanogui::ref<nanogui::Window> m_window;
|
||||||
|
|
||||||
|
std::vector<LinkUI*> m_linkUIArr;
|
||||||
|
std::unique_ptr<TargetUI> m_targetUI;
|
||||||
|
std::unique_ptr<gti320::Armature> m_armature;
|
||||||
|
gti320::Vector3f m_targetPos;
|
||||||
|
};
|
|
@ -0,0 +1,372 @@
|
||||||
|
#include "IKGLCanvas.h"
|
||||||
|
|
||||||
|
#include "IKApplication.h"
|
||||||
|
#include "Armature.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace nanogui;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
static int numCubeVerts, numSphereVerts;
|
||||||
|
static std::vector<float> cubeVerts, sphereVerts;
|
||||||
|
static std::vector<float> cubeNormals, sphereNormals;
|
||||||
|
|
||||||
|
static float axesVerts[] = {
|
||||||
|
0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
|
||||||
|
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f,
|
||||||
|
};
|
||||||
|
|
||||||
|
static float axesColors[] = {
|
||||||
|
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||||
|
0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||||
|
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load OBJ file
|
||||||
|
int loadFile(const std::string& filename, std::vector<float>& _verts, std::vector<float>& _normals)
|
||||||
|
{
|
||||||
|
// Open the input file
|
||||||
|
std::ifstream fs(filename, std::ifstream::in);
|
||||||
|
if (!fs.is_open())
|
||||||
|
{
|
||||||
|
std::cout << "Error: Failed to open file " << filename << " for reading!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read file - first pass count the vertices
|
||||||
|
std::string line;
|
||||||
|
unsigned int vertCount = 0;
|
||||||
|
unsigned int triCount = 0;
|
||||||
|
while (std::getline(fs, line))
|
||||||
|
{
|
||||||
|
if (line[0] == 'v' && line[1] == ' ') ++vertCount;
|
||||||
|
else if (line[0] == 'f' && line[1] == ' ') ++triCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
_verts.resize(triCount * 9);
|
||||||
|
_normals.resize(triCount * 9);
|
||||||
|
|
||||||
|
std::vector<Vector3f> v, vn;
|
||||||
|
|
||||||
|
// Read file - first pass count the vertices
|
||||||
|
int vertIndex = 0;
|
||||||
|
int normalIndex = 0;
|
||||||
|
fs.clear();
|
||||||
|
fs.seekg(std::ios::beg);
|
||||||
|
while (std::getline(fs, line))
|
||||||
|
{
|
||||||
|
if (line[0] == 'v' && line[1] == ' ')
|
||||||
|
{
|
||||||
|
// Vertex! Add it to the list.
|
||||||
|
float x, y, z;
|
||||||
|
std::stringstream ss(line.substr(2));
|
||||||
|
ss >> x >> y >> z;
|
||||||
|
v.push_back(Vector3f(x, y, z));
|
||||||
|
}
|
||||||
|
else if (line[0] == 'v' && line[1] == 'n')
|
||||||
|
{
|
||||||
|
// Normal! Add it to the list.
|
||||||
|
float x, y, z;
|
||||||
|
std::stringstream ss(line.substr(3));
|
||||||
|
ss >> x >> y >> z;
|
||||||
|
vn.push_back(Vector3f(x, y, z));
|
||||||
|
}
|
||||||
|
else if (line[0] == 'f' && line[1] == ' ')
|
||||||
|
{
|
||||||
|
std::stringstream ss(line.substr(2));
|
||||||
|
std::string tok;
|
||||||
|
|
||||||
|
// First tuple
|
||||||
|
for (int k = 0; k < 3; ++k)
|
||||||
|
{
|
||||||
|
if (std::getline(ss, tok, '/'))
|
||||||
|
{
|
||||||
|
const int i = std::stoi(tok);
|
||||||
|
memcpy(&_verts[3 * vertIndex++], v[i - 1].v, sizeof(Vector3f::v));
|
||||||
|
}
|
||||||
|
std::getline(ss, tok, '/');
|
||||||
|
if (std::getline(ss, tok, ' '))
|
||||||
|
{
|
||||||
|
const int i = std::stoi(tok);
|
||||||
|
memcpy(&_normals[3 * normalIndex++], vn[i - 1].v, sizeof(Vector3f::v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.close();
|
||||||
|
return vertIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Matrix3f computeNormalMatrix(const Matrix4f& m)
|
||||||
|
{
|
||||||
|
Matrix3f n;
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
n.m[j][i] = m.m[j][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline Vector3f transformPoint(const Matrix4f& A, const Vector3f& p)
|
||||||
|
{
|
||||||
|
Vector3f p2(0, 0, 0);
|
||||||
|
for (int j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
p2.v[j] += A.m[j][i] * p.v[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p2.v[0] += A.m[3][0];
|
||||||
|
p2.v[1] += A.m[3][1];
|
||||||
|
p2.v[2] += A.m[3][2];
|
||||||
|
return p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void computeVectorRotation(const Vector3f& a, const Vector3f& b, Vector3f& axis, float& theta)
|
||||||
|
{
|
||||||
|
const Vector3f v1 = (nanogui::squared_norm(a) > 1e-4f) ? nanogui::normalize(a) : Vector3f(0.0f, 0.0f, 1.0f);
|
||||||
|
const Vector3f v2 = (nanogui::squared_norm(b) > 1e-4f) ? nanogui::normalize(b) : Vector3f(0.0f, 0.0f, 1.0f);
|
||||||
|
const float dp = std::min(1.0f, std::max(-1.0f, nanogui::dot(v1, v2)));
|
||||||
|
theta = std::acos(dp);
|
||||||
|
if (theta < 1e-4f)
|
||||||
|
{
|
||||||
|
axis.v[0] = 1.0f; axis.v[1] = 0.0f; axis.v[2] = 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
axis = nanogui::normalize(nanogui::cross(v1, v2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IKGLCanvas::IKGLCanvas(IKApplication* _app) : Canvas(_app->getWindow()), m_app(_app)
|
||||||
|
{
|
||||||
|
resetCamera();
|
||||||
|
|
||||||
|
// A simple shader to draw triangle meshes with normals.
|
||||||
|
m_shader = new Shader(render_pass(),
|
||||||
|
// Shader name
|
||||||
|
"draw_link",
|
||||||
|
// Vertex shader
|
||||||
|
R"(#version 410
|
||||||
|
uniform mat4 mvMatrix;
|
||||||
|
uniform mat4 projMatrix;
|
||||||
|
uniform mat3 normalMatrix;
|
||||||
|
in vec3 position;
|
||||||
|
in vec3 normal;
|
||||||
|
out vec3 fPosition;
|
||||||
|
out vec3 fNormal;
|
||||||
|
void main() {
|
||||||
|
vec4 vEyeCoord = mvMatrix * vec4(position, 1.0);
|
||||||
|
gl_Position = projMatrix * vEyeCoord;
|
||||||
|
fPosition = vEyeCoord.xyz;
|
||||||
|
fNormal = normalMatrix * normal;
|
||||||
|
})",
|
||||||
|
|
||||||
|
// Fragment shader
|
||||||
|
R"(#version 410
|
||||||
|
uniform vec4 Kd;
|
||||||
|
in vec3 fPosition;
|
||||||
|
in vec3 fNormal;
|
||||||
|
out vec4 fColor;
|
||||||
|
void
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
vec3 normal = normalize(fNormal);
|
||||||
|
vec3 LightDirection = normalize(-fPosition);
|
||||||
|
vec3 viewDirection = normalize(-fPosition);
|
||||||
|
float diffuse = max(0.0, dot(normal, LightDirection));
|
||||||
|
fColor = Kd * (diffuse + 0.1);
|
||||||
|
})", Shader::BlendMode::AlphaBlend
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// A simple shader to draw triangle meshes with normals.
|
||||||
|
m_lineShader = new Shader(render_pass(),
|
||||||
|
// Shader name
|
||||||
|
"draw_lines",
|
||||||
|
// Vertex shader
|
||||||
|
R"(#version 410
|
||||||
|
uniform mat4 mvMatrix;
|
||||||
|
uniform mat4 projMatrix;
|
||||||
|
in vec3 position;
|
||||||
|
in vec3 color;
|
||||||
|
out vec3 fColor;
|
||||||
|
void main() {
|
||||||
|
gl_Position = projMatrix * mvMatrix * vec4(position, 1.0);
|
||||||
|
fColor = color;
|
||||||
|
})",
|
||||||
|
|
||||||
|
// Fragment shader
|
||||||
|
R"(#version 410
|
||||||
|
in vec3 fColor;
|
||||||
|
out vec4 outColor;
|
||||||
|
void
|
||||||
|
main()
|
||||||
|
{
|
||||||
|
outColor = vec4(fColor, 1.0);
|
||||||
|
})"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load cube from OBJ file.
|
||||||
|
//
|
||||||
|
numCubeVerts = loadFile("cube.obj", cubeVerts, cubeNormals);
|
||||||
|
numSphereVerts = loadFile("sphere.obj", sphereVerts, sphereNormals);
|
||||||
|
|
||||||
|
m_shader->set_buffer("position", VariableType::Float32, { (unsigned int)numCubeVerts, 3 }, cubeVerts.data());
|
||||||
|
m_shader->set_buffer("normal", VariableType::Float32, { (unsigned int)numCubeVerts, 3 }, cubeNormals.data());
|
||||||
|
|
||||||
|
m_lineShader->set_buffer("position", VariableType::Float32, { 6, 3 }, axesVerts);
|
||||||
|
m_lineShader->set_buffer("color", VariableType::Float32, { 6, 3 }, axesColors);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKGLCanvas::draw_contents()
|
||||||
|
{
|
||||||
|
static const Vector3f zplus(0.0f, 0.0f, 1.0f);
|
||||||
|
Vector3f axis;
|
||||||
|
float theta;
|
||||||
|
float length;
|
||||||
|
gti320::Armature* armature = m_app->getArmature();
|
||||||
|
|
||||||
|
{
|
||||||
|
const float fov = 1.57f;
|
||||||
|
const float n = 0.2f;
|
||||||
|
const float f = 20.0f;
|
||||||
|
const float aspect = (float)width() / (float)height();
|
||||||
|
const Matrix4f projMat = Matrix4f::perspective(fov / 2.0f, n, f, aspect);
|
||||||
|
|
||||||
|
const Vector3f p = transformPoint(Matrix4f::rotate(Vector3f(1.0f, 0.0f, 0.0f), phi[1]) * Matrix4f::rotate(Vector3f(0, 1, 0), phi[0]), Vector3f(0, 0, dist));
|
||||||
|
const Matrix4f viewMat = Matrix4f::look_at(p, Vector3f(0, 1.0f, 0), Vector3f(0, 1, 0));
|
||||||
|
|
||||||
|
// Draw the joint axes.
|
||||||
|
//
|
||||||
|
m_lineShader->set_uniform("projMatrix", projMat);
|
||||||
|
m_lineShader->set_buffer("position", VariableType::Float32, { 6, 3 }, axesVerts);
|
||||||
|
for (gti320::Link* l : armature->links)
|
||||||
|
{
|
||||||
|
if (l->isEndEffector())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Matrix4f linkM;
|
||||||
|
memcpy(linkM.m, l->M.data(), sizeof(Matrix4f::m));
|
||||||
|
|
||||||
|
Matrix4f modelMat = linkM;
|
||||||
|
const Matrix4f mvMat = viewMat * modelMat;
|
||||||
|
m_lineShader->set_uniform("mvMatrix", mvMat);
|
||||||
|
|
||||||
|
m_lineShader->begin();
|
||||||
|
m_lineShader->draw_array(Shader::PrimitiveType::Line, 0, 6, false);
|
||||||
|
m_lineShader->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shader->set_uniform("projMatrix", projMat);
|
||||||
|
|
||||||
|
// Draw the armature.
|
||||||
|
//
|
||||||
|
m_shader->set_uniform("Kd", Vector4f(0.0f, 0.0f, 0.8f, 0.6f));
|
||||||
|
m_shader->set_buffer("position", VariableType::Float32, { (unsigned int)numCubeVerts, 3 }, cubeVerts.data());
|
||||||
|
m_shader->set_buffer("normal", VariableType::Float32, { (unsigned int)numCubeVerts, 3 }, cubeNormals.data());
|
||||||
|
|
||||||
|
// Draw the armature links.
|
||||||
|
//
|
||||||
|
for (gti320::Link* l : armature->links)
|
||||||
|
{
|
||||||
|
Matrix4f linkM, parentM;
|
||||||
|
if (l->parent)
|
||||||
|
{
|
||||||
|
memcpy(parentM.m, l->parent->M.data(), sizeof(parentM.m));
|
||||||
|
|
||||||
|
// Compute orientation of the link
|
||||||
|
// in parent reference frame
|
||||||
|
Vector3f trans;
|
||||||
|
memcpy(trans.v, l->trans.data(), sizeof(trans.v));
|
||||||
|
computeVectorRotation(zplus, trans, axis, theta);
|
||||||
|
|
||||||
|
// Compute length of the link
|
||||||
|
length = nanogui::norm(trans);
|
||||||
|
|
||||||
|
Matrix4f modelMat = parentM * Matrix4f::rotate(axis, theta) * Matrix4f::scale(Vector3f(0.16f, 0.16f, length)) * Matrix4f::translate(0.5f * zplus);
|
||||||
|
const Matrix4f mvMat = viewMat * modelMat;
|
||||||
|
const Matrix3f normalMat = computeNormalMatrix(mvMat);
|
||||||
|
m_shader->set_uniform("mvMatrix", mvMat);
|
||||||
|
m_shader->set_uniform("normalMatrix", normalMat);
|
||||||
|
|
||||||
|
m_shader->begin();
|
||||||
|
m_shader->draw_array(Shader::PrimitiveType::Triangle, 0, 3 * (unsigned int)numCubeVerts, false);
|
||||||
|
m_shader->end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shader->set_uniform("Kd", Vector4f(0.8f, 0.1f, 0.1f, 0.8f));
|
||||||
|
m_shader->set_buffer("position", VariableType::Float32, { (unsigned int)numSphereVerts, 3 }, sphereVerts.data());
|
||||||
|
m_shader->set_buffer("normal", VariableType::Float32, { (unsigned int)numSphereVerts, 3 }, sphereNormals.data());
|
||||||
|
|
||||||
|
// Draw the armature joints.
|
||||||
|
for (gti320::Link* l : armature->links)
|
||||||
|
{
|
||||||
|
if (l->isEndEffector())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Matrix4f linkM;
|
||||||
|
memcpy(linkM.m, l->M.data(), sizeof(Matrix4f::m));
|
||||||
|
|
||||||
|
Matrix4f modelMat = linkM;
|
||||||
|
const Matrix4f mvMat = viewMat * modelMat;
|
||||||
|
const Matrix3f normalMat = computeNormalMatrix(mvMat);
|
||||||
|
m_shader->set_uniform("mvMatrix", mvMat);
|
||||||
|
m_shader->set_uniform("normalMatrix", normalMat);
|
||||||
|
|
||||||
|
m_shader->begin();
|
||||||
|
m_shader->draw_array(Shader::PrimitiveType::Triangle, 0, 3 * (unsigned int)numSphereVerts, false);
|
||||||
|
m_shader->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shader->set_uniform("Kd", Vector4f(0.1f, 0.8f, 0.1f, 1.0f));
|
||||||
|
|
||||||
|
// Draw the target.
|
||||||
|
{
|
||||||
|
const gti320::Vector3f& t = m_app->getTargetPos();
|
||||||
|
Matrix4f modelMat = Matrix4f::translate(nanogui::Vector3f(t(0), t(1), t(2)));
|
||||||
|
const Matrix4f mvMat = viewMat * modelMat;
|
||||||
|
const Matrix3f normalMat = computeNormalMatrix(mvMat);
|
||||||
|
m_shader->set_uniform("mvMatrix", mvMat);
|
||||||
|
m_shader->set_uniform("normalMatrix", normalMat);
|
||||||
|
|
||||||
|
m_shader->begin();
|
||||||
|
m_shader->draw_array(Shader::PrimitiveType::Triangle, 0, 3 * (unsigned int)numSphereVerts, false);
|
||||||
|
m_shader->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IKGLCanvas::mouse_drag_event(const Vector2i& p, const Vector2i& rel, int button, int modifiers)
|
||||||
|
{
|
||||||
|
phi[0] = std::max(-1.57f, std::min(1.57f, phi[0] + 0.01f * (float)rel.x()));
|
||||||
|
phi[1] = std::max(-1.57f, std::min(1.57f, phi[1] - 0.01f * (float)rel.y()));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IKGLCanvas::scroll_event(const Vector2i& p, const Vector2f& rel)
|
||||||
|
{
|
||||||
|
dist = std::max(2.0f, std::min(8.0f, dist - 0.1f * (float)rel.y()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKGLCanvas::resetCamera()
|
||||||
|
{
|
||||||
|
phi[0] = phi[1] = 0.0f;
|
||||||
|
dist = 4.0f;
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file IKGLCanvas.h
|
||||||
|
*
|
||||||
|
* @brief Canvas class for drawing OpenGL scenes.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <nanogui/window.h>
|
||||||
|
#include <nanogui/canvas.h>
|
||||||
|
#include <nanogui/shader.h>
|
||||||
|
|
||||||
|
class IKApplication;
|
||||||
|
|
||||||
|
// An OpenGL canvas class to draw point clouds
|
||||||
|
//
|
||||||
|
class IKGLCanvas : public nanogui::Canvas
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IKGLCanvas(IKApplication* _app);
|
||||||
|
|
||||||
|
virtual void draw_contents() override;
|
||||||
|
|
||||||
|
virtual bool mouse_drag_event(const nanogui::Vector2i& p, const nanogui::Vector2i& rel, int button, int modifiers) override;
|
||||||
|
|
||||||
|
virtual bool scroll_event(const nanogui::Vector2i& p, const nanogui::Vector2f& rel) override;
|
||||||
|
|
||||||
|
void resetCamera();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
nanogui::ref<nanogui::Shader> m_shader;
|
||||||
|
nanogui::ref<nanogui::Shader> m_lineShader;
|
||||||
|
IKApplication* m_app;
|
||||||
|
|
||||||
|
// Camera parameters
|
||||||
|
float phi[2];
|
||||||
|
float dist;
|
||||||
|
|
||||||
|
};
|
|
@ -0,0 +1,59 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IKSolver.h"
|
||||||
|
#include "Armature.h"
|
||||||
|
#include "SVD.h"
|
||||||
|
|
||||||
|
using namespace gti320;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
IKSolver::IKSolver(Armature* _armature, Vector3f& _targetPos) : m_armature(_armature), m_targetPos(_targetPos), m_J()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float IKSolver::getError(Vector3f& dx) const
|
||||||
|
{
|
||||||
|
// TODO Compute the error between the current end effector
|
||||||
|
// position and the target position
|
||||||
|
dx.setZero();
|
||||||
|
return FLT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IKSolver::solve()
|
||||||
|
{
|
||||||
|
const int numLinks = m_armature->links.size();
|
||||||
|
const int dim = 3 * (numLinks);
|
||||||
|
m_J.resize(3, dim);
|
||||||
|
|
||||||
|
// We assume that the last link is the "end effector"
|
||||||
|
//
|
||||||
|
Link* endEffector = m_armature->links[numLinks - 1];
|
||||||
|
|
||||||
|
// TODO Juild the Jacobian matrix m_J.
|
||||||
|
// Each column corresponds to a separate
|
||||||
|
|
||||||
|
// TODO Compute the error between the current end effector
|
||||||
|
// position and the target position by calling getError()
|
||||||
|
//
|
||||||
|
|
||||||
|
// TODO Compute the change in the joint angles by solving:
|
||||||
|
// df/dtheta * delta_theta = delta_x
|
||||||
|
// where df/dtheta is the Jacobian matrix.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
// TODO Perform gradient descent method with line search
|
||||||
|
// to move the end effector toward the target position.
|
||||||
|
//
|
||||||
|
// Hint: use the Armature::unpack() and Armature::pack() functions
|
||||||
|
// to set and get the joint angles of the armature.
|
||||||
|
//
|
||||||
|
// Hint: whenever you change the joint angles, you must also call
|
||||||
|
// armature->updateKinematics() to compute the global position.
|
||||||
|
//
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Math3D.h"
|
||||||
|
|
||||||
|
namespace gti320
|
||||||
|
{
|
||||||
|
class Armature;
|
||||||
|
|
||||||
|
typedef Matrix<float, 3, Dynamic, ColumnStorage> Jacobianf;
|
||||||
|
|
||||||
|
|
||||||
|
// An inverse kinematics solver for a simple armature.
|
||||||
|
//
|
||||||
|
class IKSolver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor.
|
||||||
|
// @a _armature = The armature (see class Armature).
|
||||||
|
// @a _targetPos = A reference to the target position of the end effector.
|
||||||
|
//
|
||||||
|
IKSolver(Armature* _armature, Vector3f& _targetPos);
|
||||||
|
|
||||||
|
// Execute one solver step.
|
||||||
|
// A gradient descent method with line search is used.
|
||||||
|
// Euler angles of the armature links are automatically computed and updated.
|
||||||
|
//
|
||||||
|
void solve();
|
||||||
|
|
||||||
|
// Return the error as the distance between the end effector and the target position.
|
||||||
|
// The displacement vector @a _dx is updated with the value:
|
||||||
|
// _dx = m_targetPos - f(theta)
|
||||||
|
//
|
||||||
|
float getError(Vector3f& _dx) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Armature* m_armature; // The armature.
|
||||||
|
Vector3f& m_targetPos; // The target position of the end effector.
|
||||||
|
Jacobianf m_J; // The end effector Jacobian.
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
#include "LinkUI.h"
|
||||||
|
|
||||||
|
LinkUI::LinkUI(gti320::Link* _link, int _id, nanogui::Widget* _parent) : link(_link), id(_id)
|
||||||
|
{
|
||||||
|
panel = new nanogui::Widget(_parent);
|
||||||
|
panel->set_layout(new nanogui::BoxLayout(nanogui::Orientation::Vertical, nanogui::Alignment::Middle, 0, 5));
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkUI::init()
|
||||||
|
{
|
||||||
|
static char buf[64];
|
||||||
|
static const auto rotateMinMax = std::make_pair<float, float>(-1.57f, 1.57f);
|
||||||
|
static const std::string baseName = "link ";
|
||||||
|
|
||||||
|
// Rotate X
|
||||||
|
panelRotateX = new nanogui::Widget(panel);
|
||||||
|
panelRotateX->set_layout(new nanogui::BoxLayout(nanogui::Orientation::Horizontal, nanogui::Alignment::Middle, 0, 20));
|
||||||
|
labelRotateX = new nanogui::Label(panelRotateX, baseName + itoa(id, buf, 10) + " (X): ");
|
||||||
|
sliderRotateX = new nanogui::Slider(panelRotateX);
|
||||||
|
sliderRotateX->set_range(rotateMinMax);
|
||||||
|
textboxRotateX = new nanogui::TextBox(panelRotateX);
|
||||||
|
sliderRotateX->set_callback([this](float value)
|
||||||
|
{
|
||||||
|
link->eulerAng(0) = value;
|
||||||
|
onSlidersChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rotate Y
|
||||||
|
panelRotateY = new nanogui::Widget(panel);
|
||||||
|
panelRotateY->set_layout(new nanogui::BoxLayout(nanogui::Orientation::Horizontal, nanogui::Alignment::Middle, 0, 20));
|
||||||
|
labelRotateY = new nanogui::Label(panelRotateY, baseName + itoa(id, buf, 10) + " (Y): ");
|
||||||
|
sliderRotateY = new nanogui::Slider(panelRotateY);
|
||||||
|
sliderRotateY->set_range(rotateMinMax);
|
||||||
|
textboxRotateY = new nanogui::TextBox(panelRotateY);
|
||||||
|
sliderRotateY->set_callback([this](float value)
|
||||||
|
{
|
||||||
|
link->eulerAng(1) = value;
|
||||||
|
onSlidersChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rotate Z
|
||||||
|
panelRotateZ = new nanogui::Widget(panel);
|
||||||
|
panelRotateZ->set_layout(new nanogui::BoxLayout(nanogui::Orientation::Horizontal, nanogui::Alignment::Middle, 0, 20));
|
||||||
|
labelRotateZ = new nanogui::Label(panelRotateZ, baseName + itoa(id, buf, 10) + " (Z): ");
|
||||||
|
sliderRotateZ = new nanogui::Slider(panelRotateZ);
|
||||||
|
sliderRotateZ->set_range(rotateMinMax);
|
||||||
|
textboxRotateZ = new nanogui::TextBox(panelRotateZ);
|
||||||
|
sliderRotateZ->set_callback([this](float value)
|
||||||
|
{
|
||||||
|
link->eulerAng(2) = value;
|
||||||
|
onSlidersChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
onSlidersChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkUI::onSlidersChanged()
|
||||||
|
{
|
||||||
|
static char buf[64];
|
||||||
|
snprintf(buf, sizeof(buf), "%3.3f", link->eulerAng(0));
|
||||||
|
textboxRotateX->set_value(buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%3.3f", link->eulerAng(1));
|
||||||
|
textboxRotateY->set_value(buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%3.3f", link->eulerAng(2));
|
||||||
|
textboxRotateZ->set_value(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinkUI::onArmatureChanged()
|
||||||
|
{
|
||||||
|
sliderRotateX->set_value(link->eulerAng(0));
|
||||||
|
sliderRotateY->set_value(link->eulerAng(1));
|
||||||
|
sliderRotateZ->set_value(link->eulerAng(2));
|
||||||
|
|
||||||
|
onSlidersChanged();
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file LinkUI.h
|
||||||
|
*
|
||||||
|
* @brief User interface for armature links.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <nanogui/window.h>
|
||||||
|
#include <nanogui/textbox.h>
|
||||||
|
#include <nanogui/label.h>
|
||||||
|
#include <nanogui/layout.h>
|
||||||
|
#include <nanogui/slider.h>
|
||||||
|
#include <nanogui/screen.h>
|
||||||
|
#include <nanogui/vscrollpanel.h>
|
||||||
|
|
||||||
|
#include "Armature.h"
|
||||||
|
#include "Math3D.h"
|
||||||
|
|
||||||
|
// Link UI
|
||||||
|
//
|
||||||
|
class LinkUI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LinkUI(gti320::Link* _link, int _id, nanogui::Widget* _parent);
|
||||||
|
|
||||||
|
void onArmatureChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void onSlidersChanged();
|
||||||
|
|
||||||
|
gti320::Link* link;
|
||||||
|
int id;
|
||||||
|
nanogui::ref<nanogui::Widget> panel, panelRotateX, panelRotateY, panelRotateZ;
|
||||||
|
nanogui::ref<nanogui::TextBox> textboxRotateX, textboxRotateY, textboxRotateZ;
|
||||||
|
nanogui::ref<nanogui::Label> labelRotateX, labelRotateY, labelRotateZ;
|
||||||
|
nanogui::ref<nanogui::Slider> sliderRotateX, sliderRotateY, sliderRotateZ;
|
||||||
|
};
|
|
@ -0,0 +1,372 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file SVD.hpp
|
||||||
|
*
|
||||||
|
* @brief Singular value decomposition.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Matrix.h"
|
||||||
|
#include "Math3D.h"
|
||||||
|
#include "Operators.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace gti320
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// An implementation of SVD from "Numerical Recipes in C".
|
||||||
|
// http://numerical.recipes/webnotes/nr3web2.pdf
|
||||||
|
//
|
||||||
|
template<typename _Scalar>
|
||||||
|
static inline _Scalar sign(const _Scalar a, const _Scalar b)
|
||||||
|
{
|
||||||
|
return (b > 0.0) ? std::abs(a) : -std::abs(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Scalar>
|
||||||
|
static inline _Scalar sq(const _Scalar a)
|
||||||
|
{
|
||||||
|
return (a * a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculates sqrt( a^2 + b^2 )
|
||||||
|
template<typename _Scalar>
|
||||||
|
static inline _Scalar pythag(_Scalar a, _Scalar b)
|
||||||
|
{
|
||||||
|
return std::sqrt(a * a + b * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename _Scalar, int _Rows = Dynamic, int _Cols = Dynamic, int _Storage = ColumnStorage>
|
||||||
|
class SVD
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit SVD(const Matrix<_Scalar, _Rows, _Cols, _Storage>& _A) :
|
||||||
|
m_U(_A), m_V(_A.cols(), _A.cols()), m_S(_A.cols())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const Matrix<_Scalar, _Rows, _Cols>& getU() const { return m_U; }
|
||||||
|
|
||||||
|
const Matrix<_Scalar, _Cols, _Cols>& getV() const { return m_V; }
|
||||||
|
|
||||||
|
const Vector<_Scalar, _Cols>& getSigma() const { return m_S; }
|
||||||
|
|
||||||
|
void decompose()
|
||||||
|
{
|
||||||
|
bool flag;
|
||||||
|
int i, its, j, jj, k, l, nm;
|
||||||
|
_Scalar anorm, c, f, g, h, s, scale, x, y, z;
|
||||||
|
|
||||||
|
const int ncols = m_U.cols();
|
||||||
|
const int nrows = m_U.rows();
|
||||||
|
Vector<_Scalar> rv1(ncols);
|
||||||
|
|
||||||
|
// Householder reduction to bidiagonal form
|
||||||
|
//
|
||||||
|
g = scale = anorm = 0.0;
|
||||||
|
for (i = 0; i < ncols; ++i)
|
||||||
|
{
|
||||||
|
l = i + 1;
|
||||||
|
rv1(i) = scale * g;
|
||||||
|
g = s = scale = 0.0;
|
||||||
|
if (i < nrows)
|
||||||
|
{
|
||||||
|
for (k = i; k < nrows; ++k)
|
||||||
|
{
|
||||||
|
scale += std::abs(m_U(k, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale != 0.0)
|
||||||
|
{
|
||||||
|
for (k = i; k < nrows; ++k)
|
||||||
|
{
|
||||||
|
m_U(k, i) /= scale;
|
||||||
|
s += m_U(k, i) * m_U(k, i);
|
||||||
|
}
|
||||||
|
f = m_U(i, i);
|
||||||
|
g = -sign(std::sqrt(s), f);
|
||||||
|
h = f * g - s;
|
||||||
|
m_U(i, i) = f - g;
|
||||||
|
for (j = l; j < ncols; ++j)
|
||||||
|
{
|
||||||
|
for (s = 0.0, k = i; k < nrows; ++k)
|
||||||
|
s += m_U(k, i) * m_U(k, j);
|
||||||
|
f = s / h;
|
||||||
|
for (k = i; k < nrows; ++k)
|
||||||
|
m_U(k, j) += f * m_U(k, i);
|
||||||
|
}
|
||||||
|
for (k = i; k < nrows; ++k)
|
||||||
|
m_U(k, i) *= scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_S(i) = scale * g;
|
||||||
|
g = s = scale = 0.0;
|
||||||
|
if (i < nrows && i != ncols - 1)
|
||||||
|
{
|
||||||
|
for (k = l; k < ncols; ++k)
|
||||||
|
scale += std::abs(m_U(i, k));
|
||||||
|
|
||||||
|
if (scale)
|
||||||
|
{
|
||||||
|
for (k = l; k < ncols; ++k)
|
||||||
|
{
|
||||||
|
m_U(i, k) /= scale;
|
||||||
|
s += m_U(i, k) * m_U(i, k);
|
||||||
|
}
|
||||||
|
f = m_U(i, l);
|
||||||
|
g = -sign(std::sqrt(s), f);
|
||||||
|
h = f * g - s;
|
||||||
|
m_U(i, l) = f - g;
|
||||||
|
for (k = l; k < ncols; ++k)
|
||||||
|
{
|
||||||
|
rv1(k) = m_U(i, k) / h;
|
||||||
|
}
|
||||||
|
for (j = l; j < nrows; ++j)
|
||||||
|
{
|
||||||
|
for (s = 0.0, k = l; k < ncols; ++k)
|
||||||
|
s += m_U(j, k) * m_U(i, k);
|
||||||
|
for (k = l; k < ncols; ++k)
|
||||||
|
m_U(j, k) += s * rv1(k);
|
||||||
|
}
|
||||||
|
for (k = l; k < ncols; ++k)
|
||||||
|
m_U(i, k) *= scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const _Scalar tmp = (std::abs(m_S(i)) + std::abs(rv1(i)));
|
||||||
|
anorm = std::max(anorm, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulation of right-hand transformations
|
||||||
|
//
|
||||||
|
for (i = ncols - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
if (i < ncols - 1)
|
||||||
|
{
|
||||||
|
if (g) {
|
||||||
|
for (j = l; j < ncols; ++j)
|
||||||
|
m_V(j, i) = (m_U(i, j) / m_U(i, l)) / g; // double division to avoid possible underflow
|
||||||
|
|
||||||
|
for (j = l; j < ncols; ++j)
|
||||||
|
{
|
||||||
|
for (s = 0.0, k = l; k < ncols; ++k)
|
||||||
|
s += m_U(i, k) * m_V(k, j);
|
||||||
|
for (k = l; k < ncols; ++k)
|
||||||
|
m_V(k, j) += s * m_V(k, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (j = l; j < ncols; ++j)
|
||||||
|
m_V(i, j) = m_V(j, i) = 0.0;
|
||||||
|
}
|
||||||
|
m_V(i, i) = 1.0;
|
||||||
|
g = rv1(i);
|
||||||
|
l = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulation of left-hand transformations
|
||||||
|
//
|
||||||
|
for (i = std::min(nrows, ncols) - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
l = i + 1;
|
||||||
|
g = m_S(i);
|
||||||
|
for (j = l; j < ncols; ++j)
|
||||||
|
m_U(i, j) = 0.0;
|
||||||
|
if (g)
|
||||||
|
{
|
||||||
|
g = 1.0 / g;
|
||||||
|
for (j = l; j < ncols; ++j)
|
||||||
|
{
|
||||||
|
for (s = 0.0, k = l; k < nrows; ++k)
|
||||||
|
s += m_U(k, i) * m_U(k, j);
|
||||||
|
f = (s / m_U(i, i)) * g;
|
||||||
|
for (k = i; k < nrows; ++k)
|
||||||
|
m_U(k, j) += f * m_U(k, i);
|
||||||
|
}
|
||||||
|
for (j = i; j < nrows; ++j)
|
||||||
|
m_U(j, i) *= g;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for (j = i; j < nrows; ++j)
|
||||||
|
m_U(j, i) = 0.0;
|
||||||
|
m_U(i, i) = m_U(i, i) + 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diagonalization of the bidiagonal form.
|
||||||
|
// Loops over singular values using iterations.
|
||||||
|
//
|
||||||
|
for (k = ncols - 1; k >= 0; --k)
|
||||||
|
{
|
||||||
|
// Max iterations: 30
|
||||||
|
for (its = 0; its < 30; ++its)
|
||||||
|
{
|
||||||
|
flag = true;
|
||||||
|
for (l = k; l >= 0; --l) // Test for splitting
|
||||||
|
{
|
||||||
|
nm = l - 1;
|
||||||
|
if ((std::abs(rv1(l)) + anorm) == anorm)
|
||||||
|
{
|
||||||
|
flag = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (std::abs(m_S(nm) + anorm) == anorm)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag)
|
||||||
|
{ // Cancellation of rv1(l) if l > 0
|
||||||
|
c = 0.0;
|
||||||
|
s = 1.0;
|
||||||
|
for (i = l; i <= k; ++i)
|
||||||
|
{
|
||||||
|
f = s * rv1(i);
|
||||||
|
rv1(i) = c * rv1(i);
|
||||||
|
if ((std::abs(f) + anorm) == anorm)
|
||||||
|
break;
|
||||||
|
|
||||||
|
g = m_S(i);
|
||||||
|
h = pythag(f, g);
|
||||||
|
m_S(i) = h;
|
||||||
|
h = 1.0 / h;
|
||||||
|
c = g * h;
|
||||||
|
s = -f * h;
|
||||||
|
for (j = 0; j < nrows; ++j)
|
||||||
|
{
|
||||||
|
y = m_U(j, nm);
|
||||||
|
z = m_U(j, i);
|
||||||
|
m_U(j, nm) = y * c + z * s;
|
||||||
|
m_U(j, i) = z * c - y * s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
z = m_S(k);
|
||||||
|
if (l == k) // Convergence.
|
||||||
|
{
|
||||||
|
if (z < 0.0) // Compute non-negative singular values
|
||||||
|
{
|
||||||
|
m_S(k) = -z;
|
||||||
|
for (j = 0; j < ncols; ++j)
|
||||||
|
{
|
||||||
|
m_V(j, k) = -m_V(j, k); // Reverse bases direction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assertion when max iterations reached without convergence
|
||||||
|
assert(its < 29);
|
||||||
|
|
||||||
|
x = m_S(l); // Shift from bottom 2-by-2 minor
|
||||||
|
nm = k - 1;
|
||||||
|
y = m_S(nm);
|
||||||
|
g = rv1(nm);
|
||||||
|
h = rv1(k);
|
||||||
|
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
|
||||||
|
g = pythag(f, (_Scalar)1.0);
|
||||||
|
f = ((x - z) * (x + z) + h * ((y / (f + sign(g, f))) - h)) / x;
|
||||||
|
c = s = 1.0; // Next QR transformation
|
||||||
|
for (j = l; j <= nm; ++j)
|
||||||
|
{
|
||||||
|
i = j + 1;
|
||||||
|
g = rv1(i);
|
||||||
|
y = m_S(i);
|
||||||
|
h = s * g;
|
||||||
|
g = c * g;
|
||||||
|
z = pythag(f, h);
|
||||||
|
rv1(j) = z;
|
||||||
|
c = f / z;
|
||||||
|
s = h / z;
|
||||||
|
f = x * c + g * s;
|
||||||
|
g = g * c - x * s;
|
||||||
|
h = y * s;
|
||||||
|
y *= c;
|
||||||
|
for (jj = 0; jj < ncols; ++jj)
|
||||||
|
{
|
||||||
|
x = m_V(jj, j);
|
||||||
|
z = m_V(jj, i);
|
||||||
|
m_V(jj, j) = x * c + z * s;
|
||||||
|
m_V(jj, i) = z * c - x * s;
|
||||||
|
}
|
||||||
|
z = pythag(f, h);
|
||||||
|
m_S(j) = z; // Rotation can be arbitrary if z == 0
|
||||||
|
if (z != 0.0)
|
||||||
|
{
|
||||||
|
z = 1.0 / z;
|
||||||
|
c = f * z;
|
||||||
|
s = h * z;
|
||||||
|
}
|
||||||
|
f = c * g + s * y;
|
||||||
|
x = c * y - s * g;
|
||||||
|
for (jj = 0; jj < nrows; ++jj)
|
||||||
|
{
|
||||||
|
y = m_U(jj, j);
|
||||||
|
z = m_U(jj, i);
|
||||||
|
m_U(jj, j) = y * c + z * s;
|
||||||
|
m_U(jj, i) = z * c - y * s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv1(l) = 0.0;
|
||||||
|
rv1(k) = f;
|
||||||
|
m_S(k) = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void reorder() {
|
||||||
|
int s, inc = 1;
|
||||||
|
_Scalar sw;
|
||||||
|
|
||||||
|
const int ncols = m_U.cols();
|
||||||
|
const int nrows = m_U.rows();
|
||||||
|
Vector<_Scalar> su(nrows), sv(ncols);
|
||||||
|
do { inc *= 3; inc++; } while (inc <= ncols); // Sort using Shell’s sort.
|
||||||
|
|
||||||
|
do {
|
||||||
|
inc /= 3;
|
||||||
|
for (int i = inc; i < ncols; ++i) {
|
||||||
|
sw = m_S(i);
|
||||||
|
for (int k = 0; k < nrows; ++k) su(k) = m_U(k, i);
|
||||||
|
for (int k = 0; k < ncols; ++k) sv(k) = m_V(k, i);
|
||||||
|
int j = i;
|
||||||
|
while (m_S(j - inc) < sw) {
|
||||||
|
m_S(j) = m_S(j - inc);
|
||||||
|
for (int k = 0; k < nrows; ++k) m_U(k, j) = m_U(k, j - inc);
|
||||||
|
for (int k = 0; k < ncols; ++k) m_V(k, j) = m_V(k, j - inc);
|
||||||
|
j -= inc;
|
||||||
|
if (j < inc) break;
|
||||||
|
}
|
||||||
|
m_S(j) = sw;
|
||||||
|
for (int k = 0; k < nrows; ++k) m_U(k, j) = su(k);
|
||||||
|
for (int k = 0; k < ncols; ++k) m_V(k, j) = sv(k);
|
||||||
|
}
|
||||||
|
} while (inc > 1);
|
||||||
|
|
||||||
|
for (int k = 0; k < ncols; ++k)
|
||||||
|
{
|
||||||
|
// Flip signs.
|
||||||
|
s = 0;
|
||||||
|
for (int i = 0; i < nrows; ++i) if (m_U(i, k) < 0.0) ++s;
|
||||||
|
for (int j = 0; j < ncols; ++j) if (m_V(j, k) < 0.0) ++s;
|
||||||
|
if (s > (nrows + ncols) / 2)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nrows; ++i) m_U(i, k) = -m_U(i, k);
|
||||||
|
for (int j = 0; j < ncols; ++j) m_V(j, k) = -m_V(j, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Matrix<_Scalar, _Rows, _Cols, _Storage> m_U;
|
||||||
|
Matrix<_Scalar, _Cols, _Cols> m_V;
|
||||||
|
Vector<_Scalar, _Cols> m_S;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
#include "TargetUI.h"
|
||||||
|
|
||||||
|
TargetUI::TargetUI(nanogui::Widget* _parent, gti320::Vector3f& _target) : target(_target)
|
||||||
|
{
|
||||||
|
panel = new nanogui::Widget(_parent);
|
||||||
|
panel->set_layout(new nanogui::BoxLayout(nanogui::Orientation::Vertical, nanogui::Alignment::Middle, 0, 5));
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TargetUI::init()
|
||||||
|
{
|
||||||
|
static const auto translateMinMax = std::make_pair<float, float>(-4.0f, 4.0f);
|
||||||
|
|
||||||
|
// Translate X
|
||||||
|
panelTranslateX = new nanogui::Widget(panel);
|
||||||
|
panelTranslateX->set_layout(new nanogui::BoxLayout(nanogui::Orientation::Horizontal, nanogui::Alignment::Middle, 0, 20));
|
||||||
|
labelTranslateX = new nanogui::Label(panelTranslateX, "Target X : ");
|
||||||
|
sliderTranslateX = new nanogui::Slider(panelTranslateX);
|
||||||
|
sliderTranslateX->set_range(translateMinMax);
|
||||||
|
textboxTranslateX = new nanogui::TextBox(panelTranslateX);
|
||||||
|
sliderTranslateX->set_callback([this](float value)
|
||||||
|
{
|
||||||
|
target(0) = value;
|
||||||
|
onSlidersChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rotate Y
|
||||||
|
panelTranslateY = new nanogui::Widget(panel);
|
||||||
|
panelTranslateY->set_layout(new nanogui::BoxLayout(nanogui::Orientation::Horizontal, nanogui::Alignment::Middle, 0, 20));
|
||||||
|
labelTranslateY = new nanogui::Label(panelTranslateY, "Target Y : ");
|
||||||
|
sliderTranslateY = new nanogui::Slider(panelTranslateY);
|
||||||
|
sliderTranslateY->set_range(translateMinMax);
|
||||||
|
textboxTranslateY = new nanogui::TextBox(panelTranslateY);
|
||||||
|
sliderTranslateY->set_callback([this](float value)
|
||||||
|
{
|
||||||
|
target(1) = value;
|
||||||
|
onSlidersChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Rotate Z
|
||||||
|
panelTranslateZ = new nanogui::Widget(panel);
|
||||||
|
panelTranslateZ->set_layout(new nanogui::BoxLayout(nanogui::Orientation::Horizontal, nanogui::Alignment::Middle, 0, 20));
|
||||||
|
labelTranslateZ = new nanogui::Label(panelTranslateZ, "Target Z : ");
|
||||||
|
sliderTranslateZ = new nanogui::Slider(panelTranslateZ);
|
||||||
|
sliderTranslateZ->set_range(translateMinMax);
|
||||||
|
textboxTranslateZ = new nanogui::TextBox(panelTranslateZ);
|
||||||
|
sliderTranslateZ->set_callback([this](float value)
|
||||||
|
{
|
||||||
|
target(2) = value;
|
||||||
|
onSlidersChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
onSlidersChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TargetUI::onSlidersChanged()
|
||||||
|
{
|
||||||
|
static char buf[64];
|
||||||
|
snprintf(buf, sizeof(buf), "%3.3f", target(0));
|
||||||
|
textboxTranslateX->set_value(buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%3.3f", target(1));
|
||||||
|
textboxTranslateY->set_value(buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%3.3f", target(2));
|
||||||
|
textboxTranslateZ->set_value(buf);
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file TargetUI.h
|
||||||
|
*
|
||||||
|
* @brief User interface for end-effector target.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <nanogui/window.h>
|
||||||
|
#include <nanogui/textbox.h>
|
||||||
|
#include <nanogui/label.h>
|
||||||
|
#include <nanogui/layout.h>
|
||||||
|
#include <nanogui/slider.h>
|
||||||
|
#include <nanogui/screen.h>
|
||||||
|
#include <nanogui/vscrollpanel.h>
|
||||||
|
|
||||||
|
#include "Armature.h"
|
||||||
|
#include "Math3D.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Target UI
|
||||||
|
//
|
||||||
|
class TargetUI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TargetUI(nanogui::Widget* _parent, gti320::Vector3f& _target);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void onSlidersChanged();
|
||||||
|
|
||||||
|
nanogui::ref<nanogui::Widget> panel, panelTranslateX, panelTranslateY, panelTranslateZ;
|
||||||
|
nanogui::ref<nanogui::TextBox> textboxTranslateX, textboxTranslateY, textboxTranslateZ;
|
||||||
|
nanogui::ref<nanogui::Label> labelTranslateX, labelTranslateY, labelTranslateZ;
|
||||||
|
nanogui::ref<nanogui::Slider> sliderTranslateX, sliderTranslateY, sliderTranslateZ;
|
||||||
|
gti320::Vector3f& target;
|
||||||
|
};
|
|
@ -0,0 +1,58 @@
|
||||||
|
# Blender v3.0.1 OBJ File: ''
|
||||||
|
# www.blender.org
|
||||||
|
o Cube
|
||||||
|
v 0.500000 0.500000 -0.500000
|
||||||
|
v 0.500000 -0.500000 -0.500000
|
||||||
|
v 0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 -0.500000
|
||||||
|
v -0.500000 -0.500000 -0.500000
|
||||||
|
v -0.500000 0.500000 0.500000
|
||||||
|
v -0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 -0.500000 -0.500000
|
||||||
|
v -0.500000 -0.500000 -0.500000
|
||||||
|
v -0.500000 -0.500000 -0.500000
|
||||||
|
v -0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 -0.500000 0.500000
|
||||||
|
v 0.500000 -0.500000 -0.500000
|
||||||
|
v 0.500000 -0.500000 -0.500000
|
||||||
|
v 0.500000 -0.500000 -0.500000
|
||||||
|
v 0.500000 -0.500000 -0.500000
|
||||||
|
v 0.500000 0.500000 -0.500000
|
||||||
|
v 0.500000 0.500000 -0.500000
|
||||||
|
v 0.500000 0.500000 -0.500000
|
||||||
|
v -0.500000 0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 -0.500000 0.500000
|
||||||
|
v 0.500000 -0.500000 0.500000
|
||||||
|
v 0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 -0.500000
|
||||||
|
v -0.500000 0.500000 -0.500000
|
||||||
|
v -0.500000 0.500000 -0.500000
|
||||||
|
v -0.500000 0.500000 -0.500000
|
||||||
|
vn 0.0000 1.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 1.0000
|
||||||
|
vn -1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 -1.0000 0.0000
|
||||||
|
vn 1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 -1.0000
|
||||||
|
s off
|
||||||
|
f 35//1 28//1 21//1
|
||||||
|
f 26//2 13//2 30//2
|
||||||
|
f 23//3 9//3 12//3
|
||||||
|
f 16//4 14//4 10//4
|
||||||
|
f 20//5 31//5 17//5
|
||||||
|
f 33//6 18//6 11//6
|
||||||
|
f 34//1 24//1 27//1
|
||||||
|
f 29//2 7//2 15//2
|
||||||
|
f 25//3 36//3 6//3
|
||||||
|
f 19//4 32//4 8//4
|
||||||
|
f 1//5 3//5 4//5
|
||||||
|
f 5//6 22//6 2//6
|
|
@ -0,0 +1,42 @@
|
||||||
|
/**
|
||||||
|
* @file main.cpp
|
||||||
|
*
|
||||||
|
* @brief GTI320 Labo 2 - creates a NanoGUI application.
|
||||||
|
*
|
||||||
|
* Nom:
|
||||||
|
* Code permanent :
|
||||||
|
* Email :
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IKApplication.h"
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# pragma warning(push)
|
||||||
|
# pragma warning(disable: 4457 4456 4005 4312)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# if defined(APIENTRY)
|
||||||
|
# undef APIENTRY
|
||||||
|
# endif
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
nanogui::init();
|
||||||
|
nanogui::ref<IKApplication> app = new IKApplication();
|
||||||
|
app->draw_all();
|
||||||
|
app->set_visible(true);
|
||||||
|
nanogui::mainloop();
|
||||||
|
nanogui::shutdown();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue