00001
00002 #include "vimt3d_transform_3d.h"
00003
00004
00005
00006
00007
00008 #include <vcl_cassert.h>
00009 #include <vcl_cstdlib.h>
00010 #include <vcl_sstream.h>
00011 #include <vsl/vsl_indent.h>
00012 #include <vnl/vnl_matrix_fixed.h>
00013 #include <vnl/vnl_vector.h>
00014 #include <vnl/algo/vnl_determinant.h>
00015 #include <vnl/vnl_math.h>
00016 #include <vul/vul_string.h>
00017 #include <vul/vul_sprintf.h>
00018 #include <mbl/mbl_read_props.h>
00019 #include <mbl/mbl_exception.h>
00020 #include <mbl/mbl_parse_sequence.h>
00021
00022
00023
00024
00025 vnl_matrix<double> vimt3d_transform_3d::matrix() const
00026 {
00027 vnl_matrix<double> M(4,4);
00028 matrix(M);
00029 return M;
00030 }
00031
00032
00033
00034 void vimt3d_transform_3d::matrix(vnl_matrix<double>& M) const
00035 {
00036 #if 0 //grv
00037 if ((M.rows()!=4) || (M.columns()!=4)) M.resize(4,4);
00038 #endif
00039 M.set_size(4,4);
00040 double**m_data = M.data_array();
00041 m_data[0][0]=xx_; m_data[0][1]=xy_; m_data[0][2]=xz_; m_data[0][3]=xt_;
00042 m_data[1][0]=yx_; m_data[1][1]=yy_; m_data[1][2]=yz_; m_data[1][3]=yt_;
00043 m_data[2][0]=zx_; m_data[2][1]=zy_; m_data[2][2]=zz_; m_data[2][3]=zt_;
00044 m_data[3][0]=tx_; m_data[3][1]=ty_; m_data[3][2]=tz_; m_data[3][3]=tt_;
00045 }
00046
00047
00048
00049 void vimt3d_transform_3d::set_matrix(const vnl_matrix<double>& M)
00050 {
00051 if (M.rows()!=4 || M.cols()!=4)
00052 mbl_exception_error(mbl_exception_abort("vimt3d_transform_3d::set_matrix(matrix): input matrix must be 4x4"));
00053
00054 form_=Affine;
00055 xx_=M[0][0]; xy_=M[0][1]; xz_=M[0][2]; xt_=M[0][3];
00056 yx_=M[1][0]; yy_=M[1][1]; yz_=M[1][2]; yt_=M[1][3];
00057 zx_=M[2][0]; zy_=M[2][1]; zz_=M[2][2]; zt_=M[2][3];
00058 tx_=M[3][0]; ty_=M[3][1]; tz_=M[3][2]; tt_=M[3][3];
00059 }
00060
00061
00062
00063 void vimt3d_transform_3d::angles(double& phi_x, double& phi_y, double& phi_z) const
00064 {
00065
00066
00067 double det=+xx_*yy_*zz_-xx_*zy_*yz_-yx_*xy_*zz_+yx_*zy_*xz_+zx_*xy_*yz_-zx_*yy_*xz_;
00068
00069 double xlen = vcl_sqrt(xx_*xx_ + yx_*yx_ + zx_*zx_)* vnl_math_sgn(det);
00070 double ylen = vcl_sqrt(xy_*xy_ + yy_*yy_ + zy_*zy_)* vnl_math_sgn(det);
00071 double zlen = vcl_sqrt(xz_*xz_ + yz_*yz_ + zz_*zz_)* vnl_math_sgn(det);
00072
00073 double xx3 = xx_ / xlen;
00074 double xy3 = xy_ / ylen;
00075 double xz3 = xz_ / zlen;
00076 double yz3 = yz_ / zlen;
00077 double zz3 = zz_ / zlen;
00078
00079 phi_x = vcl_atan2(-yz3,zz3);
00080 phi_y = vcl_atan2(-xz3*vcl_cos(phi_x),zz3);
00081 phi_z=vcl_atan2(-xy3,xx3);
00082
00083
00084
00085
00086
00087
00088
00089
00090 double s;
00091 if (vcl_sin(phi_y) < 1e-20)
00092 s = 1.0;
00093 else
00094 s = vcl_fabs( xz3/ (-1*vcl_sin(phi_y) ) );
00095
00096 #ifdef DEBUG
00097 vcl_cout<<"s= "<<s<<vcl_endl;
00098 #endif
00099
00100
00101
00102
00103 if (vcl_fabs(vcl_sin(phi_y)*s + xz3) > 1e-6)
00104 {
00105 if (phi_y > 0)
00106 phi_y -= vnl_math::pi;
00107 else
00108 phi_y += vnl_math::pi;
00109
00110 }
00111
00112 const double cos_y = vcl_cos(phi_y);
00113
00114 if (vcl_fabs(vcl_sin(phi_x)*cos_y*s + yz3) > 1e-6 ||
00115 vcl_fabs(vcl_cos(phi_x)*cos_y*s - zz3) > 1e-6)
00116 {
00117 if (phi_x > 0)
00118 phi_x -= vnl_math::pi;
00119 else
00120 phi_x += vnl_math::pi;
00121 }
00122
00123 if (vcl_fabs(vcl_cos(phi_z)*cos_y*s - xx3) > 1e-6 ||
00124 vcl_fabs(vcl_sin(phi_z)*cos_y*s + xy3) > 1e-6)
00125 {
00126 if (phi_z > 0)
00127 phi_z -= vnl_math::pi;
00128 else
00129 phi_z += vnl_math::pi;
00130 }
00131
00132
00133
00134
00135 int count = 0;
00136 if (vcl_fabs(phi_x) > vnl_math::pi/2) ++count;
00137 if (vcl_fabs(phi_y) > vnl_math::pi/2) ++count;
00138 if (vcl_fabs(phi_z) > vnl_math::pi/2) ++count;
00139
00140 if (count > 1)
00141 {
00142 if (phi_x > 0)
00143 phi_x -= vnl_math::pi;
00144 else
00145 phi_x += vnl_math::pi;
00146
00147 phi_y=-phi_y;
00148 if (phi_y > 0)
00149 phi_y -= vnl_math::pi;
00150 else
00151 phi_y += vnl_math::pi;
00152
00153 if (phi_z > 0)
00154 phi_z -= vnl_math::pi;
00155 else
00156 phi_z += vnl_math::pi;
00157 }
00158 }
00159
00160
00161
00162 void vimt3d_transform_3d::params(vnl_vector<double>& v) const
00163 {
00164 switch (form_)
00165 {
00166 case (Identity):
00167 v.set_size(0);
00168 break;
00169 case (Translation):
00170 if (v.size()!=3) v.set_size(3);
00171 v[0]=xt_; v[1]=yt_; v[2]=zt_;
00172 break;
00173 case (ZoomOnly):
00174 if (v.size()!=6) v.set_size(6);
00175 v[0]=xx_; v[1]=yy_; v[2]=zz_;
00176 v[3]=xt_; v[4]=yt_; v[5]=zt_;
00177 break;
00178 case (RigidBody):
00179 if (v.size()!=6) v.set_size(6);
00180 angles(v[0],v[1],v[2]);
00181 v[3]=xt_; v[4]=yt_; v[5]=zt_;
00182 break;
00183 case (Similarity):
00184
00185 if (v.size()!=7) v.set_size(7);
00186 angles(v[1],v[2],v[3]);
00187
00188 v[0]= xx_/ ( vcl_cos( v[2] ) *vcl_cos( v[3] ) );
00189 v[4]=xt_; v[5]=yt_; v[6]=zt_;
00190 break;
00191 case (Affine):
00192
00193 {
00194 v.set_size(9);
00195
00196
00197
00198 angles(v[3],v[4],v[5]);
00199
00200 double det=+xx_*yy_*zz_-xx_*zy_*yz_-yx_*xy_*zz_+yx_*zy_*xz_+zx_*xy_*yz_-zx_*yy_*xz_;
00201 v[0]=vcl_sqrt(xx_*xx_ + yx_*yx_ + zx_*zx_)* vnl_math_sgn(det);
00202 v[1]=vcl_sqrt(xy_*xy_ + yy_*yy_ + zy_*zy_)* vnl_math_sgn(det);
00203 v[2]=vcl_sqrt(xz_*xz_ + yz_*yz_ + zz_*zz_)* vnl_math_sgn(det);
00204 v[6]=xt_; v[7]=yt_; v[8]=zt_;
00205 break;
00206 }
00207 default:
00208 mbl_exception_error(mbl_exception_abort(
00209 vul_sprintf("vimt3d_transform_3d::params() Unexpected form: %d", form_) ));
00210 }
00211 }
00212
00213
00214
00215 void vimt3d_transform_3d::simplify(double tol )
00216 {
00217 double rx, ry, rz;
00218 double sx, sy, sz;
00219 double det;
00220 switch (form_)
00221 {
00222 case Affine:
00223 {
00224 angles(rx, ry, rz);
00225 double matrix_form[]= {xx_, yx_, zx_, xy_, yy_, zy_, xz_, yz_, zz_};
00226 vnl_matrix_fixed<double, 3, 3> X(matrix_form);
00227 vnl_matrix_fixed<double, 3, 3> S2 = X.transpose() * X;
00228
00229
00230 if (S2(0,1)*S2(0,1) + S2(0,2)*S2(0,2) + S2(1,0)*S2(1,0) +
00231 S2(1,2)*S2(1,2) + S2(2,0)*S2(2,0) + S2(2,1)*S2(2,1) >= tol*tol*6)
00232 return;
00233
00234
00235 double mirror=vnl_math_sgn(vnl_determinant(X[0], X[1], X[2]));
00236
00237 sx = vcl_sqrt(vcl_abs(S2(0,0))) * mirror;
00238 sy = vcl_sqrt(vcl_abs(S2(1,1))) * mirror;
00239 sz = vcl_sqrt(vcl_abs(S2(2,2))) * mirror;
00240 if (vnl_math_sqr(sx-sy) + vnl_math_sqr(sx-sz) < tol*tol)
00241 this->set_similarity(sx, rx, ry, rz,
00242 xt_, yt_, zt_ );
00243 else if (rx*rx+ry*ry+rz*rz < tol*tol)
00244 this->set_zoom_only(sx, sy, sz,
00245 xt_, yt_, zt_);
00246 else
00247 return;
00248 simplify(tol);
00249 return;
00250 }
00251 case Similarity:
00252 angles(rx, ry, rz);
00253 det=+xx_*yy_*zz_-xx_*zy_*yz_-yx_*xy_*zz_+yx_*zy_*xz_+zx_*xy_*yz_-zx_*yy_*xz_;
00254 sx=vcl_sqrt(xx_*xx_ + yx_*yx_ + zx_*zx_)* vnl_math_sgn(det);
00255 if (rx*rx+ry*ry+rz*rz < tol*tol)
00256 this->set_zoom_only(sx, xt_, yt_, zt_);
00257 else if (vnl_math_sqr(sx-1.0) < tol*tol)
00258 this->set_rigid_body(rx, ry, rz, xt_, yt_, zt_);
00259 else
00260 return;
00261 simplify(tol);
00262 return;
00263
00264 case RigidBody:
00265 angles(rx, ry, rz);
00266 if (rx*rx+ry*ry+rz*rz >= tol*tol)
00267 return;
00268 this->set_translation(xt_, yt_, zt_);
00269 simplify(tol);
00270 return;
00271 case ZoomOnly:
00272 if (vnl_math_sqr(xx_-1.0) + vnl_math_sqr(yy_-1.0) + vnl_math_sqr(zz_-1.0) >= tol*tol)
00273 return;
00274 set_translation(xt_, yt_, zt_);
00275 case Translation:
00276 if (xt_*xt_+yt_*yt_+zt_*zt_<tol*tol)
00277 set_identity();
00278 return;
00279 case Identity:
00280 return;
00281 default:
00282 mbl_exception_error(mbl_exception_abort(
00283 vul_sprintf("vimt3d_transform_3d::simplify() Unexpected form: %d", form_) ));
00284 }
00285 }
00286
00287
00288
00289 void vimt3d_transform_3d::setCheck(int n1,int n2,const char* str) const
00290 {
00291 if (n1==n2) return;
00292 vcl_ostringstream ss;
00293 ss << "vimt3d_transform_3d::set() " << n1 << " parameters required for "
00294 << str << ". Passed " << n2;
00295 mbl_exception_error(mbl_exception_abort(ss.str()));
00296 }
00297
00298
00299
00300 void vimt3d_transform_3d::set(const vnl_vector<double>& v, Form form)
00301 {
00302 int n=v.size();
00303
00304 switch (form)
00305 {
00306 case (Identity):
00307 set_identity();
00308 break;
00309 case (Translation):
00310 setCheck(3,n,"Translation");
00311 set_translation(v[0],v[1],v[2]);
00312 break;
00313 case (ZoomOnly):
00314 setCheck(6,n,"ZoomOnly");
00315 set_zoom_only( v[0],v[1],v[2],
00316 v[3],v[4],v[5]);
00317 break;
00318 case (RigidBody):
00319 setCheck(6,n,"RigidBody");
00320 set_rigid_body( v[0],v[1],v[2],
00321 v[3],v[4],v[5]);
00322 break;
00323 case (Similarity):
00324 setCheck(7,n,"Similarity");
00325 set_similarity( v[0],v[1],v[2],
00326 v[3],v[4],v[5], v[6]);
00327 form_ = Similarity;
00328 inv_uptodate_=false;
00329 break;
00330 case (Affine):
00331
00332
00333
00334 setCheck(9,n,"Affine");
00335 set_affine( v[0],v[1],v[2],
00336 v[3],v[4],v[5],
00337 v[6],v[7],v[8]);
00338 form_ = Affine;
00339 inv_uptodate_=false;
00340 break;
00341 default:
00342 mbl_exception_error(mbl_exception_abort(
00343 vul_sprintf("vimt3d_transform_3d::set() Unexpected form: %d", form_) ));
00344 }
00345 }
00346
00347
00348
00349 void vimt3d_transform_3d::setRotMat( double r_x, double r_y, double r_z )
00350 {
00351 double sinx=vcl_sin(r_x);
00352 double siny=vcl_sin(r_y);
00353 double sinz=vcl_sin(r_z);
00354 double cosx=vcl_cos(r_x);
00355 double cosy=vcl_cos(r_y);
00356 double cosz=vcl_cos(r_z);
00357
00358
00359 xx_ = cosy*cosz;
00360 xy_ = -cosy*sinz;
00361 xz_ = -siny;
00362 yx_ = cosx*sinz - sinx*siny*cosz;
00363 yy_ = cosx*cosz + sinx*siny*sinz;
00364 yz_ = -sinx*cosy;
00365 zx_ = sinx*sinz + cosx*siny*cosz;
00366 zy_ = sinx*cosz - cosx*siny*sinz;
00367 zz_ = cosx*cosy;
00368 }
00369
00370
00371
00372 void vimt3d_transform_3d::set_origin( const vgl_point_3d<double> & p )
00373 {
00374 xt_=p.x()*tt_;
00375 yt_=p.y()*tt_;
00376 zt_=p.z()*tt_;
00377
00378 if (form_ == Identity) form_=Translation;
00379
00380 inv_uptodate_=false;
00381 }
00382
00383
00384
00385 void vimt3d_transform_3d::set_identity()
00386 {
00387 if (form_==Identity) return;
00388 form_=Identity;
00389
00390 xx_=yy_=zz_=tt_=1;
00391 xy_=xz_=xt_=0;
00392 yx_=yz_=yt_=0;
00393 zx_=zy_=zt_=0;
00394 tx_=ty_=tz_=0;
00395 inv_uptodate_=false;
00396 }
00397
00398
00399
00400 void vimt3d_transform_3d::set_translation(double t_x, double t_y, double t_z)
00401 {
00402 if (t_x==0 && t_y==0 && t_z==0)
00403 set_identity();
00404 else
00405 {
00406 form_=Translation;
00407
00408
00409 xt_=t_x;
00410 yt_=t_y;
00411 zt_=t_z;
00412
00413
00414 xx_=yy_=zz_=tt_=1;
00415 xy_=xz_=yx_=yz_=zx_=zy_=0;
00416 tx_=ty_=tz_=0;
00417 }
00418
00419 inv_uptodate_=false;
00420 }
00421
00422
00423
00424 void vimt3d_transform_3d::set_zoom_only(double s_x, double s_y, double s_z,
00425 double t_x, double t_y, double t_z)
00426 {
00427 form_=ZoomOnly;
00428
00429
00430 xx_=s_x;
00431 yy_=s_y;
00432 zz_=s_z;
00433
00434
00435 xt_=t_x;
00436 yt_=t_y;
00437 zt_=t_z;
00438
00439
00440 tx_=ty_=tz_=0;
00441 xy_=xz_=yx_=yz_=zx_=zy_=0;
00442 tt_=1;
00443
00444 inv_uptodate_=false;
00445 }
00446
00447
00448
00449 void vimt3d_transform_3d::set_rigid_body(double r_x, double r_y, double r_z,
00450 double t_x, double t_y, double t_z)
00451 {
00452 if (r_x==0.0 && r_y==0.0 && r_z==0.0)
00453 {
00454 set_translation(t_x,t_y,t_z);
00455 }
00456 else
00457 {
00458 form_=RigidBody;
00459
00460
00461 setRotMat(r_x,r_y,r_z);
00462
00463
00464 xt_=t_x;
00465 yt_=t_y;
00466 zt_=t_z;
00467
00468
00469 tx_=0; ty_=0; tz_=0; tt_=1;
00470 }
00471
00472 inv_uptodate_=false;
00473 }
00474
00475
00476
00477
00478 void vimt3d_transform_3d::set_rigid_body(const vnl_quaternion<double>& q,
00479 double t_x, double t_y, double t_z)
00480 {
00481 if (q.angle()==0.0)
00482 {
00483 set_translation(t_x,t_y,t_z);
00484 return;
00485 }
00486 vnl_matrix_fixed<double,3,3> R = q.rotation_matrix_transpose();
00487 form_=RigidBody;
00488
00489
00490 xx_=R[0][0]; xy_= R[1][0]; xz_ = R[2][0];
00491 yx_=R[0][1]; yy_= R[1][1]; yz_ = R[2][1];
00492 zx_=R[0][2]; zy_= R[1][2]; zz_ = R[2][2];
00493
00494
00495 xt_=t_x;
00496 yt_=t_y;
00497 zt_=t_z;
00498
00499 inv_uptodate_=false;
00500 }
00501
00502
00503
00504
00505 void vimt3d_transform_3d::set_similarity(double s, const vnl_quaternion<double>& q,
00506 double t_x, double t_y, double t_z)
00507 {
00508 if (q.angle()==0.0)
00509 {
00510 set_zoom_only(s,t_x,t_y,t_z);
00511 return;
00512 }
00513 vnl_matrix_fixed<double,3,3> R = q.rotation_matrix_transpose();
00514 form_=RigidBody;
00515
00516
00517 xx_=s*R[0][0]; xy_= s*R[1][0]; xz_ = s*R[2][0];
00518 yx_=s*R[0][1]; yy_= s*R[1][1]; yz_ = s*R[2][1];
00519 zx_=s*R[0][2]; zy_= s*R[1][2]; zz_ = s*R[2][2];
00520
00521
00522 xt_=t_x;
00523 yt_=t_y;
00524 zt_=t_z;
00525
00526 inv_uptodate_=false;
00527 }
00528
00529
00530 void vimt3d_transform_3d::set_similarity(double s,
00531 double r_x, double r_y, double r_z,
00532 double t_x, double t_y, double t_z)
00533 {
00534 if (s==1.0)
00535 {
00536 set_rigid_body(r_x,r_y,r_z,t_x,t_y,t_z);
00537 }
00538 else
00539 {
00540 form_=Similarity;
00541
00542
00543 setRotMat(r_x,r_y,r_z);
00544
00545 #ifdef DEBUG // debug test
00546 double r_x1, r_y1, r_z1;
00547 angles( r_x1, r_y1, r_z1 );
00548 vcl_cout << "r_x = " << r_x << vcl_endl
00549 << "r_x1= " << r_x1 << vcl_endl
00550 << "r_y = " << r_y << vcl_endl
00551 << "r_y1= " << r_y1 << vcl_endl
00552 << "r_z = " << r_z << vcl_endl
00553 << "r_z1= " << r_z1 << vcl_endl;
00554 #endif
00555
00556
00557 xx_*=s; xy_*=s; xz_*=s;
00558 yx_*=s; yy_*=s; yz_*=s;
00559 zx_*=s; zy_*=s; zz_*=s;
00560
00561
00562 xt_=t_x;
00563 yt_=t_y;
00564 zt_=t_z;
00565
00566
00567 tx_=0; ty_=0; tz_=0; tt_=1;
00568 }
00569 inv_uptodate_=false;
00570 }
00571
00572
00573
00574 void vimt3d_transform_3d::set_affine(double s_x, double s_y, double s_z,
00575 double r_x, double r_y, double r_z,
00576 double t_x, double t_y, double t_z)
00577 {
00578 form_=Affine;
00579
00580
00581 setRotMat(r_x,r_y,r_z);
00582
00583
00584 xx_*=s_x; xy_*=s_y; xz_*=s_z;
00585 yx_*=s_x; yy_*=s_y; yz_*=s_z;
00586 zx_*=s_x; zy_*=s_y; zz_*=s_z;
00587
00588
00589 xt_=t_x;
00590 yt_=t_y;
00591 zt_=t_z;
00592
00593
00594 tx_=0; ty_=0; tz_=0; tt_=1;
00595
00596 inv_uptodate_=false;
00597 }
00598
00599
00600 void vimt3d_transform_3d::set_affine(double s_x, double s_y, double s_z,
00601 vgl_vector_3d<double> c_x,
00602 vgl_vector_3d<double> c_y,
00603 vgl_vector_3d<double> c_z,
00604 double t_x, double t_y, double t_z)
00605 {
00606 form_=Affine;
00607
00608
00609 xx_ = c_x.x(); xy_ = c_y.x(); xz_ = c_z.x();
00610 yx_ = c_x.y(); yy_ = c_y.y(); yz_ = c_z.y();
00611 zx_ = c_x.z(); zy_ = c_y.z(); zz_ = c_z.z();
00612
00613
00614
00615 xx_*=s_x; xy_*=s_y; xz_*=s_z;
00616 yx_*=s_x; yy_*=s_y; yz_*=s_z;
00617 zx_*=s_x; zy_*=s_y; zz_*=s_z;
00618
00619
00620 xt_=t_x;
00621 yt_=t_y;
00622 zt_=t_z;
00623
00624
00625 tx_=0; ty_=0; tz_=0; tt_=1;
00626
00627 inv_uptodate_=false;
00628 }
00629
00630
00631
00632 void vimt3d_transform_3d::set_affine(const vgl_point_3d<double>& p,
00633 const vgl_vector_3d<double>& u,
00634 const vgl_vector_3d<double>& v,
00635 const vgl_vector_3d<double>& w)
00636 {
00637 form_=Affine;
00638
00639 #ifndef NDEBUG
00640 const double tol=1e-6;
00641
00642
00643 vgl_vector_3d<double> uh = normalized(u);
00644 vgl_vector_3d<double> vh = normalized(v);
00645 vgl_vector_3d<double> wh = normalized(w);
00646
00647
00648 assert(vcl_fabs(dot_product(uh,vh))<tol);
00649 assert(vcl_fabs(dot_product(vh,wh))<tol);
00650 assert(vcl_fabs(dot_product(wh,uh))<tol);
00651
00652
00653 assert(vcl_fabs((cross_product(uh,vh)-wh).length())<tol);
00654 #endif
00655
00656
00657 xx_=u.x(); xy_=v.x(); xz_=w.x();
00658 yx_=u.y(); yy_=v.y(); yz_=w.y();
00659 zx_=u.z(); zy_=v.z(); zz_=w.z();
00660
00661
00662 xt_=p.x();
00663 yt_=p.y();
00664 zt_=p.z();
00665
00666
00667 tx_=0; ty_=0; tz_=0; tt_=1;
00668
00669 inv_uptodate_=false;
00670 }
00671
00672
00673
00674 vimt3d_transform_3d vimt3d_transform_3d::inverse() const
00675 {
00676 if (!inv_uptodate_) calcInverse();
00677
00678 vimt3d_transform_3d inv;
00679
00680 inv.xx_ = xx2_; inv.xy_ = xy2_; inv.xz_ = xz2_; inv.xt_ = xt2_;
00681 inv.yx_ = yx2_; inv.yy_ = yy2_; inv.yz_ = yz2_; inv.yt_ = yt2_;
00682 inv.zx_ = zx2_; inv.zy_ = zy2_; inv.zz_ = zz2_; inv.zt_ = zt2_;
00683 inv.tx_ = tx2_; inv.ty_ = ty2_; inv.tz_ = tz2_; inv.tt_ = tt2_;
00684
00685 inv.xx2_ = xx_; inv.xy2_ = xy_; inv.xz2_ = xz_; inv.xt2_ = xt_;
00686 inv.yx2_ = yx_; inv.yy2_ = yy_; inv.yz2_ = yz_; inv.yt2_ = yt_;
00687 inv.zx2_ = zx_; inv.zy2_ = zy_; inv.zz2_ = zz_; inv.zt2_ = zt_;
00688 inv.tx2_ = tx_; inv.ty2_ = ty_; inv.tz2_ = tz_; inv.tt2_ = tt_;
00689
00690 inv.form_ = form_;
00691 inv.inv_uptodate_ = true;
00692
00693 return inv;
00694 }
00695
00696
00697
00698 void vimt3d_transform_3d::calcInverse() const
00699 {
00700 xx2_=yy2_=zz2_=tt2_=1;
00701 xy2_ = xz2_= xt2_ = yx2_ = yz2_= yt2_ = zx2_ = zy2_ = zt2_ = tx2_ = ty2_ = tz2_ = 0;
00702
00703 switch (form_)
00704 {
00705 case Identity :
00706 break;
00707 case Translation :
00708 xt2_=-xt_;
00709 yt2_=-yt_;
00710 zt2_=-zt_;
00711 break;
00712 case ZoomOnly :
00713 xx2_=1.0/xx_;
00714 yy2_=1.0/yy_;
00715 zz2_=1.0/zz_;
00716 xt2_=-xt_/xx_;
00717 yt2_=-yt_/yy_;
00718 zt2_=-zt_/zz_;
00719 break;
00720 case RigidBody :
00721
00722 xx2_=xx_;
00723 xy2_=yx_;
00724 xz2_=zx_;
00725 yx2_=xy_;
00726 yy2_=yy_;
00727 yz2_=zy_;
00728 zx2_=xz_;
00729 zy2_=yz_;
00730 zz2_=zz_;
00731 xt2_=-(xx2_*xt_ + xy2_*yt_ + xz2_*zt_);
00732 yt2_=-(yx2_*xt_ + yy2_*yt_ + yz2_*zt_);
00733 zt2_=-(zx2_*xt_ + zy2_*yt_ + zz2_*zt_);
00734 break;
00735 case Similarity :
00736 case Affine : {
00737
00738 double det=-xx_*yy_*zz_+xx_*zy_*yz_+yx_*xy_*zz_-yx_*zy_*xz_-zx_*xy_*yz_+zx_*yy_*xz_;
00739 if (det==0)
00740 {
00741 vcl_cerr<<"vimt3d_transform_3d() : No inverse exists for this affine transform (det==0)\n";
00742 vcl_abort();
00743 }
00744
00745 xx2_=(-yy_*zz_+zy_*yz_)/det;
00746 xy2_=( xy_*zz_-zy_*xz_)/det;
00747 xz2_=(-xy_*yz_+yy_*xz_)/det;
00748 xt2_=(xy_*yz_*zt_-xy_*yt_*zz_-yy_*xz_*zt_+yy_*xt_*zz_+zy_*xz_*yt_-zy_*xt_*yz_)/det;
00749
00750 yx2_=( yx_*zz_-zx_*yz_)/det;
00751 yy2_=(-xx_*zz_+zx_*xz_)/det;
00752 yz2_=( xx_*yz_-yx_*xz_)/det;
00753 yt2_=(-xx_*yz_*zt_+xx_*yt_*zz_+yx_*xz_*zt_-yx_*xt_*zz_-zx_*xz_*yt_+zx_*xt_*yz_)/det;
00754
00755 zx2_=(-yx_*zy_+zx_*yy_)/det;
00756 zy2_=( xx_*zy_-zx_*xy_)/det;
00757 zz2_=(-xx_*yy_+yx_*xy_)/det;
00758 zt2_=( xx_*yy_*zt_-xx_*yt_*zy_-yx_*xy_*zt_+yx_*xt_*zy_+zx_*xy_*yt_-zx_*xt_*yy_)/det;
00759
00760 break; }
00761 default:
00762 mbl_exception_error(mbl_exception_abort(
00763 vul_sprintf("vimt3d_transform_3d::calcInverse() Unexpected form: %d", form_) ));
00764 }
00765
00766 inv_uptodate_=true;
00767 }
00768
00769
00770
00771 bool vimt3d_transform_3d::operator==( const vimt3d_transform_3d& t) const
00772 {
00773 return
00774 xx_ == t.xx_ &&
00775 yy_ == t.yy_ &&
00776 zz_ == t.zz_ &&
00777 tt_ == t.tt_ &&
00778 xy_ == t.xy_ &&
00779 xz_ == t.xz_ &&
00780 xt_ == t.xt_ &&
00781 yx_ == t.yx_ &&
00782 yz_ == t.yz_ &&
00783 yt_ == t.yt_ &&
00784 zx_ == t.zx_ &&
00785 zy_ == t.zy_ &&
00786 zt_ == t.zt_ &&
00787 tx_ == t.tx_ &&
00788 ty_ == t.ty_ &&
00789 tz_ == t.tz_ ;
00790 }
00791
00792
00793
00794
00795
00796
00797 vimt3d_transform_3d operator*(const vimt3d_transform_3d& L, const vimt3d_transform_3d& R)
00798 {
00799 vimt3d_transform_3d T;
00800
00801 if (L.form() == vimt3d_transform_3d::Identity)
00802 return R;
00803 else
00804 if (R.form() == vimt3d_transform_3d::Identity)
00805 return L;
00806 else
00807 {
00808
00809
00810 T.xx_ = L.xx_*R.xx_ + L.xy_*R.yx_+ L.xz_*R.zx_ + L.xt_*R.tx_;
00811 T.xy_ = L.xx_*R.xy_ + L.xy_*R.yy_+ L.xz_*R.zy_ + L.xt_*R.ty_;
00812 T.xz_ = L.xx_*R.xz_ + L.xy_*R.yz_+ L.xz_*R.zz_ + L.xt_*R.tz_;
00813 T.xt_ = L.xx_*R.xt_ + L.xy_*R.yt_+ L.xz_*R.zt_ + L.xt_*R.tt_;
00814
00815 T.yx_ = L.yx_*R.xx_ + L.yy_*R.yx_+ L.yz_*R.zx_ + L.yt_*R.tx_;
00816 T.yy_ = L.yx_*R.xy_ + L.yy_*R.yy_+ L.yz_*R.zy_ + L.yt_*R.ty_;
00817 T.yz_ = L.yx_*R.xz_ + L.yy_*R.yz_+ L.yz_*R.zz_ + L.yt_*R.tz_;
00818 T.yt_ = L.yx_*R.xt_ + L.yy_*R.yt_+ L.yz_*R.zt_ + L.yt_*R.tt_;
00819
00820 T.zx_ = L.zx_*R.xx_ + L.zy_*R.yx_+ L.zz_*R.zx_ + L.zt_*R.tx_;
00821 T.zy_ = L.zx_*R.xy_ + L.zy_*R.yy_+ L.zz_*R.zy_ + L.zt_*R.ty_;
00822 T.zz_ = L.zx_*R.xz_ + L.zy_*R.yz_+ L.zz_*R.zz_ + L.zt_*R.tz_;
00823 T.zt_ = L.zx_*R.xt_ + L.zy_*R.yt_+ L.zz_*R.zt_ + L.zt_*R.tt_;
00824
00825 T.tx_ = L.tx_*R.xx_ + L.ty_*R.yx_+ L.tz_*R.zx_ + L.tt_*R.tx_;
00826 T.ty_ = L.tx_*R.xy_ + L.ty_*R.yy_+ L.tz_*R.zy_ + L.tt_*R.ty_;
00827 T.tz_ = L.tx_*R.xz_ + L.ty_*R.yz_+ L.tz_*R.zz_ + L.tt_*R.tz_;
00828 T.tt_ = L.tx_*R.xt_ + L.ty_*R.yt_+ L.tz_*R.zt_ + L.tt_*R.tt_;
00829
00830
00831
00832 if (R.form() == L.form())
00833 T.form_ = R.form();
00834 else
00835 {
00836 if (R.form() == vimt3d_transform_3d::Affine ||
00837 L.form() == vimt3d_transform_3d::Affine)
00838 T.form_ = vimt3d_transform_3d::Affine;
00839 else
00840 if (R.form() == vimt3d_transform_3d::Similarity ||
00841 L.form() == vimt3d_transform_3d::Similarity)
00842 T.form_ = vimt3d_transform_3d::Similarity;
00843 else
00844 if (R.form() == vimt3d_transform_3d::RigidBody ||
00845 L.form() == vimt3d_transform_3d::RigidBody)
00846 {
00847 if (R.form() == vimt3d_transform_3d::ZoomOnly)
00848 {
00849 if (R.xx_ == R.yy_ &&
00850 R.xx_ == R.zz_)
00851 T.form_ = vimt3d_transform_3d::Similarity;
00852 else
00853 T.form_ = vimt3d_transform_3d::Affine;
00854 }
00855 else
00856 if (L.form() == vimt3d_transform_3d::ZoomOnly)
00857 {
00858 if (L.xx_ == L.yy_ &&
00859 L.xx_ == L.zz_)
00860 T.form_ = vimt3d_transform_3d::Similarity;
00861 else
00862 T.form_ = vimt3d_transform_3d::Affine;
00863 }
00864 else
00865 T.form_ = vimt3d_transform_3d::RigidBody;
00866 }
00867 else
00868 if (R.form() == vimt3d_transform_3d::ZoomOnly ||
00869 L.form() == vimt3d_transform_3d::ZoomOnly)
00870 T.form_ = vimt3d_transform_3d::ZoomOnly;
00871 else
00872 T.form_ = vimt3d_transform_3d::Translation;
00873 }
00874 }
00875
00876 T.inv_uptodate_ = false;
00877
00878 return T;
00879 }
00880
00881
00882 void vimt3d_transform_3d::print_summary(vcl_ostream& o) const
00883 {
00884 o << vsl_indent()<< "Form: ";
00885 vsl_indent_inc(o);
00886 switch (form_)
00887 {
00888 case Identity:
00889 o << "Identity\n";
00890 break;
00891
00892 case Translation: {
00893 vnl_vector<double> p(3);
00894 params(p);
00895 o << "Translation (" << p(0) << ',' << p(1) << ',' << p(2) << ")\n";
00896 break; }
00897
00898 case ZoomOnly: {
00899 vnl_vector<double> p(6);
00900 params(p);
00901 o << "ZoomOnly\n"
00902 << vsl_indent()<< "scale factor = (" << p(0) << ',' << p(1) << ',' << p(2) << ")\n"
00903 << vsl_indent() << "translation = (" << p(3) << ',' << p(4) << ',' << p(5) << ")\n";
00904 break; }
00905
00906 case RigidBody: {
00907 vnl_vector<double> p(6);
00908 params(p);
00909 o << "RigidBody\n"
00910 << vsl_indent()<< "angles = " << p(0) << ',' << p(1) << ',' << p(2) << '\n'
00911 << vsl_indent()<< "translation = (" << p(3) << ',' << p(4) << ',' << p(5) << ")\n";
00912 break; }
00913
00914 case Similarity: {
00915 vnl_vector<double> p(7);
00916 params(p);
00917
00918
00919
00920
00921 o << "Similarity\n"
00922 << vsl_indent()<< "scale factor = " << p(0) << '\n'
00923 << vsl_indent()<< "angles = " << p(1) << ',' << p(2) << ',' << p(3) << '\n'
00924 << vsl_indent()<< "translation = (" << p(4) << ',' << p(5) << ',' << p(6) << ")\n";
00925 break; }
00926 case Affine: {
00927 vnl_vector<double> p(9);
00928 params(p);
00929
00930
00931
00932 o << "Affine\n"
00933 << vsl_indent()<< "scale factors = " << p(0) << ',' << p(1) << ',' << p(2) << '\n'
00934 << vsl_indent()<< "angles = " << p(3) << ',' << p(4) << ',' << p(5) << '\n'
00935 << vsl_indent()<< "translation = (" << p(6) << ',' << p(7) << ',' << p(8) << ")\n";
00936 break; }
00937 default:
00938 mbl_exception_error(mbl_exception_abort(
00939 vul_sprintf("vimt3d_transform_3d::print_summary() Unexpected form: %d", form_) ));
00940 }
00941 vsl_indent_dec(o);
00942 }
00943
00944
00945
00946 void vimt3d_transform_3d::print_all(vcl_ostream& os) const
00947 {
00948 os << vsl_indent() << "Form: ";
00949 switch (form_)
00950 {
00951 case Identity:
00952 os << "Identity\n";
00953 break;
00954
00955 case Translation:
00956 os << "Translation\n";
00957 break;
00958
00959 case ZoomOnly:
00960 os << "ZoomOnly\n";
00961 break;
00962
00963 case RigidBody:
00964 os << "RigidBody\n";
00965 break;
00966
00967 case Similarity:
00968 os << "Similarity\n";
00969 break;
00970
00971 case Affine:
00972 os << "Affine\n";
00973 break;
00974 default:
00975 mbl_exception_error(mbl_exception_abort(
00976 vul_sprintf("vimt3d_transform_3d::print_all() Unexpected form: %d", form_) ));
00977 }
00978
00979 os << vsl_indent() << "Matrix:\n";
00980 vsl_indent_inc(os);
00981 os << vsl_indent() << xx_ << ' ' << xy_ << ' ' << xz_ << ' ' << xt_ << '\n'
00982 << vsl_indent() << yx_ << ' ' << yy_ << ' ' << yz_ << ' ' << yt_ << '\n'
00983 << vsl_indent() << zx_ << ' ' << zy_ << ' ' << zz_ << ' ' << zt_ << '\n'
00984 << vsl_indent() << tx_ << ' ' << ty_ << ' ' << tz_ << ' ' << tt_ << '\n';
00985 vsl_indent_dec(os);
00986 }
00987
00988
00989
00990 void vimt3d_transform_3d::config(vcl_istream& is)
00991 {
00992 mbl_read_props_type props = mbl_read_props_ws(is);
00993 vcl_string form = props.get_required_property("form");
00994 vul_string_downcase(form);
00995
00996 bool done=false;
00997
00998 if (form == "identity")
00999 {
01000 done=true;
01001 form_ = Identity;
01002 }
01003 else if (form == "translation")
01004 form_ = Translation;
01005 else if (form == "zoomonly")
01006 form_ = ZoomOnly;
01007 else if (form == "rigidbody")
01008 form_ = RigidBody;
01009 else if (form == "similarity")
01010 form_ = Similarity;
01011 else if (form == "affine")
01012 form_ = Affine;
01013 else
01014 throw mbl_exception_parse_error("Unknown transformation: \"" + form + "\"");
01015
01016 vcl_string vector = props.get_optional_property("vector");
01017 if (!vector.empty())
01018 {
01019 vcl_istringstream ss(vector);
01020
01021 vcl_vector<double> vec1;
01022 mbl_parse_sequence(ss, vcl_back_inserter(vec1), double());
01023 if (vec1.empty())
01024 throw mbl_exception_parse_error("Could not find elements for transformation vector: \""+vector+"\"");
01025 vnl_vector<double> vec2(&vec1.front(), vec1.size());
01026 try
01027 {
01028 this->set(vec2, form_);
01029 }
01030 catch (mbl_exception_abort & e)
01031 {
01032 throw mbl_exception_parse_error(e.what());
01033 }
01034 done = true;
01035 }
01036 if (!done && form_==Translation)
01037 {
01038 this->set_translation(
01039 vul_string_atof(props.get_required_property("t_x")),
01040 vul_string_atof(props.get_required_property("t_y")),
01041 vul_string_atof(props.get_required_property("t_z")) );
01042 done = true;
01043 }
01044 if (!done && form_==ZoomOnly)
01045 {
01046 vcl_string s_str = props.get_optional_property("s");
01047 if (!s_str.empty())
01048 this->set_zoom_only(
01049 vul_string_atof(s_str),
01050 vul_string_atof(props.get_optional_property("t_x")),
01051 vul_string_atof(props.get_optional_property("t_y")),
01052 vul_string_atof(props.get_optional_property("t_z")) );
01053 else
01054 this->set_zoom_only(
01055 vul_string_atof(props.get_optional_property("s_x")),
01056 vul_string_atof(props.get_optional_property("s_y")),
01057 vul_string_atof(props.get_optional_property("s_z")),
01058 vul_string_atof(props.get_optional_property("t_x")),
01059 vul_string_atof(props.get_optional_property("t_y")),
01060 vul_string_atof(props.get_optional_property("t_z")) );
01061 done = true;
01062 }
01063 if (!done && form_==RigidBody)
01064 {
01065 set_rigid_body(
01066 vul_string_atof(props.get_optional_property("r_x")),
01067 vul_string_atof(props.get_optional_property("r_y")),
01068 vul_string_atof(props.get_optional_property("r_z")),
01069 vul_string_atof(props.get_optional_property("t_x")),
01070 vul_string_atof(props.get_optional_property("t_y")),
01071 vul_string_atof(props.get_optional_property("t_z")) );
01072 done = true;
01073 }
01074
01075 if (!done) throw mbl_exception_parse_error("Not enough transformation values specified");
01076
01077 mbl_read_props_look_for_unused_props(
01078 "vimt3d_transform_3d::config", props, mbl_read_props_type());
01079 return;
01080 }
01081
01082
01083
01084
01085 void vimt3d_transform_3d::b_write(vsl_b_ostream& bfs) const
01086 {
01087 const short version_no = 2;
01088 vsl_b_write(bfs,version_no);
01089 vsl_b_write(bfs,int(form_));
01090 vsl_b_write(bfs,xx_); vsl_b_write(bfs,xy_); vsl_b_write(bfs,xz_); vsl_b_write(bfs,xt_);
01091 vsl_b_write(bfs,yx_); vsl_b_write(bfs,yy_); vsl_b_write(bfs,yz_); vsl_b_write(bfs,yt_);
01092 vsl_b_write(bfs,zx_); vsl_b_write(bfs,zy_); vsl_b_write(bfs,zz_); vsl_b_write(bfs,zt_);
01093 vsl_b_write(bfs,tx_); vsl_b_write(bfs,ty_); vsl_b_write(bfs,tz_); vsl_b_write(bfs,tt_);
01094 }
01095
01096
01097
01098 void vimt3d_transform_3d::b_read(vsl_b_istream& bfs)
01099 {
01100 short version;
01101 vsl_b_read(bfs,version);
01102 int f;
01103 switch (version)
01104 {
01105 case 1:
01106 vsl_b_read(bfs,f);
01107 if (f==0)
01108 set_identity();
01109 else
01110 {
01111 form_=Form(f-1);
01112 vsl_b_read(bfs,xx_); vsl_b_read(bfs,xy_); vsl_b_read(bfs,xz_); vsl_b_read(bfs,xt_);
01113 vsl_b_read(bfs,yx_); vsl_b_read(bfs,yy_); vsl_b_read(bfs,yz_); vsl_b_read(bfs,yt_);
01114 vsl_b_read(bfs,zx_); vsl_b_read(bfs,zy_); vsl_b_read(bfs,zz_); vsl_b_read(bfs,zt_);
01115 vsl_b_read(bfs,tx_); vsl_b_read(bfs,ty_); vsl_b_read(bfs,tz_); vsl_b_read(bfs,tt_);
01116 }
01117 break;
01118 case 2:
01119 vsl_b_read(bfs,f); form_=Form(f);
01120 vsl_b_read(bfs,xx_); vsl_b_read(bfs,xy_); vsl_b_read(bfs,xz_); vsl_b_read(bfs,xt_);
01121 vsl_b_read(bfs,yx_); vsl_b_read(bfs,yy_); vsl_b_read(bfs,yz_); vsl_b_read(bfs,yt_);
01122 vsl_b_read(bfs,zx_); vsl_b_read(bfs,zy_); vsl_b_read(bfs,zz_); vsl_b_read(bfs,zt_);
01123 vsl_b_read(bfs,tx_); vsl_b_read(bfs,ty_); vsl_b_read(bfs,tz_); vsl_b_read(bfs,tt_);
01124 break;
01125 default:
01126 vcl_cerr<<"vimt3d_transform_3d::load : Illegal version number "<<version<<'\n';
01127 vcl_abort();
01128 }
01129
01130 inv_uptodate_ = 0;
01131 }
01132
01133
01134
01135 void vsl_b_write(vsl_b_ostream& bfs, const vimt3d_transform_3d& b)
01136 {
01137 b.b_write(bfs);
01138 }
01139
01140
01141
01142 void vsl_b_read(vsl_b_istream& bfs, vimt3d_transform_3d& b)
01143 {
01144 b.b_read(bfs);
01145 }
01146
01147
01148
01149 vcl_ostream& operator<<(vcl_ostream& os,const vimt3d_transform_3d& b)
01150 {
01151 vsl_indent_inc(os);
01152 b.print_summary(os);
01153 vsl_indent_dec(os);
01154 return os;
01155 }
01156
01157
01158
01159
01160
01161
01162
01163 bool vimt3d_transform_is_zoom_only(const vimt3d_transform_3d& transf,
01164 const double zero_tol)
01165 {
01166
01167
01168
01169 vnl_matrix<double> M = transf.matrix().extract(3,3,0,0);
01170
01171
01172 for (unsigned i=0; i<3; ++i)
01173 if (M(i,i)<=zero_tol) return false;
01174
01175
01176 for (unsigned j=0; j<3; ++j)
01177 {
01178 for (unsigned i=0; i<3; ++i)
01179 {
01180 if (i!=j && vcl_fabs(M(i,j))>=zero_tol) return false;
01181 }
01182 }
01183
01184 return true;
01185 }
01186