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