00001 00005 /* 00006 * Author: Steven Ludtke (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 00037 #ifndef eman__transform_h__ 00038 #define eman__transform_h__ 1 00039 00040 #ifdef _WIN32 00041 #pragma warning(disable:4819) 00042 #endif //_WIN32 00043 00044 #include "vec3.h" 00045 #include "emobject.h" 00046 #include <cstdio> 00047 // #include <vector> 00048 // using std::vector; 00049 // 00050 // #include <map> 00051 // using std::map; 00052 // 00053 // #include <string> 00054 // using std::string; 00055 00056 00057 00058 namespace EMAN 00059 { 00083 class Transform { 00084 // friend Transform EMAN::operator*(const Transform & M2, const Transform & M1); 00085 public: 00086 static const float ERR_LIMIT; 00087 00091 Transform(); 00092 00096 Transform( const Transform& rhs ); 00097 00101 Transform& operator=(const Transform& that); 00102 00107 bool operator==(const Transform& rhs) const; 00108 00113 bool operator!=(const Transform& rhs) const; 00114 00118 Transform(const Dict& d); 00119 00123 Transform(const float array[12]); 00124 00128 Transform(const vector<float> array); 00129 00130 00131 ~Transform() { } 00132 00137 void set_rotation( const Dict &rotation ); 00138 00144 void set_rotation(const Vec3f & v); 00145 00149 void rotate_origin(const Transform& by); 00150 00154 void rotate(const Transform& by); 00155 00160 Dict get_rotation(const string& euler_type = "eman") const; 00161 00162 00166 Transform get_rotation_transform() const; 00167 00171 Transform get_hflip_transform() const; 00172 00176 Transform get_vflip_transform() const; 00177 00183 void set_params(const Dict& d); 00184 00191 void set_params_inverse(const Dict& d); 00192 00197 Dict get_params(const string& euler_type) const; 00198 00203 Dict get_params_inverse(const string& euler_type) const; 00204 00205 //=============== set and get post trans ============= 00211 void set_trans(const float& x, const float& y, const float& z=0); 00212 00216 inline void set_trans(const Vec3f& v) { set_trans(v[0],v[1],v[2]); } 00217 00221 inline void set_trans(const Vec2f& v) { set_trans(v[0],v[1]); } 00222 00226 Vec3f get_trans() const; 00227 00233 void translate(const float& tx, const float& ty, const float& tz=0); 00234 00238 inline void translate(const Vec3f& v) { translate(v[0],v[1],v[2]); } 00239 00243 inline void translate(const Vec2f& v) { translate(v[0],v[1]); } 00244 00248 Vec2f get_trans_2d() const; 00249 00250 //================= get pre trans is supported ========= 00251 00256 Vec3f get_pre_trans() const; 00257 00262 Vec2f get_pre_trans_2d() const; 00263 00268 template<typename type> 00269 void set_pre_trans(const type& v); 00270 00271 //=============== set and get scale ============= 00275 void set_scale(const float& scale); 00276 00280 float get_scale() const; 00281 00285 void scale(const float& scale); 00286 00287 //=============== set and get post x mirror ============= 00291 bool get_mirror() const; 00292 00296 void set_mirror(const bool x_mirror); 00297 00298 //=============== other stuff ============================ 00304 void get_scale_and_mirror(float& scale, bool& x_mirror) const; 00305 00308 void to_identity(); 00309 00312 bool is_identity() const; 00313 00320 void orthogonalize(); 00321 00325 float get_determinant() const; 00326 00329 void printme() const { 00330 printf("%8.6f %8.6f %8.6f %8.6f\n",matrix[0][0],matrix[0][1],matrix[0][2],matrix[0][3]); 00331 printf("%8.6f %8.6f %8.6f %8.6f\n",matrix[1][0],matrix[1][1],matrix[1][2],matrix[1][3]); 00332 printf("%8.6f %8.6f %8.6f %8.6f\n",matrix[2][0],matrix[2][1],matrix[2][2],matrix[2][3]); 00333 printf("%8.6f %8.6f %8.6f %8.6f\n",0.0,0.0,0.0,1.0); 00334 00335 } 00336 00337 //=============== get set matrix ============================ 00341 void set_matrix(const vector<float>& v); 00342 00346 vector<float> get_matrix() const; 00347 00351 vector<float> get_matrix_4x4() const; 00352 00356 void invert(); 00357 00361 Transform inverse() const; 00362 00365 void transpose_inplace(); 00366 00370 Transform transpose() const; 00371 00374 inline float at(int r,int c) const { return matrix[r][c]; } 00375 00378 inline void set(int r, int c, float value) { matrix[r][c] = value; } 00379 00383 inline float * operator[] (int i) { return matrix[i]; } 00384 00388 inline const float * operator[] (int i) const { return matrix[i]; } 00389 00395 inline Vec2f transform(const float& x, const float& y) const { 00396 // assert_valid_2d(); 00397 Vec2f ret; 00398 ret[0] = matrix[0][0]*x + matrix[0][1]*y + matrix[0][3]; 00399 ret[1] = matrix[1][0]*x + matrix[1][1]*y + matrix[1][3]; 00400 return ret; 00401 } 00402 00407 template<typename Type> 00408 inline Vec2f transform(const Vec2<Type>& v) const { 00409 return transform(v[0],v[1]); 00410 } 00411 00418 inline Vec3f transform(const float& x, const float& y, const float& z) const { 00419 // assert_consistent_type(THREED); 00420 Vec3f ret; 00421 ret[0] = matrix[0][0] * x + matrix[0][1] * y + matrix[0][2] * z + matrix[0][3]; 00422 ret[1] = matrix[1][0] * x + matrix[1][1] * y + matrix[1][2] * z + matrix[1][3]; 00423 ret[2] = matrix[2][0] * x + matrix[2][1] * y + matrix[2][2] * z + matrix[2][3]; 00424 return ret; 00425 } 00426 00431 template<typename Type> 00432 inline Vec3f transform(const Vec3<Type>& v) const { 00433 // assert_consistent_type(THREED); // Transform does the assertion 00434 return transform(v[0],v[1],v[2]); 00435 } 00436 00437 00443 inline Vec3f get_matrix3_row(int i) const { 00444 return Vec3f(matrix[i][0], matrix[i][1], matrix[i][2]); 00445 } 00446 00449 static int get_nsym(const string & sym); 00450 00455 Transform get_sym(const string & sym, int n) const; 00456 vector<Transform > get_sym_proj(const string & sym) const; 00457 00460 void copy_matrix_into_array(float* const) const; 00461 00466 Transform negate() const; 00467 00471 static Transform tet_3_to_2(); 00472 00476 static Transform icos_5_to_2(); 00477 00478 private: 00479 float matrix[3][4]; 00480 00481 void assert_valid_2d() const; 00482 00484 static vector<string> permissable_2d_not_rot; 00485 static vector<string> permissable_3d_not_rot; 00486 static map<string,vector<string> > permissable_rot_keys; 00487 00490 void init_permissable_keys(); 00491 00499 void detect_problem_keys(const Dict& d); 00500 00501 }; 00503 Transform operator*(const Transform & M2, const Transform & M1); 00504 00506 template<typename Type> 00507 Vec3f operator*( const Transform& M, const Vec3<Type> & v) 00508 { 00509 return M.transform(v); 00510 } 00511 00513 template<typename Type> 00514 Vec2f operator*( const Transform& M, const Vec2<Type> & v) 00515 { 00516 return M.transform(v); 00517 } 00518 00522 template<typename Type> 00523 Vec3f operator*(const Vec3<Type> & v, const Transform & M) 00524 { 00525 float x = v[0] * M[0][0] + v[1] * M[1][0] + v[2] * M[2][0] ; 00526 float y = v[0] * M[0][1] + v[1] * M[1][1] + v[2] * M[2][1]; 00527 float z = v[0] * M[0][2] + v[1] * M[1][2] + v[2] * M[2][2]; 00528 return Vec3f(x, y, z); 00529 } 00530 00531 template<typename type> 00532 void Transform::set_pre_trans(const type& v) { 00533 00534 Transform tmp; 00535 Dict rot = get_rotation("eman"); 00536 tmp.set_rotation(rot); 00537 00538 float scale = get_scale(); 00539 if (scale != 1.0 ) tmp.set_scale(scale); 00540 00541 Transform trans; 00542 trans.set_trans(v); 00543 00544 trans = tmp*trans; 00545 00546 Transform tmp2; 00547 tmp2.set_rotation(rot); 00548 tmp2.invert(); // invert 00549 if (scale != 1.0 ) tmp2.set_scale(1.0f/scale); 00550 00551 00552 trans = trans*tmp2; 00553 00554 set_trans(trans.get_trans()); 00555 } 00556 00600 // class Transform3D 00601 // { 00602 // public: 00603 // static const float ERR_LIMIT; 00604 // enum EulerType 00605 // { 00606 // UNKNOWN, 00607 // EMAN, 00608 // IMAGIC, 00609 // SPIN, 00610 // QUATERNION, 00611 // SGIROT, 00612 // SPIDER, 00613 // MRC, 00614 // XYZ, 00615 // MATRIX 00616 // }; 00617 // 00618 // /** Default constructor 00619 // * Internal matrix is the identity 00620 // */ 00621 // Transform3D(); 00622 // 00623 // /** Copy constructor 00624 // * @param rhs the object to be copied 00625 // */ 00626 // Transform3D( const Transform3D& rhs ); 00627 // 00628 // /** Construct a Transform3D object describing a rotation, assuming the EMAN Euler type 00629 // * @param az EMAN - az 00630 // * @param alt EMAN - alt 00631 // * @param phi EMAN - phi 00632 // */ 00633 // Transform3D(const float& az,const float& alt,const float& phi); // EMAN by default 00634 // 00635 // /** Construct a Transform3D object describing a rotation (assuming the EMAN Euler type) and 00636 // * a post translation 00637 // * @param az EMAN - az 00638 // * @param alt EMAN - alt 00639 // * @param phi EMAN - phi 00640 // * @param posttrans the post translation vector 00641 // */ 00642 // Transform3D(const float& az, const float& alt, const float& phi, const Vec3f& posttrans); 00643 // 00644 // /** Construct a Transform3D object describing a pre trans, a rotation 00645 // * assuming the EMAN Euler type) and a post translation 00646 // * @param pretrans the pre translation vector 00647 // * @param az EMAN - az 00648 // * @param alt EMAN - alt 00649 // * @param phi EMAN - phi 00650 // * @param posttrans the post translation vector 00651 // */ 00652 // Transform3D(const Vec3f & pretrans, const float& az,const float& alt,const float& phi, const Vec3f& posttrans); 00653 // 00654 // /** Construct a Transform3D object describing a rotation, using a specific Euler type. 00655 // * works for EMAN, SPIDER, MRC, IMAGIC and XYZ (Euler types required 3 parameters) 00656 // * @param euler_type the Euler type either EMAN, SPIDER, MRC, IMAGIC and XYZ 00657 // * @param a1 EMAN - az, SPIDER - phi, MRC - phi, IMAGIC - alpha, XYZ - xtilt 00658 // * @param a2 EMAN - alt, SPIDER - theta, MRC - theta, IMAGIC - beta, XYZ - ytilt 00659 // * @param a3 EMAN - phi, SPIDER - psi, MRC - omega, IMAGIC - gamma, XYZ - ztilt 00660 // */ 00661 // Transform3D(EulerType euler_type, const float& a1, const float& a2, const float& a3) ; 00662 // 00663 // /** Construct a Transform3D object describing a rotation, using a specific Euler type. 00664 // * Works for Euler types that require 4 parameters 00665 // * @param euler_type the Euler type either QUATERNION, SPIN or SGIROT 00666 // * @param a1 QUATERNION - e0, SPN and SGIROT - Omega 00667 // * @param a2 QUATERNION - e1, SPN and SGIROT - n1 00668 // * @param a3 QUATERNION - e2, SPN and SGIROT - n2 00669 // * @param a4 QUATERNION - e3, SPN and SGIROT - n3 00670 // */ 00671 // Transform3D(EulerType euler_type, const float& a1, const float& a2, const float& a3, const float& a4) ; // o 00672 // 00673 // /** Construct a Transform3D object consisting only of a rotation, using a specific Euler type. 00674 // * Works for all Euler types 00675 // * @param euler_type any Euler type 00676 // * @param rotation a dictionary containing all key-entry pair required of the associated Euler type 00677 // */ 00678 // Transform3D(EulerType euler_type, const Dict& rotation); 00679 // 00680 // /** Construct a Transform3D object consisting only of a rotation by initializing the internal 00681 // * rotation matrix component wise 00682 // * @param mij the value to be placed in the internal transformation matrix at coordinate (i-1,j-1) 00683 // */ 00684 // Transform3D(const float& m11, const float& m12, const float& m13, 00685 // const float& m21, const float& m22, const float& m23, 00686 // const float& m31, const float& m32, const float& m33); 00687 // 00688 // /** Destructor 00689 // */ 00690 // ~Transform3D(); 00691 // 00692 // /** FIXME insert comments 00693 // */ 00694 // void apply_scale(const float& scale); 00695 // 00696 // /** FIXME insert comments 00697 // */ 00698 // void set_scale(const float& scale); 00699 // 00700 // /** Reorthogonalize the matrix 00701 // */ 00702 // void orthogonalize(); 00703 // 00704 // /** create the transpose in place 00705 // */ 00706 // void transpose(); 00707 // 00708 // void set_rotation(const float& az, const float& alt,const float& phi); 00709 // 00710 // /** Sets the rotation as defined by the EulerType 00711 // * works for EMAN, SPIDER, MRC, IMAGIC and XYZ 00712 // * @param euler_type the Euler type either EMAN, SPIDER, MRC, IMAGIC and XYZ 00713 // * @param a1 EMAN - az, SPIDER - phi, MRC - phi, IMAGIC - alpha, XYZ - xtilt 00714 // * @param a2 EMAN - alt, SPIDER - theta, MRC - theta, IMAGIC - beta, XYZ - ytilt 00715 // * @param a3 EMAN - phi, SPIDER - psi, MRC - omega, IMAGIC - gamma, XYZ - ztilt 00716 // */ 00717 // void set_rotation(EulerType euler_type,const float& a1,const float& a2,const float& a3); 00718 // 00719 // /** Set quaternion-based rotations 00720 // * Works for QUATERNION, SPIN and SGIROT 00721 // * @param euler_type the Euler type either QUATERNION, SPIN or SGIROT 00722 // * @param a1 QUATERNION - e0, SPN and SGIROT - Omega 00723 // * @param a2 QUATERNION - e1, SPN and SGIROT - n1 00724 // * @param a3 QUATERNION - e2, SPN and SGIROT - n2 00725 // * @param a4 QUATERNION - e3, SPN and SGIROT - n3 00726 // */ 00727 // void set_rotation(EulerType euler_type,const float& a1,const float& a2,const float& a3, const float& a4); 00728 // 00729 // /** set the internal rotation matrix component wise 00730 // * @param mij the value to be placed in the internal transformation matrix at coordinate (i-1,j-1) 00731 // */ 00732 // void set_rotation(const float& m11, const float& m12, const float& m13, 00733 // const float& m21, const float& m22, const float& m23, 00734 // const float& m31, const float& m32, const float& m33); 00735 // 00739 // 00740 // /** Set a rotation using a specific Euler type and the dictionary interface 00741 // * Works for all Euler types 00742 // * @param euler_type any Euler type 00743 // * @param rotation a dictionary containing all key-entry pair required of the associated Euler type 00744 // */ 00745 // void set_rotation(EulerType euler_type, const Dict &rotation ); 00746 // 00747 // /** Get a rotation in any Euler format 00748 // * @param euler_type the requested Euler type 00749 // * @return a dictionary containing the key-entry pairs describing the rotations in terms of the requested Euler type 00750 // */ 00751 // Dict get_rotation(EulerType euler_type=EMAN) const; 00752 // 00753 // /** returns a rotation that maps a pair of unit vectors, a,b to a second pair A,B 00754 // * @param eahat, ebhat, eAhat, eBhat are all unit vectors 00755 // * @return a transform3D rotation 00756 // */ 00757 // void set_rotation(const Vec3f & eahat, const Vec3f & ebhat, 00758 // const Vec3f & eAhat, const Vec3f & eBhat); 00759 // /** returns the magnitude of the rotation 00760 // */ 00761 // float get_mag() const; 00762 // 00763 // /** returns the spin-axis (or finger) of the rotation 00764 // */ 00765 // Vec3f get_finger() const; 00766 // 00767 // /** Gets one of two pre translation vectors 00768 // * @param flag if 0 returns the pre translation vector, if 1 all translation is treated as pre 00769 // * @return the translation vector 00770 // */ 00771 // Vec3f get_pretrans( int flag=0) const; // flag=1 => all trans is pre 00772 // 00773 // /** Gets one of two post translation vectors. 00774 // * when the flag is 1 then the contents of the Transform3D matrix right column are returned 00775 // * @param flag if 0 returns the post translation vector, if 1 all translation is treated as post 00776 // * @return the translation vector 00777 // */ 00778 // Vec3f get_posttrans(int flag=0) const; // flag=1 => all trans is post 00779 // 00780 // /** Get the total translation as a post translation. Calls get_postrans(1) 00781 // * @return the translation vector 00782 // */ 00783 // Vec3f get_total_posttrans() const; 00784 // 00785 // /** Get the total translation as a pre translation. Calls get_pretrans(1) 00786 // * @return the translation vector 00787 // */ 00788 // Vec3f get_total_pretrans() const; 00789 // 00790 // /** This doesn't do anything, it returns an empty vector. Why is it being used? 00791 // */ 00792 // Vec3f get_center() const; // This doesn't do anything 00793 // 00794 // /** Get a matrix column as a Vec3f 00795 // * @param i the column number (starting at 0) 00796 // * @return the ith column 00797 // */ 00798 // Vec3f get_matrix3_col(int i) const; 00799 // 00800 // /** Get a matrix row as a Vec3f 00801 // * @param i the row number (starting at 0) 00802 // * @return the ith row 00803 // */ 00804 // Vec3f get_matrix3_row(int i) const; 00805 // 00806 // /** Perform a full transform a Vec3f using the internal transformation matrix 00807 // * @param v3f the vector to be transformed 00808 // * @return the transformed vector 00809 // */ 00810 // Vec3f transform(const Vec3f & v3f) const; 00811 // 00812 // /** Rotate a Vec3f using the internal rotation matrix 00813 // * @param v3f the vector to be rotated 00814 // * @return the rotated vector 00815 // */ 00816 // Vec3f rotate(const Vec3f & v3f) const; 00817 // 00818 // /** FIXME insert comments 00819 // */ 00820 // Transform3D inverseUsingAngs() const; 00821 // 00822 // /** FIXME insert comments 00823 // */ 00824 // Transform3D inverse() const; 00825 // 00826 // 00827 // /** Print the Transform3D matrix 00828 // */ 00829 // void printme() const { 00830 // for (int i=0; i<3; i++) { 00831 // printf("%6.15f\t%6.15f\t%6.15f\t%6.1f\n", 00832 // matrix[i][0],matrix[i][1],matrix[i][2],matrix[i][3]); 00833 // } 00834 // printf("%6.3f\t%6.3f\t%6.3f\t%6.3f\n",0.0,0.0,0.0,1.0); 00835 // printf("\n"); 00836 // } 00837 // 00838 // /** Get the value stored in the internal transformation matrix at at coordinate (r,c) 00839 // */ 00840 // inline float at(int r,int c) const { return matrix[r][c]; } 00841 // 00842 // /** Set the value stored in the internal transformation matrix at at coordinate (r,c) to value 00843 // */ 00844 // void set(int r, int c, float value) { matrix[r][c] = value; } 00845 // 00846 // /** Operator[] convenience 00847 // * so Transform3D[2][2] etc terminology can be used 00848 // */ 00849 // inline float * operator[] (int i) { return matrix[i]; } 00850 // 00851 // /** Operator[] convenience 00852 // * so Transform3D[2][2] etc terminology can be used 00853 // */ 00854 // inline const float * operator[] (int i) const { return matrix[i]; } 00855 // 00856 // static int get_nsym(const string & sym); 00857 // Transform3D get_sym(const string & sym, int n) const; 00858 // 00859 // /** Set functions FIXME insert more comments from here down 00860 // */ 00861 // void set_center(const Vec3f & center); 00862 // void set_pretrans(const Vec3f & pretrans); 00863 // void set_pretrans(const float& dx, const float& dy, const float& dz); 00864 // void set_pretrans(const float& dx, const float& dy); 00865 // void set_pretrans(const Vec2f& pretrans); 00866 // void set_posttrans(const Vec3f & posttrans); 00867 // void set_posttrans(const float& dx, const float& dy, const float& dz); 00868 // void set_posttrans(const float& dx, const float& dy); 00869 // void set_posttrans(const Vec2f& posttrans); 00870 // 00871 // void set_post_x_mirror(const bool b) { post_x_mirror = b; } 00872 // bool get_post_x_mirror() const { return post_x_mirror; } 00873 // 00874 // float get_scale() const; 00875 // 00876 // void to_identity(); 00877 // bool is_identity(); 00878 // 00879 // /** Convert a list of euler angles to a vector of Transform3D objects. 00880 // * 00881 // * @param[in] eulertype The type of Euler angles that is being passed in. 00882 // * @param[in] angles A flat vector of angles. 00883 // * 00884 // * @return Vector of pointers to Transform3D objects. 00885 // */ 00886 // static vector<Transform3D*> 00887 // angles2tfvec(EulerType eulertype, const vector<float> angles); 00888 // 00889 // /** This added by d.woolford, will eventually be removed by author 00890 // */ 00891 // void dsaw_zero_hack(){ 00892 // for (int j=0; j<4; ++j) { 00893 // for (int i=0; i<4; i++) { 00894 // if ( fabs(matrix[j][i]) < 0.000001 ) 00895 // matrix[j][i] = 0.0; 00896 // } 00897 // } 00898 // 00899 // } 00900 // 00901 // protected: 00902 // enum SymType 00903 // { CSYM, 00904 // DSYM, 00905 // TET_SYM, 00906 // ICOS_SYM, 00907 // OCT_SYM, 00908 // ISYM, 00909 // UNKNOWN_SYM 00910 // }; 00911 // 00912 // void init(); 00913 // 00914 // static SymType get_sym_type(const string & symname); 00915 // 00916 // float matrix[4][4]; 00917 // 00918 // bool post_x_mirror; 00919 // 00920 // Transform3D::EulerType s; 00921 // }; // ends Class 00922 // 00923 // Transform3D operator*(const Transform3D & M1, const Transform3D & M2); 00924 // Vec3f operator*(const Vec3f & v , const Transform3D & M); 00925 // Vec3f operator*(const Transform3D & M, const Vec3f & v ); 00926 00927 // template<typename Type> 00928 // Vec3f operator*(const Vec3<Type> & v, const Transform3D & M) // YYY 00929 // { 00931 // float x = v[0] * M[0][0] + v[1] * M[1][0] + v[2] * M[2][0] ; 00932 // float y = v[0] * M[0][1] + v[1] * M[1][1] + v[2] * M[2][1]; 00933 // float z = v[0] * M[0][2] + v[1] * M[1][2] + v[2] * M[2][2]; 00934 // return Vec3f(x, y, z); 00935 // } 00936 // 00937 // template<typename Type> 00938 // Vec3f operator*( const Transform3D & M, const Vec3<Type> & v) // YYY 00939 // { 00941 // float x = M[0][0] * v[0] + M[0][1] * v[1] + M[0][2] * v[2] + M[0][3]; 00942 // float y = M[1][0] * v[0] + M[1][1] * v[1] + M[1][2] * v[2] + M[1][3]; 00943 // float z = M[2][0] * v[0] + M[2][1] * v[1] + M[2][2] * v[2] + M[2][3]; 00944 // return Vec3f(x, y, z); 00945 // } 00946 // 00947 // 00948 // template<typename Type> 00949 // Vec2f operator*( const Transform3D & M, const Vec2<Type> & v) // YYY 00950 // { 00952 // float x = M[0][0] * v[0] + M[0][1] * v[1] + M[0][3] ; 00953 // float y = M[1][0] * v[0] + M[1][1] * v[1] + M[1][3]; 00954 // return Vec2f(x, y); 00955 // } 00956 00957 } // ends NameSpace EMAN 00958 00959 00960 00961 #endif 00962 00963 00964 /* vim: set ts=4 noet: */