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