00001
00002 #ifndef vgl_h_matrix_3d_txx_
00003 #define vgl_h_matrix_3d_txx_
00004
00005
00006
00007 #include "vgl_h_matrix_3d.h"
00008 #include <vcl_iostream.h>
00009 #include <vcl_fstream.h>
00010 #include <vcl_cmath.h>
00011 #include <vcl_limits.h>
00012 #include <vcl_cassert.h>
00013 #include <vcl_cstdlib.h>
00014 #include <vnl/vnl_inverse.h>
00015 #include <vnl/vnl_numeric_traits.h>
00016 #include <vnl/vnl_vector_fixed.h>
00017 #include <vnl/vnl_quaternion.h>
00018 #include <vnl/algo/vnl_svd.h>
00019
00020
00021
00022
00023 template <class T>
00024 vgl_h_matrix_3d<T>::vgl_h_matrix_3d(vgl_h_matrix_3d<T> const& M)
00025 {
00026 t12_matrix_ = M.t12_matrix_;
00027 }
00028
00029
00030
00031
00032 template <class T>
00033 vgl_h_matrix_3d<T>::vgl_h_matrix_3d(vnl_matrix_fixed<T, 4, 4> const& M)
00034 {
00035 t12_matrix_ = M;
00036 }
00037
00038
00039
00040
00041 template <class T>
00042 vgl_h_matrix_3d<T>::vgl_h_matrix_3d(vcl_vector<vgl_homg_point_3d<T> > const& points1,
00043 vcl_vector<vgl_homg_point_3d<T> > const& points2)
00044 {
00045 vnl_matrix<T> W;
00046 assert(points1.size() == points2.size());
00047 unsigned int numpoints = points1.size();
00048 if (numpoints < 5)
00049 {
00050 vcl_cerr << "\nvhl_h_matrix_3d - minimum of 5 points required\n";
00051 vcl_exit(0);
00052 }
00053
00054 W.set_size(3*numpoints, 16);
00055
00056 for (unsigned int i = 0; i < numpoints; i++)
00057 {
00058 T x1 = points1[i].x(), y1 = points1[i].y(), z1 = points1[i].z(), w1 = points1[i].w();
00059 T x2 = points2[i].x(), y2 = points2[i].y(), z2 = points2[i].z(), w2 = points2[i].w();
00060
00061 W[i*3][0]=x1*w2; W[i*3][1]=y1*w2; W[i*3][2]=z1*w2; W[i*3][3]=w1*w2;
00062 W[i*3][4]=0.0; W[i*3][5]=0.0; W[i*3][6]=0.0; W[i*3][7]=0.0;
00063 W[i*3][8]=0.0; W[i*3][9]=0.0; W[i*3][10]=0.0; W[i*3][11]=0.0;
00064 W[i*3][12]=-x1*x2; W[i*3][13]=-y1*x2; W[i*3][14]=-z1*x2; W[i*3][15]=-w1*x2;
00065
00066 W[i*3+1][0]=0.0; W[i*3+1][1]=0.0; W[i*3+1][2]=0.0; W[i*3+1][3]=0.0;
00067 W[i*3+1][4]=x1*w2; W[i*3+1][5]=y1*w2; W[i*3+1][6]=z1*w2; W[i*3+1][7]=w1*w2;
00068 W[i*3+1][8]=0.0; W[i*3+1][9]=0.0; W[i*3+1][10]=0.0; W[i*3+1][11]=0.0;
00069 W[i*3+1][12]=-x1*y2; W[i*3+1][13]=-y1*y2; W[i*3+1][14]=-z1*y2; W[i*3+1][15]=-w1*y2;
00070
00071 W[i*3+2][0]=0.0; W[i*3+2][1]=0.0; W[i*3+2][2]=0.0; W[i*3+2][3]=0.0;
00072 W[i*3+2][4]=0.0; W[i*3+2][5]=0.0; W[i*3+2][6]=0.0; W[i*3+2][7]=0.0;
00073 W[i*3+2][8]=x1*w2; W[i*3+2][9]=y1*w2; W[i*3+2][10]=z1*w2; W[i*3+2][11]=w1*w2;
00074 W[i*3+2][12]=-x1*z2; W[i*3+2][13]=-y1*z2; W[i*3+2][14]=-z1*z2; W[i*3+2][15]=-w1*z2;
00075 }
00076
00077 vnl_svd<T> SVD(W);
00078 t12_matrix_ = vnl_matrix<T>(SVD.nullvector().data_block(), 4, 4);
00079 }
00080
00081
00082
00083
00084 template <class T>
00085 vgl_h_matrix_3d<T>::vgl_h_matrix_3d(vcl_istream& s)
00086 {
00087 read(s);
00088 }
00089
00090
00091
00092
00093 template <class T>
00094 vgl_h_matrix_3d<T>::vgl_h_matrix_3d(char const* filename)
00095 {
00096 vcl_ifstream f(filename);
00097 if (!f.good())
00098 vcl_cerr << "vgl_h_matrix_3d::read: Error opening " << filename << vcl_endl;
00099 else
00100 t12_matrix_.read_ascii(f);
00101 }
00102
00103
00104
00105
00106
00107 template <class T>
00108 vgl_h_matrix_3d<T>::vgl_h_matrix_3d(vnl_matrix_fixed<T,3,3> const& M,
00109 vnl_vector_fixed<T,3> const& m)
00110 {
00111 for (int r = 0; r < 3; ++r) {
00112 for (int c = 0; c < 3; ++c)
00113 (t12_matrix_)(r, c) = M(r,c);
00114 (t12_matrix_)(r, 3) = m(r);
00115 }
00116 for (int c = 0; c < 3; ++c)
00117 (t12_matrix_)(3,c) = 0;
00118 (t12_matrix_)(3,3) = 1;
00119 }
00120
00121
00122
00123
00124 template <class T>
00125 vgl_h_matrix_3d<T>::vgl_h_matrix_3d (T const* t_matrix)
00126 : t12_matrix_ (t_matrix)
00127 {
00128 }
00129
00130
00131
00132
00133
00134
00135 template <class T>
00136 vgl_homg_point_3d<T>
00137 vgl_h_matrix_3d<T>::operator()(vgl_homg_point_3d<T> const& x) const
00138 {
00139 vnl_vector_fixed<T, 4> v;
00140 v[0]=x.x(); v[1]=x.y(); v[2]=x.z(); v[3]=x.w();
00141 vnl_vector_fixed<T,4> v2 = t12_matrix_ * v;
00142 return vgl_homg_point_3d<T>(v2[0], v2[1], v2[2], v2[3]);
00143 }
00144
00145
00146
00147
00148 template <class T>
00149 vgl_homg_plane_3d<T>
00150 vgl_h_matrix_3d<T>::preimage(vgl_homg_plane_3d<T> const& p)
00151 {
00152 vnl_vector_fixed<T, 4> v;
00153 v[0]=p.a(); v[1]=p.b(); v[2]=p.c(); v[3]=p.d();
00154 vnl_vector_fixed<T,4> v2 = (t12_matrix_.transpose()) * v;
00155 return vgl_homg_plane_3d<T>(v2[0], v2[1], v2[2], v2[3]);
00156 }
00157
00158
00159
00160
00161 template <class T>
00162 vgl_homg_point_3d<T>
00163 vgl_h_matrix_3d<T>::preimage(vgl_homg_point_3d<T> const& x) const
00164 {
00165 vnl_vector_fixed<T, 4> v;
00166 v[0]=x.x(); v[1]=x.y(); v[2]=x.z(); v[3]=x.w();
00167 v = vnl_inverse(t12_matrix_) * v;
00168 return vgl_homg_point_3d<T>(v[0], v[1], v[2], v[3]);
00169 }
00170
00171
00172
00173
00174 template <class T>
00175 vgl_homg_plane_3d<T>
00176 vgl_h_matrix_3d<T>::operator()(vgl_homg_plane_3d<T> const& p) const
00177 {
00178 vnl_vector_fixed<T, 4> v;
00179 v[0]=p.a(); v[1]=p.b(); v[2]=p.c(); v[3]=p.d();
00180 v = vnl_inverse_transpose(t12_matrix_) * v;
00181 return vgl_homg_plane_3d<T>(v[0], v[1], v[2], v[3]);
00182 }
00183
00184
00185
00186
00187 template <class T>
00188 vcl_ostream& operator<<(vcl_ostream& s, vgl_h_matrix_3d<T> const& h)
00189 {
00190 return s << h.get_matrix();
00191 }
00192
00193
00194 template <class T>
00195 bool vgl_h_matrix_3d<T>::read(vcl_istream& s)
00196 {
00197 t12_matrix_.read_ascii(s);
00198 return s.good() || s.eof();
00199 }
00200
00201
00202 template <class T>
00203 vcl_istream& operator>>(vcl_istream& s, vgl_h_matrix_3d<T>& H)
00204 {
00205 H.read(s);
00206 return s;
00207 }
00208
00209
00210
00211
00212
00213
00214 template <class T>
00215 T vgl_h_matrix_3d<T>::get (unsigned int row_index, unsigned int col_index) const
00216 {
00217 return t12_matrix_.get(row_index, col_index);
00218 }
00219
00220
00221
00222
00223 template <class T>
00224 void vgl_h_matrix_3d<T>::get (T* t_matrix) const
00225 {
00226 for (int row_index = 0; row_index < 4; row_index++)
00227 for (int col_index = 0; col_index < 4; col_index++)
00228 *t_matrix++ = t12_matrix_.get(row_index, col_index);
00229 }
00230
00231
00232
00233
00234 template <class T>
00235 void vgl_h_matrix_3d<T>::get (vnl_matrix_fixed<T, 4, 4>* t_matrix) const
00236 {
00237 *t_matrix = t12_matrix_;
00238 }
00239
00240
00241
00242
00243 template <class T>
00244 vgl_h_matrix_3d<T> vgl_h_matrix_3d<T>::get_inverse() const
00245 {
00246 vnl_matrix_fixed<T, 4, 4> temp = vnl_inverse(t12_matrix_);
00247 return vgl_h_matrix_3d<T>(temp);
00248 }
00249
00250
00251
00252 template <class T>
00253 void vgl_h_matrix_3d<T>::set (T const* H)
00254 {
00255 for (int row_index = 0; row_index < 4; row_index++)
00256 for (int col_index = 0; col_index < 4; col_index++)
00257 t12_matrix_. put (row_index, col_index, *H++);
00258 }
00259
00260
00261
00262 template <class T>
00263 void vgl_h_matrix_3d<T>::set (vnl_matrix_fixed<T,4,4> const& H)
00264 {
00265 t12_matrix_ = H;
00266 }
00267
00268
00269
00270 template <class T>
00271 bool vgl_h_matrix_3d<T>::
00272 projective_basis(vcl_vector<vgl_homg_point_3d<T> > const& )
00273 {
00274 vcl_cerr << "vgl_h_matrix_3d<T>::projective_basis(5pts) not yet implemented\n";
00275 return false;
00276 }
00277
00278
00279
00280 template <class T>
00281 void vgl_h_matrix_3d<T>::set_identity ()
00282 {
00283 t12_matrix_.set_identity();
00284 }
00285
00286
00287
00288 template <class T>
00289 void vgl_h_matrix_3d<T>::set_translation(T tx, T ty, T tz)
00290 {
00291 (t12_matrix_)(0, 3) = tx;
00292 (t12_matrix_)(1, 3) = ty;
00293 (t12_matrix_)(2, 3) = tz;
00294 }
00295
00296
00297
00298 template <class T>
00299 void vgl_h_matrix_3d<T>::
00300 set_rotation_about_axis(vnl_vector_fixed<T,3> const& axis, T angle)
00301 {
00302 vnl_quaternion<T> q(axis, angle);
00303
00304 vnl_matrix_fixed<T,3,3> R = q.rotation_matrix_transpose();
00305
00306 for (int c = 0; c<3; c++)
00307 for (int r = 0; r<3; r++)
00308 t12_matrix_[r][c]=R[c][r];
00309 }
00310
00311
00312
00313
00314
00315
00316 template <class T>
00317 void vgl_h_matrix_3d<T>::
00318 set_rotation_roll_pitch_yaw(T yaw, T pitch, T roll)
00319 {
00320 typedef typename vnl_numeric_traits<T>::real_t real_t;
00321 real_t ax = yaw/2, ay = pitch/2, az = roll/2;
00322
00323 vnl_quaternion<T> qx((T)vcl_sin(ax),0,0,(T)vcl_cos(ax));
00324 vnl_quaternion<T> qy(0,(T)vcl_sin(ay),0,(T)vcl_cos(ay));
00325 vnl_quaternion<T> qz(0,0,(T)vcl_sin(az),(T)vcl_cos(az));
00326 vnl_quaternion<T> q = qz*qy*qx;
00327
00328 vnl_matrix_fixed<T,3,3> R = q.rotation_matrix_transpose();
00329
00330 for (int c = 0; c<3; c++)
00331 for (int r = 0; r<3; r++)
00332 t12_matrix_[r][c]=R[c][r];
00333 }
00334
00335
00336
00337 template <class T>
00338 void vgl_h_matrix_3d<T>::
00339 set_rotation_euler(T rz1, T ry, T rz2)
00340 {
00341 typedef typename vnl_numeric_traits<T>::real_t real_t;
00342 real_t az1 = rz1/2, ay = ry/2, az2 = rz2/2;
00343
00344 vnl_quaternion<T> qz1(0,0,T(vcl_sin(az1)),T(vcl_cos(az1)));
00345 vnl_quaternion<T> qy(0,T(vcl_sin(ay)),0,T(vcl_cos(ay)));
00346 vnl_quaternion<T> qz2(0,0,T(vcl_sin(az2)),T(vcl_cos(az2)));
00347 vnl_quaternion<T> q = qz2*qy*qz1;
00348
00349 vnl_matrix_fixed<T,3,3> R = q.rotation_matrix_transpose();
00350
00351 for (int c = 0; c<3; c++)
00352 for (int r = 0; r<3; r++)
00353 t12_matrix_[r][c]=R[c][r];
00354 }
00355
00356 template <class T>
00357 void
00358 vgl_h_matrix_3d<T>::set_rotation_matrix(vnl_matrix_fixed<T, 3, 3> const& R)
00359 {
00360 for (unsigned r = 0; r<3; ++r)
00361 for (unsigned c = 0; c<3; ++c)
00362 t12_matrix_[r][c] = R[r][c];
00363 }
00364
00365 template <class T>
00366 bool vgl_h_matrix_3d<T>::is_rotation() const
00367 {
00368 const vnl_matrix_fixed<T,4,4>& H = t12_matrix_;
00369 return H.get(0,3) == (T)0
00370 && H.get(1,3) == (T)0
00371 && H.get(2,3) == (T)0
00372 && this->is_euclidean();
00373 }
00374
00375
00376 template <class T>
00377 bool vgl_h_matrix_3d<T>::is_euclidean() const
00378 {
00379 const vnl_matrix_fixed<T,4,4>& H = t12_matrix_;
00380 if ( H.get(3,0) == (T)0 &&
00381 H.get(3,1) == (T)0 &&
00382 H.get(3,2) == (T)0 &&
00383 H.get(3,3) == (T)1 )
00384 {
00385
00386 vnl_matrix_fixed<T, 3,3> R = get_upper_3x3_matrix();
00387 R *= R.transpose();
00388 R(0,0) -= T(1);
00389 R(1,1) -= T(1);
00390 R(2,2) -= T(1);
00391 double absolute_error = R.absolute_value_max();
00392 if ( absolute_error <= 10*vcl_numeric_limits<T>::epsilon() )
00393 return true;
00394 }
00395 return false;
00396 }
00397
00398
00399 template <class T>
00400 vgl_h_matrix_3d<T>
00401 vgl_h_matrix_3d<T>::get_upper_3x3() const
00402 {
00403
00404 double u = (double)t12_matrix_[3][3];
00405 assert(vcl_fabs(u)>1e-9);
00406 T d = static_cast<T>(u);
00407 vnl_matrix_fixed<T,4,4> m(0.0);
00408 for (unsigned r = 0; r<3; r++)
00409 for (unsigned c = 0; c<3; c++)
00410 m[r][c] = t12_matrix_[r][c]/d;
00411 m[3][3]=1.0;
00412 return vgl_h_matrix_3d<T>(m);
00413 }
00414
00415 template <class T>
00416 vnl_matrix_fixed<T, 3,3> vgl_h_matrix_3d<T>::get_upper_3x3_matrix() const
00417 {
00418 vnl_matrix_fixed<T,3,3> R;
00419 vgl_h_matrix_3d<T> m = this->get_upper_3x3();
00420 for (unsigned r = 0; r<3; r++)
00421 for (unsigned c = 0; c<3; c++)
00422 R[r][c] = m.get(r,c);
00423 return R;
00424 }
00425
00426 template <class T>
00427 vgl_homg_point_3d<T>
00428 vgl_h_matrix_3d<T>::get_translation() const
00429 {
00430
00431 double u = (double)t12_matrix_[3][3];
00432 assert(vcl_fabs(u)>1e-9);
00433 T d = static_cast<T>(u);
00434 return vgl_homg_point_3d<T>(t12_matrix_[0][3]/d,
00435 t12_matrix_[1][3]/d,
00436 t12_matrix_[2][3]/d
00437 ,(T)1.0);
00438 }
00439
00440 template <class T>
00441 vnl_vector_fixed<T, 3>
00442 vgl_h_matrix_3d<T>::get_translation_vector() const
00443 {
00444 vgl_homg_point_3d<T> p = this->get_translation();
00445 return vnl_vector_fixed<T,3>(p.x(), p.y(), p.z());
00446 }
00447
00448
00449 #undef VGL_H_MATRIX_3D_INSTANTIATE
00450 #define VGL_H_MATRIX_3D_INSTANTIATE(T) \
00451 template class vgl_h_matrix_3d<T >; \
00452 template vcl_ostream& operator<<(vcl_ostream&, vgl_h_matrix_3d<T > const& ); \
00453 template vcl_istream& operator>>(vcl_istream&, vgl_h_matrix_3d<T >& )
00454
00455 #endif // vgl_h_matrix_3d_txx_