|
Point Cloud Library (PCL)
1.5.1
|
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_
1.8.0