00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "main.h"
00026 #include <Eigen/Geometry>
00027 #include <Eigen/LU>
00028 #include <Eigen/SVD>
00029
00030 template<typename Scalar, int Mode, int Options> void non_projective_only()
00031 {
00032
00033
00034
00035 typedef Matrix<Scalar,2,2> Matrix2;
00036 typedef Matrix<Scalar,3,3> Matrix3;
00037 typedef Matrix<Scalar,4,4> Matrix4;
00038 typedef Matrix<Scalar,2,1> Vector2;
00039 typedef Matrix<Scalar,3,1> Vector3;
00040 typedef Matrix<Scalar,4,1> Vector4;
00041 typedef Quaternion<Scalar> Quaternionx;
00042 typedef AngleAxis<Scalar> AngleAxisx;
00043 typedef Transform<Scalar,2,Mode,Options> Transform2;
00044 typedef Transform<Scalar,3,Mode,Options> Transform3;
00045 typedef Transform<Scalar,2,Isometry,Options> Isometry2;
00046 typedef Transform<Scalar,3,Isometry,Options> Isometry3;
00047 typedef typename Transform3::MatrixType MatrixType;
00048 typedef DiagonalMatrix<Scalar,2> AlignedScaling2;
00049 typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
00050 typedef Translation<Scalar,2> Translation2;
00051 typedef Translation<Scalar,3> Translation3;
00052
00053 Vector3 v0 = Vector3::Random(),
00054 v1 = Vector3::Random();
00055
00056 Transform3 t0, t1, t2;
00057
00058 Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
00059
00060 Quaternionx q1, q2;
00061
00062 q1 = AngleAxisx(a, v0.normalized());
00063
00064 t0 = Transform3::Identity();
00065 VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
00066
00067 t0.linear() = q1.toRotationMatrix();
00068
00069 v0 << 50, 2, 1;
00070 t0.scale(v0);
00071
00072 VERIFY_IS_APPROX( (t0 * Vector3(1,0,0)).template head<3>().norm(), v0.x());
00073
00074 t0.setIdentity();
00075 t1.setIdentity();
00076 v1 << 1, 2, 3;
00077 t0.linear() = q1.toRotationMatrix();
00078 t0.pretranslate(v0);
00079 t0.scale(v1);
00080 t1.linear() = q1.conjugate().toRotationMatrix();
00081 t1.prescale(v1.cwiseInverse());
00082 t1.translate(-v0);
00083
00084 VERIFY((t0 * t1).matrix().isIdentity(test_precision<Scalar>()));
00085
00086 t1.fromPositionOrientationScale(v0, q1, v1);
00087 VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
00088 VERIFY_IS_APPROX(t1*v1, t0*v1);
00089
00090
00091 t0.setIdentity();
00092 t0.translate(v0);
00093 VERIFY_IS_APPROX((t0 * v1).template head<3>(), Translation3(v0) * v1);
00094
00095
00096 t0.setIdentity();
00097 t0.scale(v0);
00098 VERIFY_IS_APPROX((t0 * v1).template head<3>(), AlignedScaling3(v0) * v1);
00099 }
00100
00101 template<typename Scalar, int Mode, int Options> void transformations()
00102 {
00103
00104
00105
00106 typedef Matrix<Scalar,2,2> Matrix2;
00107 typedef Matrix<Scalar,3,3> Matrix3;
00108 typedef Matrix<Scalar,4,4> Matrix4;
00109 typedef Matrix<Scalar,2,1> Vector2;
00110 typedef Matrix<Scalar,3,1> Vector3;
00111 typedef Matrix<Scalar,4,1> Vector4;
00112 typedef Quaternion<Scalar> Quaternionx;
00113 typedef AngleAxis<Scalar> AngleAxisx;
00114 typedef Transform<Scalar,2,Mode,Options> Transform2;
00115 typedef Transform<Scalar,3,Mode,Options> Transform3;
00116 typedef Transform<Scalar,2,Isometry,Options> Isometry2;
00117 typedef Transform<Scalar,3,Isometry,Options> Isometry3;
00118 typedef typename Transform3::MatrixType MatrixType;
00119 typedef DiagonalMatrix<Scalar,2> AlignedScaling2;
00120 typedef DiagonalMatrix<Scalar,3> AlignedScaling3;
00121 typedef Translation<Scalar,2> Translation2;
00122 typedef Translation<Scalar,3> Translation3;
00123
00124 Vector3 v0 = Vector3::Random(),
00125 v1 = Vector3::Random(),
00126 v2 = Vector3::Random();
00127 Vector2 u0 = Vector2::Random();
00128 Matrix3 matrot1, m;
00129
00130 Scalar a = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
00131 Scalar s0 = internal::random<Scalar>();
00132
00133 VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
00134 VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
00135 VERIFY_IS_APPROX(internal::cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
00136 m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint();
00137 VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
00138 VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
00139
00140 Quaternionx q1, q2;
00141 q1 = AngleAxisx(a, v0.normalized());
00142 q2 = AngleAxisx(a, v1.normalized());
00143
00144
00145 matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
00146 * AngleAxisx(Scalar(0.2), Vector3::UnitY())
00147 * AngleAxisx(Scalar(0.3), Vector3::UnitZ());
00148 VERIFY_IS_APPROX(matrot1 * v1,
00149 AngleAxisx(Scalar(0.1), Vector3(1,0,0)).toRotationMatrix()
00150 * (AngleAxisx(Scalar(0.2), Vector3(0,1,0)).toRotationMatrix()
00151 * (AngleAxisx(Scalar(0.3), Vector3(0,0,1)).toRotationMatrix() * v1)));
00152
00153
00154 AngleAxisx aa = AngleAxisx(q1);
00155 VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
00156 VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
00157
00158 aa.fromRotationMatrix(aa.toRotationMatrix());
00159 VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
00160 VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
00161
00162
00163 VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
00164 Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
00165
00166 AngleAxisx aa1;
00167 m = q1.toRotationMatrix();
00168 aa1 = m;
00169 VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(),
00170 Quaternionx(m).toRotationMatrix());
00171
00172
00173
00174 a = 0;
00175 while (internal::abs(a)<Scalar(0.1))
00176 a = internal::random<Scalar>(-Scalar(0.4)*Scalar(M_PI), Scalar(0.4)*Scalar(M_PI));
00177 q1 = AngleAxisx(a, v0.normalized());
00178 Transform3 t0, t1, t2;
00179
00180
00181 t0.setIdentity();
00182 VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
00183 t0.matrix().setZero();
00184 t0 = Transform3::Identity();
00185 VERIFY_IS_APPROX(t0.matrix(), Transform3::MatrixType::Identity());
00186
00187 t0.setIdentity();
00188 t1.setIdentity();
00189 v1 << 1, 2, 3;
00190 t0.linear() = q1.toRotationMatrix();
00191 t0.pretranslate(v0);
00192 t0.scale(v1);
00193 t1.linear() = q1.conjugate().toRotationMatrix();
00194 t1.prescale(v1.cwiseInverse());
00195 t1.translate(-v0);
00196
00197 VERIFY((t0 * t1).matrix().isIdentity(test_precision<Scalar>()));
00198
00199 t1.fromPositionOrientationScale(v0, q1, v1);
00200 VERIFY_IS_APPROX(t1.matrix(), t0.matrix());
00201
00202 t0.setIdentity(); t0.scale(v0).rotate(q1.toRotationMatrix());
00203 t1.setIdentity(); t1.scale(v0).rotate(q1);
00204 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00205
00206 t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1));
00207 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00208
00209 VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix());
00210 VERIFY_IS_APPROX(t0.prescale(a).matrix(), t1.prescale(Vector3::Constant(a)).matrix());
00211
00212
00213
00214 Matrix3 mat3 = Matrix3::Random();
00215 Matrix4 mat4;
00216 mat4 << mat3 , Vector3::Zero() , Vector4::Zero().transpose();
00217 Transform3 tmat3(mat3), tmat4(mat4);
00218 if(Mode!=int(AffineCompact))
00219 tmat4.matrix()(3,3) = Scalar(1);
00220 VERIFY_IS_APPROX(tmat3.matrix(), tmat4.matrix());
00221
00222 Scalar a3 = internal::random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
00223 Vector3 v3 = Vector3::Random().normalized();
00224 AngleAxisx aa3(a3, v3);
00225 Transform3 t3(aa3);
00226 Transform3 t4;
00227 t4 = aa3;
00228 VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
00229 t4.rotate(AngleAxisx(-a3,v3));
00230 VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
00231 t4 *= aa3;
00232 VERIFY_IS_APPROX(t3.matrix(), t4.matrix());
00233
00234 v3 = Vector3::Random();
00235 Translation3 tv3(v3);
00236 Transform3 t5(tv3);
00237 t4 = tv3;
00238 VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
00239 t4.translate(-v3);
00240 VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
00241 t4 *= tv3;
00242 VERIFY_IS_APPROX(t5.matrix(), t4.matrix());
00243
00244 AlignedScaling3 sv3(v3);
00245 Transform3 t6(sv3);
00246 t4 = sv3;
00247 VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
00248 t4.scale(v3.cwiseInverse());
00249 VERIFY_IS_APPROX(t4.matrix(), MatrixType::Identity());
00250 t4 *= sv3;
00251 VERIFY_IS_APPROX(t6.matrix(), t4.matrix());
00252
00253
00254 VERIFY_IS_APPROX((t3.matrix()*t4).matrix(), (t3*t4).matrix());
00255
00256
00257 VERIFY_IS_APPROX(((t3*t4)*t5).matrix(), (t3*(t4*t5)).matrix());
00258
00259
00260 t5 = t4;
00261 t5 = t5*t5;
00262 VERIFY_IS_APPROX(t5, t4*t4);
00263
00264
00265 Transform2 t20, t21;
00266 Vector2 v20 = Vector2::Random();
00267 Vector2 v21 = Vector2::Random();
00268 for (int k=0; k<2; ++k)
00269 if (internal::abs(v21[k])<Scalar(1e-3)) v21[k] = Scalar(1e-3);
00270 t21.setIdentity();
00271 t21.linear() = Rotation2D<Scalar>(a).toRotationMatrix();
00272 VERIFY_IS_APPROX(t20.fromPositionOrientationScale(v20,a,v21).matrix(),
00273 t21.pretranslate(v20).scale(v21).matrix());
00274
00275 t21.setIdentity();
00276 t21.linear() = Rotation2D<Scalar>(-a).toRotationMatrix();
00277 VERIFY( (t20.fromPositionOrientationScale(v20,a,v21)
00278 * (t21.prescale(v21.cwiseInverse()).translate(-v20))).matrix().isIdentity(test_precision<Scalar>()) );
00279
00280
00281
00282 t0.setIdentity();
00283 t0.rotate(q1).scale(v0).translate(v0);
00284
00285 t1 = (Matrix3(q1) * AlignedScaling3(v0)) * Translation3(v0);
00286 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00287 t1 = (Matrix3(q1) * Scaling(v0)) * Translation3(v0);
00288 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00289 t1 = (q1 * Scaling(v0)) * Translation3(v0);
00290 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00291
00292 t1 = Matrix3(q1) * (AlignedScaling3(v0) * Translation3(v0));
00293 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00294
00295
00296 t0.setIdentity();
00297 t0.scale(s0).translate(v0);
00298 t1 = Scaling(s0) * Translation3(v0);
00299 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00300 t0.prescale(s0);
00301 t1 = Scaling(s0) * t1;
00302 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00303
00304 t0 = t3;
00305 t0.scale(s0);
00306 t1 = t3 * Scaling(s0,s0,s0);
00307 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00308 t0.prescale(s0);
00309 t1 = Scaling(s0,s0,s0) * t1;
00310 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00311
00312
00313 t0.setIdentity();
00314 t0.prerotate(q1).prescale(v0).pretranslate(v0);
00315
00316 t1 = (Translation3(v0) * AlignedScaling3(v0)) * Transform3(q1);
00317 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00318
00319 t1 = Translation3(v0) * (AlignedScaling3(v0) * Transform3(q1));
00320 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00321
00322 t0.setIdentity();
00323 t0.scale(v0).translate(v0).rotate(q1);
00324
00325 t1 = AlignedScaling3(v0) * (Translation3(v0) * Transform3(q1));
00326 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00327
00328 t0.scale(v0);
00329 t1 *= AlignedScaling3(v0);
00330 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00331
00332 t0.translate(v0);
00333 t1 = t1 * Translation3(v0);
00334 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00335
00336 t0.pretranslate(v0);
00337 t1 = Translation3(v0) * t1;
00338 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00339
00340
00341 t0.rotate(q1);
00342 t1 = t1 * q1;
00343 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00344
00345
00346 t0.translate(v1).rotate(q1);
00347 t1 = t1 * (Translation3(v1) * q1);
00348 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00349
00350
00351 t0.scale(v1).rotate(q1);
00352 t1 = t1 * (AlignedScaling3(v1) * q1);
00353 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00354
00355
00356 t0.prerotate(q1);
00357 t1 = q1 * t1;
00358 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00359
00360
00361 t0.rotate(q1).translate(v1);
00362 t1 = t1 * (q1 * Translation3(v1));
00363 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00364
00365
00366 t0.rotate(q1).scale(v1);
00367 t1 = t1 * (q1 * AlignedScaling3(v1));
00368 VERIFY_IS_APPROX(t0.matrix(), t1.matrix());
00369
00370
00371 t0.setIdentity();
00372 t0.translate(v0);
00373 t0.linear().setRandom();
00374 Matrix4 t044 = Matrix4::Zero();
00375 t044(3,3) = 1;
00376 t044.block(0,0,t0.matrix().rows(),4) = t0.matrix();
00377 VERIFY_IS_APPROX(t0.inverse(Affine).matrix(), t044.inverse().block(0,0,t0.matrix().rows(),4));
00378 t0.setIdentity();
00379 t0.translate(v0).rotate(q1);
00380 t044 = Matrix4::Zero();
00381 t044(3,3) = 1;
00382 t044.block(0,0,t0.matrix().rows(),4) = t0.matrix();
00383 VERIFY_IS_APPROX(t0.inverse(Isometry).matrix(), t044.inverse().block(0,0,t0.matrix().rows(),4));
00384
00385 Matrix3 mat_rotation, mat_scaling;
00386 t0.setIdentity();
00387 t0.translate(v0).rotate(q1).scale(v1);
00388 t0.computeRotationScaling(&mat_rotation, &mat_scaling);
00389 VERIFY_IS_APPROX(t0.linear(), mat_rotation * mat_scaling);
00390 VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
00391 VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
00392 t0.computeScalingRotation(&mat_scaling, &mat_rotation);
00393 VERIFY_IS_APPROX(t0.linear(), mat_scaling * mat_rotation);
00394 VERIFY_IS_APPROX(mat_rotation*mat_rotation.adjoint(), Matrix3::Identity());
00395 VERIFY_IS_APPROX(mat_rotation.determinant(), Scalar(1));
00396
00397
00398 Transform<float,3,Mode> t1f = t1.template cast<float>();
00399 VERIFY_IS_APPROX(t1f.template cast<Scalar>(),t1);
00400 Transform<double,3,Mode> t1d = t1.template cast<double>();
00401 VERIFY_IS_APPROX(t1d.template cast<Scalar>(),t1);
00402
00403 Translation3 tr1(v0);
00404 Translation<float,3> tr1f = tr1.template cast<float>();
00405 VERIFY_IS_APPROX(tr1f.template cast<Scalar>(),tr1);
00406 Translation<double,3> tr1d = tr1.template cast<double>();
00407 VERIFY_IS_APPROX(tr1d.template cast<Scalar>(),tr1);
00408
00409 AngleAxis<float> aa1f = aa1.template cast<float>();
00410 VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
00411 AngleAxis<double> aa1d = aa1.template cast<double>();
00412 VERIFY_IS_APPROX(aa1d.template cast<Scalar>(),aa1);
00413
00414 Rotation2D<Scalar> r2d1(internal::random<Scalar>());
00415 Rotation2D<float> r2d1f = r2d1.template cast<float>();
00416 VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
00417 Rotation2D<double> r2d1d = r2d1.template cast<double>();
00418 VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
00419
00420 }
00421
00422 template<typename Scalar> void transform_alignment()
00423 {
00424 typedef Transform<Scalar,3,Projective,AutoAlign> Projective3a;
00425 typedef Transform<Scalar,3,Projective,DontAlign> Projective3u;
00426
00427 EIGEN_ALIGN16 Scalar array1[16];
00428 EIGEN_ALIGN16 Scalar array2[16];
00429 EIGEN_ALIGN16 Scalar array3[16+1];
00430 Scalar* array3u = array3+1;
00431
00432 Projective3a *p1 = ::new(reinterpret_cast<void*>(array1)) Projective3a;
00433 Projective3u *p2 = ::new(reinterpret_cast<void*>(array2)) Projective3u;
00434 Projective3u *p3 = ::new(reinterpret_cast<void*>(array3u)) Projective3u;
00435
00436 p1->matrix().setRandom();
00437 *p2 = *p1;
00438 *p3 = *p1;
00439
00440 VERIFY_IS_APPROX(p1->matrix(), p2->matrix());
00441 VERIFY_IS_APPROX(p1->matrix(), p3->matrix());
00442
00443 VERIFY_IS_APPROX( (*p1) * (*p1), (*p2)*(*p3));
00444
00445 #if defined(EIGEN_VECTORIZE) && EIGEN_ALIGN_STATICALLY
00446 if(internal::packet_traits<Scalar>::Vectorizable)
00447 VERIFY_RAISES_ASSERT((::new(reinterpret_cast<void*>(array3u)) Projective3a));
00448 #endif
00449 }
00450
00451 void test_geo_transformations()
00452 {
00453 for(int i = 0; i < g_repeat; i++) {
00454 CALL_SUBTEST_1(( transformations<double,Affine,AutoAlign>() ));
00455 CALL_SUBTEST_1(( non_projective_only<double,Affine,AutoAlign>() ));
00456
00457 CALL_SUBTEST_2(( transformations<float,AffineCompact,AutoAlign>() ));
00458 CALL_SUBTEST_2(( non_projective_only<float,AffineCompact,AutoAlign>() ));
00459 CALL_SUBTEST_2(( transform_alignment<float>() ));
00460
00461 CALL_SUBTEST_3(( transformations<double,Projective,AutoAlign>() ));
00462 CALL_SUBTEST_3(( transformations<double,Projective,DontAlign>() ));
00463 CALL_SUBTEST_3(( transform_alignment<double>() ));
00464
00465 CALL_SUBTEST_4(( transformations<float,Affine,RowMajor|AutoAlign>() ));
00466 CALL_SUBTEST_4(( non_projective_only<float,Affine,RowMajor>() ));
00467
00468 CALL_SUBTEST_5(( transformations<double,AffineCompact,RowMajor|AutoAlign>() ));
00469 CALL_SUBTEST_5(( non_projective_only<double,AffineCompact,RowMajor>() ));
00470
00471 CALL_SUBTEST_6(( transformations<double,Projective,RowMajor|AutoAlign>() ));
00472 CALL_SUBTEST_6(( transformations<double,Projective,RowMajor|DontAlign>() ));
00473 }
00474 }