Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
eigen.h
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, Willow Garage, Inc.
00005  *  Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of Willow Garage, Inc. nor the names of its
00019  *     contributors may be used to endorse or promote products derived
00020  *     from this software without specific prior written permission.
00021  *
00022  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033  *  POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  * $Id: eigen.h 4702 2012-02-23 09:39:33Z gedikli $
00036  *
00037  */
00038 // The computeRoots function included in this is based on materials
00039 // covered by the following copyright and license:
00040 //
00041 // Geometric Tools, LLC
00042 // Copyright (c) 1998-2010
00043 // Distributed under the Boost Software License, Version 1.0.
00044 //
00045 // Permission is hereby granted, free of charge, to any person or organization
00046 // obtaining a copy of the software and accompanying documentation covered by
00047 // this license (the "Software") to use, reproduce, display, distribute,
00048 // execute, and transmit the Software, and to prepare derivative works of the
00049 // Software, and to permit third-parties to whom the Software is furnished to
00050 // do so, all subject to the following:
00051 //
00052 // The copyright notices in the Software and this entire statement, including
00053 // the above license grant, this restriction and the following disclaimer,
00054 // must be included in all copies of the Software, in whole or in part, and
00055 // all derivative works of the Software, unless such copies or derivative
00056 // works are solely in the form of machine-executable object code generated by
00057 // a source language processor.
00058 //
00059 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00060 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00061 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
00062 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
00063 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
00064 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00065 // DEALINGS IN THE SOFTWARE.
00066 
00067 #ifndef PCL_EIGEN_H_
00068 #define PCL_EIGEN_H_
00069 
00070 #ifndef NOMINMAX
00071 #define NOMINMAX
00072 #endif
00073 
00074 #include <Eigen/Core>
00075 #include <Eigen/Eigenvalues>
00076 #include <Eigen/Geometry>
00077 
00078 namespace pcl
00079 {
00080 
00087   template<typename Scalar, typename Roots> inline void
00088   computeRoots2 (const Scalar& b, const Scalar& c, Roots& roots)
00089   {
00090     roots (0) = Scalar (0);
00091     Scalar d = Scalar (b * b - 4.0 * c);
00092     if (d < 0.0) // no real roots!!!! THIS SHOULD NOT HAPPEN!
00093       d = 0.0;
00094 
00095     Scalar sd = sqrt (d);
00096 
00097     roots (2) = 0.5f * (b + sd);
00098     roots (1) = 0.5f * (b - sd);
00099   }
00100 
00106   template<typename Matrix, typename Roots> inline void
00107   computeRoots (const Matrix& m, Roots& roots)
00108   {
00109     typedef typename Matrix::Scalar Scalar;
00110 
00111     // The characteristic equation is x^3 - c2*x^2 + c1*x - c0 = 0.  The
00112     // eigenvalues are the roots to this equation, all guaranteed to be
00113     // real-valued, because the matrix is symmetric.
00114     Scalar c0 =            m (0, 0) * m (1, 1) * m (2, 2)
00115             + Scalar (2) * m (0, 1) * m (0, 2) * m (1, 2)
00116                          - m (0, 0) * m (1, 2) * m (1, 2)
00117                          - m (1, 1) * m (0, 2) * m (0, 2)
00118                          - m (2, 2) * m (0, 1) * m (0, 1);
00119     Scalar c1 = m (0, 0) * m (1, 1) -
00120                 m (0, 1) * m (0, 1) +
00121                 m (0, 0) * m (2, 2) -
00122                 m (0, 2) * m (0, 2) +
00123                 m (1, 1) * m (2, 2) -
00124                 m (1, 2) * m (1, 2);
00125     Scalar c2 = m (0, 0) + m (1, 1) + m (2, 2);
00126 
00127 
00128     if (fabs (c0) < Eigen::NumTraits<Scalar>::epsilon ())// one root is 0 -> quadratic equation
00129       computeRoots2 (c2, c1, roots);
00130     else
00131     {
00132       const Scalar s_inv3 = Scalar (1.0 / 3.0);
00133       const Scalar s_sqrt3 = Eigen::internal::sqrt (Scalar (3.0));
00134       // Construct the parameters used in classifying the roots of the equation
00135       // and in solving the equation for the roots in closed form.
00136       Scalar c2_over_3 = c2*s_inv3;
00137       Scalar a_over_3 = (c1 - c2 * c2_over_3) * s_inv3;
00138       if (a_over_3 > Scalar (0))
00139         a_over_3 = Scalar (0);
00140 
00141       Scalar half_b = Scalar (0.5) * (c0 + c2_over_3 * (Scalar (2) * c2_over_3 * c2_over_3 - c1));
00142 
00143       Scalar q = half_b * half_b + a_over_3 * a_over_3*a_over_3;
00144       if (q > Scalar (0))
00145         q = Scalar (0);
00146 
00147       // Compute the eigenvalues by solving for the roots of the polynomial.
00148       Scalar rho = Eigen::internal::sqrt (-a_over_3);
00149       Scalar theta = std::atan2 (Eigen::internal::sqrt (-q), half_b) * s_inv3;
00150       Scalar cos_theta = Eigen::internal::cos (theta);
00151       Scalar sin_theta = Eigen::internal::sin (theta);
00152       roots (0) = c2_over_3 + Scalar (2) * rho * cos_theta;
00153       roots (1) = c2_over_3 - rho * (cos_theta + s_sqrt3 * sin_theta);
00154       roots (2) = c2_over_3 - rho * (cos_theta - s_sqrt3 * sin_theta);
00155 
00156       // Sort in increasing order.
00157       if (roots (0) >= roots (1))
00158         std::swap (roots (0), roots (1));
00159       if (roots (1) >= roots (2))
00160       {
00161         std::swap (roots (1), roots (2));
00162         if (roots (0) >= roots (1))
00163           std::swap (roots (0), roots (1));
00164       }
00165 
00166       if (roots (0) <= 0) // eigenval for symetric positive semi-definite matrix can not be negative! Set it to 0
00167         computeRoots2 (c2, c1, roots);
00168     }
00169   }
00170 
00177   template <typename Matrix, typename Vector> inline void
00178   eigen22 (const Matrix& mat, typename Matrix::Scalar& eigenvalue, Vector& eigenvector)
00179   {
00180     // 0.5 to optimize further calculations
00181     typename Matrix::Scalar trace = 0.5 * (mat (0, 0) + mat (1, 1));
00182     typename Matrix::Scalar determinant = mat (0, 0) * mat (1, 1) - mat (0,1) * mat (1, 0);
00183 
00184     typename Matrix::Scalar temp = trace * trace - determinant;
00185     if (temp < 0)
00186       temp = 0;
00187 
00188     eigenvalue = trace - sqrt (temp);
00189 
00190     eigenvector (0) = - mat (0, 1);
00191     eigenvector (1) = mat (0, 0) - eigenvalue;
00192 
00193     eigenvector.normalize ();
00194   }
00195 
00201   template <typename Matrix, typename Vector> inline void
00202   eigen22 (const Matrix& mat, Matrix& eigenvectors, Vector& eigenvalues)
00203   {
00204     // if diagonal matrix, the eigenvalues are the diagonal elements
00205     // and the eigenvectors are not unique, thus set to Identity
00206     if (fabs(mat.coeff (1)) <= std::numeric_limits<typename Matrix::Scalar>::min ())
00207     {
00208       eigenvalues.coeffRef (0) = std::min(mat.coeff (0), mat.coeff (2));
00209       eigenvalues.coeffRef (1) = std::max(mat.coeff (0), mat.coeff (2));
00210       eigenvectors.coeffRef (0) = 1.0;
00211       eigenvectors.coeffRef (1) = 0.0;
00212       eigenvectors.coeffRef (2) = 0.0;
00213       eigenvectors.coeffRef (3) = 1.0;
00214       return;
00215     }
00216 
00217     // 0.5 to optimize further calculations
00218     typename Matrix::Scalar trace = 0.5 * (mat.coeff (0) + mat.coeff (3));
00219     typename Matrix::Scalar determinant = mat.coeff (0) * mat.coeff (3) - mat.coeff (1) * mat.coeff (1);
00220 
00221     typename Matrix::Scalar temp = trace * trace - determinant;
00222 
00223     if (temp < 0)
00224       temp = 0;
00225     else
00226       temp = sqrt (temp);
00227 
00228     eigenvalues.coeffRef (0) = trace - temp;
00229     eigenvalues.coeffRef (1) = trace + temp;
00230 
00231     // either this is in a row or column depending on RowMajor or ColumnMajor
00232     eigenvectors.coeffRef (0) = - mat.coeff (1);
00233     eigenvectors.coeffRef (2) = mat.coeff (0) - eigenvalues.coeff (0);
00234     typename Matrix::Scalar norm = 1.0 / sqrt (eigenvectors.coeffRef (0) * eigenvectors.coeffRef (0) + eigenvectors.coeffRef (2) * eigenvectors.coeffRef (2));
00235     eigenvectors.coeffRef (0) *= norm;
00236     eigenvectors.coeffRef (2) *= norm;
00237     eigenvectors.coeffRef (1) = eigenvectors.coeffRef (2);
00238     eigenvectors.coeffRef (3) = -eigenvectors.coeffRef (0);
00239   }
00240 
00247   template<typename Matrix, typename Vector> inline void
00248   computeCorrespondingEigenVector (const Matrix& mat, const typename Matrix::Scalar& eigenvalue, Vector& eigenvector)
00249   {
00250     typedef typename Matrix::Scalar Scalar;
00251     // Scale the matrix so its entries are in [-1,1].  The scaling is applied
00252     // only when at least one matrix entry has magnitude larger than 1.
00253 
00254     Scalar scale = mat.cwiseAbs ().maxCoeff ();
00255     if (scale <= std::numeric_limits<Scalar>::min ())
00256       scale = Scalar (1.0);
00257 
00258     Matrix scaledMat = mat / scale;
00259 
00260     scaledMat.diagonal ().array () -= eigenvalue / scale;
00261 
00262     Vector vec1 = scaledMat.row (0).cross (scaledMat.row (1));
00263     Vector vec2 = scaledMat.row (0).cross (scaledMat.row (2));
00264     Vector vec3 = scaledMat.row (1).cross (scaledMat.row (2));
00265 
00266     Scalar len1 = vec1.squaredNorm ();
00267     Scalar len2 = vec2.squaredNorm ();
00268     Scalar len3 = vec3.squaredNorm ();
00269 
00270     if (len1 >= len2 && len1 >= len3)
00271       eigenvector = vec1 / Eigen::internal::sqrt (len1);
00272     else if (len2 >= len1 && len2 >= len3)
00273       eigenvector = vec2 / Eigen::internal::sqrt (len2);
00274     else
00275       eigenvector = vec3 / Eigen::internal::sqrt (len3);
00276   }
00277   
00285   template<typename Matrix, typename Vector> inline void
00286   eigen33 (const Matrix& mat, typename Matrix::Scalar& eigenvalue, Vector& eigenvector)
00287   {
00288     typedef typename Matrix::Scalar Scalar;
00289     // Scale the matrix so its entries are in [-1,1].  The scaling is applied
00290     // only when at least one matrix entry has magnitude larger than 1.
00291 
00292     Scalar scale = mat.cwiseAbs ().maxCoeff ();
00293     if (scale <= std::numeric_limits<Scalar>::min ())
00294       scale = Scalar (1.0);
00295 
00296     Matrix scaledMat = mat / scale;
00297 
00298     Vector eigenvalues;
00299     computeRoots (scaledMat, eigenvalues);
00300 
00301     eigenvalue = eigenvalues (0) * scale;
00302 
00303     scaledMat.diagonal ().array () -= eigenvalues (0);
00304 
00305     Vector vec1 = scaledMat.row (0).cross (scaledMat.row (1));
00306     Vector vec2 = scaledMat.row (0).cross (scaledMat.row (2));
00307     Vector vec3 = scaledMat.row (1).cross (scaledMat.row (2));
00308 
00309     Scalar len1 = vec1.squaredNorm ();
00310     Scalar len2 = vec2.squaredNorm ();
00311     Scalar len3 = vec3.squaredNorm ();
00312 
00313     if (len1 >= len2 && len1 >= len3)
00314       eigenvector = vec1 / Eigen::internal::sqrt (len1);
00315     else if (len2 >= len1 && len2 >= len3)
00316       eigenvector = vec2 / Eigen::internal::sqrt (len2);
00317     else
00318       eigenvector = vec3 / Eigen::internal::sqrt (len3);
00319   }
00320 
00326   template<typename Matrix, typename Vector> inline void
00327   eigen33 (const Matrix& mat, Vector& evals)
00328   {
00329     typedef typename Matrix::Scalar Scalar;
00330     Scalar scale = mat.cwiseAbs ().maxCoeff ();
00331     if (scale <= std::numeric_limits<Scalar>::min ())
00332       scale = Scalar (1.0);
00333 
00334     Matrix scaledMat = mat / scale;
00335     computeRoots (scaledMat, evals);
00336     evals *= scale;
00337   }
00338 
00345   template<typename Matrix, typename Vector> inline void
00346   eigen33 (const Matrix& mat, Matrix& evecs, Vector& evals)
00347   {
00348     typedef typename Matrix::Scalar Scalar;
00349     // Scale the matrix so its entries are in [-1,1].  The scaling is applied
00350     // only when at least one matrix entry has magnitude larger than 1.
00351 
00352     Scalar scale = mat.cwiseAbs ().maxCoeff ();
00353     if (scale <= std::numeric_limits<Scalar>::min ())
00354       scale = Scalar (1.0);
00355 
00356     Matrix scaledMat = mat / scale;
00357 
00358     // Compute the eigenvalues
00359     computeRoots (scaledMat, evals);
00360 
00361     if ((evals (2) - evals (0)) <= Eigen::NumTraits<Scalar>::epsilon ())
00362     {
00363       // all three equal
00364       evecs.setIdentity ();
00365     }
00366     else if ((evals (1) - evals (0)) <= Eigen::NumTraits<Scalar>::epsilon () )
00367     {
00368       // first and second equal
00369       Matrix tmp;
00370       tmp = scaledMat;
00371       tmp.diagonal ().array () -= evals (2);
00372 
00373       Vector vec1 = tmp.row (0).cross (tmp.row (1));
00374       Vector vec2 = tmp.row (0).cross (tmp.row (2));
00375       Vector vec3 = tmp.row (1).cross (tmp.row (2));
00376 
00377       Scalar len1 = vec1.squaredNorm ();
00378       Scalar len2 = vec2.squaredNorm ();
00379       Scalar len3 = vec3.squaredNorm ();
00380 
00381       if (len1 >= len2 && len1 >= len3)
00382         evecs.col (2) = vec1 / Eigen::internal::sqrt (len1);
00383       else if (len2 >= len1 && len2 >= len3)
00384         evecs.col (2) = vec2 / Eigen::internal::sqrt (len2);
00385       else
00386         evecs.col (2) = vec3 / Eigen::internal::sqrt (len3);
00387 
00388       evecs.col (1) = evecs.col (2).unitOrthogonal ();
00389       evecs.col (0) = evecs.col (1).cross (evecs.col (2));
00390     }
00391     else if ((evals (2) - evals (1)) <= Eigen::NumTraits<Scalar>::epsilon () )
00392     {
00393       // second and third equal
00394       Matrix tmp;
00395       tmp = scaledMat;
00396       tmp.diagonal ().array () -= evals (0);
00397 
00398       Vector vec1 = tmp.row (0).cross (tmp.row (1));
00399       Vector vec2 = tmp.row (0).cross (tmp.row (2));
00400       Vector vec3 = tmp.row (1).cross (tmp.row (2));
00401 
00402       Scalar len1 = vec1.squaredNorm ();
00403       Scalar len2 = vec2.squaredNorm ();
00404       Scalar len3 = vec3.squaredNorm ();
00405 
00406       if (len1 >= len2 && len1 >= len3)
00407         evecs.col (0) = vec1 / Eigen::internal::sqrt (len1);
00408       else if (len2 >= len1 && len2 >= len3)
00409         evecs.col (0) = vec2 / Eigen::internal::sqrt (len2);
00410       else
00411         evecs.col (0) = vec3 / Eigen::internal::sqrt (len3);
00412 
00413       evecs.col (1) = evecs.col (0).unitOrthogonal ();
00414       evecs.col (2) = evecs.col (0).cross (evecs.col (1));
00415     }
00416     else
00417     {
00418       Matrix tmp;
00419       tmp = scaledMat;
00420       tmp.diagonal ().array () -= evals (2);
00421 
00422       Vector vec1 = tmp.row (0).cross (tmp.row (1));
00423       Vector vec2 = tmp.row (0).cross (tmp.row (2));
00424       Vector vec3 = tmp.row (1).cross (tmp.row (2));
00425 
00426       Scalar len1 = vec1.squaredNorm ();
00427       Scalar len2 = vec2.squaredNorm ();
00428       Scalar len3 = vec3.squaredNorm ();
00429 #ifdef _WIN32
00430       Scalar *mmax = new Scalar[3];
00431 #else
00432       Scalar mmax[3];
00433 #endif
00434       unsigned int min_el = 2;
00435       unsigned int max_el = 2;
00436       if (len1 >= len2 && len1 >= len3)
00437       {
00438         mmax[2] = len1;
00439         evecs.col (2) = vec1 / Eigen::internal::sqrt (len1);
00440       }
00441       else if (len2 >= len1 && len2 >= len3)
00442       {
00443         mmax[2] = len2;
00444         evecs.col (2) = vec2 / Eigen::internal::sqrt (len2);
00445       }
00446       else
00447       {
00448         mmax[2] = len3;
00449         evecs.col (2) = vec3 / Eigen::internal::sqrt (len3);
00450       }
00451 
00452       tmp = scaledMat;
00453       tmp.diagonal ().array () -= evals (1);
00454 
00455       vec1 = tmp.row (0).cross (tmp.row (1));
00456       vec2 = tmp.row (0).cross (tmp.row (2));
00457       vec3 = tmp.row (1).cross (tmp.row (2));
00458 
00459       len1 = vec1.squaredNorm ();
00460       len2 = vec2.squaredNorm ();
00461       len3 = vec3.squaredNorm ();
00462       if (len1 >= len2 && len1 >= len3)
00463       {
00464         mmax[1] = len1;
00465         evecs.col (1) = vec1 / Eigen::internal::sqrt (len1);
00466         min_el = len1 <= mmax[min_el] ? 1 : min_el;
00467         max_el = len1 > mmax[max_el] ? 1 : max_el;
00468       }
00469       else if (len2 >= len1 && len2 >= len3)
00470       {
00471         mmax[1] = len2;
00472         evecs.col (1) = vec2 / Eigen::internal::sqrt (len2);
00473         min_el = len2 <= mmax[min_el] ? 1 : min_el;
00474         max_el = len2 > mmax[max_el] ? 1 : max_el;
00475       }
00476       else
00477       {
00478         mmax[1] = len3;
00479         evecs.col (1) = vec3 / Eigen::internal::sqrt (len3);
00480         min_el = len3 <= mmax[min_el] ? 1 : min_el;
00481         max_el = len3 > mmax[max_el] ? 1 : max_el;
00482       }
00483 
00484       tmp = scaledMat;
00485       tmp.diagonal ().array () -= evals (0);
00486 
00487       vec1 = tmp.row (0).cross (tmp.row (1));
00488       vec2 = tmp.row (0).cross (tmp.row (2));
00489       vec3 = tmp.row (1).cross (tmp.row (2));
00490 
00491       len1 = vec1.squaredNorm ();
00492       len2 = vec2.squaredNorm ();
00493       len3 = vec3.squaredNorm ();
00494       if (len1 >= len2 && len1 >= len3)
00495       {
00496         mmax[0] = len1;
00497         evecs.col (0) = vec1 / Eigen::internal::sqrt (len1);
00498         min_el = len3 <= mmax[min_el] ? 0 : min_el;
00499         max_el = len3 > mmax[max_el] ? 0 : max_el;
00500       }
00501       else if (len2 >= len1 && len2 >= len3)
00502       {
00503         mmax[0] = len2;
00504         evecs.col (0) = vec2 / Eigen::internal::sqrt (len2);
00505         min_el = len3 <= mmax[min_el] ? 0 : min_el;
00506         max_el = len3 > mmax[max_el] ? 0 : max_el;
00507       }
00508       else
00509       {
00510         mmax[0] = len3;
00511         evecs.col (0) = vec3 / Eigen::internal::sqrt (len3);
00512         min_el = len3 <= mmax[min_el] ? 0 : min_el;
00513         max_el = len3 > mmax[max_el] ? 0 : max_el;
00514       }
00515 
00516       unsigned mid_el = 3 - min_el - max_el;
00517       evecs.col (min_el) = evecs.col ((min_el + 1) % 3).cross ( evecs.col ((min_el + 2) % 3) ).normalized ();
00518       evecs.col (mid_el) = evecs.col ((mid_el + 1) % 3).cross ( evecs.col ((mid_el + 2) % 3) ).normalized ();
00519 #ifdef _WIN32
00520       delete [] mmax;
00521 #endif
00522     }
00523     // Rescale back to the original size.
00524     evals *= scale;
00525   }
00526 
00534   template<typename Matrix> inline typename Matrix::Scalar
00535   invert2x2 (const Matrix& matrix, Matrix& inverse)
00536   {
00537     typedef typename Matrix::Scalar Scalar;
00538     Scalar det = matrix.coeff (0) * matrix.coeff (3) - matrix.coeff (1) * matrix.coeff (2) ;
00539 
00540     if (det != 0)
00541     {
00542       //Scalar inv_det = Scalar (1.0) / det;
00543       inverse.coeffRef (0) =   matrix.coeff (3);
00544       inverse.coeffRef (1) = - matrix.coeff (1);
00545       inverse.coeffRef (2) = - matrix.coeff (2);
00546       inverse.coeffRef (3) =   matrix.coeff (0);
00547       inverse /= det;
00548     }
00549     return det;
00550   }
00551 
00559   template<typename Matrix> inline typename Matrix::Scalar
00560   invert3x3SymMatrix (const Matrix& matrix, Matrix& inverse)
00561   {
00562     typedef typename Matrix::Scalar Scalar;
00563     // elements
00564     // a b c
00565     // b d e
00566     // c e f
00567     //| a b c |-1             |   fd-ee    ce-bf   be-cd  |
00568     //| b d e |    =  1/det * |   ce-bf    af-cc   bc-ae  |
00569     //| c e f |               |   be-cd    bc-ae   ad-bb  |
00570 
00571     //det = a(fd-ee) + b(ec-fb) + c(eb-dc)
00572 
00573     Scalar fd_ee = matrix.coeff (4) * matrix.coeff (8) - matrix.coeff (7) * matrix.coeff (5);
00574     Scalar ce_bf = matrix.coeff (2) * matrix.coeff (5) - matrix.coeff (1) * matrix.coeff (8);
00575     Scalar be_cd = matrix.coeff (1) * matrix.coeff (5) - matrix.coeff (2) * matrix.coeff (4);
00576 
00577     Scalar det = matrix.coeff (0) * fd_ee + matrix.coeff (1) * ce_bf + matrix.coeff (2) * be_cd;
00578 
00579     if (det != 0)
00580     {
00581       //Scalar inv_det = Scalar (1.0) / det;
00582       inverse.coeffRef (0) = fd_ee;
00583       inverse.coeffRef (1) = inverse.coeffRef (3) = ce_bf;
00584       inverse.coeffRef (2) = inverse.coeffRef (6) = be_cd;
00585       inverse.coeffRef (4) = (matrix.coeff (0) * matrix.coeff (8) - matrix.coeff (2) * matrix.coeff (2));
00586       inverse.coeffRef (5) = inverse.coeffRef (7) = (matrix.coeff (1) * matrix.coeff (2) - matrix.coeff (0) * matrix.coeff (5));
00587       inverse.coeffRef (8) = (matrix.coeff (0) * matrix.coeff (4) - matrix.coeff (1) * matrix.coeff (1));
00588       inverse /= det;
00589     }
00590     return det;
00591   }
00592 
00599   template<typename Matrix> inline typename Matrix::Scalar
00600   invert3x3Matrix (const Matrix& matrix, Matrix& inverse)
00601   {
00602     typedef typename Matrix::Scalar Scalar;
00603 
00604     //| a b c |-1             |   ie-hf    hc-ib   fb-ec  |
00605     //| d e f |    =  1/det * |   gf-id    ia-gc   dc-fa  |
00606     //| g h i |               |   hd-ge    gb-ha   ea-db  |
00607     //det = a(ie-hf) + d(hc-ib) + g(fb-ec)
00608 
00609     Scalar ie_hf = matrix.coeff (8) * matrix.coeff (4) - matrix.coeff (7) * matrix.coeff (5);
00610     Scalar hc_ib = matrix.coeff (7) * matrix.coeff (2) - matrix.coeff (8) * matrix.coeff (1);
00611     Scalar fb_ec = matrix.coeff (5) * matrix.coeff (1) - matrix.coeff (4) * matrix.coeff (2);
00612     Scalar det = matrix.coeff (0) * (ie_hf) + matrix.coeff (3) * (hc_ib) + matrix.coeff (6) * (fb_ec) ;
00613 
00614     if (det != 0)
00615     {
00616       inverse.coeffRef (0) = ie_hf;
00617       inverse.coeffRef (1) = hc_ib;
00618       inverse.coeffRef (2) = fb_ec;
00619       inverse.coeffRef (3) = matrix.coeff (6) * matrix.coeff (5) - matrix.coeff (8) * matrix.coeff (3);
00620       inverse.coeffRef (4) = matrix.coeff (8) * matrix.coeff (0) - matrix.coeff (6) * matrix.coeff (2);
00621       inverse.coeffRef (5) = matrix.coeff (3) * matrix.coeff (2) - matrix.coeff (5) * matrix.coeff (0);
00622       inverse.coeffRef (6) = matrix.coeff (7) * matrix.coeff (3) - matrix.coeff (6) * matrix.coeff (4);
00623       inverse.coeffRef (7) = matrix.coeff (6) * matrix.coeff (1) - matrix.coeff (7) * matrix.coeff (0);
00624       inverse.coeffRef (8) = matrix.coeff (4) * matrix.coeff (0) - matrix.coeff (3) * matrix.coeff (1);
00625 
00626       inverse /= det;
00627     }
00628     return det;
00629   }
00630 
00631   template<typename Matrix> inline typename Matrix::Scalar
00632   determinant3x3Matrix (const Matrix& matrix)
00633   {
00634     // result is independent of Row/Col Major storage!
00635     return matrix.coeff (0) * (matrix.coeff (4) * matrix.coeff (8) - matrix.coeff (5) * matrix.coeff (7)) +
00636            matrix.coeff (1) * (matrix.coeff (5) * matrix.coeff (6) - matrix.coeff (3) * matrix.coeff (8)) +
00637            matrix.coeff (2) * (matrix.coeff (3) * matrix.coeff (7) - matrix.coeff (4) * matrix.coeff (6)) ;
00638   }
00639   
00647   inline void
00648   getTransFromUnitVectorsZY (const Eigen::Vector3f& z_axis, const Eigen::Vector3f& y_direction,
00649                              Eigen::Affine3f& transformation);
00650 
00658   inline Eigen::Affine3f
00659   getTransFromUnitVectorsZY (const Eigen::Vector3f& z_axis, const Eigen::Vector3f& y_direction);
00660 
00668   inline void
00669   getTransFromUnitVectorsXY (const Eigen::Vector3f& x_axis, const Eigen::Vector3f& y_direction,
00670                              Eigen::Affine3f& transformation);
00671 
00679   inline Eigen::Affine3f
00680   getTransFromUnitVectorsXY (const Eigen::Vector3f& x_axis, const Eigen::Vector3f& y_direction);
00681 
00689   inline void
00690   getTransformationFromTwoUnitVectors (const Eigen::Vector3f& y_direction, const Eigen::Vector3f& z_axis,
00691                                        Eigen::Affine3f& transformation);
00692 
00700   inline Eigen::Affine3f
00701   getTransformationFromTwoUnitVectors (const Eigen::Vector3f& y_direction, const Eigen::Vector3f& z_axis);
00702 
00711   inline void
00712   getTransformationFromTwoUnitVectorsAndOrigin (const Eigen::Vector3f& y_direction, const Eigen::Vector3f& z_axis,
00713                                                 const Eigen::Vector3f& origin, Eigen::Affine3f& transformation);
00714 
00722   inline void
00723   getEulerAngles (const Eigen::Affine3f& t, float& roll, float& pitch, float& yaw);
00724 
00735   inline void
00736   getTranslationAndEulerAngles (const Eigen::Affine3f& t, float& x, float& y, float& z,
00737                                 float& roll, float& pitch, float& yaw);
00738 
00749   inline void
00750   getTransformation (float x, float y, float z, float roll, float pitch, float yaw, Eigen::Affine3f& t);
00751 
00762   inline Eigen::Affine3f
00763   getTransformation (float x, float y, float z, float roll, float pitch, float yaw);
00764 
00770   template <typename Derived> void
00771   saveBinary (const Eigen::MatrixBase<Derived>& matrix, std::ostream& file);
00772 
00778   template <typename Derived> void
00779   loadBinary (Eigen::MatrixBase<Derived> const& matrix, std::istream& file);
00780 }
00781 
00782 #include "pcl/common/impl/eigen.hpp"
00783 
00784 #endif  //#ifndef PCL_EIGEN_H_