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 vector<Transform > Transform::get_sym_proj(const string & sym_name) const
01204 {
01205         vector<Transform> ret;
01206         Transform t;
01207         Symmetry3D* sym = Factory<Symmetry3D>::get(sym_name);
01208         int nsym = sym->get_nsym();
01209         int n = nsym;
01210         
01211         if ((sym_name[0] == 'c' || sym_name[0] == 'd' ) &&  fabs(matrix[2][2]) < 1.e-6){
01212                 
01213                 Dict d1,d2;                             
01214                 d2["theta"] = (double)90.0;
01215                 d2["psi"] = (double)0.0;
01216                 d2["phi"] = (double)0.0;
01217                 d2["type"] = "spider";
01218                 d1 = this->get_rotation("spider");
01219                 
01220                 if (sym_name[0] == 'c') {
01221                         if( nsym%2 == 0)        n = nsym/2;
01222                         
01223                         for (int k=0;k<n;k++) {                         
01224                                 d2["phi"] = (double)d1["phi"] + k*double(360.0)/ nsym;
01225                                 d2["psi"] = d1["psi"];
01226                                 t.set_rotation(d2);
01227                                 ret.push_back( t );
01228                         }
01229                                 
01230                 }
01231                 else {
01232                         nsym = nsym/2;
01233                         
01234                         if (nsym%2 == 0) {
01235                                 n = nsym;
01236                                 float cos_phi = cos( EMConsts::deg2rad*360.0/2/nsym );
01237                         
01238                                 for (int k=0;k<n;k++){
01239                                         
01240                                         if(k%2==0)      {
01241                                         
01242                                                 d2["phi"] = (double)d1["phi"] + k/2*double(360.0)/ nsym;
01243                                                 d2["psi"] = d1["psi"];
01244                                                 t.set_rotation(d2);
01245                                                 ret.push_back( t );     
01246                                         }
01247                                         else    {
01248                                                         
01249                                                 if( ( fabs(1.0-matrix[2][0])>1.0e-6 )&& fabs( matrix[2][0]-cos_phi)>1.0e-6  ){
01250                                                         //cout<<"jumped into"<<endl;
01251                                                         d2["phi"] = k/2*double(360.0)/ nsym +180 - (double)d1["phi"];
01252                                                         d2["psi"] = (double)d1["psi"] + 180;
01253                                                         t.set_rotation(d2);
01254                                                         ret.push_back( t );
01255                                                 }
01256                                         }
01257                                 
01258                                 }
01259                         }
01260                         
01261                         
01262                         
01263                         else    {
01264                                 n = nsym*2;
01265                                 float cos_phi = cos( EMConsts::deg2rad*360.0/4/nsym );
01266                                 for (int k=0;k<n;k++){
01267                                         
01268                                         if(k%4==0)      {
01269                                         
01270                                                 d2["phi"] = (double)d1["phi"] + k/4*360.0/ nsym;
01271                                                 d2["psi"] = (double)d1["psi"];
01272                                                 t.set_rotation(d2);
01273                                                 ret.push_back( t );     
01274                                         }
01275                                         else if( k%4 ==1)       {
01276                                                 if( ( fabs(1.0-matrix[2][0])>1.0e-6 )&& fabs( matrix[2][0]-cos_phi)>1.0e-6  ){
01277                                                 
01278                                                         d2["phi"] = k/4*360.0/nsym + 360.0/2/nsym+180 - (double)d1["phi"];
01279                                                         d2["psi"] = (double)d1["psi"] + 180;
01280                                                         t.set_rotation(d2);
01281                                                         ret.push_back( t );
01282                                                 }
01283                                 
01284                                         }
01285                                         
01286                                         else if( k%4 ==2)       {
01287                                         
01288                                                 d2["phi"] =  k/4*360.0/ nsym+360.0/2/nsym+180 + (double)d1["phi"];
01289                                                 d2["psi"] = (double)d1["psi"];
01290                                                 t.set_rotation(d2);
01291                                                 ret.push_back( t );
01292                                 
01293                                         }
01294                                         
01295                                         else if( k%4 ==3)       {
01296                                                 if( ( fabs(1.0-matrix[2][0])>1.0e-6 )&& fabs( matrix[2][0]-cos_phi)>1.0e-6  ) {
01297                                                         d2["phi"] = k/4*360.0/nsym+ 2.0*360.0/2/nsym - (double)d1["phi"];
01298                                                         d2["psi"] = (double)d1["psi"] + 180;
01299                                                         t.set_rotation(d2);
01300                                                         ret.push_back( t );
01301                                                 }
01302                                         }
01303                                 
01304                                 }
01305                         }
01306                         
01307                 }
01308                 
01309         }
01310         else {
01311                 for (int k=0;k<nsym;k++) {
01312                         t =  sym->get_sym(k);
01313                         ret.push_back( (*this) * t );
01314                 }
01315                 
01316         }
01317         delete sym;
01318         return ret;
01319 }
01320 
01321 
01322 int Transform::get_nsym(const string & sym_name)
01323 {
01324         Symmetry3D* sym = Factory<Symmetry3D>::get(sym_name);
01325         int nsym = sym->get_nsym();
01326         delete sym;
01327         return nsym;
01328 }
01329 
01330 //
01331 //Transform3D::Transform3D()  //    C1
01332 //{
01333 //      init();
01334 //}
01335 //
01336 //Transform3D::Transform3D( const Transform3D& rhs )
01337 //{
01338 //    for( int i=0; i < 4; ++i )
01339 //    {
01340 //        for( int j=0; j < 4; ++j )
01341 //      {
01342 //          matrix[i][j] = rhs.matrix[i][j];
01343 //      }
01344 //    }
01345 //}
01346 //
01348 //Transform3D::Transform3D(const float& az, const float& alt, const float& phi)
01349 //{
01350 //      init();
01351 //      set_rotation(az,alt,phi);
01352 //}
01353 //
01354 //
01356 //Transform3D::Transform3D(const float& az, const float& alt, const float& phi, const Vec3f& posttrans )
01357 //{
01358 //      init(); // This is called in set_rotation
01359 //      set_rotation(az,alt,phi);
01360 //      set_posttrans(posttrans);
01361 //}
01362 //
01363 //Transform3D::Transform3D(const float& m11, const float& m12, const float& m13,
01364 //                                               const float& m21, const float& m22, const float& m23,
01365 //                                               const float& m31, const float& m32, const float& m33)
01366 //{
01367 //      init();
01368 //      set_rotation(m11,m12,m13,m21,m22,m23,m31,m32,m33);
01369 //}
01370 //
01372 //Transform3D::Transform3D(EulerType euler_type, const float& a1, const float& a2, const float& a3)
01373 //{
01374 //      init();
01375 //      set_rotation(euler_type,a1,a2,a3);
01376 //}
01377 //
01378 //Transform3D::Transform3D(EulerType euler_type, const float& a1, const float& a2, const float& a3, const float& a4)
01379 //{
01380 //      init();
01381 //      set_rotation(euler_type,a1,a2,a3,a4);
01382 //}
01383 //
01384 //
01386 //Transform3D::Transform3D(EulerType euler_type, const Dict& rotation)  //YYY
01387 //{
01388 //      init();
01389 //      set_rotation(euler_type,rotation);
01390 //}
01391 //
01392 //
01394 //
01395 //Transform3D::Transform3D(  const Vec3f& pretrans,  const float& az, const float& alt, const float& phi, const Vec3f& posttrans )  //YYY  by default EMAN
01396 //{
01397 //      init();
01398 //      set_pretrans(pretrans);
01399 //      set_rotation(az,alt,phi);
01400 //      set_posttrans(posttrans);
01401 //}
01402 //
01403 //
01404 //
01405 //
01406 //Transform3D::~Transform3D()
01407 //{
01408 //}
01409 //
01410 //
01411 //
01412 //void Transform3D::to_identity()
01413 //{
01417 //
01418 //      for(int i=0; i<4; ++i) {
01419 //              for(int j=0; j<4; ++j) {
01420 //                      if(i==j) {
01421 //                              matrix[i][j] = 1;
01422 //                      }
01423 //                      else {
01424 //                              matrix[i][j] = 0;
01425 //                      }
01426 //              }
01427 //      }
01428 //      post_x_mirror = false;
01429 //      set_center(Vec3f(0,0,0));
01430 //}
01431 //
01432 //
01433 //
01434 //bool Transform3D::is_identity()  // YYY
01435 //{
01436 //      for (int i=0; i<4; i++) {
01437 //              for (int j=0; j<4; j++) {
01438 //                      if (i==j && matrix[i][j]!=1.0) return 0;
01439 //                      if (i!=j && matrix[i][j]!=0.0) return 0;
01440 //              }
01441 //      }
01442 //      return 1;
01443 //}
01444 //
01445 //
01446 //void Transform3D::set_center(const Vec3f & center) //YYN
01447 //{
01448 //      set_pretrans( Vec3f(0,0,0)-center);
01449 //      for (int i = 0; i < 3; i++) {
01450 //              matrix[i][3]=center[i];
01451 //      }
01452 //}
01453 //
01456 //void Transform3D::init()  // M1
01457 //{
01458 //      to_identity();
01459 //}
01460 //
01462 //
01463 //void Transform3D::set_pretrans(const float& dx, const float& dy, const float& dz) // YYY
01464 //{    set_pretrans( Vec3f(dx,dy,dz)); }
01465 //
01466 //
01467 //void Transform3D::set_pretrans(const float& dx, const float& dy) // YYY
01468 //{    set_pretrans( Vec3f(dx,dy,0)); }
01469 //
01470 //void Transform3D::set_pretrans(const Vec2f& pretrans) // YYY
01471 //{    set_pretrans( Vec3f(pretrans[0],pretrans[1],0)); }
01472 //
01473 //void Transform3D::set_pretrans(const Vec3f & preT)  // flag=1 means keep the old value of total trans
01474 //{
01475 //              int flag=0;
01476 //
01479 //    if (flag==0){
01480 //              matrix[0][3] = matrix[3][0] + matrix[0][0]*preT[0] + matrix[0][1]*preT[1] + matrix[0][2]*preT[2]  ;
01481 //              matrix[1][3] = matrix[3][1] + matrix[1][0]*preT[0] + matrix[1][1]*preT[1] + matrix[1][2]*preT[2]  ;
01482 //              matrix[2][3] = matrix[3][2] + matrix[2][0]*preT[0] + matrix[2][1]*preT[1] + matrix[2][2]*preT[2]  ;
01483 //      }
01485 //    if (flag==1){
01486 //              matrix[3][0] = matrix[0][3] - (matrix[0][0]*preT[0] + matrix[0][1]*preT[1] + matrix[0][2]*preT[2])  ;
01487 //              matrix[3][1] = matrix[1][3] - (matrix[1][0]*preT[0] + matrix[1][1]*preT[1] + matrix[1][2]*preT[2])  ;
01488 //              matrix[3][2] = matrix[2][3] - (matrix[2][0]*preT[0] + matrix[2][1]*preT[1] + matrix[2][2]*preT[2])  ;
01489 //      }
01490 //}
01491 //
01492 //
01493 //void Transform3D::set_posttrans(const float& dx, const float& dy, const float& dz) // YYY
01494 //{    set_posttrans( Vec3f(dx,dy,dz)); }
01495 //
01496 //
01497 //void Transform3D::set_posttrans(const float& dx, const float& dy) // YYY
01498 //{    set_posttrans( Vec3f(dx,dy,0)); }
01499 //
01500 //void Transform3D::set_posttrans(const Vec2f& posttrans) // YYY
01501 //{    set_pretrans( Vec3f(posttrans[0],posttrans[1],0)); }
01502 //
01503 //void Transform3D::set_posttrans(const Vec3f & posttrans) // flag=1 means keep the old value of total trans
01504 //{
01505 //      int flag=0;
01506 //    Vec3f preT   = get_pretrans(0) ;
01507 //      for (int i = 0; i < 3; i++) {
01508 //              matrix[3][i] = posttrans[i];
01509 //      }
01512 //      if (flag==0) {
01513 //              matrix[0][3] = matrix[3][0] + matrix[0][0]*preT[0] + matrix[0][1]*preT[1] + matrix[0][2]*preT[2]  ;
01514 //              matrix[1][3] = matrix[3][1] + matrix[1][0]*preT[0] + matrix[1][1]*preT[1] + matrix[1][2]*preT[2]  ;
01515 //              matrix[2][3] = matrix[3][2] + matrix[2][0]*preT[0] + matrix[2][1]*preT[1] + matrix[2][2]*preT[2]  ;
01516 //      }
01518 //      if (flag==1) { // Don't do anything
01519 //      }
01520 //}
01521 //
01522 //
01523 //
01524 //
01525 //void Transform3D::apply_scale(const float& scale)    // YYY
01526 //{
01527 //      for (int i = 0; i < 3; i++) {
01528 //              for (int j = 0; j < 4; j++) {
01529 //                      matrix[i][j] *= scale;
01530 //              }
01531 //      }
01532 //      for (int j = 0; j < 3; j++) {
01533 //              matrix[3][j] *= scale;
01534 //      }
01535 //}
01536 //
01537 //void Transform3D::orthogonalize()  // YYY
01538 //{
01539 //      //EulerType EMAN;
01540 //      float scale = get_scale() ;
01541 //      float inverseScale= 1/scale ;
01542 //      apply_scale(inverseScale);
01545 //}
01546 //
01547 //
01548 //void Transform3D::transpose()  // YYY
01549 //{
01550 //      float tempij;
01551 //      for (int i = 0; i < 3; i++) {
01552 //              for (int j = 0; j < i; j++) {
01553 //                      tempij= matrix[i][j];
01554 //                      matrix[i][j] = matrix[j][i];
01555 //                      matrix[j][i] = tempij;
01556 //              }
01557 //      }
01558 //}
01559 //
01560 //void Transform3D::set_scale(const float& scale)    // YYY
01561 //{
01562 //      float OldScale= get_scale();
01563 //      float Scale2Apply = scale/OldScale;
01564 //      apply_scale(Scale2Apply);
01565 //}
01566 //
01567 //float Transform3D::get_mag() const //
01568 //{
01569 //      EulerType eulertype= SPIN ;
01570 //      Dict AA= get_rotation(eulertype);
01571 //      return AA["Omega"];
01572 //}
01573 //
01574 //Vec3f Transform3D::get_finger() const //
01575 //{
01576 //      EulerType eulertype= SPIN ;
01577 //      Dict AA= get_rotation(eulertype);
01578 //      return Vec3f(AA["n1"],AA["n2"],AA["n3"]);
01579 //}
01580 //
01581 //Vec3f Transform3D::get_posttrans(int flag) const    //
01582 //{
01583 //      if (flag==0){
01584 //              return Vec3f(matrix[3][0], matrix[3][1], matrix[3][2]);
01585 //      }
01586 //      // otherwise as if all the translation was post
01587 //      return Vec3f(matrix[0][3], matrix[1][3], matrix[2][3]);
01588 //}
01589 //
01590 //Vec3f Transform3D::get_total_posttrans() const {
01591 //      return get_posttrans(1);
01592 //}
01593 //
01594 //Vec3f Transform3D::get_total_pretrans() const {
01595 //      return get_pretrans(1);
01596 //}
01597 //
01598 //
01599 //Vec3f Transform3D::get_pretrans(int flag) const    // Fix Me
01600 //{
01602 //
01603 //      Vec3f pretrans;
01604 //      Vec3f posttrans(matrix[3][0], matrix[3][1], matrix[3][2]);
01605 //      Vec3f tottrans(matrix[0][3], matrix[1][3], matrix[2][3]);
01606 //      Vec3f totminuspost;
01607 //
01608 //      totminuspost = tottrans;
01609 //      if (flag==0) {
01610 //              totminuspost = tottrans-posttrans;
01611 //      }
01612 //
01613 //      Transform3D Rinv = inverse();
01614 //      for (int i=0; i<3; i++) {
01615 //                float ptnow=0;
01616 //              for (int j=0; j<3; j++) {
01617 //                      ptnow +=   Rinv.matrix[i][j]* totminuspost[j] ;
01618 //              }
01619 //              pretrans.set_value_at(i,ptnow) ;  //
01620 //      }
01621 //      return pretrans;
01622 //}
01623 //
01624 //
01625 // Vec3f Transform3D::get_center() const  // YYY
01626 // {
01627 //      return Vec3f();
01628 // }
01629 //
01630 //
01631 //
01632 //Vec3f Transform3D::get_matrix3_col(int i) const     // YYY
01633 //{
01634 //      return Vec3f(matrix[0][i], matrix[1][i], matrix[2][i]);
01635 //}
01636 //
01637 //
01638 //Vec3f Transform3D::get_matrix3_row(int i) const     // YYY
01639 //{
01640 //      return Vec3f(matrix[i][0], matrix[i][1], matrix[i][2]);
01641 //}
01642 //
01643 //Vec3f Transform3D::transform(const Vec3f & v3f) const     // YYY
01644 //{
01646 //      float x = matrix[0][0] * v3f[0] + matrix[0][1] * v3f[1] + matrix[0][2] * v3f[2] + matrix[0][3] ;
01647 //      float y = matrix[1][0] * v3f[0] + matrix[1][1] * v3f[1] + matrix[1][2] * v3f[2] + matrix[1][3] ;
01648 //      float z = matrix[2][0] * v3f[0] + matrix[2][1] * v3f[1] + matrix[2][2] * v3f[2] + matrix[2][3] ;
01649 //      return Vec3f(x, y, z);
01650 //}
01651 //
01652 //
01653 //Vec3f Transform3D::rotate(const Vec3f & v3f) const     // YYY
01654 //{
01656 //      float x = matrix[0][0] * v3f[0] + matrix[0][1] * v3f[1] + matrix[0][2] * v3f[2]  ;
01657 //      float y = matrix[1][0] * v3f[0] + matrix[1][1] * v3f[1] + matrix[1][2] * v3f[2]  ;
01658 //      float z = matrix[2][0] * v3f[0] + matrix[2][1] * v3f[1] + matrix[2][2] * v3f[2]  ;
01659 //      return Vec3f(x, y, z);
01660 //}
01661 //
01662 //
01663 //Transform3D EMAN::operator*(const Transform3D & M2, const Transform3D & M1)     // YYY
01664 //{
01667 //      Transform3D resultant;
01668 //      for (int i=0; i<3; i++) {
01669 //              for (int j=0; j<4; j++) {
01670 //                      resultant[i][j] = M2[i][0] * M1[0][j] +  M2[i][1] * M1[1][j] + M2[i][2] * M1[2][j];
01671 //              }
01672 //              resultant[i][3] += M2[i][3];  // add on the new translation (not included above)
01673 //      }
01674 //
01675 //      for (int j=0; j<3; j++) {
01676 //              resultant[3][j] = M2[3][j];
01677 //      }
01678 //
01679 //      return resultant; // This will have the post_trans of M2
01680 //}
01681 
01682 /*             Here starts the pure rotation stuff */
01683 
01753 //
01754 //void Transform3D::set_rotation(const float& az, const float& alt, const float& phi )
01755 //{
01756 //      EulerType euler_type=EMAN;
01757 //      Dict rot;
01758 //      rot["az"]  = az;
01759 //      rot["alt"] = alt;
01760 //      rot["phi"] = phi;
01761 //      set_rotation(euler_type, rot);
01762 //}
01763 //
01765 //void Transform3D::set_rotation(EulerType euler_type, const float& a1, const float& a2, const float& a3)
01766 //{
01767 //      init();
01768 //      Dict rot;
01769 //      switch(euler_type) {
01770 //              case EMAN:
01771 //                      rot["az"]  = a1;
01772 //                      rot["alt"] = a2;
01773 //                      rot["phi"] = a3;
01774 //                      break;
01775 //              case SPIDER:
01776 //                      rot["phi"]   = a1;
01777 //                      rot["theta"] = a2;
01778 //                      rot["psi"]   = a3;
01779 //                      break;
01780 //              case IMAGIC:
01781 //                      rot["alpha"]   = a1;
01782 //                      rot["beta"] = a2;
01783 //                      rot["gamma"]   = a3;
01784 //                      break;
01785 //              case MRC:
01786 //                      rot["phi"]   = a1;
01787 //                      rot["theta"] = a2;
01788 //                      rot["omega"]   = a3;
01789 //                      break;
01790 //              case XYZ:
01791 //                      rot["xtilt"]   = a1;
01792 //                      rot["ytilt"] = a2;
01793 //                      rot["ztilt"]   = a3;
01794 //                      break;
01795 //              default:
01796 //              throw InvalidValueException(euler_type, "cannot instantiate this Euler Type");
01797 //      }  // ends switch euler_type
01798 //      set_rotation(euler_type, rot);
01799 //}
01800 //
01802 //void Transform3D::set_rotation(EulerType euler_type, const float& a1, const float& a2, const float& a3, const float& a4)
01803 //{
01804 //      init();
01805 //      Dict rot;
01806 //      switch(euler_type) {
01807 //              case QUATERNION:
01808 //                      rot["e0"]  = a1;
01809 //                      rot["e1"] = a2;
01810 //                      rot["e2"] = a3;
01811 //                      rot["e3"] = a4;
01812 //                      break;
01813 //              case SGIROT:
01814 //                      rot["q"]  = a1;
01815 //                      rot["n1"] = a2;
01816 //                      rot["n2"] = a3;
01817 //                      rot["n3"] = a4;
01818 //              case SPIN:
01819 //                      rot["Omega"]  = a1;
01820 //                      rot["n1"] = a2;
01821 //                      rot["n2"] = a3;
01822 //                      rot["n3"] = a4;
01823 //                      break;
01824 //              default:
01825 //                      throw InvalidValueException(euler_type, "cannot instantiate this Euler Type");
01826 //      }  // ends switch euler_type
01827 //      set_rotation(euler_type, rot);
01828 //}
01829 //
01830 //void Transform3D::set_rotation(EulerType euler_type, const Dict& rotation)
01831 //{
01832 //      double e0  = 0; double e1=0; double e2=0; double e3=0;
01833 //      double Omega=0;
01834 //      double az  = 0;
01835 //      double alt = 0;
01836 //      double phi = 0;
01837 //      double cxtilt = 0;
01838 //      double sxtilt = 0;
01839 //      double cytilt = 0;
01840 //      double sytilt = 0;
01841 //      bool is_quaternion = 0;
01842 //      bool is_matrix = 0;
01843 //
01844 //      switch(euler_type) {
01845 //      case EMAN:
01846 //              az  = (double)rotation["az"] ;
01847 //              alt = (double)rotation["alt"]  ;
01848 //              phi = (double)rotation["phi"] ;
01849 //              break;
01850 //      case IMAGIC:
01851 //              az  = (double)rotation["alpha"] ;
01852 //              alt = (double)rotation["beta"]  ;
01853 //              phi = (double)rotation["gamma"] ;
01854 //              break;
01855 //
01856 //      case SPIDER:
01857 //              az =  (double)rotation["phi"]    + 90.0;
01858 //              alt = (double)rotation["theta"] ;
01859 //              phi = (double)rotation["psi"]    - 90.0;
01860 //              break;
01861 //
01862 //      case XYZ:
01863 //              cxtilt = cos( (M_PI/180.0f)*(double)rotation["xtilt"]);
01864 //              sxtilt = sin( (M_PI/180.0f)*(double)rotation["xtilt"]);
01865 //              cytilt = cos( (M_PI/180.0f)*(double)rotation["ytilt"]);
01866 //              sytilt = sin( (M_PI/180.0f)*(double)rotation["ytilt"]);
01867 //              az =  (180.0f/M_PI)*atan2(-cytilt*sxtilt,sytilt)   + 90.0f ;
01868 //              alt = (180.0f/M_PI)*acos(cytilt*cxtilt)  ;
01869 //              phi = (double)rotation["ztilt"] +(180.0f/M_PI)*atan2(sxtilt,cxtilt*sytilt)   - 90.0f ;
01870 //              break;
01871 //
01872 //      case MRC:
01873 //              az  = (double)rotation["phi"]   + 90.0f ;
01874 //              alt = (double)rotation["theta"] ;
01875 //              phi = (double)rotation["omega"] - 90.0f ;
01876 //              break;
01877 //
01878 //      case QUATERNION:
01879 //              is_quaternion = 1;
01880 //              e0 = (double)rotation["e0"];
01881 //              e1 = (double)rotation["e1"];
01882 //              e2 = (double)rotation["e2"];
01883 //              e3 = (double)rotation["e3"];
01884 //              break;
01885 //
01886 //      case SPIN:
01887 //              is_quaternion = 1;
01888 //              Omega = (double)rotation["Omega"];
01889 //              e0 = cos(Omega*M_PI/360.0f);
01890 //              e1 = sin(Omega*M_PI/360.0f)* (double)rotation["n1"];
01891 //              e2 = sin(Omega*M_PI/360.0f)* (double)rotation["n2"];
01892 //              e3 = sin(Omega*M_PI/360.0f)* (double)rotation["n3"];
01893 //              break;
01894 //
01895 //      case SGIROT:
01896 //              is_quaternion = 1;
01897 //              Omega = (double)rotation["q"]  ;
01898 //              e0 = cos(Omega*M_PI/360.0f);
01899 //              e1 = sin(Omega*M_PI/360.0f)* (double)rotation["n1"];
01900 //              e2 = sin(Omega*M_PI/360.0f)* (double)rotation["n2"];
01901 //              e3 = sin(Omega*M_PI/360.0f)* (double)rotation["n3"];
01902 //              break;
01903 //
01904 //      case MATRIX:
01905 //              is_matrix = 1;
01906 //              matrix[0][0] = (float)rotation["m11"]  ;
01907 //              matrix[0][1] = (float)rotation["m12"]  ;
01908 //              matrix[0][2] = (float)rotation["m13"]  ;
01909 //              matrix[1][0] = (float)rotation["m21"]  ;
01910 //              matrix[1][1] = (float)rotation["m22"]  ;
01911 //              matrix[1][2] = (float)rotation["m23"]  ;
01912 //              matrix[2][0] = (float)rotation["m31"]  ;
01913 //              matrix[2][1] = (float)rotation["m32"]  ;
01914 //              matrix[2][2] = (float)rotation["m33"]  ;
01915 //              break;
01916 //
01917 //      default:
01918 //              throw InvalidValueException(euler_type, "unknown Euler Type");
01919 //      }  // ends switch euler_type
01920 //
01921 //
01922 //      Vec3f postT  = get_posttrans( ) ;
01923 //      Vec3f preT   = get_pretrans( ) ;
01924 //
01925 //
01926 //      double azp  = fmod(az,360.0)*M_PI/180.0;
01927 //      double altp  = alt*M_PI/180.0;
01928 //      double phip = fmod(phi,360.0)*M_PI/180.0;
01929 //
01930 //      if (!is_quaternion && !is_matrix) {
01931 //              matrix[0][0] =  (float)(cos(phip)*cos(azp) - cos(altp)*sin(azp)*sin(phip));
01932 //              matrix[0][1] =  (float)(cos(phip)*sin(azp) + cos(altp)*cos(azp)*sin(phip));
01933 //              matrix[0][2] =  (float)(sin(altp)*sin(phip));
01934 //              matrix[1][0] =  (float)(-sin(phip)*cos(azp) - cos(altp)*sin(azp)*cos(phip));
01935 //              matrix[1][1] =  (float)(-sin(phip)*sin(azp) + cos(altp)*cos(azp)*cos(phip));
01936 //              matrix[1][2] =  (float)(sin(altp)*cos(phip));
01937 //              matrix[2][0] =  (float)(sin(altp)*sin(azp));
01938 //              matrix[2][1] =  (float)(-sin(altp)*cos(azp));
01939 //              matrix[2][2] =  (float)cos(altp);
01940 //      }
01941 //      if (is_quaternion){
01942 //              matrix[0][0] = (float)(e0 * e0 + e1 * e1 - e2 * e2 - e3 * e3);
01943 //              matrix[0][1] = (float)(2.0f * (e1 * e2 + e0 * e3));
01944 //              matrix[0][2] = (float)(2.0f * (e1 * e3 - e0 * e2));
01945 //              matrix[1][0] = (float)(2.0f * (e2 * e1 - e0 * e3));
01946 //              matrix[1][1] = (float)(e0 * e0 - e1 * e1 + e2 * e2 - e3 * e3);
01947 //              matrix[1][2] = (float)(2.0f * (e2 * e3 + e0 * e1));
01948 //              matrix[2][0] = (float)(2.0f * (e3 * e1 + e0 * e2));
01949 //              matrix[2][1] = (float)(2.0f * (e3 * e2 - e0 * e1));
01950 //              matrix[2][2] = (float)(e0 * e0 - e1 * e1 - e2 * e2 + e3 * e3);
01951 //              // keep in mind matrix[0][2] is M13 gives an e0 e2 piece, etc
01952 //      }
01953 //      // Now do post and pretrans: vfinal = vpost + R vpre;
01954 //
01955 //      matrix[0][3] = postT[0] + matrix[0][0]*preT[0] + matrix[0][1]*preT[1] + matrix[0][2]*preT[2]  ;
01956 //      matrix[1][3] = postT[1] + matrix[1][0]*preT[0] + matrix[1][1]*preT[1] + matrix[1][2]*preT[2]  ;
01957 //      matrix[2][3] = postT[2] + matrix[2][0]*preT[0] + matrix[2][1]*preT[1] + matrix[2][2]*preT[2]  ;
01958 //}
01959 //
01960 //
01961 //void Transform3D::set_rotation(const float& m11, const float& m12, const float& m13,
01962 //                                                         const float& m21, const float& m22, const float& m23,
01963 //                const float& m31, const float& m32, const float& m33)
01964 //{
01965 //      EulerType euler_type = MATRIX;
01966 //      Dict rot;
01967 //      rot["m11"]  = m11;
01968 //      rot["m12"]  = m12;
01969 //      rot["m13"]  = m13;
01970 //      rot["m21"]  = m21;
01971 //      rot["m22"]  = m22;
01972 //      rot["m23"]  = m23;
01973 //      rot["m31"]  = m31;
01974 //      rot["m32"]  = m32;
01975 //      rot["m33"]  = m33;
01976 //      set_rotation(euler_type, rot);  // Or should it be &rot ?
01977 //}
01978 //
01979 //void Transform3D::set_rotation(const Vec3f & eahat, const Vec3f & ebhat,
01980 //                                    const Vec3f & eAhat, const Vec3f & eBhat)
01981 //{// this rotation rotates unit vectors a,b into A,B;
01983 //      Vec3f eahatcp(eahat);
01984 //      Vec3f ebhatcp(ebhat);
01985 //      Vec3f eAhatcp(eAhat);
01986 //      Vec3f eBhatcp(eBhat);
01987 //
01988 //      eahatcp.normalize();
01989 //      ebhatcp.normalize();
01990 //      eAhatcp.normalize();
01991 //      eBhatcp.normalize();
01992 //
01993 //      Vec3f aMinusA(eahatcp);
01994 //      aMinusA  -= eAhatcp;
01995 //      Vec3f bMinusB(ebhatcp);
01996 //      bMinusB  -= eBhatcp;
01997 //
01998 //
01999 //      Vec3f  nhat;
02000 //      float aAlength = aMinusA.length();
02001 //      float bBlength = bMinusB.length();
02002 //      if (aAlength==0){
02003 //              nhat=eahatcp;
02004 //      }else if (bBlength==0){
02005 //              nhat=ebhatcp;
02006 //      }else{
02007 //              nhat= aMinusA.cross(bMinusB);
02008 //              nhat.normalize();
02009 //      }
02010 //
02012 //
02013 //      Vec3f neahat  = eahatcp.cross(nhat);
02014 //      Vec3f nebhat  = ebhatcp.cross(nhat);
02015 //      Vec3f neAhat  = eAhatcp.cross(nhat);
02016 //      Vec3f neBhat  = eBhatcp.cross(nhat);
02017 //
02018 //      double cosOmegaA = (neahat.dot(neAhat))  / (neahat.dot(neahat));
02020 //      double sinOmegaA = (neahat.dot(eAhatcp)) / (neahat.dot(neahat));
02022 //
02023 //      double OmegaA = atan2(sinOmegaA,cosOmegaA);
02025 //
02026 //      EulerType euler_type=SPIN;
02027 //      Dict rotation;
02028 //      rotation["n1"]= nhat[0];
02029 //      rotation["n2"]= nhat[1];
02030 //      rotation["n3"]= nhat[2];
02031 //      rotation["Omega"] = (float)(OmegaA*180.0/M_PI);
02032 //      set_rotation(euler_type,  rotation);
02033 //}
02034 //
02035 //
02036 //float Transform3D::get_scale() const     // YYY
02037 //{
02038 //      // Assumes uniform scaling, calculation uses Z only.
02039 //      float scale =0;
02040 //      for (int i=0; i<3; i++) {
02041 //              for (int j=0; j<3; j++) {
02042 //                      scale = scale + matrix[i][j]*matrix[i][j];
02043 //              }
02044 //      }
02045 //
02046 //      return sqrt(scale/3);
02047 //}
02048 //
02049 //
02050 //
02051 //Dict Transform3D::get_rotation(EulerType euler_type) const
02052 //{
02053 //      Dict result;
02054 //
02055 //      double max = 1 - ERR_LIMIT;
02056 //      double sca=get_scale();
02057 //      double cosalt=matrix[2][2]/sca;
02058 //
02059 //
02060 //      double az=0;
02061 //      double alt = 0;
02062 //      double phi=0;
02063 //      double phiS = 0; // like az     (but in SPIDER ZXZ)
02064 //      double psiS =0;  // like phi  (but in SPIDER ZYZ)
02065 //
02066 //
02068 //
02069 //      if (cosalt > max) {  // that is, alt close to 0
02070 //              alt = 0;
02071 //              az=0;
02072 //              phi = (double)EMConsts::rad2deg * atan2(matrix[0][1], matrix[0][0]);
02073 //      }
02074 //      else if (cosalt < -max) { // alt close to pi
02075 //              alt = 180;
02076 //              az=0;
02077 //              phi=360.0f-(double)EMConsts::rad2deg * atan2(matrix[0][1], matrix[0][0]);
02078 //      }
02079 //      else {
02080 //              alt = (double)EMConsts::rad2deg * acos(cosalt);
02081 //              az  = 360.0f+(double)EMConsts::rad2deg * atan2(matrix[2][0], -matrix[2][1]);
02082 //              phi = 360.0f+(double)EMConsts::rad2deg * atan2(matrix[0][2], matrix[1][2]);
02083 //      }
02084 //      az =fmod(az+180.0,360.0)-180.0;
02085 //      phi=fmod(phi+180.0,360.0)-180.0;
02086 //
02088 //      if (fabs(cosalt) > max) {  // that is, alt close to 0
02089 //              phiS=0;
02090 //              psiS = az+phi;
02091 //      }
02092 //      else {
02093 //              phiS = az   - 90.0;
02094 //              psiS = phi  + 90.0;
02095 //      }
02096 //      phiS = fmod((phiS   + 360.0 ), 360.0) ;
02097 //      psiS = fmod((psiS   + 360.0 ), 360.0) ;
02098 //
02100 //
02101 //      double nphi = (az-phi)/2.0;
02102 //    // The next is also e0
02103 //      double cosOover2 = (cos((az+phi)*M_PI/360) * cos(alt*M_PI/360)) ;
02104 //      double sinOover2 = sqrt(1 -cosOover2*cosOover2);
02105 //      double cosnTheta = sin((az+phi)*M_PI/360) * cos(alt*M_PI/360) / sqrt(1-cosOover2*cosOover2) ;
02106 //      double sinnTheta = sqrt(1-cosnTheta*cosnTheta);
02107 //      double n1 = sinnTheta*cos(nphi*M_PI/180);
02108 //      double n2 = sinnTheta*sin(nphi*M_PI/180);
02109 //      double n3 = cosnTheta;
02110 //      double xtilt = 0;
02111 //      double ytilt = 0;
02112 //      double ztilt = 0;
02113 //
02114 //
02115 //      if (cosOover2<0) {
02116 //              cosOover2*=-1; n1 *=-1; n2*=-1; n3*=-1;
02117 //      }
02118 //
02119 //
02120 //      switch (euler_type) {
02121 //      case EMAN:
02122 //              result["az"]  = az;
02123 //              result["alt"] = alt;
02124 //              result["phi"] = phi;
02125 //              break;
02126 //
02127 //      case IMAGIC:
02128 //              result["alpha"] = az;
02129 //              result["beta"] = alt;
02130 //              result["gamma"] = phi;
02131 //              break;
02132 //
02133 //      case SPIDER:
02134 //              result["phi"]   = phiS;  // The first Euler like az
02135 //              result["theta"] = alt;
02136 //              result["psi"]   = psiS;
02137 //              break;
02138 //
02139 //      case MRC:
02140 //              result["phi"]   = phiS;
02141 //              result["theta"] = alt;
02142 //              result["omega"] = psiS;
02143 //              break;
02144 //
02145 //      case XYZ:
02146 //              xtilt = atan2(-sin((M_PI/180.0f)*phiS)*sin((M_PI/180.0f)*alt),cos((M_PI/180.0f)*alt));
02147 //              ytilt = asin(  cos((M_PI/180.0f)*phiS)*sin((M_PI/180.0f)*alt));
02148 //              ztilt = psiS*M_PI/180.0f - atan2(sin(xtilt), cos(xtilt) *sin(ytilt));
02149 //
02150 //              xtilt=fmod(xtilt*180/M_PI+540.0,360.0) -180.0;
02151 //              ztilt=fmod(ztilt*180/M_PI+540.0,360.0) -180.0;
02152 //
02153 //              result["xtilt"]  = xtilt;
02154 //              result["ytilt"]  = ytilt*180/M_PI;
02155 //              result["ztilt"]  = ztilt;
02156 //              break;
02157 //
02158 //      case QUATERNION:
02159 //              result["e0"] = cosOover2 ;
02160 //              result["e1"] = sinOover2 * n1 ;
02161 //              result["e2"] = sinOover2 * n2;
02162 //              result["e3"] = sinOover2 * n3;
02163 //              break;
02164 //
02165 //      case SPIN:
02166 //              result["Omega"] =360.0f* acos(cosOover2)/ M_PI ;
02167 //              result["n1"] = n1;
02168 //              result["n2"] = n2;
02169 //              result["n3"] = n3;
02170 //              break;
02171 //
02172 //      case SGIROT:
02173 //              result["q"] = 360.0f*acos(cosOover2)/M_PI ;
02174 //              result["n1"] = n1;
02175 //              result["n2"] = n2;
02176 //              result["n3"] = n3;
02177 //              break;
02178 //
02179 //      case MATRIX:
02180 //              result["m11"] = matrix[0][0] ;
02181 //              result["m12"] = matrix[0][1] ;
02182 //              result["m13"] = matrix[0][2] ;
02183 //              result["m21"] = matrix[1][0] ;
02184 //              result["m22"] = matrix[1][1] ;
02185 //              result["m23"] = matrix[1][2] ;
02186 //              result["m31"] = matrix[2][0] ;
02187 //              result["m32"] = matrix[2][1] ;
02188 //              result["m33"] = matrix[2][2] ;
02189 //              break;
02190 //
02191 //      default:
02192 //              throw InvalidValueException(euler_type, "unknown Euler Type");
02193 //      }
02194 //
02195 //      return result;
02196 //}
02197 //
02198 //Transform3D Transform3D::inverseUsingAngs() const    //   YYN need to test it for sure
02199 //{
02200 //      // First Find the scale
02201 //      EulerType eE=EMAN;
02202 //
02203 //
02204 //      float scale   = get_scale();
02205 //      Vec3f preT   = get_pretrans( ) ;
02206 //      Vec3f postT   = get_posttrans( ) ;
02207 //      Dict angs     = get_rotation(eE);
02208 //      Dict invAngs  ;
02209 //
02210 //      invAngs["phi"]   = 180.0f - (float) angs["az"] ;
02211 //      invAngs["az"]    = 180.0f - (float) angs["phi"] ;
02212 //      invAngs["alt"]   = angs["alt"] ;
02213 //
02220 //
02221 //      float inverseScale= 1/scale ;
02222 //
02223 //      Transform3D invM;
02224 //
02225 //      invM.set_rotation(EMAN, invAngs);
02226 //      invM.apply_scale(inverseScale);
02227 //      invM.set_pretrans(-postT );
02228 //      invM.set_posttrans(-preT );
02229 //
02230 //
02231 //      return invM;
02232 //
02233 //}
02234 //
02235 //Transform3D Transform3D::inverse() const    //   YYN need to test it for sure
02236 //{
02237 //      // This assumes the matrix is 4 by 4 and the last row reads [0 0 0 1]
02238 //
02239 //      double m00 = matrix[0][0]; double m01=matrix[0][1]; double m02=matrix[0][2];
02240 //      double m10 = matrix[1][0]; double m11=matrix[1][1]; double m12=matrix[1][2];
02241 //      double m20 = matrix[2][0]; double m21=matrix[2][1]; double m22=matrix[2][2];
02242 //      double v0  = matrix[0][3]; double v1 =matrix[1][3]; double v2 =matrix[2][3];
02243 //
02244 //    double cof00 = m11*m22-m12*m21;
02245 //    double cof11 = m22*m00-m20*m02;
02246 //    double cof22 = m00*m11-m01*m10;
02247 //    double cof01 = m10*m22-m20*m12;
02248 //    double cof02 = m10*m21-m20*m11;
02249 //    double cof12 = m00*m21-m01*m20;
02250 //    double cof10 = m01*m22-m02*m21;
02251 //    double cof20 = m01*m12-m02*m11;
02252 //    double cof21 = m00*m12-m10*m02;
02253 //
02254 //    double Det = m00* cof00 + m02* cof02 -m01*cof01;
02255 //
02256 //    Transform3D invM;
02257 //
02258 //    invM.matrix[0][0] =  (float)(cof00/Det);
02259 //    invM.matrix[0][1] =  (float)(-cof10/Det);
02260 //    invM.matrix[0][2] =  (float)(cof20/Det);
02261 //    invM.matrix[1][0] =  (float)(-cof01/Det);
02262 //    invM.matrix[1][1] =  (float)(cof11/Det);
02263 //    invM.matrix[1][2] =  (float)(-cof21/Det);
02264 //    invM.matrix[2][0] =  (float)(cof02/Det);
02265 //    invM.matrix[2][1] =  (float)(-cof12/Det);
02266 //    invM.matrix[2][2] =  (float)(cof22/Det);
02267 //
02268 //    invM.matrix[0][3] =  (float)((-cof00*v0 + cof10*v1 - cof20*v2)/Det);
02269 //    invM.matrix[1][3] =  (float)(( cof01*v0 - cof11*v1 + cof21*v2)/Det);
02270 //    invM.matrix[2][3] =  (float)((-cof02*v0 + cof12*v1 - cof22*v2)/Det);
02271 //
02272 //      Vec3f postT   = get_posttrans( ) ;
02273 //      Vec3f invMpre   = - postT;
02274 //      Vec3f invMpost   ;
02275 //      for ( int i = 0; i < 3; i++) {
02276 //              invMpost[i] = invM.matrix[i][3];
02277 //              for ( int j = 0; j < 3; j++) {
02278 //                      invMpost[i] += - invM.matrix[i][j]*invMpre[j];
02279 //              }
02280 //              invM.matrix[3][i] = invMpost[i];
02281 //      }
02282 //
02283 //      return invM;
02284 //}
02285 //
02286 //
02287 //
02289 //
02290 //Transform3D Transform3D::get_sym(const string & symname, int n) const
02291 //{
02292 //      int nsym = get_nsym(symname);
02293 //
02296 //
02297 //      // see www.math.utah.edu/~alfeld/math/polyhedra/polyhedra.html for pictures
02298 //      // By default we will put largest symmetry along z-axis.
02299 //
02300 //      // Each Platonic Solid has 2E symmetry elements.
02301 //
02302 //
02303 //      // An icosahedron has   m=5, n=3, F=20 E=30=nF/2, V=12=nF/m,since vertices shared by 5 triangles;
02304 //      // It is composed of 20 triangles. E=3*20/2;
02305 //
02306 //
02307 //      // An dodecahedron has m=3, n=5   F=12 E=30  V=20
02308 //      // It is composed of 12 pentagons. E=5*12/2;   V= 5*12/3, since vertices shared by 3 pentagons;
02309 //
02310 //
02311 //
02312 //    // The ICOS symmetry group has the face along z-axis
02313 //
02314 //      float lvl0=0;                             //  there is one pentagon on top; five-fold along z
02315 //      float lvl1= 63.4349f; // that is atan(2)  // there are 5 pentagons with centers at this height (angle)
02316 //      float lvl2=116.5651f; //that is 180-lvl1  // there are 5 pentagons with centers at this height (angle)
02317 //      float lvl3=180.f;                           // there is one pentagon on the bottom
02318 //             // Notice that 63.439 is the angle between two faces of the dual object
02319 //
02320 //      static double ICOS[180] = { // This is with a pentagon normal to z
02321 //                0,lvl0,0,    0,lvl0,288,   0,lvl0,216,   0,lvl0,144,  0,lvl0,72,
02322 //                0,lvl1,36,   0,lvl1,324,   0,lvl1,252,   0,lvl1,180,  0,lvl1,108,
02323 //               72,lvl1,36,  72,lvl1,324,  72,lvl1,252,  72,lvl1,180,  72,lvl1,108,
02324 //              144,lvl1,36, 144,lvl1,324, 144,lvl1,252, 144,lvl1,180, 144,lvl1,108,
02325 //              216,lvl1,36, 216,lvl1,324, 216,lvl1,252, 216,lvl1,180, 216,lvl1,108,
02326 //              288,lvl1,36, 288,lvl1,324, 288,lvl1,252, 288,lvl1,180, 288,lvl1,108,
02327 //               36,lvl2,0,   36,lvl2,288,  36,lvl2,216,  36,lvl2,144,  36,lvl2,72,
02328 //              108,lvl2,0,  108,lvl2,288, 108,lvl2,216, 108,lvl2,144, 108,lvl2,72,
02329 //              180,lvl2,0,  180,lvl2,288, 180,lvl2,216, 180,lvl2,144, 180,lvl2,72,
02330 //              252,lvl2,0,  252,lvl2,288, 252,lvl2,216, 252,lvl2,144, 252,lvl2,72,
02331 //              324,lvl2,0,  324,lvl2,288, 324,lvl2,216, 324,lvl2,144, 324,lvl2,72,
02332 //                0,lvl3,0,    0,lvl3,288,   0,lvl3,216,   0,lvl3,144,   0,lvl3,72
02333 //      };
02334 //
02335 //
02336 //      // A cube has   m=3, n=4, F=6 E=12=nF/2, V=8=nF/m,since vertices shared by 3 squares;
02337 //      // It is composed of 6 squares.
02338 //
02339 //
02340 //      // An octahedron has   m=4, n=3, F=8 E=12=nF/2, V=6=nF/m,since vertices shared by 4 triangles;
02341 //      // It is composed of 8 triangles.
02342 //
02343 //    // We have placed the OCT symmetry group with a face along the z-axis
02344 //        lvl0=0;
02345 //      lvl1=90;
02346 //      lvl2=180;
02347 //
02348 //      static float OCT[72] = {// This is with a face of a cube along z
02349 //                    0,lvl0,0,   0,lvl0,90,    0,lvl0,180,    0,lvl0,270,
02350 //                    0,lvl1,0,   0,lvl1,90,    0,lvl1,180,    0,lvl1,270,
02351 //                   90,lvl1,0,  90,lvl1,90,   90,lvl1,180,   90,lvl1,270,
02352 //                  180,lvl1,0, 180,lvl1,90,  180,lvl1,180,  180,lvl1,270,
02353 //                  270,lvl1,0, 270,lvl1,90,  270,lvl1,180,  270,lvl1,270,
02354 //                    0,lvl2,0,   0,lvl2,90,    0,lvl2,180,    0,lvl2,270
02355 //      };
02356 //      // B^4=A^3=1;  BABA=1; implies   AA=BAB, ABA=B^3 , AB^2A = BBBABBB and
02357 //      //   20 words with at most a single A
02358 //    //   1 B BB BBB A  BA AB BBA BAB ABB BBBA BBAB BABB ABBB BBBAB BBABB BABBB
02359 //    //                        BBBABB BBABBB BBBABBB
02360 //     // also     ABBBA is distinct yields 4 more words
02361 //     //    ABBBA   BABBBA BBABBBA BBBABBBA
02362 //     // for a total of 24 words
02363 //     // Note A BBB A BBB A  reduces to BBABB
02364 //     //  and  B A BBB A is the same as A BBB A BBB etc.
02365 //
02366 //    // The TET symmetry group has a face along the z-axis
02367 //    // It has n=m=3; F=4, E=6=nF/2, V=4=nF/m
02368 //        lvl0=0;         // There is a face along z
02369 //      lvl1=109.4712f;  //  that is acos(-1/3)  // There  are 3 faces at this angle
02370 //
02371 //      static float TET[36] = {// This is with the face along z
02372 //            0,lvl0,0,   0,lvl0,120,    0,lvl0,240,
02373 //            0,lvl1,60,   0,lvl1,180,    0,lvl1,300,
02374 //          120,lvl1,60, 120,lvl1,180,  120,lvl1,300,
02375 //          240,lvl1,60, 240,lvl1,180,  240,lvl1,300
02376 //      };
02377 //      // B^3=A^3=1;  BABA=1; implies   A^2=BAB, ABA=B^2 , AB^2A = B^2AB^2 and
02378 //      //   12 words with at most a single A
02379 //    //   1 B BB  A  BA AB BBA BAB ABB BBAB BABB BBABB
02380 //    // at most one A is necessary
02381 //
02382 //      Transform3D ret;
02383 //      SymType type = get_sym_type(symname);
02384 //
02385 //      switch (type) {
02386 //      case CSYM:
02387 //              ret.set_rotation( n * 360.0f / nsym, 0, 0);
02388 //              break;
02389 //      case DSYM:
02390 //              if (n >= nsym / 2) {
02391 //                      ret.set_rotation((n - nsym/2) * 360.0f / (nsym / 2),180.0f, 0);
02392 //              }
02393 //              else {
02394 //                      ret.set_rotation( n * 360.0f / (nsym / 2),0, 0);
02395 //              }
02396 //              break;
02397 //      case ICOS_SYM:
02398 //              ret.set_rotation((float)ICOS[n * 3 ],
02399 //                               (float)ICOS[n * 3 + 1],
02400 //                               (float)ICOS[n * 3 + 2] );
02401 //              break;
02402 //      case OCT_SYM:
02403 //              ret.set_rotation((float)OCT[n * 3],
02404 //                               (float)OCT[n * 3 + 1],
02405 //                               (float)OCT[n * 3 + 2] );
02406 //              break;
02407 //      case TET_SYM:
02408 //              ret.set_rotation((float)TET[n * 3 ],
02409 //                               (float)TET[n * 3 + 1] ,
02410 //                               (float)TET[n * 3 + 2] );
02411 //              break;
02412 //      case ISYM:
02413 //              ret.set_rotation(0, 0, 0);
02414 //              break;
02415 //      default:
02416 //              throw InvalidValueException(type, symname);
02417 //      }
02418 //
02419 //      ret = (*this) * ret;
02420 //
02421 //      return ret;
02422 //}
02423 //
02424 //int Transform3D::get_nsym(const string & name)
02425 //{
02426 //      string symname = name;
02427 //
02428 //      for (size_t i = 0; i < name.size(); i++) {
02429 //              if (isalpha(name[i])) {
02430 //                      symname[i] = (char)tolower(name[i]);
02431 //              }
02432 //      }
02433 //
02434 //      SymType type = get_sym_type(symname);
02435 //      int nsym = 0;
02436 //
02437 //      switch (type) {
02438 //      case CSYM:
02439 //              nsym = atoi(symname.c_str() + 1);
02440 //              break;
02441 //      case DSYM:
02442 //              nsym = atoi(symname.c_str() + 1) * 2;
02443 //              break;
02444 //      case ICOS_SYM:
02445 //              nsym = 60;
02446 //              break;
02447 //      case OCT_SYM:
02448 //              nsym = 24;
02449 //              break;
02450 //      case TET_SYM:
02451 //              nsym = 12;
02452 //              break;
02453 //      case ISYM:
02454 //              nsym = 1;
02455 //              break;
02456 //      case UNKNOWN_SYM:
02457 //      default:
02458 //              throw InvalidValueException(type, name);
02459 //      }
02460 //      return nsym;
02461 //}
02462 //
02463 //
02464 //
02465 //Transform3D::SymType Transform3D::get_sym_type(const string & name)
02466 //{
02467 //      SymType t = UNKNOWN_SYM;
02468 //
02469 //      if (name[0] == 'c') {
02470 //              t = CSYM;
02471 //      }
02472 //      else if (name[0] == 'd') {
02473 //              t = DSYM;
02474 //      }
02475 //      else if (name == "icos") {
02476 //              t = ICOS_SYM;
02477 //      }
02478 //      else if (name == "oct") {
02479 //              t = OCT_SYM;
02480 //      }
02481 //      else if (name == "tet") {
02482 //              t = TET_SYM;
02483 //      }
02484 //      else if (name == "i" || name == "") {
02485 //              t = ISYM;
02486 //      }
02487 //      return t;
02488 //}
02489 //
02490 //vector<Transform3D*>
02491 //Transform3D::angles2tfvec(EulerType eulertype, const vector<float> ang) {
02492 //      int nangles = ang.size() / 3;
02493 //      vector<Transform3D*> tfvec;
02494 //      for (int i = 0; i < nangles; i++) {
02495 //              tfvec.push_back(new Transform3D(eulertype,ang[3*i],ang[3*i+1],ang[3*i+2]));
02496 //      }
02497 //      return tfvec;
02498 //}
02499 //
02500 
02501 
02502 
02503 /* vim: set ts=4 noet: */
02504 
02505 
02506 /*    Rotation stuff */
02507 

Generated on Mon May 2 13:26:57 2011 for EMAN2 by  doxygen 1.4.7