1// This file is part of Eigen, a lightweight C++ template library 2// for linear algebra. 3// 4// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr> 5// 6// This Source Code Form is subject to the terms of the Mozilla 7// Public License v. 2.0. If a copy of the MPL was not distributed 8// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 10#include "main.h" 11#include <Eigen/Geometry> 12#include <Eigen/LU> 13#include <Eigen/SVD> 14 15/* this test covers the following files: 16 Geometry/OrthoMethods.h 17*/ 18 19template<typename Scalar> void orthomethods_3() 20{ 21 typedef typename NumTraits<Scalar>::Real RealScalar; 22 typedef Matrix<Scalar,3,3> Matrix3; 23 typedef Matrix<Scalar,3,1> Vector3; 24 25 typedef Matrix<Scalar,4,1> Vector4; 26 27 Vector3 v0 = Vector3::Random(), 28 v1 = Vector3::Random(), 29 v2 = Vector3::Random(); 30 31 // cross product 32 VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1)); 33 VERIFY_IS_MUCH_SMALLER_THAN(v1.dot(v1.cross(v2)), Scalar(1)); 34 VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v2), Scalar(1)); 35 VERIFY_IS_MUCH_SMALLER_THAN(v2.dot(v1.cross(v2)), Scalar(1)); 36 VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(Vector3::Random()).dot(v1), Scalar(1)); 37 Matrix3 mat3; 38 mat3 << v0.normalized(), 39 (v0.cross(v1)).normalized(), 40 (v0.cross(v1).cross(v0)).normalized(); 41 VERIFY(mat3.isUnitary()); 42 43 mat3.setRandom(); 44 VERIFY_IS_APPROX(v0.cross(mat3*v1), -(mat3*v1).cross(v0)); 45 VERIFY_IS_APPROX(v0.cross(mat3.lazyProduct(v1)), -(mat3.lazyProduct(v1)).cross(v0)); 46 47 // colwise/rowwise cross product 48 mat3.setRandom(); 49 Vector3 vec3 = Vector3::Random(); 50 Matrix3 mcross; 51 int i = internal::random<int>(0,2); 52 mcross = mat3.colwise().cross(vec3); 53 VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3)); 54 55 VERIFY_IS_MUCH_SMALLER_THAN((mat3.adjoint() * mat3.colwise().cross(vec3)).diagonal().cwiseAbs().sum(), Scalar(1)); 56 VERIFY_IS_MUCH_SMALLER_THAN((mat3.adjoint() * mat3.colwise().cross(Vector3::Random())).diagonal().cwiseAbs().sum(), Scalar(1)); 57 58 VERIFY_IS_MUCH_SMALLER_THAN((vec3.adjoint() * mat3.colwise().cross(vec3)).cwiseAbs().sum(), Scalar(1)); 59 VERIFY_IS_MUCH_SMALLER_THAN((vec3.adjoint() * Matrix3::Random().colwise().cross(vec3)).cwiseAbs().sum(), Scalar(1)); 60 61 mcross = mat3.rowwise().cross(vec3); 62 VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3)); 63 64 // cross3 65 Vector4 v40 = Vector4::Random(), 66 v41 = Vector4::Random(), 67 v42 = Vector4::Random(); 68 v40.w() = v41.w() = v42.w() = 0; 69 v42.template head<3>() = v40.template head<3>().cross(v41.template head<3>()); 70 VERIFY_IS_APPROX(v40.cross3(v41), v42); 71 VERIFY_IS_MUCH_SMALLER_THAN(v40.cross3(Vector4::Random()).dot(v40), Scalar(1)); 72 73 // check mixed product 74 typedef Matrix<RealScalar, 3, 1> RealVector3; 75 RealVector3 rv1 = RealVector3::Random(); 76 VERIFY_IS_APPROX(v1.cross(rv1.template cast<Scalar>()), v1.cross(rv1)); 77 VERIFY_IS_APPROX(rv1.template cast<Scalar>().cross(v1), rv1.cross(v1)); 78} 79 80template<typename Scalar, int Size> void orthomethods(int size=Size) 81{ 82 typedef typename NumTraits<Scalar>::Real RealScalar; 83 typedef Matrix<Scalar,Size,1> VectorType; 84 typedef Matrix<Scalar,3,Size> Matrix3N; 85 typedef Matrix<Scalar,Size,3> MatrixN3; 86 typedef Matrix<Scalar,3,1> Vector3; 87 88 VectorType v0 = VectorType::Random(size); 89 90 // unitOrthogonal 91 VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1)); 92 VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1)); 93 94 if (size>=3) 95 { 96 v0.template head<2>().setZero(); 97 v0.tail(size-2).setRandom(); 98 99 VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1)); 100 VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), RealScalar(1)); 101 } 102 103 // colwise/rowwise cross product 104 Vector3 vec3 = Vector3::Random(); 105 int i = internal::random<int>(0,size-1); 106 107 Matrix3N mat3N(3,size), mcross3N(3,size); 108 mat3N.setRandom(); 109 mcross3N = mat3N.colwise().cross(vec3); 110 VERIFY_IS_APPROX(mcross3N.col(i), mat3N.col(i).cross(vec3)); 111 112 MatrixN3 matN3(size,3), mcrossN3(size,3); 113 matN3.setRandom(); 114 mcrossN3 = matN3.rowwise().cross(vec3); 115 VERIFY_IS_APPROX(mcrossN3.row(i), matN3.row(i).cross(vec3)); 116} 117 118void test_geo_orthomethods() 119{ 120 for(int i = 0; i < g_repeat; i++) { 121 CALL_SUBTEST_1( orthomethods_3<float>() ); 122 CALL_SUBTEST_2( orthomethods_3<double>() ); 123 CALL_SUBTEST_4( orthomethods_3<std::complex<double> >() ); 124 CALL_SUBTEST_1( (orthomethods<float,2>()) ); 125 CALL_SUBTEST_2( (orthomethods<double,2>()) ); 126 CALL_SUBTEST_1( (orthomethods<float,3>()) ); 127 CALL_SUBTEST_2( (orthomethods<double,3>()) ); 128 CALL_SUBTEST_3( (orthomethods<float,7>()) ); 129 CALL_SUBTEST_4( (orthomethods<std::complex<double>,8>()) ); 130 CALL_SUBTEST_5( (orthomethods<float,Dynamic>(36)) ); 131 CALL_SUBTEST_6( (orthomethods<double,Dynamic>(35)) ); 132 } 133} 134