TooN 2.1
|
00001 // -*- c++ -*- 00002 00003 // Copyright (C) 2005,2009 Tom Drummond (twd20@cam.ac.uk), 00004 // Gerhard Reitmayr (gr281@cam.ac.uk) 00005 // 00006 // This file is part of the TooN Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 2, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // You should have received a copy of the GNU General Public License along 00018 // with this library; see the file COPYING. If not, write to the Free 00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00020 // USA. 00021 00022 // As a special exception, you may use this file as part of a free software 00023 // library without restriction. Specifically, if other files instantiate 00024 // templates or use macros or inline functions from this file, or you compile 00025 // this file and link it with other files to produce an executable, this 00026 // file does not by itself cause the resulting executable to be covered by 00027 // the GNU General Public License. This exception does not however 00028 // invalidate any other reasons why the executable file might be covered by 00029 // the GNU General Public License. 00030 00031 #ifndef TOON_INCLUDE_SL_H 00032 #define TOON_INCLUDE_SL_H 00033 00034 #include <TooN/TooN.h> 00035 #include <TooN/helpers.h> 00036 #include <TooN/gaussian_elimination.h> 00037 #include <TooN/determinant.h> 00038 #include <cassert> 00039 00040 namespace TooN { 00041 00042 template <int N, typename P> class SL; 00043 template <int N, typename P> std::istream & operator>>(std::istream &, SL<N, P> &); 00044 00045 /// represents an element from the group SL(n), the NxN matrices M with det(M) = 1. 00046 /// This can be used to conveniently estimate homographies on n-1 dimentional spaces. 00047 /// The implementation uses the matrix exponential function @ref exp for 00048 /// exponentiation from an element in the Lie algebra and LU to compute an inverse. 00049 /// 00050 /// The Lie algebra are the NxN matrices M with trace(M) = 0. The N*N-1 generators used 00051 /// to represent this vector space are the following: 00052 /// - diag(...,1,-1,...), n-1 along the diagonal 00053 /// - symmetric generators for every pair of off-diagonal elements 00054 /// - anti-symmetric generators for every pair of off-diagonal elements 00055 /// This choice represents the fact that SL(n) can be interpreted as the product 00056 /// of all symmetric matrices with det() = 1 times SO(n). 00057 /// @ingroup gTransforms 00058 template <int N, typename Precision = DefaultPrecision> 00059 class SL { 00060 friend std::istream & operator>> <N,Precision>(std::istream &, SL &); 00061 public: 00062 static const int size = N; ///< size of the matrices represented by SL<N> 00063 static const int dim = N*N - 1; ///< dimension of the vector space represented by SL<N> 00064 00065 /// default constructor, creates identity element 00066 SL() : my_matrix(Identity) {} 00067 00068 /// exp constructor, creates element through exponentiation of Lie algebra vector. see @ref SL::exp. 00069 template <int S, typename P, typename B> 00070 SL( const Vector<S,P,B> & v ) { *this = exp(v); } 00071 00072 /// copy constructor from a matrix, coerces matrix to be of determinant = 1 00073 template <int R, int C, typename P, typename A> 00074 SL(const Matrix<R,C,P,A>& M) : my_matrix(M) { coerce(); } 00075 00076 /// returns the represented matrix 00077 const Matrix<N,N,Precision> & get_matrix() const { return my_matrix; } 00078 /// returns the inverse using LU 00079 SL inverse() const { return SL(*this, Invert()); } 00080 00081 /// multiplies to SLs together by multiplying the underlying matrices 00082 template <typename P> 00083 SL<N,typename Internal::MultiplyType<Precision, P>::type> operator*( const SL<N,P> & rhs) const { return SL<N,typename Internal::MultiplyType<Precision, P>::type>(*this, rhs); } 00084 00085 /// right multiplies this SL with another one 00086 template <typename P> 00087 SL operator*=( const SL<N,P> & rhs) { *this = *this*rhs; return *this; } 00088 00089 /// exponentiates a vector in the Lie algebra to compute the corresponding element 00090 /// @arg v a vector of dimension SL::dim 00091 template <int S, typename P, typename B> 00092 static inline SL exp( const Vector<S,P,B> &); 00093 00094 inline Vector<N*N-1, Precision> ln() const ; 00095 00096 /// returns one generator of the group. see SL for a detailed description of 00097 /// the generators used. 00098 /// @arg i number of the generator between 0 and SL::dim -1 inclusive 00099 static inline Matrix<N,N,Precision> generator(int); 00100 00101 private: 00102 struct Invert {}; 00103 SL( const SL & from, struct Invert ) { 00104 const Matrix<N> id = Identity; 00105 my_matrix = gaussian_elimination(from.my_matrix, id); 00106 } 00107 SL( const SL & a, const SL & b) : my_matrix(a.get_matrix() * b.get_matrix()) {} 00108 00109 void coerce(){ 00110 using std::abs; 00111 Precision det = determinant(my_matrix); 00112 assert(abs(det) > 0); 00113 using std::pow; 00114 my_matrix /= pow(det, 1.0/N); 00115 } 00116 00117 /// these constants indicate which parts of the parameter vector 00118 /// map to which generators 00119 ///{ 00120 static const int COUNT_DIAG = N - 1; 00121 static const int COUNT_SYMM = (dim - COUNT_DIAG)/2; 00122 static const int COUNT_ASYMM = COUNT_SYMM; 00123 static const int DIAG_LIMIT = COUNT_DIAG; 00124 static const int SYMM_LIMIT = COUNT_SYMM + DIAG_LIMIT; 00125 ///} 00126 00127 Matrix<N,N,Precision> my_matrix; 00128 }; 00129 00130 template <int N, typename Precision> 00131 template <int S, typename P, typename B> 00132 inline SL<N, Precision> SL<N, Precision>::exp( const Vector<S,P,B> & v){ 00133 SizeMismatch<S,dim>::test(v.size(), dim); 00134 Matrix<N,N,Precision> t(Zeros); 00135 for(int i = 0; i < dim; ++i) 00136 t += generator(i) * v[i]; 00137 SL<N, Precision> result; 00138 result.my_matrix = TooN::exp(t); 00139 return result; 00140 } 00141 00142 template <int N, typename Precision> 00143 inline Vector<N*N-1, Precision> SL<N, Precision>::ln() const { 00144 const Matrix<N> l = TooN::log(my_matrix); 00145 Vector<SL<N,Precision>::dim, Precision> v; 00146 Precision last = 0; 00147 for(int i = 0; i < DIAG_LIMIT; ++i){ // diagonal elements 00148 v[i] = l(i,i) + last; 00149 last = l(i,i); 00150 } 00151 for(int i = DIAG_LIMIT, row = 0, col = 1; i < SYMM_LIMIT; ++i) { // calculate symmetric and antisymmetric in one go 00152 // do the right thing here to calculate the correct indices ! 00153 v[i] = (l(row, col) + l(col, row))*0.5; 00154 v[i+COUNT_SYMM] = (-l(row, col) + l(col, row))*0.5; 00155 ++col; 00156 if( col == N ){ 00157 ++row; 00158 col = row+1; 00159 } 00160 } 00161 return v; 00162 } 00163 00164 template <int N, typename Precision> 00165 inline Matrix<N,N,Precision> SL<N, Precision>::generator(int i){ 00166 assert( i > -1 && i < dim ); 00167 Matrix<N,N,Precision> result(Zeros); 00168 if(i < DIAG_LIMIT) { // first ones are the diagonal ones 00169 result(i,i) = 1; 00170 result(i+1,i+1) = -1; 00171 } else if(i < SYMM_LIMIT){ // then the symmetric ones 00172 int row = 0, col = i - DIAG_LIMIT + 1; 00173 while(col > (N - row - 1)){ 00174 col -= (N - row - 1); 00175 ++row; 00176 } 00177 col += row; 00178 result(row, col) = result(col, row) = 1; 00179 } else { // finally the antisymmetric ones 00180 int row = 0, col = i - SYMM_LIMIT + 1; 00181 while(col > N - row - 1){ 00182 col -= N - row - 1; 00183 ++row; 00184 } 00185 col += row; 00186 result(row, col) = -1; 00187 result(col, row) = 1; 00188 } 00189 return result; 00190 } 00191 00192 template <int S, typename PV, typename B, int N, typename P> 00193 Vector<N, typename Internal::MultiplyType<P, PV>::type> operator*( const SL<N, P> & lhs, const Vector<S,PV,B> & rhs ){ 00194 return lhs.get_matrix() * rhs; 00195 } 00196 00197 template <int S, typename PV, typename B, int N, typename P> 00198 Vector<N, typename Internal::MultiplyType<PV, P>::type> operator*( const Vector<S,PV,B> & lhs, const SL<N,P> & rhs ){ 00199 return lhs * rhs.get_matrix(); 00200 } 00201 00202 template<int R, int C, typename PM, typename A, int N, typename P> inline 00203 Matrix<N, C, typename Internal::MultiplyType<P, PM>::type> operator*(const SL<N,P>& lhs, const Matrix<R, C, PM, A>& rhs){ 00204 return lhs.get_matrix() * rhs; 00205 } 00206 00207 template<int R, int C, typename PM, typename A, int N, typename P> inline 00208 Matrix<R, N, typename Internal::MultiplyType<PM, P>::type> operator*(const Matrix<R, C, PM, A>& lhs, const SL<N,P>& rhs){ 00209 return lhs * rhs.get_matrix(); 00210 } 00211 00212 template <int N, typename P> 00213 std::ostream & operator<<(std::ostream & out, const SL<N, P> & h){ 00214 out << h.get_matrix(); 00215 return out; 00216 } 00217 00218 template <int N, typename P> 00219 std::istream & operator>>(std::istream & in, SL<N, P> & h){ 00220 in >> h.my_matrix; 00221 h.coerce(); 00222 return in; 00223 } 00224 00225 }; 00226 00227 #endif