TooN: sl.h Source File

TooN 2.0.0-beta8

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

sl.h

    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