Brian Silverman | 72890c2 | 2015-09-19 14:37:37 -0400 | [diff] [blame^] | 1 | // This file is part of Eigen, a lightweight C++ template library |
| 2 | // for linear algebra. Eigen itself is part of the KDE project. |
| 3 | // |
| 4 | // Copyright (C) 2008 Gael Guennebaud <g.gael@free.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 | template<typename Scalar> void geometry(void) |
| 16 | { |
| 17 | /* this test covers the following files: |
| 18 | Cross.h Quaternion.h, Transform.cpp |
| 19 | */ |
| 20 | |
| 21 | typedef Matrix<Scalar,2,2> Matrix2; |
| 22 | typedef Matrix<Scalar,3,3> Matrix3; |
| 23 | typedef Matrix<Scalar,4,4> Matrix4; |
| 24 | typedef Matrix<Scalar,2,1> Vector2; |
| 25 | typedef Matrix<Scalar,3,1> Vector3; |
| 26 | typedef Matrix<Scalar,4,1> Vector4; |
| 27 | typedef Quaternion<Scalar> Quaternionx; |
| 28 | typedef AngleAxis<Scalar> AngleAxisx; |
| 29 | typedef Transform<Scalar,2> Transform2; |
| 30 | typedef Transform<Scalar,3> Transform3; |
| 31 | typedef Scaling<Scalar,2> Scaling2; |
| 32 | typedef Scaling<Scalar,3> Scaling3; |
| 33 | typedef Translation<Scalar,2> Translation2; |
| 34 | typedef Translation<Scalar,3> Translation3; |
| 35 | |
| 36 | Scalar largeEps = test_precision<Scalar>(); |
| 37 | if (ei_is_same_type<Scalar,float>::ret) |
| 38 | largeEps = 1e-2f; |
| 39 | |
| 40 | Vector3 v0 = Vector3::Random(), |
| 41 | v1 = Vector3::Random(), |
| 42 | v2 = Vector3::Random(); |
| 43 | Vector2 u0 = Vector2::Random(); |
| 44 | Matrix3 matrot1; |
| 45 | |
| 46 | Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI)); |
| 47 | |
| 48 | // cross product |
| 49 | VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).eigen2_dot(v1), Scalar(1)); |
| 50 | Matrix3 m; |
| 51 | m << v0.normalized(), |
| 52 | (v0.cross(v1)).normalized(), |
| 53 | (v0.cross(v1).cross(v0)).normalized(); |
| 54 | VERIFY(m.isUnitary()); |
| 55 | |
| 56 | // Quaternion: Identity(), setIdentity(); |
| 57 | Quaternionx q1, q2; |
| 58 | q2.setIdentity(); |
| 59 | VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs()); |
| 60 | q1.coeffs().setRandom(); |
| 61 | VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs()); |
| 62 | |
| 63 | // unitOrthogonal |
| 64 | VERIFY_IS_MUCH_SMALLER_THAN(u0.unitOrthogonal().eigen2_dot(u0), Scalar(1)); |
| 65 | VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().eigen2_dot(v0), Scalar(1)); |
| 66 | VERIFY_IS_APPROX(u0.unitOrthogonal().norm(), Scalar(1)); |
| 67 | VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1)); |
| 68 | |
| 69 | |
| 70 | VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0); |
| 71 | VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0); |
| 72 | VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.eigen2_dot(AngleAxisx(a, v0.unitOrthogonal()) * v0)); |
| 73 | m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint(); |
| 74 | VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized())); |
| 75 | VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m); |
| 76 | |
| 77 | q1 = AngleAxisx(a, v0.normalized()); |
| 78 | q2 = AngleAxisx(a, v1.normalized()); |
| 79 | |
| 80 | // angular distance |
| 81 | Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle()); |
| 82 | if (refangle>Scalar(M_PI)) |
| 83 | refangle = Scalar(2)*Scalar(M_PI) - refangle; |
| 84 | |
| 85 | if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps) |
| 86 | { |
| 87 | VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps)); |
| 88 | } |
| 89 | |
| 90 | // rotation matrix conversion |
| 91 | VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2); |
| 92 | VERIFY_IS_APPROX(q1 * q2 * v2, |
| 93 | q1.toRotationMatrix() * q2.toRotationMatrix() * v2); |
| 94 | |
| 95 | VERIFY( (q2*q1).isApprox(q1*q2, largeEps) || !(q2 * q1 * v2).isApprox( |
| 96 | q1.toRotationMatrix() * q2.toRotationMatrix() * v2)); |
| 97 | |
| 98 | q2 = q1.toRotationMatrix(); |
| 99 | VERIFY_IS_APPROX(q1*v1,q2*v1); |
| 100 | |
| 101 | matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX()) |
| 102 | * AngleAxisx(Scalar(0.2), Vector3::UnitY()) |
| 103 | * AngleAxisx(Scalar(0.3), Vector3::UnitZ()); |
| 104 | VERIFY_IS_APPROX(matrot1 * v1, |
| 105 | AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix() |
| 106 | * (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix() |
| 107 | * (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1))); |
| 108 | |
| 109 | // angle-axis conversion |
| 110 | AngleAxisx aa = q1; |
| 111 | VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1); |
| 112 | VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1); |
| 113 | |
| 114 | // from two vector creation |
| 115 | VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized()); |
| 116 | VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized()); |
| 117 | |
| 118 | // inverse and conjugate |
| 119 | VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1); |
| 120 | VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1); |
| 121 | |
| 122 | // AngleAxis |
| 123 | VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(), |
| 124 | Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix()); |
| 125 | |
| 126 | AngleAxisx aa1; |
| 127 | m = q1.toRotationMatrix(); |
| 128 | aa1 = m; |
| 129 | VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(), |
| 130 | Quaternionx(m).toRotationMatrix()); |
| 131 | |
| 132 | // Transform |
| 133 | // TODO complete the tests ! |
| 134 | a = 0; |
| 135 | while (ei_abs(a)<Scalar(0.1)) |
| 136 | a = ei_random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI)); |
| 137 | q1 = AngleAxisx(a, v0.normalized()); |
| 138 | Transform3 t0, t1, t2; |
| 139 | // first test setIdentity() and Identity() |
| 140 | t0.setIdentity(); |
| 141 | VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity()); |
| 142 | t0.matrix().setZero(); |
| 143 | t0 = Transform3::Identity(); |
| 144 | VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity()); |
| 145 | |
| 146 | t0.linear() = q1.toRotationMatrix(); |
| 147 | t1.setIdentity(); |
| 148 | t1.linear() = q1.toRotationMatrix(); |
| 149 | |
| 150 | v0 << 50, 2, 1;//= ei_random_matrix<Vector3>().cwiseProduct(Vector3(10,2,0.5)); |
| 151 | t0.scale(v0); |
| 152 | t1.prescale(v0); |
| 153 | |
| 154 | VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).norm(), v0.x()); |
| 155 | //VERIFY(!ei_isApprox((t1 * Vector3(1,0,0)).norm(), v0.x())); |
| 156 | |
| 157 | t0.setIdentity(); |
| 158 | t1.setIdentity(); |
| 159 | v1 << 1, 2, 3; |
| 160 | t0.linear() = q1.toRotationMatrix(); |
| 161 | t0.pretranslate(v0); |
| 162 | t0.scale(v1); |
| 163 | t1.linear() = q1.conjugate().toRotationMatrix(); |
| 164 | t1.prescale(v1.cwise().inverse()); |
| 165 | t1.translate(-v0); |
| 166 | |
| 167 | VERIFY((t0.matrix() * t1.matrix()).isIdentity(test_precision<Scalar>())); |
| 168 | |
| 169 | t1.fromPositionOrientationScale(v0, q1, v1); |
| 170 | VERIFY_IS_APPROX(t1.matrix(), t0.matrix()); |
| 171 | VERIFY_IS_APPROX(t1*v1, t0*v1); |
| 172 | |
| 173 | t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix()); |
| 174 | t1.setIdentity(); t1.scale(v0).rotate(q1); |
| 175 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 176 | |
| 177 | t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1)); |
| 178 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 179 | |
| 180 | VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix()); |
| 181 | VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix()); |
| 182 | |
| 183 | // More transform constructors, operator=, operator*= |
| 184 | |
| 185 | Matrix3 mat3 = Matrix3::Random(); |
| 186 | Matrix4 mat4; |
| 187 | mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose(); |
| 188 | Transform3 tmat3(mat3), tmat4(mat4); |
| 189 | tmat4.matrix()(3,3) = Scalar(1); |
| 190 | VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix()); |
| 191 | |
| 192 | Scalar a3 = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI)); |
| 193 | Vector3 v3 = Vector3::Random().normalized(); |
| 194 | AngleAxisx aa3(a3, v3); |
| 195 | Transform3 t3(aa3); |
| 196 | Transform3 t4; |
| 197 | t4 = aa3; |
| 198 | VERIFY_IS_APPROX(t3.matrix(), t4.matrix()); |
| 199 | t4.rotate(AngleAxisx(-a3,v3)); |
| 200 | VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity()); |
| 201 | t4 *= aa3; |
| 202 | VERIFY_IS_APPROX(t3.matrix(), t4.matrix()); |
| 203 | |
| 204 | v3 = Vector3::Random(); |
| 205 | Translation3 tv3(v3); |
| 206 | Transform3 t5(tv3); |
| 207 | t4 = tv3; |
| 208 | VERIFY_IS_APPROX(t5.matrix(), t4.matrix()); |
| 209 | t4.translate(-v3); |
| 210 | VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity()); |
| 211 | t4 *= tv3; |
| 212 | VERIFY_IS_APPROX(t5.matrix(), t4.matrix()); |
| 213 | |
| 214 | Scaling3 sv3(v3); |
| 215 | Transform3 t6(sv3); |
| 216 | t4 = sv3; |
| 217 | VERIFY_IS_APPROX(t6.matrix(), t4.matrix()); |
| 218 | t4.scale(v3.cwise().inverse()); |
| 219 | VERIFY_IS_APPROX(t4.matrix(), Matrix4::Identity()); |
| 220 | t4 *= sv3; |
| 221 | VERIFY_IS_APPROX(t6.matrix(), t4.matrix()); |
| 222 | |
| 223 | // matrix * transform |
| 224 | VERIFY_IS_APPROX(Transform3(t3.matrix()*t4).matrix(), Transform3(t3*t4).matrix()); |
| 225 | |
| 226 | // chained Transform product |
| 227 | VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix()); |
| 228 | |
| 229 | // check that Transform product doesn't have aliasing problems |
| 230 | t5 = t4; |
| 231 | t5 = t5*t5; |
| 232 | VERIFY_IS_APPROX(t5, t4*t4); |
| 233 | |
| 234 | // 2D transformation |
| 235 | Transform2 t20, t21; |
| 236 | Vector2 v20 = Vector2::Random(); |
| 237 | Vector2 v21 = Vector2::Random(); |
| 238 | for (int k=0; k<2; ++k) |
| 239 | if (ei_abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3); |
| 240 | t21.setIdentity(); |
| 241 | t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix(); |
| 242 | VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(), |
| 243 | t21.pretranslate(v20).scale(v21).matrix()); |
| 244 | |
| 245 | t21.setIdentity(); |
| 246 | t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix(); |
| 247 | VERIFY( (t20.fromPositionOrientationScale(v20,a,v21) |
| 248 | * (t21.prescale(v21.cwise().inverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) ); |
| 249 | |
| 250 | // Transform - new API |
| 251 | // 3D |
| 252 | t0.setIdentity(); |
| 253 | t0.rotate(q1).scale(v0).translate(v0); |
| 254 | // mat * scaling and mat * translation |
| 255 | t1 = (Matrix3(q1) * Scaling3(v0)) * Translation3(v0); |
| 256 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 257 | // mat * transformation and scaling * translation |
| 258 | t1 = Matrix3(q1) * (Scaling3(v0) * Translation3(v0)); |
| 259 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 260 | |
| 261 | t0.setIdentity(); |
| 262 | t0.prerotate(q1).prescale(v0).pretranslate(v0); |
| 263 | // translation * scaling and transformation * mat |
| 264 | t1 = (Translation3(v0) * Scaling3(v0)) * Matrix3(q1); |
| 265 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 266 | // scaling * mat and translation * mat |
| 267 | t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1)); |
| 268 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 269 | |
| 270 | t0.setIdentity(); |
| 271 | t0.scale(v0).translate(v0).rotate(q1); |
| 272 | // translation * mat and scaling * transformation |
| 273 | t1 = Scaling3(v0) * (Translation3(v0) * Matrix3(q1)); |
| 274 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 275 | // transformation * scaling |
| 276 | t0.scale(v0); |
| 277 | t1 = t1 * Scaling3(v0); |
| 278 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 279 | // transformation * translation |
| 280 | t0.translate(v0); |
| 281 | t1 = t1 * Translation3(v0); |
| 282 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 283 | // translation * transformation |
| 284 | t0.pretranslate(v0); |
| 285 | t1 = Translation3(v0) * t1; |
| 286 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 287 | |
| 288 | // transform * quaternion |
| 289 | t0.rotate(q1); |
| 290 | t1 = t1 * q1; |
| 291 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 292 | |
| 293 | // translation * quaternion |
| 294 | t0.translate(v1).rotate(q1); |
| 295 | t1 = t1 * (Translation3(v1) * q1); |
| 296 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 297 | |
| 298 | // scaling * quaternion |
| 299 | t0.scale(v1).rotate(q1); |
| 300 | t1 = t1 * (Scaling3(v1) * q1); |
| 301 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 302 | |
| 303 | // quaternion * transform |
| 304 | t0.prerotate(q1); |
| 305 | t1 = q1 * t1; |
| 306 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 307 | |
| 308 | // quaternion * translation |
| 309 | t0.rotate(q1).translate(v1); |
| 310 | t1 = t1 * (q1 * Translation3(v1)); |
| 311 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 312 | |
| 313 | // quaternion * scaling |
| 314 | t0.rotate(q1).scale(v1); |
| 315 | t1 = t1 * (q1 * Scaling3(v1)); |
| 316 | VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); |
| 317 | |
| 318 | // translation * vector |
| 319 | t0.setIdentity(); |
| 320 | t0.translate(v0); |
| 321 | VERIFY_IS_APPROX(t0 * v1, Translation3(v0) * v1); |
| 322 | |
| 323 | // scaling * vector |
| 324 | t0.setIdentity(); |
| 325 | t0.scale(v0); |
| 326 | VERIFY_IS_APPROX(t0 * v1, Scaling3(v0) * v1); |
| 327 | |
| 328 | // test transform inversion |
| 329 | t0.setIdentity(); |
| 330 | t0.translate(v0); |
| 331 | t0.linear().setRandom(); |
| 332 | VERIFY_IS_APPROX(t0.inverse(Affine), t0.matrix().inverse()); |
| 333 | t0.setIdentity(); |
| 334 | t0.translate(v0).rotate(q1); |
| 335 | VERIFY_IS_APPROX(t0.inverse(Isometry), t0.matrix().inverse()); |
| 336 | |
| 337 | // test extract rotation and scaling |
| 338 | t0.setIdentity(); |
| 339 | t0.translate(v0).rotate(q1).scale(v1); |
| 340 | VERIFY_IS_APPROX(t0.rotation() * v1, Matrix3(q1) * v1); |
| 341 | |
| 342 | Matrix3 mat_rotation, mat_scaling; |
| 343 | t0.setIdentity(); |
| 344 | t0.translate(v0).rotate(q1).scale(v1); |
| 345 | t0.computeRotationScaling(&mat_rotation, &mat_scaling); |
| 346 | VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling); |
| 347 | VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity()); |
| 348 | VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1)); |
| 349 | t0.computeScalingRotation(&mat_scaling, &mat_rotation); |
| 350 | VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation); |
| 351 | VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity()); |
| 352 | VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1)); |
| 353 | |
| 354 | // test casting |
| 355 | Transform<float,3> t1f = t1.template cast<float>(); |
| 356 | VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1); |
| 357 | Transform<double,3> t1d = t1.template cast<double>(); |
| 358 | VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1); |
| 359 | |
| 360 | Translation3 tr1(v0); |
| 361 | Translation<float,3> tr1f = tr1.template cast<float>(); |
| 362 | VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1); |
| 363 | Translation<double,3> tr1d = tr1.template cast<double>(); |
| 364 | VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1); |
| 365 | |
| 366 | Scaling3 sc1(v0); |
| 367 | Scaling<float,3> sc1f = sc1.template cast<float>(); |
| 368 | VERIFY_IS_APPROX(sc1f.template cast<Scalar>(),sc1); |
| 369 | Scaling<double,3> sc1d = sc1.template cast<double>(); |
| 370 | VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1); |
| 371 | |
| 372 | Quaternion<float> q1f = q1.template cast<float>(); |
| 373 | VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1); |
| 374 | Quaternion<double> q1d = q1.template cast<double>(); |
| 375 | VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1); |
| 376 | |
| 377 | AngleAxis<float> aa1f = aa1.template cast<float>(); |
| 378 | VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1); |
| 379 | AngleAxis<double> aa1d = aa1.template cast<double>(); |
| 380 | VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1); |
| 381 | |
| 382 | Rotation2D<Scalar> r2d1(ei_random<Scalar>()); |
| 383 | Rotation2D<float> r2d1f = r2d1.template cast<float>(); |
| 384 | VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1); |
| 385 | Rotation2D<double> r2d1d = r2d1.template cast<double>(); |
| 386 | VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1); |
| 387 | |
| 388 | m = q1; |
| 389 | // m.col(1) = Vector3(0,ei_random<Scalar>(),ei_random<Scalar>()).normalized(); |
| 390 | // m.col(0) = Vector3(-1,0,0).normalized(); |
| 391 | // m.col(2) = m.col(0).cross(m.col(1)); |
| 392 | #define VERIFY_EULER(I,J,K, X,Y,Z) { \ |
| 393 | Vector3 ea = m.eulerAngles(I,J,K); \ |
| 394 | Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \ |
| 395 | VERIFY_IS_APPROX(m, m1); \ |
| 396 | VERIFY_IS_APPROX(m, Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \ |
| 397 | } |
| 398 | VERIFY_EULER(0,1,2, X,Y,Z); |
| 399 | VERIFY_EULER(0,1,0, X,Y,X); |
| 400 | VERIFY_EULER(0,2,1, X,Z,Y); |
| 401 | VERIFY_EULER(0,2,0, X,Z,X); |
| 402 | |
| 403 | VERIFY_EULER(1,2,0, Y,Z,X); |
| 404 | VERIFY_EULER(1,2,1, Y,Z,Y); |
| 405 | VERIFY_EULER(1,0,2, Y,X,Z); |
| 406 | VERIFY_EULER(1,0,1, Y,X,Y); |
| 407 | |
| 408 | VERIFY_EULER(2,0,1, Z,X,Y); |
| 409 | VERIFY_EULER(2,0,2, Z,X,Z); |
| 410 | VERIFY_EULER(2,1,0, Z,Y,X); |
| 411 | VERIFY_EULER(2,1,2, Z,Y,Z); |
| 412 | |
| 413 | // colwise/rowwise cross product |
| 414 | mat3.setRandom(); |
| 415 | Vector3 vec3 = Vector3::Random(); |
| 416 | Matrix3 mcross; |
| 417 | int i = ei_random<int>(0,2); |
| 418 | mcross = mat3.colwise().cross(vec3); |
| 419 | VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3)); |
| 420 | mcross = mat3.rowwise().cross(vec3); |
| 421 | VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3)); |
| 422 | |
| 423 | |
| 424 | } |
| 425 | |
| 426 | void test_eigen2_geometry() |
| 427 | { |
| 428 | for(int i = 0; i < g_repeat; i++) { |
| 429 | CALL_SUBTEST_1( geometry<float>() ); |
| 430 | CALL_SUBTEST_2( geometry<double>() ); |
| 431 | } |
| 432 | } |