Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

transform.cpp

Go to the documentation of this file.
00001 
00005 /*
00006  * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
00007  * Copyright (c) 2000-2006 Baylor College of Medicine
00008  *
00009  * This software is issued under a joint BSD/GNU license. You may use the
00010  * source code in this file under either license. However, note that the
00011  * complete EMAN2 and SPARX software packages have some GPL dependencies,
00012  * so you are responsible for compliance with the licenses of these packages
00013  * if you opt to use BSD licensing. The warranty disclaimer below holds
00014  * in either instance.
00015  *
00016  * This complete copyright notice must be included in any revised version of the
00017  * source code. Additional authorship citations may be added, but existing
00018  * author citations must be preserved.
00019  *
00020  * This program is free software; you can redistribute it and/or modify
00021  * it under the terms of the GNU General Public License as published by
00022  * the Free Software Foundation; either version 2 of the License, or
00023  * (at your option) any later version.
00024  *
00025  * This program is distributed in the hope that it will be useful,
00026  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00027  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00028  * GNU General Public License for more details.
00029  *
00030  * You should have received a copy of the GNU General Public License
00031  * along with this program; if not, write to the Free Software
00032  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00033  *
00034  * */
00035 
00036 #include "transform.h"
00037 #include "util.h"
00038 #include "emobject.h"
00039 #include <cctype> // for std::tolower
00040 #include <cstring>  // for memcpy
00041 #include "symmetry.h"
00042 using namespace EMAN;
00043 
00044 #ifdef WIN32
00045 #ifndef M_PI
00046 #define M_PI 3.14159265358979323846
00047 #endif
00048 #endif
00049 
00050 #include <algorithm> // for std::transform
00051 
00052 #include <gsl_matrix.h>
00053 #include <gsl_blas.h>
00054 #include <gsl_linalg.h>
00055 
00056 #include <ostream>
00057 using std::ostream_iterator;
00058 
00059 //const float Transform3D::ERR_LIMIT = 0.000001f;
00060 
00061 const float Transform::ERR_LIMIT = 0.000001f;
00062 
00063 vector<string>  Transform::permissable_2d_not_rot;
00064 vector<string>  Transform::permissable_3d_not_rot;
00065 map<string,vector<string> >  Transform::permissable_rot_keys;
00066 
00067 Transform Transform::icos_5_to_2() {
00068         Transform t;
00069         Dict d;
00070         d["type"] = "eman";
00071         d["phi"] = 0.0f;
00072         d["az"] = 270.0f;
00073         d["alt"] = 58.282523f; // 5 fold to a 3 fold to a 2 fold
00079         t.set_rotation(d);
00080         return t;
00081 }
00082 
00083 Transform Transform::tet_3_to_2() {
00084         Transform t;
00085         Dict d;
00086         d["type"] = "eman";
00087         d["phi"] = 45.0f;
00088         d["az"] = 0.0f;
00089         d["alt"] = 54.73561f; // 3 fold to a 2 fold
00093         t.set_rotation(d);
00094         return t;
00095 }
00096 
00097 
00098 Transform::Transform()
00099 {
00100         to_identity();
00101 }
00102 
00103 Transform::Transform( const Transform& that )
00104 {
00105         *this = that;
00106 }
00107 
00108 Transform& Transform::operator=(const Transform& that ) {
00109         if (this != &that ) {
00110                 memcpy(matrix,that.matrix,12*sizeof(float));
00111 //              transform_type = that.transform_type;
00112         }
00113         return *this;
00114 }
00115 
00116 bool Transform::operator==(const Transform& rhs) const{
00117         if (memcmp(this->matrix, rhs.matrix, 3*4*sizeof(float)) == 0) {
00118                 return true;
00119         }
00120         else {
00121                 return false;
00122         }
00123 }
00124 
00125 bool Transform::operator!=(const Transform& rhs) const{
00126         return !(operator==(rhs));
00127 }
00128 
00129 Transform::Transform(const Dict& d)  {
00130         to_identity();
00131         set_params(d);
00132 }
00133 
00134 
00135 Transform::Transform(const float array[12]) {
00136         memcpy(matrix,array,12*sizeof(float));
00137 }
00138 
00139 Transform::Transform(const vector<float> array)
00140 {
00141         set_matrix(array);
00142 }
00143 
00144 void Transform::set_matrix(const vector<float>& v)
00145 {
00146         if (v.size() != 12 ) throw InvalidParameterException("The construction array must be of size 12");
00147 
00148         for(int i=0; i<3; ++i) {
00149                 for(int j=0; j<4; ++j) {
00150                         matrix[i][j] = v[i*4+j];
00151                 }
00152         }
00153 }
00154 
00155 void Transform::copy_matrix_into_array(float* const array) const {
00156 
00157         int idx = 0;
00158         for(int i=0; i<3; ++i) {
00159                 for(int j=0; j<4; ++j) {
00160                         array[idx] = matrix[i][j];
00161                         idx ++;
00162                 }
00163         }
00164 }
00165 
00166 vector<float> Transform::get_matrix() const
00167 {
00168         vector<float> ret(12);
00169         for(int i=0; i<3; ++i) {
00170                 for(int j=0; j<4; ++j) {
00171                         ret[i*4+j] = matrix[i][j];
00172                 }
00173         }
00174         return ret;
00175 }
00176 
00177 void Transform::to_identity()
00178 {
00179 //      transform_type = UNKNOWN;
00180         for(int i=0; i<3; ++i) {
00181                 for(int j=0; j<4; ++j) {
00182                         if(i==j) {
00183                                 matrix[i][j] = 1;
00184                         }
00185                         else {
00186                                 matrix[i][j] = 0;
00187                         }
00188                 }
00189         }
00190 }
00191 
00192 bool Transform::is_identity() const {
00193         for(int i=0; i<3; ++i) {
00194                 for(int j=0; j<4; ++j) {
00195                         float c = matrix[i][j];
00196                         Util::apply_precision(c,ERR_LIMIT);
00197                         if(i==j) {
00198                                 if (c != 1.0) return false;
00199                         }
00200                         else {
00201                                 if (c != 0.0) return false;
00202                         }
00203                 }
00204         }
00205         return true;
00206 }
00207 
00208 
00209 void Transform::set_params(const Dict& d) {
00210         detect_problem_keys(d);
00211 
00212         if (d.has_key_ci("type") ) set_rotation(d);
00213 
00214         if (d.has_key_ci("scale")) {
00215                 float scale = static_cast<float>(d.get_ci("scale"));
00216                 set_scale(scale);
00217         }
00218 
00219         float dx=0,dy=0,dz=0;
00220 
00221         if (d.has_key_ci("tx")) dx = static_cast<float>(d.get_ci("tx"));
00222         if (d.has_key_ci("ty")) dy = static_cast<float>(d.get_ci("ty"));
00223         if (d.has_key_ci("tz")) dz = static_cast<float>(d.get_ci("tz"));
00224 
00225         if ( dx != 0.0 || dy != 0.0 || dz != 0.0 ) {
00226                 set_trans(dx,dy,dz);
00227         }
00228 
00229         if (d.has_key_ci("mirror")) {
00230                 EMObject e = d.get_ci("mirror");
00231                 if ( (e.get_type() != EMObject::BOOL ) && (e.get_type() != EMObject::INT ) && (e.get_type() != EMObject::UNSIGNEDINT ) )
00232                         throw InvalidParameterException("Error, mirror must be a bool or an int");
00233 
00234                 bool mirror = static_cast<bool>(e);
00235                 set_mirror(mirror);
00236         }
00237 }
00238 
00239 
00240 void Transform::init_permissable_keys()
00241 {
00242 
00243         permissable_2d_not_rot.push_back("tx");
00244         permissable_2d_not_rot.push_back("ty");
00245         permissable_2d_not_rot.push_back("scale");
00246         permissable_2d_not_rot.push_back("mirror");
00247         permissable_2d_not_rot.push_back("type");
00248 
00249         permissable_3d_not_rot.push_back("tx");
00250         permissable_3d_not_rot.push_back("ty");
00251         permissable_3d_not_rot.push_back("tz");
00252         permissable_3d_not_rot.push_back("scale");
00253         permissable_3d_not_rot.push_back("mirror");
00254         permissable_3d_not_rot.push_back("type");
00255 
00256         vector<string> tmp;
00257         tmp.push_back("alpha");
00258         permissable_rot_keys["2d"] = tmp;
00259 
00260         tmp.clear();
00261         tmp.push_back("alt");
00262         tmp.push_back("az");
00263         tmp.push_back("phi");
00264         permissable_rot_keys["eman"] = tmp;
00265 
00266         tmp.clear();
00267         tmp.push_back("psi");
00268         tmp.push_back("theta");
00269         tmp.push_back("phi");
00270         permissable_rot_keys["spider"] = tmp;
00271 
00272         tmp.clear();
00273         tmp.push_back("alpha");
00274         tmp.push_back("beta");
00275         tmp.push_back("gamma");
00276         permissable_rot_keys["imagic"] = tmp;
00277 
00278         tmp.clear();
00279         tmp.push_back("ztilt");
00280         tmp.push_back("xtilt");
00281         tmp.push_back("ytilt");
00282         permissable_rot_keys["xyz"] = tmp;
00283 
00284         tmp.clear();
00285         tmp.push_back("phi");
00286         tmp.push_back("theta");
00287         tmp.push_back("omega");
00288         permissable_rot_keys["mrc"] = tmp;
00289 
00290         tmp.clear();
00291         tmp.push_back("e0");
00292         tmp.push_back("e1");
00293         tmp.push_back("e2");
00294         tmp.push_back("e3");
00295         permissable_rot_keys["quaternion"] = tmp;
00296 
00297         tmp.clear();
00298         tmp.push_back("n1");
00299         tmp.push_back("n2");
00300         tmp.push_back("n3");
00301         tmp.push_back("Omega");
00302         permissable_rot_keys["spin"] = tmp;
00303 
00304         tmp.clear();
00305         tmp.push_back("n1");
00306         tmp.push_back("n2");
00307         tmp.push_back("n3");
00308         tmp.push_back("q");
00309         permissable_rot_keys["sgirot"] = tmp;
00310 
00311         tmp.clear();
00312         tmp.push_back("m11");
00313         tmp.push_back("m12");
00314         tmp.push_back("m13");
00315         tmp.push_back("m21");
00316         tmp.push_back("m22");
00317         tmp.push_back("m23");
00318         tmp.push_back("m31");
00319         tmp.push_back("m32");
00320         tmp.push_back("m33");
00321         permissable_rot_keys["matrix"] = tmp;
00322 }
00323 
00324 
00325 void Transform::detect_problem_keys(const Dict& d) {
00326         if (permissable_rot_keys.size() == 0 ) {
00327                 init_permissable_keys();
00328         }
00329 
00330         vector<string> verification;
00331         vector<string> problem_keys;
00332         bool is_2d = false;
00333         if (d.has_key_ci("type") ) {
00334                 string type = Util::str_to_lower((string)d["type"]);
00335                 bool problem = false;
00336                 if (permissable_rot_keys.find(type) == permissable_rot_keys.end() ) {
00337                         problem_keys.push_back(type);
00338                         problem = true;
00339                 }
00340                 if ( !problem ) {
00341                         vector<string> perm = permissable_rot_keys[type];
00342                         std::copy(perm.begin(),perm.end(),back_inserter(verification));
00343 
00344                         if ( type == "2d" ) {
00345                                 is_2d = true;
00346                                 std::copy(permissable_2d_not_rot.begin(),permissable_2d_not_rot.end(),back_inserter(verification));
00347                         }
00348                 }
00349         }
00350         if ( !is_2d ) {
00351                 std::copy(permissable_3d_not_rot.begin(),permissable_3d_not_rot.end(),back_inserter(verification));
00352         }
00353 
00354         for (Dict::const_iterator it = d.begin(); it != d.end();  ++it) {
00355                 if ( std::find(verification.begin(),verification.end(), it->first) == verification.end() ) {
00356                         problem_keys.push_back(it->first);
00357                 }
00358         }
00359 
00360         if (problem_keys.size() != 0 ) {
00361                 string error;
00362                 if (problem_keys.size() == 1) {
00363                         error = "Transform Error: The \"" +problem_keys[0]+ "\" key is unsupported";
00364                 } else {
00365                         error = "Transform Error: The ";
00366                         for(vector<string>::const_iterator cit = problem_keys.begin(); cit != problem_keys.end(); ++cit ) {
00367                                 if ( cit != problem_keys.begin() ) {
00368                                         if (cit == (problem_keys.end() -1) ) error += " and ";
00369                                         else error += ", ";
00370                                 }
00371                                 error += "\"";
00372                                 error += *cit;
00373                                 error += "\"";
00374                         }
00375                         error += " keys are unsupported";
00376                 }
00377                 throw InvalidParameterException(error);
00378         }
00379 }
00380 
00381 void Transform::set_params_inverse(const Dict& d) {
00382         detect_problem_keys(d);
00383 
00384         if (d.has_key_ci("type") ) set_rotation(d);
00385 
00386         float dx=0,dy=0,dz=0;
00387         if (d.has_key_ci("tx")) dx = static_cast<float>(d.get_ci("tx"));
00388         if (d.has_key_ci("ty")) dy = static_cast<float>(d.get_ci("ty"));
00389         if (d.has_key_ci("tz")) dz = static_cast<float>(d.get_ci("tz"));
00390 
00391         if ( (dx != 0.0 || dy != 0.0 || dz != 0.0) && d.has_key_ci("type") ) {
00392                 Transform pre_trans;
00393                 pre_trans.set_trans(dx,dy,dz);
00394 
00395                 Transform tmp;
00396                 tmp.set_rotation(d);
00397 
00398                 if (d.has_key_ci("scale")) {
00399                         float scale = static_cast<float>(d.get_ci("scale"));
00400                         tmp.set_scale(scale);
00401                 }
00402 
00403                 Transform solution_trans = tmp*pre_trans;
00404 
00405                 if (d.has_key_ci("scale")) {
00406                         Transform tmp;
00407                         float scale = static_cast<float>(d.get_ci("scale"));
00408                         tmp.set_scale(scale);
00409                         solution_trans = solution_trans*tmp;
00410                 }
00411 
00412                 tmp = Transform();
00413                 tmp.set_rotation(d);
00414                 solution_trans = solution_trans*tmp;
00415                 set_trans(solution_trans.get_trans());
00416         }
00417 
00418         if (d.has_key_ci("scale")) {
00419                 float scale = static_cast<float>(d.get_ci("scale"));
00420                 set_scale(scale);
00421         }
00422 
00423         if (d.has_key_ci("mirror")) {
00424                 EMObject e = d.get_ci("mirror");
00425                 if ( (e.get_type() != EMObject::BOOL ) && (e.get_type() != EMObject::INT ) && (e.get_type() != EMObject::UNSIGNEDINT ) )
00426                         throw InvalidParameterException("Error, mirror must be a bool or an int");
00427 
00428                 bool mirror = static_cast<bool>(e);
00429                 set_mirror(mirror);
00430         }
00431         invert();
00432 }
00433 
00434 
00435 Dict Transform::get_params(const string& euler_type) const {
00436         Dict params = get_rotation(euler_type);
00437 
00438         Vec3f v = get_trans();
00439         params["tx"] = v[0]; params["ty"] = v[1];
00440 
00441         string type = Util::str_to_lower(euler_type);
00442         if ( type != "2d") params["tz"] = v[2];
00443 
00444         float scale = get_scale();
00445         params["scale"] = scale;
00446 
00447         bool mirror = get_mirror();
00448         params["mirror"] = mirror;
00449 
00450         return params;
00451 }
00452 
00453 
00454 
00455 Dict Transform::get_params_inverse(const string& euler_type) const {
00456         Transform inv(inverse());
00457 
00458         Dict params = inv.get_rotation(euler_type);
00459         Vec3f v = inv.get_pre_trans();
00460         params["tx"] = v[0]; params["ty"] = v[1];
00461 
00462         string type = Util::str_to_lower(euler_type);
00463         if ( type != "2d") params["tz"] = v[2];
00464 
00465         float scale = inv.get_scale();
00466         params["scale"] = scale;
00467 
00468         bool mirror = inv.get_mirror();
00469         params["mirror"] = mirror;
00470 
00471         return params;
00472 }
00473 
00474 
00475 void Transform::set_rotation(const Dict& rotation)
00476 {
00477         detect_problem_keys(rotation);
00478         string euler_type;
00479 
00480         if (!rotation.has_key_ci("type") ){
00481                         throw InvalidParameterException("argument dictionary does not contain the type key");
00482         }
00483 
00484         euler_type = static_cast<string>(rotation.get_ci("type"));// Warning, will throw
00485 
00486 
00487         double e0=0; double e1=0; double e2=0; double e3=0;
00488         double Omega=0;
00489         double az  = 0;
00490         double alt = 0;
00491         double phi = 0;
00492         double cxtilt = 0;
00493         double sxtilt = 0;
00494         double cytilt = 0;
00495         double sytilt = 0;
00496         double cztilt = 0;
00497         double sztilt = 0;
00498         bool is_quaternion = 0;
00499         bool is_matrix = 0;
00500         bool is_xyz = 0;
00501 
00502         bool x_mirror;
00503         float scale;
00504         // Get these before anything changes so we can apply them again after the rotation is set
00505         get_scale_and_mirror(scale,x_mirror);
00506         if (scale == 0) throw UnexpectedBehaviorException("The determinant of the Transform is 0. This is unexpected.");
00507 
00508         string type = Util::str_to_lower(euler_type);
00509         if (type == "2d") {
00510                 assert_valid_2d();
00511                 az  = 0;
00512                 alt = 0;
00513                 phi = (double)rotation["alpha"] ;
00514         } else if ( type == "eman" ) {
00515 //              validate_and_set_type(THREED);
00516                 az  = (double)rotation["az"] ;
00517                 alt = (double)rotation["alt"]  ;
00518                 phi = (double)rotation["phi"] ;
00519         } else if ( type == "imagic" ) {
00520 //              validate_and_set_type(THREED);
00521                 az  = (double)rotation["alpha"] ;
00522                 alt = (double)rotation["beta"]  ;
00523                 phi = (double)rotation["gamma"] ;
00524         } else if ( type == "spider" ) {
00525 //              validate_and_set_type(THREED);
00526                 az =  (double)rotation["phi"]    + 90.0;
00527                 alt = (double)rotation["theta"] ;
00528                 phi = (double)rotation["psi"]    - 90.0;
00529         } else if ( type == "xyz" ) {
00530 //              validate_and_set_type(THREED);
00531                 is_xyz = 1;
00532                 cxtilt = cos(EMConsts::deg2rad*(double)rotation["xtilt"]);
00533                 sxtilt = sin(EMConsts::deg2rad*(double)rotation["xtilt"]);
00534                 cytilt = cos(EMConsts::deg2rad*(double)rotation["ytilt"]);
00535                 sytilt = sin(EMConsts::deg2rad*(double)rotation["ytilt"]);
00536                 cztilt = cos(EMConsts::deg2rad*(double)rotation["ztilt"]);
00537                 sztilt = sin(EMConsts::deg2rad*(double)rotation["ztilt"]);
00538         } else if ( type == "mrc" ) {
00539 //              validate_and_set_type(THREED);
00540                 az  = (double)rotation["phi"]   + 90.0f ;
00541                 alt = (double)rotation["theta"] ;
00542                 phi = (double)rotation["omega"] - 90.0f ;
00543         } else if ( type == "quaternion" ) {
00544 //              validate_and_set_type(THREED);
00545                 is_quaternion = 1;
00546                 e0 = (double)rotation["e0"];
00547                 e1 = (double)rotation["e1"];
00548                 e2 = (double)rotation["e2"];
00549                 e3 = (double)rotation["e3"];
00550         } else if ( type == "spin" ) {
00551 //              validate_and_set_type(THREED);
00552                 is_quaternion = 1;
00553                 Omega = (double)rotation["Omega"];
00554                 e0 = cos(Omega*EMConsts::deg2rad/2.0);
00555                 e1 = sin(Omega*EMConsts::deg2rad/2.0) * (double)rotation["n1"];
00556                 e2 = sin(Omega*EMConsts::deg2rad/2.0) * (double)rotation["n2"];
00557                 e3 = sin(Omega*EMConsts::deg2rad/2.0) * (double)rotation["n3"];
00558         } else if ( type == "sgirot" ) {
00559 //              validate_and_set_type(THREED);
00560                 is_quaternion = 1;
00561                 Omega = (double)rotation["q"] ;
00562                 e0 = cos(Omega*EMConsts::deg2rad/2.0);
00563                 e1 = sin(Omega*EMConsts::deg2rad/2.0) * (double)rotation["n1"];
00564                 e2 = sin(Omega*EMConsts::deg2rad/2.0) * (double)rotation["n2"];
00565                 e3 = sin(Omega*EMConsts::deg2rad/2.0) * (double)rotation["n3"];
00566         } else if ( type == "matrix" ) {
00567                 is_matrix = 1;
00568                 matrix[0][0] = (float)rotation["m11"];
00569                 matrix[0][1] = (float)rotation["m12"];
00570                 matrix[0][2] = (float)rotation["m13"];
00571                 matrix[1][0] = (float)rotation["m21"];
00572                 matrix[1][1] = (float)rotation["m22"];
00573                 matrix[1][2] = (float)rotation["m23"];
00574                 matrix[2][0] = (float)rotation["m31"];
00575                 matrix[2][1] = (float)rotation["m32"];
00576                 matrix[2][2] = (float)rotation["m33"];
00577         } else {
00578 //              transform_type = UNKNOWN;
00579                 throw InvalidStringException(euler_type, "unknown Euler Type");
00580         }
00581 
00582         double azp  =  az*EMConsts::deg2rad;
00583         double altp = alt*EMConsts::deg2rad;
00584         double phip = phi*EMConsts::deg2rad;
00585 
00586         if (!is_quaternion && !is_matrix && !is_xyz) {
00587                 matrix[0][0] =  (float)(cos(phip)*cos(azp) - cos(altp)*sin(azp)*sin(phip));
00588                 matrix[0][1] =  (float)(cos(phip)*sin(azp) + cos(altp)*cos(azp)*sin(phip));
00589                 matrix[0][2] =  (float)(sin(altp)*sin(phip));
00590                 matrix[1][0] =  (float)(-sin(phip)*cos(azp) - cos(altp)*sin(azp)*cos(phip));
00591                 matrix[1][1] =  (float)(-sin(phip)*sin(azp) + cos(altp)*cos(azp)*cos(phip));
00592                 matrix[1][2] =  (float)(sin(altp)*cos(phip));
00593                 matrix[2][0] =  (float)(sin(altp)*sin(azp));
00594                 matrix[2][1] =  (float)(-sin(altp)*cos(azp));
00595                 matrix[2][2] =  (float)cos(altp);
00596         }
00597         if (is_quaternion){
00598                 matrix[0][0] = (float)(e0 * e0 + e1 * e1 - e2 * e2 - e3 * e3);
00599                 matrix[0][1] = (float)(2.0f * (e1 * e2 + e0 * e3));
00600                 matrix[0][2] = (float)(2.0f * (e1 * e3 - e0 * e2));
00601                 matrix[1][0] = (float)(2.0f * (e2 * e1 - e0 * e3));
00602                 matrix[1][1] = (float)(e0 * e0 - e1 * e1 + e2 * e2 - e3 * e3);
00603                 matrix[1][2] = (float)(2.0f * (e2 * e3 + e0 * e1));
00604                 matrix[2][0] = (float)(2.0f * (e3 * e1 + e0 * e2));
00605                 matrix[2][1] = (float)(2.0f * (e3 * e2 - e0 * e1));
00606                 matrix[2][2] = (float)(e0 * e0 - e1 * e1 - e2 * e2 + e3 * e3);
00607                 // keep in mind matrix[0][2] is M13 gives an e0 e2 piece, etc
00608         }
00609         if (is_xyz){
00610                 matrix[0][0] =  (float)(cytilt*cztilt);
00611                 matrix[0][1] =  (float)(cxtilt*sztilt+sxtilt*sytilt*cztilt);
00612                 matrix[0][2] =  (float)(sxtilt*sztilt-cxtilt*sytilt*cztilt);
00613                 matrix[1][0] =  (float)(-cytilt*sztilt);
00614                 matrix[1][1] =  (float)(cxtilt*cztilt-sxtilt*sytilt*sztilt);
00615                 matrix[1][2] =  (float)(sxtilt*cztilt+cxtilt*sytilt*sztilt);
00616                 matrix[2][0] =  (float)(sytilt);
00617                 matrix[2][1] =  (float)(-sxtilt*cytilt);
00618                 matrix[2][2] =  (float)(cxtilt*cytilt);
00619         }
00620         
00621         // Apply scale if it existed previously
00622         if (scale != 1.0f) {
00623                 for(int i=0; i<3; ++i) {
00624                         for(int j=0; j<3; ++j) {
00625                                 matrix[i][j] *= scale;
00626                         }
00627                 }
00628         }
00629 
00630         // Apply post x mirroring if it was applied previously
00631         if ( x_mirror ) {
00632                 for(int j=0; j<3; ++j) {
00633                         matrix[0][j] *= -1.0f;
00634                 }
00635         }
00636 }
00637 
00638 Transform Transform::get_rotation_transform() const
00639 {
00640         Transform ret(*this);
00641         ret.set_scale(1.0);
00642         ret.set_mirror(false);
00643         ret.set_trans(0,0,0);
00644         //ret.orthogonalize(); // ?
00645         return ret;
00646 }
00647 
00648 void Transform::set_rotation(const Vec3f & v)
00649 {
00650         if ( v[0] == 0 && v[1] == 0 && v[2] == 0 )
00651                 throw UnexpectedBehaviorException("Can't set rotation for the null vector");
00652 
00653         Vec3f v1(v);
00654         v1.normalize();
00655 
00656         double theta = acos(v1[2]); // in radians
00657         double psi = atan2(v1[1],-v1[0]);
00658 
00659         Dict d;
00660         d["theta"] = (double)EMConsts::rad2deg*theta;
00661         d["psi"] = (double)EMConsts::rad2deg*psi;
00662         d["phi"] = (double)0.0;
00663         d["type"] = "spider";
00664 
00665         set_rotation(d);
00666 
00667 
00668 }
00669 
00670 Transform Transform::negate() const
00671 {
00672         Transform t(*this);
00673         for(unsigned int i = 0; i < 3; ++i) {
00674                 for(unsigned int j = 0; j < 4; ++j) {
00675                         t.set(i,j,t[i][j]*-1);
00676                 }
00677         }
00678         return t;
00679 }
00680 
00681 Transform Transform::get_hflip_transform() const {
00682 
00683         Dict rot = get_rotation("eman");
00684         rot["alt"] = 180.0f + static_cast<float>(rot["alt"]);
00685         rot["phi"] = 180.0f - static_cast<float>(rot["phi"]);
00686 
00687         Transform ret(*this); // Is the identity
00688         ret.set_rotation(rot);
00689 
00690         Vec3f trans = get_trans();
00691         trans[0] = -trans[0];
00692         ret.set_trans(trans);
00693 
00694 //      ret.set_mirror(self.get_mirror());
00695 
00696         return ret;
00697 }
00698 
00699 Transform Transform::get_vflip_transform() const {
00700 
00701         Dict rot = get_rotation("eman");
00702         rot["alt"] = 180.0f + static_cast<float>(rot["alt"]);
00703         rot["phi"] = - static_cast<float>(rot["phi"]);
00704 
00705         Transform ret(*this);
00706         ret.set_rotation(rot);
00707 
00708         Vec3f trans = get_trans();
00709         trans[1] = -trans[1];
00710         ret.set_trans(trans);
00711 
00712         return ret;
00713 }
00714 
00715 Dict Transform::get_rotation(const string& euler_type) const
00716 {
00717         Dict result;
00718 
00719         //float max = 1 - ERR_LIMIT;
00720         float scale;
00721         bool x_mirror;
00722         get_scale_and_mirror(scale,x_mirror);
00723         if (scale == 0) throw UnexpectedBehaviorException("The determinant of the Transform is 0. This is unexpected.");
00724 
00725         double cosalt = matrix[2][2]/scale;
00726         double x_mirror_scale = (x_mirror ? -1.0f : 1.0f);
00727         double inv_scale = 1.0f/scale;
00728 
00729         double az  = 0;
00730         double alt = 0;
00731         double phi = 0;
00732         double phiS = 0;  // like az  (but in SPIDER ZYZ)
00733         double psiS = 0;  // like phi (but in SPIDER ZYZ)
00734 
00735         // get alt, az, phi in EMAN convention
00736 
00737         if (cosalt >= 1) {  // that is, alt close to 0
00738                         alt = 0;
00739                         az = 0;
00740                         phi = (double)EMConsts::rad2deg * atan2(x_mirror_scale*matrix[0][1], x_mirror_scale*matrix[0][0]);
00741         } else if (cosalt <= -1) {  // that is, alt close to 180
00742                         alt = 180;
00743                         az = 0;
00744                         phi = (double)EMConsts::rad2deg * atan2(-x_mirror_scale*matrix[0][1], x_mirror_scale*matrix[0][0]);
00745         } else {   // for non exceptional cases:  0 < alt < 180
00746 
00747                 az  = (double)EMConsts::rad2deg * atan2(scale*matrix[2][0], -scale*matrix[2][1]);
00748 
00749                 if (matrix[2][2]==0.0)
00750                         alt = 90.0;
00751                 else
00752                         alt = (double)EMConsts::rad2deg * atan(sqrt((double)matrix[2][0]*matrix[2][0]+(double)matrix[2][1]*matrix[2][1])/fabs(matrix[2][2]));
00753 
00754                 if (matrix[2][2] * scale < 0)
00755                         alt = 180.0f-alt;
00756                 
00757                 phi = (double)EMConsts::rad2deg * atan2(x_mirror_scale*(double)matrix[0][2], (double)matrix[1][2]);
00758 
00759         } // ends separate cases: alt close to 0, 180, or neither
00760 
00761         phi = phi-360.0*floor(phi/360.0);
00762         az  = az -360.0*floor(az/360.0);
00763 
00764 //  get phiS, psiS (SPIDER)
00765         if (cosalt >= 1) {  // that is, alt close to 0
00766                 phiS = 0;
00767                 psiS = phi;
00768         } else if (cosalt <= -1) {  // that is, alt close to 180
00769                 phiS = 0;
00770                 psiS = phi + 180.0;
00771         } else {
00772                 phiS = az  - 90.0;
00773                 psiS = phi + 90.0;
00774         }
00775 
00776         phiS = phiS-360.0*floor(phiS/360.0);
00777         psiS = psiS-360.0*floor(psiS/360.0);
00778 
00779 //   do some quaternionic stuff here
00780 
00781         double nphi = (az-phi)/2.0;
00782     // The next is also e0
00783         double cosOover2 = cos((az+phi)*EMConsts::deg2rad/2.0) * cos(alt*EMConsts::deg2rad/2.0);
00784         double sinOover2 = sqrt(1 -cosOover2*cosOover2);
00785         double cosnTheta = sin((az+phi)*EMConsts::deg2rad/2.0) * cos(alt*EMConsts::deg2rad/2.0) / sqrt(1-cosOover2*cosOover2);
00786         double sinnTheta = sqrt(1-cosnTheta*cosnTheta);
00787         double n1 = sinnTheta*cos(nphi*EMConsts::deg2rad);
00788         double n2 = sinnTheta*sin(nphi*EMConsts::deg2rad);
00789         double n3 = cosnTheta;
00790         double xtilt = 0;
00791         double ytilt = 0;
00792         double ztilt = 0;
00793 
00794 
00795         if (cosOover2<0) {
00796                 cosOover2*=-1; n1 *=-1; n2*=-1; n3*=-1;
00797         }
00798 
00799         string type = Util::str_to_lower(euler_type);
00800 
00801         result["type"] = type;
00802         if (type == "2d") {
00803                 assert_valid_2d();
00804                 result["alpha"]  = phi;
00805         } else if (type == "eman") {
00806 //              assert_consistent_type(THREED);
00807                 result["az"]  = az;
00808                 result["alt"] = alt;
00809                 result["phi"] = phi;
00810         } else if (type == "imagic") {
00811 //              assert_consistent_type(THREED);
00812                 result["alpha"] = az;
00813                 result["beta"]  = alt;
00814                 result["gamma"] = phi;
00815         } else if (type == "spider") {
00816 //              assert_consistent_type(THREED);
00817                 result["phi"]   = phiS;  // The first Euler like az
00818                 result["theta"] = alt;
00819                 result["psi"]   = psiS;
00820         } else if (type == "mrc") {
00821 //              assert_consistent_type(THREED);
00822                 result["phi"]   = phiS;
00823                 result["theta"] = alt;
00824                 result["omega"] = psiS;
00825         } else if (type == "xyz") {               // need to double-check these 3 equations ********
00826 //              assert_consistent_type(THREED);
00827                 xtilt = atan2(-sin(EMConsts::deg2rad*phiS)*sin(EMConsts::deg2rad*alt),cos(EMConsts::deg2rad*alt));
00828                 ytilt = asin(  cos(EMConsts::deg2rad*phiS)*sin(EMConsts::deg2rad*alt));
00829                 ztilt = psiS*EMConsts::deg2rad - atan2(sin(xtilt), cos(xtilt) *sin(ytilt));
00830 
00831                 xtilt *= EMConsts::rad2deg; ytilt *= EMConsts::rad2deg; ztilt *= EMConsts::rad2deg;
00832                 xtilt = xtilt-360*.0*floor((xtilt+180.0)/360.0);
00833                 ytilt = ytilt-360*.0*floor((ytilt+180.0)/360.0);  //already in range [-90,90] but anyway...
00834                 ztilt = ztilt-360*.0*floor((ztilt+180.0)/360.0);
00835 
00836                 result["xtilt"]  = xtilt;
00837                 result["ytilt"]  = ytilt;
00838                 result["ztilt"]  = ztilt;
00839         } else if (type == "quaternion") {
00840 //              assert_consistent_type(THREED);
00841                 result["e0"] = cosOover2 ;
00842                 result["e1"] = sinOover2 * n1 ;
00843                 result["e2"] = sinOover2 * n2;
00844                 result["e3"] = sinOover2 * n3;
00845         } else if (type == "spin") {
00846 //              assert_consistent_type(THREED);
00847                 result["Omega"] = 2.0*EMConsts::rad2deg * acos(cosOover2);
00848                 result["n1"] = n1;
00849                 result["n2"] = n2;
00850                 result["n3"] = n3;
00851         } else if (type == "sgirot") {
00852 //              assert_consistent_type(THREED);
00853                 result["q"] = 2.0*EMConsts::rad2deg * acos(cosOover2);
00854                 result["n1"] = n1;
00855                 result["n2"] = n2;
00856                 result["n3"] = n3;
00857         } else if (type == "matrix") {
00858 //              assert_consistent_type(THREED);
00859                 result["m11"] = x_mirror_scale*matrix[0][0]*inv_scale;
00860                 result["m12"] = x_mirror_scale*matrix[0][1]*inv_scale;
00861                 result["m13"] = x_mirror_scale*matrix[0][2]*inv_scale;
00862                 result["m21"] = matrix[1][0]*inv_scale;
00863                 result["m22"] = matrix[1][1]*inv_scale;
00864                 result["m23"] = matrix[1][2]*inv_scale;
00865                 result["m31"] = matrix[2][0]*inv_scale;
00866                 result["m32"] = matrix[2][1]*inv_scale;
00867                 result["m33"] = matrix[2][2]*inv_scale;
00868         } else {
00869                 throw InvalidStringException(euler_type, "unknown Euler Type");
00870         }
00871 
00872         return result;
00873 }
00874 
00875 void Transform::set_trans(const float& x, const float& y, const float& z)
00876 {
00877         bool x_mirror = get_mirror();
00878 
00879         if (x_mirror) matrix[0][3] = -x;
00880         else matrix[0][3] = x;
00881         matrix[1][3] = y;
00882         matrix[2][3] = z;
00883 }
00884 
00885 Vec3f Transform::get_trans() const
00886 {
00887         // No type asserted
00888         bool x_mirror = get_mirror();
00889         Vec3f v;
00890         if (x_mirror) v[0] = -matrix[0][3];
00891         else v[0] = matrix[0][3];
00892         v[1] = matrix[1][3];
00893         v[2] = matrix[2][3];
00894 
00895         Util::apply_precision(v[0],ERR_LIMIT);
00896         Util::apply_precision(v[1],ERR_LIMIT);
00897         Util::apply_precision(v[2],ERR_LIMIT);
00898 
00899         return v;
00900 }
00901 
00902 Vec2f Transform::get_trans_2d() const
00903 {
00904         bool x_mirror = get_mirror();
00905         Vec2f v;
00906         if (x_mirror) v[0] = -matrix[0][3];
00907         else v[0] = matrix[0][3];
00908         v[1] = matrix[1][3];
00909         return v;
00910 }
00911 
00912 
00913 
00914 Vec3f Transform::get_pre_trans() const
00915 {
00916         Transform T(*this);
00917         T.set_trans(0,0,0);
00918         T.invert();
00919 
00920         Transform soln  = T*(*this);
00921 //      soln.printme();
00922         return soln.get_trans();
00923 }
00924 
00925 Vec2f Transform::get_pre_trans_2d() const
00926 {
00927         Transform T(*this);
00928         T.set_trans(0,0,0);
00929         T.invert();
00930 
00931         Transform soln  = T*(*this);
00932 //      soln.printme();
00933         return soln.get_trans_2d();
00934 }
00935 
00936 
00937 void Transform::set_scale(const float& new_scale) {
00938         if (new_scale <= 0) {
00939                 throw InvalidValueException(new_scale,"The scale factor in a Transform object must be positive and non zero");
00940         }
00941         // Transform = MTSR (Mirroring, Translation, Scaling, Rotate)
00942         // So changing the scale boils down to this....
00943 
00944         float old_scale = get_scale();
00945 
00946         float n_scale = new_scale;
00947         Util::apply_precision(n_scale,ERR_LIMIT);
00948 
00949         float corrected_scale = n_scale/old_scale;
00950         if ( corrected_scale != 1.0 ) {
00951                 for(int i = 0; i < 3;  ++i ) {
00952                         for(int j = 0; j < 3; ++j ) {
00953                                 matrix[i][j] *= corrected_scale;
00954                         }
00955                 }
00956         }
00957 }
00958 
00959 float Transform::get_scale() const {
00960         float determinant = get_determinant();
00961         if (determinant < 0 ) determinant *= -1;
00962 
00963         float scale = std::pow(determinant,1.0f/3.0f);
00964         int int_scale = static_cast<int>(scale);
00965         float scale_residual = scale-static_cast<float>(int_scale);
00966         if  ( scale_residual < ERR_LIMIT ) { scale = static_cast<float>(int_scale); };
00967 
00968         Util::apply_precision(scale, ERR_LIMIT);
00969 
00970         return scale;
00971 }
00972 
00973 void print_matrix(gsl_matrix* M, unsigned int r, unsigned int c, const string& message ) {
00974         cout << "Message is " << message << endl;
00975         for ( unsigned int i = 0; i < r; ++i )
00976         {
00977                 for ( unsigned int j = 0; j < c; ++j )
00978                 {
00979                         cout << gsl_matrix_get(M,i,j) << " ";
00980                 }
00981                 cout << endl;
00982         }
00983 }
00984 
00985 void Transform::orthogonalize()
00986 {
00987         float scale;
00988         bool x_mirror;
00989         get_scale_and_mirror(scale,x_mirror);
00990         if (scale == 0) throw UnexpectedBehaviorException("The determinant of the Transform is 0. This is unexpected.");
00991         double inv_scale = 1.0/static_cast<double>(scale);
00992         double mirror_scale = (x_mirror == true ? -1.0:1.0);
00993 
00994         gsl_matrix * R = gsl_matrix_calloc(3,3);
00995         for ( unsigned int i = 0; i < 3; ++i )
00996         {
00997                 for ( unsigned int j = 0; j < 3; ++j )
00998                 {
00999                         if (i == 0 && mirror_scale != 1.0 ) {
01000                                 gsl_matrix_set( R, i, j, static_cast<double>(matrix[i][j])*mirror_scale*inv_scale );
01001                         }
01002                         else {
01003                                 gsl_matrix_set( R, i, j, static_cast<double>(matrix[i][j])*inv_scale );
01004                         }
01005                 }
01006         }
01007 
01008         gsl_matrix * V = gsl_matrix_calloc(3,3);
01009         gsl_vector * S = gsl_vector_calloc(3);
01010         gsl_vector * work = gsl_vector_calloc(3);
01011         gsl_linalg_SV_decomp (R, V, S, work); // Now R is U of the SVD R = USV^T
01012 
01013         gsl_matrix * Soln = gsl_matrix_calloc(3,3);
01014         gsl_blas_dgemm (CblasNoTrans, CblasTrans, 1.0, R, V, 0.0, Soln);
01015 
01016         for ( unsigned int i = 0; i < 3; ++i )
01017         {
01018                 for ( unsigned int j = 0; j < 3; ++j )
01019                 {
01020                         matrix[i][j] = static_cast<float>( gsl_matrix_get(Soln,i,j) );
01021                 }
01022         }
01023 
01024         // Apply scale if it existed previously
01025         if (scale != 1.0f) {
01026                 for(int i=0; i<3; ++i) {
01027                         for(int j=0; j<3; ++j) {
01028                                 matrix[i][j] *= scale;
01029                         }
01030                 }
01031         }
01032 
01033         // Apply post x mirroring if it was applied previouslys
01034         if ( x_mirror ) {
01035                 for(int j=0; j<3; ++j) {
01036                         matrix[0][j] *= -1.0f;
01037                 }
01038         }
01039 
01040         gsl_matrix_free(V); gsl_matrix_free(R); gsl_matrix_free(Soln);
01041         gsl_vector_free(S); gsl_vector_free(work);
01042 }
01043 
01044 void Transform::set_mirror(const bool x_mirror ) {
01045 
01046         bool old_x_mirror = get_mirror();
01047         if (old_x_mirror == x_mirror) return; // The user is setting the same value
01048         else {
01049                 // Toggle the mirroring operation
01050                 for (int j = 0; j < 4; ++j ) {
01051                         matrix[0][j] *= -1;
01052                 }
01053         }
01054 }
01055 
01056 bool Transform::get_mirror() const {
01057         float determinant = get_determinant();
01058 
01059         bool x_mirror = false;
01060         if ( determinant < 0 ) x_mirror = true;
01061 
01062         return x_mirror;
01063 
01064 }
01065 
01066 void Transform::get_scale_and_mirror(float& scale, bool& x_mirror) const {
01067 
01068         float determinant = get_determinant();
01069         x_mirror = false;
01070         if ( determinant < 0 ) {
01071                 x_mirror = true;
01072                 determinant *= -1;
01073         }
01074         if (determinant != 1 ) {
01075                 scale = std::pow(determinant,1.0f/3.0f);
01076                 int int_scale = static_cast<int>(scale);
01077                 float scale_residual = scale-static_cast<float>(int_scale);
01078                 if  ( scale_residual < ERR_LIMIT ) { scale = static_cast<float>(int_scale); };
01079         }
01080         else scale = 1;
01081 
01082         Util::apply_precision(scale,ERR_LIMIT);
01083 }
01084 
01085 float Transform::get_determinant() const
01086 {
01087         float det;
01088         double det2;
01089         det2  = matrix[0][0]*((double)matrix[1][1]*matrix[2][2]-(double)matrix[2][1]*matrix[1][2]);
01090         det2 -= matrix[0][1]*((double)matrix[1][0]*matrix[2][2]-(double)matrix[2][0]*matrix[1][2]);
01091         det2 += matrix[0][2]*((double)matrix[1][0]*matrix[2][1]-(double)matrix[2][0]*matrix[1][1]);
01092 
01093         det = (float)det2;
01094         Util::apply_precision(det,ERR_LIMIT);
01095 
01096         return det;
01097 }
01098 
01099 void Transform::invert() {
01100 
01101         double m00 = matrix[0][0]; double m01=matrix[0][1]; double m02=matrix[0][2];
01102         double m10 = matrix[1][0]; double m11=matrix[1][1]; double m12=matrix[1][2];
01103         double m20 = matrix[2][0]; double m21=matrix[2][1]; double m22=matrix[2][2];
01104         double v0  = matrix[0][3]; double v1 =matrix[1][3]; double v2 =matrix[2][3];
01105 
01106         double cof00 = m11*m22-m12*m21;
01107         double cof11 = m22*m00-m20*m02;
01108         double cof22 = m00*m11-m01*m10;
01109         double cof01 = m10*m22-m20*m12;
01110         double cof02 = m10*m21-m20*m11;
01111         double cof12 = m00*m21-m01*m20;
01112         double cof10 = m01*m22-m02*m21;
01113         double cof20 = m01*m12-m02*m11;
01114         double cof21 = m00*m12-m10*m02;
01115 
01116         double det = m00* cof00 + m02* cof02 -m01*cof01;
01117 
01118         matrix[0][0] =   (float)(cof00/det);
01119         matrix[0][1] = - (float)(cof10/det);
01120         matrix[0][2] =   (float)(cof20/det);
01121         matrix[1][0] = - (float)(cof01/det);
01122         matrix[1][1] =   (float)(cof11/det);
01123         matrix[1][2] = - (float)(cof21/det);
01124         matrix[2][0] =   (float)(cof02/det);
01125         matrix[2][1] = - (float)(cof12/det);
01126         matrix[2][2] =   (float)(cof22/det);
01127 
01128         matrix[0][3] =  (float)((- cof00*v0 + cof10*v1 - cof20*v2)/det);
01129         matrix[1][3] =  (float)((  cof01*v0 - cof11*v1 + cof21*v2)/det);
01130         matrix[2][3] =  (float)((- cof02*v0 + cof12*v1 - cof22*v2)/det);
01131 }
01132 
01133 Transform Transform::inverse() const {
01134         Transform t(*this);
01135         t.invert();
01136         return t;
01137 }
01138 
01139 void Transform::transpose_inplace() {
01140         float tempij;
01141         for (int i = 0; i < 3; i++) {
01142                 for (int j = 0; j < i; j++) {
01143                         if (i != j) {
01144                                 tempij= matrix[i][j];
01145                                 matrix[i][j] = matrix[j][i];
01146                                 matrix[j][i] = tempij;
01147                         }
01148                 }
01149         }
01150 }
01151 
01152 Transform Transform::transpose() const {
01153         Transform t(*this);
01154         t.transpose_inplace();
01155         return t;
01156 }
01157 
01158 
01159 Transform EMAN::operator*(const Transform & M2, const Transform & M1)     // YYY
01160 {
01161         Transform result;
01162         for (int i=0; i<3; i++) {
01163                 for (int j=0; j<4; j++) {
01164                         result[i][j] = M2[i][0] * M1[0][j] +  M2[i][1] * M1[1][j] + M2[i][2] * M1[2][j];
01165                 }
01166                 result[i][3] += M2[i][3];
01167         }
01168 
01169         return result;
01170 }
01171 
01172 void Transform::assert_valid_2d() const {
01173         int rotation_error = 0;
01174         int translation_error = 0;
01175         if (fabs(matrix[2][0]) > ERR_LIMIT) rotation_error++;
01176         if (fabs(matrix[2][1]) > ERR_LIMIT) rotation_error++;
01177         if (fabs(matrix[2][3]) > ERR_LIMIT) translation_error++;
01178         if (fabs(matrix[0][2]) > ERR_LIMIT) rotation_error++;
01179         if (fabs(matrix[1][2]) > ERR_LIMIT) rotation_error++;
01180 //      if (fabs(matrix[2][2]-1.0) >ERR_LIMIT) rotation_error++; 
01181         if ( translation_error && rotation_error ) {
01182                 throw UnexpectedBehaviorException("Error, the internal matrix contains 3D rotations and 3D translations. This object can not be considered 2D");
01183         } else if ( translation_error ) {
01184                 throw UnexpectedBehaviorException("Error, the internal matrix contains a non zero z component for a 3D translation. This object can not be considered 2D");
01185         }
01186         else if ( rotation_error ) {
01187                 throw UnexpectedBehaviorException("Error, the internal matrix contains 3D rotations and this object can not be considered 2D");
01188         }
01189 
01190 }
01191 
01192 
01193 
01194 Transform Transform::get_sym(const string & sym_name, int n) const
01195 {
01196         Symmetry3D* sym = Factory<Symmetry3D>::get(sym_name);
01197         Transform ret;
01198         ret = (*this) * sym->get_sym(n);
01199         delete sym;
01200         return ret;
01201 }
01202 
01203 int Transform::get_nsym(const string & sym_name)
01204 {
01205         Symmetry3D* sym = Factory<Symmetry3D>::get(sym_name);
01206         int nsym = sym->get_nsym();
01207         delete sym;
01208         return nsym;
01209 }
01210 
01211 //
01212 //Transform3D::Transform3D()  //    C1
01213 //{
01214 //      init();
01215 //}
01216 //
01217 //Transform3D::Transform3D( const Transform3D& rhs )
01218 //{
01219 //    for( int i=0; i < 4; ++i )
01220 //    {
01221 //        for( int j=0; j < 4; ++j )
01222 //      {
01223 //          matrix[i][j] = rhs.matrix[i][j];
01224 //      }
01225 //    }
01226 //}
01227 //
01229 //Transform3D::Transform3D(const float& az, const float& alt, const float& phi)
01230 //{
01231 //      init();
01232 //      set_rotation(az,alt,phi);
01233 //}
01234 //
01235 //
01237 //Transform3D::Transform3D(const float& az, const float& alt, const float& phi, const Vec3f& posttrans )
01238 //{
01239 //      init(); // This is called in set_rotation
01240 //      set_rotation(az,alt,phi);
01241 //      set_posttrans(posttrans);
01242 //}
01243 //
01244 //Transform3D::Transform3D(const float& m11, const float& m12, const float& m13,
01245 //                                               const float& m21, const float& m22, const float& m23,
01246 //                                               const float& m31, const float& m32, const float& m33)
01247 //{
01248 //      init();
01249 //      set_rotation(m11,m12,m13,m21,m22,m23,m31,m32,m33);
01250 //}
01251 //
01253 //Transform3D::Transform3D(EulerType euler_type, const float& a1, const float& a2, const float& a3)
01254 //{
01255 //      init();
01256 //      set_rotation(euler_type,a1,a2,a3);
01257 //}
01258 //
01259 //Transform3D::Transform3D(EulerType euler_type, const float& a1, const float& a2, const float& a3, const float& a4)
01260 //{
01261 //      init();
01262 //      set_rotation(euler_type,a1,a2,a3,a4);
01263 //}
01264 //
01265 //
01267 //Transform3D::Transform3D(EulerType euler_type, const Dict& rotation)  //YYY
01268 //{
01269 //      init();
01270 //      set_rotation(euler_type,rotation);
01271 //}
01272 //
01273 //
01275 //
01276 //Transform3D::Transform3D(  const Vec3f& pretrans,  const float& az, const float& alt, const float& phi, const Vec3f& posttrans )  //YYY  by default EMAN
01277 //{
01278 //      init();
01279 //      set_pretrans(pretrans);
01280 //      set_rotation(az,alt,phi);
01281 //      set_posttrans(posttrans);
01282 //}
01283 //
01284 //
01285 //
01286 //
01287 //Transform3D::~Transform3D()
01288 //{
01289 //}
01290 //
01291 //
01292 //
01293 //void Transform3D::to_identity()
01294 //{
01298 //
01299 //      for(int i=0; i<4; ++i) {
01300 //              for(int j=0; j<4; ++j) {
01301 //                      if(i==j) {
01302 //                              matrix[i][j] = 1;
01303 //                      }
01304 //                      else {
01305 //                              matrix[i][j] = 0;
01306 //                      }
01307 //              }
01308 //      }
01309 //      post_x_mirror = false;
01310 //      set_center(Vec3f(0,0,0));
01311 //}
01312 //
01313 //
01314 //
01315 //bool Transform3D::is_identity()  // YYY
01316 //{
01317 //      for (int i=0; i<4; i++) {
01318 //              for (int j=0; j<4; j++) {
01319 //                      if (i==j && matrix[i][j]!=1.0) return 0;
01320 //                      if (i!=j && matrix[i][j]!=0.0) return 0;
01321 //              }
01322 //      }
01323 //      return 1;
01324 //}
01325 //
01326 //
01327 //void Transform3D::set_center(const Vec3f & center) //YYN
01328 //{
01329 //      set_pretrans( Vec3f(0,0,0)-center);
01330 //      for (int i = 0; i < 3; i++) {
01331 //              matrix[i][3]=center[i];
01332 //      }
01333 //}
01334 //
01337 //void Transform3D::init()  // M1
01338 //{
01339 //      to_identity();
01340 //}
01341 //
01343 //
01344 //void Transform3D::set_pretrans(const float& dx, const float& dy, const float& dz) // YYY
01345 //{    set_pretrans( Vec3f(dx,dy,dz)); }
01346 //
01347 //
01348 //void Transform3D::set_pretrans(const float& dx, const float& dy) // YYY
01349 //{    set_pretrans( Vec3f(dx,dy,0)); }
01350 //
01351 //void Transform3D::set_pretrans(const Vec2f& pretrans) // YYY
01352 //{    set_pretrans( Vec3f(pretrans[0],pretrans[1],0)); }
01353 //
01354 //void Transform3D::set_pretrans(const Vec3f & preT)  // flag=1 means keep the old value of total trans
01355 //{
01356 //              int flag=0;
01357 //
01360 //    if (flag==0){
01361 //              matrix[0][3] = matrix[3][0] + matrix[0][0]*preT[0] + matrix[0][1]*preT[1] + matrix[0][2]*preT[2]  ;
01362 //              matrix[1][3] = matrix[3][1] + matrix[1][0]*preT[0] + matrix[1][1]*preT[1] + matrix[1][2]*preT[2]  ;
01363 //              matrix[2][3] = matrix[3][2] + matrix[2][0]*preT[0] + matrix[2][1]*preT[1] + matrix[2][2]*preT[2]  ;
01364 //      }
01366 //    if (flag==1){
01367 //              matrix[3][0] = matrix[0][3] - (matrix[0][0]*preT[0] + matrix[0][1]*preT[1] + matrix[0][2]*preT[2])  ;
01368 //              matrix[3][1] = matrix[1][3] - (matrix[1][0]*preT[0] + matrix[1][1]*preT[1] + matrix[1][2]*preT[2])  ;
01369 //              matrix[3][2] = matrix[2][3] - (matrix[2][0]*preT[0] + matrix[2][1]*preT[1] + matrix[2][2]*preT[2])  ;
01370 //      }
01371 //}
01372 //
01373 //
01374 //void Transform3D::set_posttrans(const float& dx, const float& dy, const float& dz) // YYY
01375 //{    set_posttrans( Vec3f(dx,dy,dz)); }
01376 //
01377 //
01378 //void Transform3D::set_posttrans(const float& dx, const float& dy) // YYY
01379 //{    set_posttrans( Vec3f(dx,dy,0)); }
01380 //
01381 //void Transform3D::set_posttrans(const Vec2f& posttrans) // YYY
01382 //{    set_pretrans( Vec3f(posttrans[0],posttrans[1],0)); }
01383 //
01384 //void Transform3D::set_posttrans(const Vec3f & posttrans) // flag=1 means keep the old value of total trans
01385 //{
01386 //      int flag=0;
01387 //    Vec3f preT   = get_pretrans(0) ;
01388 //      for (int i = 0; i < 3; i++) {
01389 //              matrix[3][i] = posttrans[i];
01390 //      }
01393 //      if (flag==0) {
01394 //              matrix[0][3] = matrix[3][0] + matrix[0][0]*preT[0] + matrix[0][1]*preT[1] + matrix[0][2]*preT[2]  ;
01395 //              matrix[1][3] = matrix[3][1] + matrix[1][0]*preT[0] + matrix[1][1]*preT[1] + matrix[1][2]*preT[2]  ;
01396 //              matrix[2][3] = matrix[3][2] + matrix[2][0]*preT[0] + matrix[2][1]*preT[1] + matrix[2][2]*preT[2]  ;
01397 //      }
01399 //      if (flag==1) { // Don't do anything
01400 //      }
01401 //}
01402 //
01403 //
01404 //
01405 //
01406 //void Transform3D::apply_scale(const float& scale)    // YYY
01407 //{
01408 //      for (int i = 0; i < 3; i++) {
01409 //              for (int j = 0; j < 4; j++) {
01410 //                      matrix[i][j] *= scale;
01411 //              }
01412 //      }
01413 //      for (int j = 0; j < 3; j++) {
01414 //              matrix[3][j] *= scale;
01415 //      }
01416 //}
01417 //
01418 //void Transform3D::orthogonalize()  // YYY
01419 //{
01420 //      //EulerType EMAN;
01421 //      float scale = get_scale() ;
01422 //      float inverseScale= 1/scale ;
01423 //      apply_scale(inverseScale);
01426 //}
01427 //
01428 //
01429 //void Transform3D::transpose()  // YYY
01430 //{
01431 //      float tempij;
01432 //      for (int i = 0; i < 3; i++) {
01433 //              for (int j = 0; j < i; j++) {
01434 //                      tempij= matrix[i][j];
01435 //                      matrix[i][j] = matrix[j][i];
01436 //                      matrix[j][i] = tempij;
01437 //              }
01438 //      }
01439 //}
01440 //
01441 //void Transform3D::set_scale(const float& scale)    // YYY
01442 //{
01443 //      float OldScale= get_scale();
01444 //      float Scale2Apply = scale/OldScale;
01445 //      apply_scale(Scale2Apply);
01446 //}
01447 //
01448 //float Transform3D::get_mag() const //
01449 //{
01450 //      EulerType eulertype= SPIN ;
01451 //      Dict AA= get_rotation(eulertype);
01452 //      return AA["Omega"];
01453 //}
01454 //
01455 //Vec3f Transform3D::get_finger() const //
01456 //{
01457 //      EulerType eulertype= SPIN ;
01458 //      Dict AA= get_rotation(eulertype);
01459 //      return Vec3f(AA["n1"],AA["n2"],AA["n3"]);
01460 //}
01461 //
01462 //Vec3f Transform3D::get_posttrans(int flag) const    //
01463 //{
01464 //      if (flag==0){
01465 //              return Vec3f(matrix[3][0], matrix[3][1], matrix[3][2]);
01466 //      }
01467 //      // otherwise as if all the translation was post
01468 //      return Vec3f(matrix[0][3], matrix[1][3], matrix[2][3]);
01469 //}
01470 //
01471 //Vec3f Transform3D::get_total_posttrans() const {
01472 //      return get_posttrans(1);
01473 //}
01474 //
01475 //Vec3f Transform3D::get_total_pretrans() const {
01476 //      return get_pretrans(1);
01477 //}
01478 //
01479 //
01480 //Vec3f Transform3D::get_pretrans(int flag) const    // Fix Me
01481 //{
01483 //
01484 //      Vec3f pretrans;
01485 //      Vec3f posttrans(matrix[3][0], matrix[3][1], matrix[3][2]);
01486 //      Vec3f tottrans(matrix[0][3], matrix[1][3], matrix[2][3]);
01487 //      Vec3f totminuspost;
01488 //
01489 //      totminuspost = tottrans;
01490 //      if (flag==0) {
01491 //              totminuspost = tottrans-posttrans;
01492 //      }
01493 //
01494 //      Transform3D Rinv = inverse();
01495 //      for (int i=0; i<3; i++) {
01496 //                float ptnow=0;
01497 //              for (int j=0; j<3; j++) {
01498 //                      ptnow +=   Rinv.matrix[i][j]* totminuspost[j] ;
01499 //              }
01500 //              pretrans.set_value_at(i,ptnow) ;  //
01501 //      }
01502 //      return pretrans;
01503 //}
01504 //
01505 //
01506 // Vec3f Transform3D::get_center() const  // YYY
01507 // {
01508 //      return Vec3f();
01509 // }
01510 //
01511 //
01512 //
01513 //Vec3f Transform3D::get_matrix3_col(int i) const     // YYY
01514 //{
01515 //      return Vec3f(matrix[0][i], matrix[1][i], matrix[2][i]);
01516 //}
01517 //
01518 //
01519 //Vec3f Transform3D::get_matrix3_row(int i) const     // YYY
01520 //{
01521 //      return Vec3f(matrix[i][0], matrix[i][1], matrix[i][2]);
01522 //}
01523 //
01524 //Vec3f Transform3D::transform(const Vec3f & v3f) const     // YYY
01525 //{
01527 //      float x = matrix[0][0] * v3f[0] + matrix[0][1] * v3f[1] + matrix[0][2] * v3f[2] + matrix[0][3] ;
01528 //      float y = matrix[1][0] * v3f[0] + matrix[1][1] * v3f[1] + matrix[1][2] * v3f[2] + matrix[1][3] ;
01529 //      float z = matrix[2][0] * v3f[0] + matrix[2][1] * v3f[1] + matrix[2][2] * v3f[2] + matrix[2][3] ;
01530 //      return Vec3f(x, y, z);
01531 //}
01532 //
01533 //
01534 //Vec3f Transform3D::rotate(const Vec3f & v3f) const     // YYY
01535 //{
01537 //      float x = matrix[0][0] * v3f[0] + matrix[0][1] * v3f[1] + matrix[0][2] * v3f[2]  ;
01538 //      float y = matrix[1][0] * v3f[0] + matrix[1][1] * v3f[1] + matrix[1][2] * v3f[2]  ;
01539 //      float z = matrix[2][0] * v3f[0] + matrix[2][1] * v3f[1] + matrix[2][2] * v3f[2]  ;
01540 //      return Vec3f(x, y, z);
01541 //}
01542 //
01543 //
01544 //Transform3D EMAN::operator*(const Transform3D & M2, const Transform3D & M1)     // YYY
01545 //{
01548 //      Transform3D resultant;
01549 //      for (int i=0; i<3; i++) {
01550 //              for (int j=0; j<4; j++) {
01551 //                      resultant[i][j] = M2[i][0] * M1[0][j] +  M2[i][1] * M1[1][j] + M2[i][2] * M1[2][j];
01552 //              }
01553 //              resultant[i][3] += M2[i][3];  // add on the new translation (not included above)
01554 //      }
01555 //
01556 //      for (int j=0; j<3; j++) {
01557 //              resultant[3][j] = M2[3][j];
01558 //      }
01559 //
01560 //      return resultant; // This will have the post_trans of M2
01561 //}
01562 
01563 /*             Here starts the pure rotation stuff */
01564 
01634 //
01635 //void Transform3D::set_rotation(const float& az, const float& alt, const float& phi )
01636 //{
01637 //      EulerType euler_type=EMAN;
01638 //      Dict rot;
01639 //      rot["az"]  = az;
01640 //      rot["alt"] = alt;
01641 //      rot["phi"] = phi;
01642 //      set_rotation(euler_type, rot);
01643 //}
01644 //
01646 //void Transform3D::set_rotation(EulerType euler_type, const float& a1, const float& a2, const float& a3)
01647 //{
01648 //      init();
01649 //      Dict rot;
01650 //      switch(euler_type) {
01651 //              case EMAN:
01652 //                      rot["az"]  = a1;
01653 //                      rot["alt"] = a2;
01654 //                      rot["phi"] = a3;
01655 //                      break;
01656 //              case SPIDER:
01657 //                      rot["phi"]   = a1;
01658 //                      rot["theta"] = a2;
01659 //                      rot["psi"]   = a3;
01660 //                      break;
01661 //              case IMAGIC:
01662 //                      rot["alpha"]   = a1;
01663 //                      rot["beta"] = a2;
01664 //                      rot["gamma"]   = a3;
01665 //                      break;
01666 //              case MRC:
01667 //                      rot["phi"]   = a1;
01668 //                      rot["theta"] = a2;
01669 //                      rot["omega"]   = a3;
01670 //                      break;
01671 //              case XYZ:
01672 //                      rot["xtilt"]   = a1;
01673 //                      rot["ytilt"] = a2;
01674 //                      rot["ztilt"]   = a3;
01675 //                      break;
01676 //              default:
01677 //              throw InvalidValueException(euler_type, "cannot instantiate this Euler Type");
01678 //      }  // ends switch euler_type
01679 //      set_rotation(euler_type, rot);
01680 //}
01681 //
01683 //void Transform3D::set_rotation(EulerType euler_type, const float& a1, const float& a2, const float& a3, const float& a4)
01684 //{
01685 //      init();
01686 //      Dict rot;
01687 //      switch(euler_type) {
01688 //              case QUATERNION:
01689 //                      rot["e0"]  = a1;
01690 //                      rot["e1"] = a2;
01691 //                      rot["e2"] = a3;
01692 //                      rot["e3"] = a4;
01693 //                      break;
01694 //              case SGIROT:
01695 //                      rot["q"]  = a1;
01696 //                      rot["n1"] = a2;
01697 //                      rot["n2"] = a3;
01698 //                      rot["n3"] = a4;
01699 //              case SPIN:
01700 //                      rot["Omega"]  = a1;
01701 //                      rot["n1"] = a2;
01702 //                      rot["n2"] = a3;
01703 //                      rot["n3"] = a4;
01704 //                      break;
01705 //              default:
01706 //                      throw InvalidValueException(euler_type, "cannot instantiate this Euler Type");
01707 //      }  // ends switch euler_type
01708 //      set_rotation(euler_type, rot);
01709 //}
01710 //
01711 //void Transform3D::set_rotation(EulerType euler_type, const Dict& rotation)
01712 //{
01713 //      double e0  = 0; double e1=0; double e2=0; double e3=0;
01714 //      double Omega=0;
01715 //      double az  = 0;
01716 //      double alt = 0;
01717 //      double phi = 0;
01718 //      double cxtilt = 0;
01719 //      double sxtilt = 0;
01720 //      double cytilt = 0;
01721 //      double sytilt = 0;
01722 //      bool is_quaternion = 0;
01723 //      bool is_matrix = 0;
01724 //
01725 //      switch(euler_type) {
01726 //      case EMAN:
01727 //              az  = (double)rotation["az"] ;
01728 //              alt = (double)rotation["alt"]  ;
01729 //              phi = (double)rotation["phi"] ;
01730 //              break;
01731 //      case IMAGIC:
01732 //              az  = (double)rotation["alpha"] ;
01733 //              alt = (double)rotation["beta"]  ;
01734 //              phi = (double)rotation["gamma"] ;
01735 //              break;
01736 //
01737 //      case SPIDER:
01738 //              az =  (double)rotation["phi"]    + 90.0;
01739 //              alt = (double)rotation["theta"] ;
01740 //              phi = (double)rotation["psi"]    - 90.0;
01741 //              break;
01742 //
01743 //      case XYZ:
01744 //              cxtilt = cos( (M_PI/180.0f)*(double)rotation["xtilt"]);
01745 //              sxtilt = sin( (M_PI/180.0f)*(double)rotation["xtilt"]);
01746 //              cytilt = cos( (M_PI/180.0f)*(double)rotation["ytilt"]);
01747 //              sytilt = sin( (M_PI/180.0f)*(double)rotation["ytilt"]);
01748 //              az =  (180.0f/M_PI)*atan2(-cytilt*sxtilt,sytilt)   + 90.0f ;
01749 //              alt = (180.0f/M_PI)*acos(cytilt*cxtilt)  ;
01750 //              phi = (double)rotation["ztilt"] +(180.0f/M_PI)*atan2(sxtilt,cxtilt*sytilt)   - 90.0f ;
01751 //              break;
01752 //
01753 //      case MRC:
01754 //              az  = (double)rotation["phi"]   + 90.0f ;
01755 //              alt = (double)rotation["theta"] ;
01756 //              phi = (double)rotation["omega"] - 90.0f ;
01757 //              break;
01758 //
01759 //      case QUATERNION:
01760 //              is_quaternion = 1;
01761 //              e0 = (double)rotation["e0"];
01762 //              e1 = (double)rotation["e1"];
01763 //              e2 = (double)rotation["e2"];
01764 //              e3 = (double)rotation["e3"];
01765 //              break;
01766 //
01767 //      case SPIN:
01768 //              is_quaternion = 1;
01769 //              Omega = (double)rotation["Omega"];
01770 //              e0 = cos(Omega*M_PI/360.0f);
01771 //              e1 = sin(Omega*M_PI/360.0f)* (double)rotation["n1"];
01772 //              e2 = sin(Omega*M_PI/360.0f)* (double)rotation["n2"];
01773 //              e3 = sin(Omega*M_PI/360.0f)* (double)rotation["n3"];
01774 //              break;
01775 //
01776 //      case SGIROT:
01777 //              is_quaternion = 1;
01778 //              Omega = (double)rotation["q"]  ;
01779 //              e0 = cos(Omega*M_PI/360.0f);
01780 //              e1 = sin(Omega*M_PI/360.0f)* (double)rotation["n1"];
01781 //              e2 = sin(Omega*M_PI/360.0f)* (double)rotation["n2"];
01782 //              e3 = sin(Omega*M_PI/360.0f)* (double)rotation["n3"];
01783 //              break;
01784 //
01785 //      case MATRIX:
01786 //              is_matrix = 1;
01787 //              matrix[0][0] = (float)rotation["m11"]  ;
01788 //              matrix[0][1] = (float)rotation["m12"]  ;
01789 //              matrix[0][2] = (float)rotation["m13"]  ;
01790 //              matrix[1][0] = (float)rotation["m21"]  ;
01791 //              matrix[1][1] = (float)rotation["m22"]  ;
01792 //              matrix[1][2] = (float)rotation["m23"]  ;
01793 //              matrix[2][0] = (float)rotation["m31"]  ;
01794 //              matrix[2][1] = (float)rotation["m32"]  ;
01795 //              matrix[2][2] = (float)rotation["m33"]  ;
01796 //              break;
01797 //
01798 //      default:
01799 //              throw InvalidValueException(euler_type, "unknown Euler Type");
01800 //      }  // ends switch euler_type
01801 //
01802 //
01803 //      Vec3f postT  = get_posttrans( ) ;
01804 //      Vec3f preT   = get_pretrans( ) ;
01805 //
01806 //
01807 //      double azp  = fmod(az,360.0)*M_PI/180.0;
01808 //      double altp  = alt*M_PI/180.0;
01809 //      double phip = fmod(phi,360.0)*M_PI/180.0;
01810 //
01811 //      if (!is_quaternion && !is_matrix) {
01812 //              matrix[0][0] =  (float)(cos(phip)*cos(azp) - cos(altp)*sin(azp)*sin(phip));
01813 //              matrix[0][1] =  (float)(cos(phip)*sin(azp) + cos(altp)*cos(azp)*sin(phip));
01814 //              matrix[0][2] =  (float)(sin(altp)*sin(phip));
01815 //              matrix[1][0] =  (float)(-sin(phip)*cos(azp) - cos(altp)*sin(azp)*cos(phip));
01816 //              matrix[1][1] =  (float)(-sin(phip)*sin(azp) + cos(altp)*cos(azp)*cos(phip));
01817 //              matrix[1][2] =  (float)(sin(altp)*cos(phip));
01818 //              matrix[2][0] =  (float)(sin(altp)*sin(azp));
01819 //              matrix[2][1] =  (float)(-sin(altp)*cos(azp));
01820 //              matrix[2][2] =  (float)cos(altp);
01821 //      }
01822 //      if (is_quaternion){
01823 //              matrix[0][0] = (float)(e0 * e0 + e1 * e1 - e2 * e2 - e3 * e3);
01824 //              matrix[0][1] = (float)(2.0f * (e1 * e2 + e0 * e3));
01825 //              matrix[0][2] = (float)(2.0f * (e1 * e3 - e0 * e2));
01826 //              matrix[1][0] = (float)(2.0f * (e2 * e1 - e0 * e3));
01827 //              matrix[1][1] = (float)(e0 * e0 - e1 * e1 + e2 * e2 - e3 * e3);
01828 //              matrix[1][2] = (float)(2.0f * (e2 * e3 + e0 * e1));
01829 //              matrix[2][0] = (float)(2.0f * (e3 * e1 + e0 * e2));
01830 //              matrix[2][1] = (float)(2.0f * (e3 * e2 - e0 * e1));
01831 //              matrix[2][2] = (float)(e0 * e0 - e1 * e1 - e2 * e2 + e3 * e3);
01832 //              // keep in mind matrix[0][2] is M13 gives an e0 e2 piece, etc
01833 //      }
01834 //      // Now do post and pretrans: vfinal = vpost + R vpre;
01835 //
01836 //      matrix[0][3] = postT[0] + matrix[0][0]*preT[0] + matrix[0][1]*preT[1] + matrix[0][2]*preT[2]  ;
01837 //      matrix[1][3] = postT[1] + matrix[1][0]*preT[0] + matrix[1][1]*preT[1] + matrix[1][2]*preT[2]  ;
01838 //      matrix[2][3] = postT[2] + matrix[2][0]*preT[0] + matrix[2][1]*preT[1] + matrix[2][2]*preT[2]  ;
01839 //}
01840 //
01841 //
01842 //void Transform3D::set_rotation(const float& m11, const float& m12, const float& m13,
01843 //                                                         const float& m21, const float& m22, const float& m23,
01844 //                const float& m31, const float& m32, const float& m33)
01845 //{
01846 //      EulerType euler_type = MATRIX;
01847 //      Dict rot;
01848 //      rot["m11"]  = m11;
01849 //      rot["m12"]  = m12;
01850 //      rot["m13"]  = m13;
01851 //      rot["m21"]  = m21;
01852 //      rot["m22"]  = m22;
01853 //      rot["m23"]  = m23;
01854 //      rot["m31"]  = m31;
01855 //      rot["m32"]  = m32;
01856 //      rot["m33"]  = m33;
01857 //      set_rotation(euler_type, rot);  // Or should it be &rot ?
01858 //}
01859 //
01860 //void Transform3D::set_rotation(const Vec3f & eahat, const Vec3f & ebhat,
01861 //                                    const Vec3f & eAhat, const Vec3f & eBhat)
01862 //{// this rotation rotates unit vectors a,b into A,B;
01864 //      Vec3f eahatcp(eahat);
01865 //      Vec3f ebhatcp(ebhat);
01866 //      Vec3f eAhatcp(eAhat);
01867 //      Vec3f eBhatcp(eBhat);
01868 //
01869 //      eahatcp.normalize();
01870 //      ebhatcp.normalize();
01871 //      eAhatcp.normalize();
01872 //      eBhatcp.normalize();
01873 //
01874 //      Vec3f aMinusA(eahatcp);
01875 //      aMinusA  -= eAhatcp;
01876 //      Vec3f bMinusB(ebhatcp);
01877 //      bMinusB  -= eBhatcp;
01878 //
01879 //
01880 //      Vec3f  nhat;
01881 //      float aAlength = aMinusA.length();
01882 //      float bBlength = bMinusB.length();
01883 //      if (aAlength==0){
01884 //              nhat=eahatcp;
01885 //      }else if (bBlength==0){
01886 //              nhat=ebhatcp;
01887 //      }else{
01888 //              nhat= aMinusA.cross(bMinusB);
01889 //              nhat.normalize();
01890 //      }
01891 //
01893 //
01894 //      Vec3f neahat  = eahatcp.cross(nhat);
01895 //      Vec3f nebhat  = ebhatcp.cross(nhat);
01896 //      Vec3f neAhat  = eAhatcp.cross(nhat);
01897 //      Vec3f neBhat  = eBhatcp.cross(nhat);
01898 //
01899 //      double cosOmegaA = (neahat.dot(neAhat))  / (neahat.dot(neahat));
01901 //      double sinOmegaA = (neahat.dot(eAhatcp)) / (neahat.dot(neahat));
01903 //
01904 //      double OmegaA = atan2(sinOmegaA,cosOmegaA);
01906 //
01907 //      EulerType euler_type=SPIN;
01908 //      Dict rotation;
01909 //      rotation["n1"]= nhat[0];
01910 //      rotation["n2"]= nhat[1];
01911 //      rotation["n3"]= nhat[2];
01912 //      rotation["Omega"] = (float)(OmegaA*180.0/M_PI);
01913 //      set_rotation(euler_type,  rotation);
01914 //}
01915 //
01916 //
01917 //float Transform3D::get_scale() const     // YYY
01918 //{
01919 //      // Assumes uniform scaling, calculation uses Z only.
01920 //      float scale =0;
01921 //      for (int i=0; i<3; i++) {
01922 //              for (int j=0; j<3; j++) {
01923 //                      scale = scale + matrix[i][j]*matrix[i][j];
01924 //              }
01925 //      }
01926 //
01927 //      return sqrt(scale/3);
01928 //}
01929 //
01930 //
01931 //
01932 //Dict Transform3D::get_rotation(EulerType euler_type) const
01933 //{
01934 //      Dict result;
01935 //
01936 //      double max = 1 - ERR_LIMIT;
01937 //      double sca=get_scale();
01938 //      double cosalt=matrix[2][2]/sca;
01939 //
01940 //
01941 //      double az=0;
01942 //      double alt = 0;
01943 //      double phi=0;
01944 //      double phiS = 0; // like az     (but in SPIDER ZXZ)
01945 //      double psiS =0;  // like phi  (but in SPIDER ZYZ)
01946 //
01947 //
01949 //
01950 //      if (cosalt > max) {  // that is, alt close to 0
01951 //              alt = 0;
01952 //              az=0;
01953 //              phi = (double)EMConsts::rad2deg * atan2(matrix[0][1], matrix[0][0]);
01954 //      }
01955 //      else if (cosalt < -max) { // alt close to pi
01956 //              alt = 180;
01957 //              az=0;
01958 //              phi=360.0f-(double)EMConsts::rad2deg * atan2(matrix[0][1], matrix[0][0]);
01959 //      }
01960 //      else {
01961 //              alt = (double)EMConsts::rad2deg * acos(cosalt);
01962 //              az  = 360.0f+(double)EMConsts::rad2deg * atan2(matrix[2][0], -matrix[2][1]);
01963 //              phi = 360.0f+(double)EMConsts::rad2deg * atan2(matrix[0][2], matrix[1][2]);
01964 //      }
01965 //      az =fmod(az+180.0,360.0)-180.0;
01966 //      phi=fmod(phi+180.0,360.0)-180.0;
01967 //
01969 //      if (fabs(cosalt) > max) {  // that is, alt close to 0
01970 //              phiS=0;
01971 //              psiS = az+phi;
01972 //      }
01973 //      else {
01974 //              phiS = az   - 90.0;
01975 //              psiS = phi  + 90.0;
01976 //      }
01977 //      phiS = fmod((phiS   + 360.0 ), 360.0) ;
01978 //      psiS = fmod((psiS   + 360.0 ), 360.0) ;
01979 //
01981 //
01982 //      double nphi = (az-phi)/2.0;
01983 //    // The next is also e0
01984 //      double cosOover2 = (cos((az+phi)*M_PI/360) * cos(alt*M_PI/360)) ;
01985 //      double sinOover2 = sqrt(1 -cosOover2*cosOover2);
01986 //      double cosnTheta = sin((az+phi)*M_PI/360) * cos(alt*M_PI/360) / sqrt(1-cosOover2*cosOover2) ;
01987 //      double sinnTheta = sqrt(1-cosnTheta*cosnTheta);
01988 //      double n1 = sinnTheta*cos(nphi*M_PI/180);
01989 //      double n2 = sinnTheta*sin(nphi*M_PI/180);
01990 //      double n3 = cosnTheta;
01991 //      double xtilt = 0;
01992 //      double ytilt = 0;
01993 //      double ztilt = 0;
01994 //
01995 //
01996 //      if (cosOover2<0) {
01997 //              cosOover2*=-1; n1 *=-1; n2*=-1; n3*=-1;
01998 //      }
01999 //
02000 //
02001 //      switch (euler_type) {
02002 //      case EMAN:
02003 //              result["az"]  = az;
02004 //              result["alt"] = alt;
02005 //              result["phi"] = phi;
02006 //              break;
02007 //
02008 //      case IMAGIC:
02009 //              result["alpha"] = az;
02010 //              result["beta"] = alt;
02011 //              result["gamma"] = phi;
02012 //              break;
02013 //
02014 //      case SPIDER:
02015 //              result["phi"]   = phiS;  // The first Euler like az
02016 //              result["theta"] = alt;
02017 //              result["psi"]   = psiS;
02018 //              break;
02019 //
02020 //      case MRC:
02021 //              result["phi"]   = phiS;
02022 //              result["theta"] = alt;
02023 //              result["omega"] = psiS;
02024 //              break;
02025 //
02026 //      case XYZ:
02027 //              xtilt = atan2(-sin((M_PI/180.0f)*phiS)*sin((M_PI/180.0f)*alt),cos((M_PI/180.0f)*alt));
02028 //              ytilt = asin(  cos((M_PI/180.0f)*phiS)*sin((M_PI/180.0f)*alt));
02029 //              ztilt = psiS*M_PI/180.0f - atan2(sin(xtilt), cos(xtilt) *sin(ytilt));
02030 //
02031 //              xtilt=fmod(xtilt*180/M_PI+540.0,360.0) -180.0;
02032 //              ztilt=fmod(ztilt*180/M_PI+540.0,360.0) -180.0;
02033 //
02034 //              result["xtilt"]  = xtilt;
02035 //              result["ytilt"]  = ytilt*180/M_PI;
02036 //              result["ztilt"]  = ztilt;
02037 //              break;
02038 //
02039 //      case QUATERNION:
02040 //              result["e0"] = cosOover2 ;
02041 //              result["e1"] = sinOover2 * n1 ;
02042 //              result["e2"] = sinOover2 * n2;
02043 //              result["e3"] = sinOover2 * n3;
02044 //              break;
02045 //
02046 //      case SPIN:
02047 //              result["Omega"] =360.0f* acos(cosOover2)/ M_PI ;
02048 //              result["n1"] = n1;
02049 //              result["n2"] = n2;
02050 //              result["n3"] = n3;
02051 //              break;
02052 //
02053 //      case SGIROT:
02054 //              result["q"] = 360.0f*acos(cosOover2)/M_PI ;
02055 //              result["n1"] = n1;
02056 //              result["n2"] = n2;
02057 //              result["n3"] = n3;
02058 //              break;
02059 //
02060 //      case MATRIX:
02061 //              result["m11"] = matrix[0][0] ;
02062 //              result["m12"] = matrix[0][1] ;
02063 //              result["m13"] = matrix[0][2] ;
02064 //              result["m21"] = matrix[1][0] ;
02065 //              result["m22"] = matrix[1][1] ;
02066 //              result["m23"] = matrix[1][2] ;
02067 //              result["m31"] = matrix[2][0] ;
02068 //              result["m32"] = matrix[2][1] ;
02069 //              result["m33"] = matrix[2][2] ;
02070 //              break;
02071 //
02072 //      default:
02073 //              throw InvalidValueException(euler_type, "unknown Euler Type");
02074 //      }
02075 //
02076 //      return result;
02077 //}
02078 //
02079 //Transform3D Transform3D::inverseUsingAngs() const    //   YYN need to test it for sure
02080 //{
02081 //      // First Find the scale
02082 //      EulerType eE=EMAN;
02083 //
02084 //
02085 //      float scale   = get_scale();
02086 //      Vec3f preT   = get_pretrans( ) ;
02087 //      Vec3f postT   = get_posttrans( ) ;
02088 //      Dict angs     = get_rotation(eE);
02089 //      Dict invAngs  ;
02090 //
02091 //      invAngs["phi"]   = 180.0f - (float) angs["az"] ;
02092 //      invAngs["az"]    = 180.0f - (float) angs["phi"] ;
02093 //      invAngs["alt"]   = angs["alt"] ;
02094 //
02101 //
02102 //      float inverseScale= 1/scale ;
02103 //
02104 //      Transform3D invM;
02105 //
02106 //      invM.set_rotation(EMAN, invAngs);
02107 //      invM.apply_scale(inverseScale);
02108 //      invM.set_pretrans(-postT );
02109 //      invM.set_posttrans(-preT );
02110 //
02111 //
02112 //      return invM;
02113 //
02114 //}
02115 //
02116 //Transform3D Transform3D::inverse() const    //   YYN need to test it for sure
02117 //{
02118 //      // This assumes the matrix is 4 by 4 and the last row reads [0 0 0 1]
02119 //
02120 //      double m00 = matrix[0][0]; double m01=matrix[0][1]; double m02=matrix[0][2];
02121 //      double m10 = matrix[1][0]; double m11=matrix[1][1]; double m12=matrix[1][2];
02122 //      double m20 = matrix[2][0]; double m21=matrix[2][1]; double m22=matrix[2][2];
02123 //      double v0  = matrix[0][3]; double v1 =matrix[1][3]; double v2 =matrix[2][3];
02124 //
02125 //    double cof00 = m11*m22-m12*m21;
02126 //    double cof11 = m22*m00-m20*m02;
02127 //    double cof22 = m00*m11-m01*m10;
02128 //    double cof01 = m10*m22-m20*m12;
02129 //    double cof02 = m10*m21-m20*m11;
02130 //    double cof12 = m00*m21-m01*m20;
02131 //    double cof10 = m01*m22-m02*m21;
02132 //    double cof20 = m01*m12-m02*m11;
02133 //    double cof21 = m00*m12-m10*m02;
02134 //
02135 //    double Det = m00* cof00 + m02* cof02 -m01*cof01;
02136 //
02137 //    Transform3D invM;
02138 //
02139 //    invM.matrix[0][0] =  (float)(cof00/Det);
02140 //    invM.matrix[0][1] =  (float)(-cof10/Det);
02141 //    invM.matrix[0][2] =  (float)(cof20/Det);
02142 //    invM.matrix[1][0] =  (float)(-cof01/Det);
02143 //    invM.matrix[1][1] =  (float)(cof11/Det);
02144 //    invM.matrix[1][2] =  (float)(-cof21/Det);
02145 //    invM.matrix[2][0] =  (float)(cof02/Det);
02146 //    invM.matrix[2][1] =  (float)(-cof12/Det);
02147 //    invM.matrix[2][2] =  (float)(cof22/Det);
02148 //
02149 //    invM.matrix[0][3] =  (float)((-cof00*v0 + cof10*v1 - cof20*v2)/Det);
02150 //    invM.matrix[1][3] =  (float)(( cof01*v0 - cof11*v1 + cof21*v2)/Det);
02151 //    invM.matrix[2][3] =  (float)((-cof02*v0 + cof12*v1 - cof22*v2)/Det);
02152 //
02153 //      Vec3f postT   = get_posttrans( ) ;
02154 //      Vec3f invMpre   = - postT;
02155 //      Vec3f invMpost   ;
02156 //      for ( int i = 0; i < 3; i++) {
02157 //              invMpost[i] = invM.matrix[i][3];
02158 //              for ( int j = 0; j < 3; j++) {
02159 //                      invMpost[i] += - invM.matrix[i][j]*invMpre[j];
02160 //              }
02161 //              invM.matrix[3][i] = invMpost[i];
02162 //      }
02163 //
02164 //      return invM;
02165 //}
02166 //
02167 //
02168 //
02170 //
02171 //Transform3D Transform3D::get_sym(const string & symname, int n) const
02172 //{
02173 //      int nsym = get_nsym(symname);
02174 //
02177 //
02178 //      // see www.math.utah.edu/~alfeld/math/polyhedra/polyhedra.html for pictures
02179 //      // By default we will put largest symmetry along z-axis.
02180 //
02181 //      // Each Platonic Solid has 2E symmetry elements.
02182 //
02183 //
02184 //      // An icosahedron has   m=5, n=3, F=20 E=30=nF/2, V=12=nF/m,since vertices shared by 5 triangles;
02185 //      // It is composed of 20 triangles. E=3*20/2;
02186 //
02187 //
02188 //      // An dodecahedron has m=3, n=5   F=12 E=30  V=20
02189 //      // It is composed of 12 pentagons. E=5*12/2;   V= 5*12/3, since vertices shared by 3 pentagons;
02190 //
02191 //
02192 //
02193 //    // The ICOS symmetry group has the face along z-axis
02194 //
02195 //      float lvl0=0;                             //  there is one pentagon on top; five-fold along z
02196 //      float lvl1= 63.4349f; // that is atan(2)  // there are 5 pentagons with centers at this height (angle)
02197 //      float lvl2=116.5651f; //that is 180-lvl1  // there are 5 pentagons with centers at this height (angle)
02198 //      float lvl3=180.f;                           // there is one pentagon on the bottom
02199 //             // Notice that 63.439 is the angle between two faces of the dual object
02200 //
02201 //      static double ICOS[180] = { // This is with a pentagon normal to z
02202 //                0,lvl0,0,    0,lvl0,288,   0,lvl0,216,   0,lvl0,144,  0,lvl0,72,
02203 //                0,lvl1,36,   0,lvl1,324,   0,lvl1,252,   0,lvl1,180,  0,lvl1,108,
02204 //               72,lvl1,36,  72,lvl1,324,  72,lvl1,252,  72,lvl1,180,  72,lvl1,108,
02205 //              144,lvl1,36, 144,lvl1,324, 144,lvl1,252, 144,lvl1,180, 144,lvl1,108,
02206 //              216,lvl1,36, 216,lvl1,324, 216,lvl1,252, 216,lvl1,180, 216,lvl1,108,
02207 //              288,lvl1,36, 288,lvl1,324, 288,lvl1,252, 288,lvl1,180, 288,lvl1,108,
02208 //               36,lvl2,0,   36,lvl2,288,  36,lvl2,216,  36,lvl2,144,  36,lvl2,72,
02209 //              108,lvl2,0,  108,lvl2,288, 108,lvl2,216, 108,lvl2,144, 108,lvl2,72,
02210 //              180,lvl2,0,  180,lvl2,288, 180,lvl2,216, 180,lvl2,144, 180,lvl2,72,
02211 //              252,lvl2,0,  252,lvl2,288, 252,lvl2,216, 252,lvl2,144, 252,lvl2,72,
02212 //              324,lvl2,0,  324,lvl2,288, 324,lvl2,216, 324,lvl2,144, 324,lvl2,72,
02213 //                0,lvl3,0,    0,lvl3,288,   0,lvl3,216,   0,lvl3,144,   0,lvl3,72
02214 //      };
02215 //
02216 //
02217 //      // A cube has   m=3, n=4, F=6 E=12=nF/2, V=8=nF/m,since vertices shared by 3 squares;
02218 //      // It is composed of 6 squares.
02219 //
02220 //
02221 //      // An octahedron has   m=4, n=3, F=8 E=12=nF/2, V=6=nF/m,since vertices shared by 4 triangles;
02222 //      // It is composed of 8 triangles.
02223 //
02224 //    // We have placed the OCT symmetry group with a face along the z-axis
02225 //        lvl0=0;
02226 //      lvl1=90;
02227 //      lvl2=180;
02228 //
02229 //      static float OCT[72] = {// This is with a face of a cube along z
02230 //                    0,lvl0,0,   0,lvl0,90,    0,lvl0,180,    0,lvl0,270,
02231 //                    0,lvl1,0,   0,lvl1,90,    0,lvl1,180,    0,lvl1,270,
02232 //                   90,lvl1,0,  90,lvl1,90,   90,lvl1,180,   90,lvl1,270,
02233 //                  180,lvl1,0, 180,lvl1,90,  180,lvl1,180,  180,lvl1,270,
02234 //                  270,lvl1,0, 270,lvl1,90,  270,lvl1,180,  270,lvl1,270,
02235 //                    0,lvl2,0,   0,lvl2,90,    0,lvl2,180,    0,lvl2,270
02236 //      };
02237 //      // B^4=A^3=1;  BABA=1; implies   AA=BAB, ABA=B^3 , AB^2A = BBBABBB and
02238 //      //   20 words with at most a single A
02239 //    //   1 B BB BBB A  BA AB BBA BAB ABB BBBA BBAB BABB ABBB BBBAB BBABB BABBB
02240 //    //                        BBBABB BBABBB BBBABBB
02241 //     // also     ABBBA is distinct yields 4 more words
02242 //     //    ABBBA   BABBBA BBABBBA BBBABBBA
02243 //     // for a total of 24 words
02244 //     // Note A BBB A BBB A  reduces to BBABB
02245 //     //  and  B A BBB A is the same as A BBB A BBB etc.
02246 //
02247 //    // The TET symmetry group has a face along the z-axis
02248 //    // It has n=m=3; F=4, E=6=nF/2, V=4=nF/m
02249 //        lvl0=0;         // There is a face along z
02250 //      lvl1=109.4712f;  //  that is acos(-1/3)  // There  are 3 faces at this angle
02251 //
02252 //      static float TET[36] = {// This is with the face along z
02253 //            0,lvl0,0,   0,lvl0,120,    0,lvl0,240,
02254 //            0,lvl1,60,   0,lvl1,180,    0,lvl1,300,
02255 //          120,lvl1,60, 120,lvl1,180,  120,lvl1,300,
02256 //          240,lvl1,60, 240,lvl1,180,  240,lvl1,300
02257 //      };
02258 //      // B^3=A^3=1;  BABA=1; implies   A^2=BAB, ABA=B^2 , AB^2A = B^2AB^2 and
02259 //      //   12 words with at most a single A
02260 //    //   1 B BB  A  BA AB BBA BAB ABB BBAB BABB BBABB
02261 //    // at most one A is necessary
02262 //
02263 //      Transform3D ret;
02264 //      SymType type = get_sym_type(symname);
02265 //
02266 //      switch (type) {
02267 //      case CSYM:
02268 //              ret.set_rotation( n * 360.0f / nsym, 0, 0);
02269 //              break;
02270 //      case DSYM:
02271 //              if (n >= nsym / 2) {
02272 //                      ret.set_rotation((n - nsym/2) * 360.0f / (nsym / 2),180.0f, 0);
02273 //              }
02274 //              else {
02275 //                      ret.set_rotation( n * 360.0f / (nsym / 2),0, 0);
02276 //              }
02277 //              break;
02278 //      case ICOS_SYM:
02279 //              ret.set_rotation((float)ICOS[n * 3 ],
02280 //                               (float)ICOS[n * 3 + 1],
02281 //                               (float)ICOS[n * 3 + 2] );
02282 //              break;
02283 //      case OCT_SYM:
02284 //              ret.set_rotation((float)OCT[n * 3],
02285 //                               (float)OCT[n * 3 + 1],
02286 //                               (float)OCT[n * 3 + 2] );
02287 //              break;
02288 //      case TET_SYM:
02289 //              ret.set_rotation((float)TET[n * 3 ],
02290 //                               (float)TET[n * 3 + 1] ,
02291 //                               (float)TET[n * 3 + 2] );
02292 //              break;
02293 //      case ISYM:
02294 //              ret.set_rotation(0, 0, 0);
02295 //              break;
02296 //      default:
02297 //              throw InvalidValueException(type, symname);
02298 //      }
02299 //
02300 //      ret = (*this) * ret;
02301 //
02302 //      return ret;
02303 //}
02304 //
02305 //int Transform3D::get_nsym(const string & name)
02306 //{
02307 //      string symname = name;
02308 //
02309 //      for (size_t i = 0; i < name.size(); i++) {
02310 //              if (isalpha(name[i])) {
02311 //                      symname[i] = (char)tolower(name[i]);
02312 //              }
02313 //      }
02314 //
02315 //      SymType type = get_sym_type(symname);
02316 //      int nsym = 0;
02317 //
02318 //      switch (type) {
02319 //      case CSYM:
02320 //              nsym = atoi(symname.c_str() + 1);
02321 //              break;
02322 //      case DSYM:
02323 //              nsym = atoi(symname.c_str() + 1) * 2;
02324 //              break;
02325 //      case ICOS_SYM:
02326 //              nsym = 60;
02327 //              break;
02328 //      case OCT_SYM:
02329 //              nsym = 24;
02330 //              break;
02331 //      case TET_SYM:
02332 //              nsym = 12;
02333 //              break;
02334 //      case ISYM:
02335 //              nsym = 1;
02336 //              break;
02337 //      case UNKNOWN_SYM:
02338 //      default:
02339 //              throw InvalidValueException(type, name);
02340 //      }
02341 //      return nsym;
02342 //}
02343 //
02344 //
02345 //
02346 //Transform3D::SymType Transform3D::get_sym_type(const string & name)
02347 //{
02348 //      SymType t = UNKNOWN_SYM;
02349 //
02350 //      if (name[0] == 'c') {
02351 //              t = CSYM;
02352 //      }
02353 //      else if (name[0] == 'd') {
02354 //              t = DSYM;
02355 //      }
02356 //      else if (name == "icos") {
02357 //              t = ICOS_SYM;
02358 //      }
02359 //      else if (name == "oct") {
02360 //              t = OCT_SYM;
02361 //      }
02362 //      else if (name == "tet") {
02363 //              t = TET_SYM;
02364 //      }
02365 //      else if (name == "i" || name == "") {
02366 //              t = ISYM;
02367 //      }
02368 //      return t;
02369 //}
02370 //
02371 //vector<Transform3D*>
02372 //Transform3D::angles2tfvec(EulerType eulertype, const vector<float> ang) {
02373 //      int nangles = ang.size() / 3;
02374 //      vector<Transform3D*> tfvec;
02375 //      for (int i = 0; i < nangles; i++) {
02376 //              tfvec.push_back(new Transform3D(eulertype,ang[3*i],ang[3*i+1],ang[3*i+2]));
02377 //      }
02378 //      return tfvec;
02379 //}
02380 //
02381 
02382 
02383 
02384 /* vim: set ts=4 noet: */
02385 
02386 
02387 /*    Rotation stuff */
02388 

Generated on Thu Mar 10 22:58:30 2011 for EMAN2 by  doxygen 1.3.9.1