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 00157 void rotate_origin_newBasis(const Transform& tcs, const float& omega, const float& n1, const float& n2, const float& n3); 00158 00162 void rotate(const Transform& by); 00163 00168 Dict get_rotation(const string& euler_type = "eman") const; 00169 00170 00174 Transform get_rotation_transform() const; 00175 00179 Transform get_hflip_transform() const; 00180 00184 Transform get_vflip_transform() const; 00185 00191 void set_params(const Dict& d); 00192 00199 void set_params_inverse(const Dict& d); 00200 00205 Dict get_params(const string& euler_type) const; 00206 00211 Dict get_params_inverse(const string& euler_type) const; 00212 00213 //=============== set and get post trans ============= 00219 void set_trans(const float& x, const float& y, const float& z=0); 00220 00224 inline void set_trans(const Vec3f& v) { set_trans(v[0],v[1],v[2]); } 00225 00229 inline void set_trans(const Vec2f& v) { set_trans(v[0],v[1]); } 00230 00234 Vec3f get_trans() const; 00235 00241 void translate(const float& tx, const float& ty, const float& tz=0); 00242 00246 inline void translate(const Vec3f& v) { translate(v[0],v[1],v[2]); } 00247 00251 inline void translate(const Vec2f& v) { translate(v[0],v[1]); } 00252 00261 void translate_newBasis(const Transform& tcs, const float& tx, const float& ty, const float& tz=0); 00262 00266 inline void translate(const Transform& tcs, const Vec3f& v) { translate_newBasis(tcs, v[0],v[1],v[2]); } 00267 00271 Vec2f get_trans_2d() const; 00272 00273 //================= get pre trans is supported ========= 00274 00279 Vec3f get_pre_trans() const; 00280 00285 Vec2f get_pre_trans_2d() const; 00286 00291 template<typename type> 00292 void set_pre_trans(const type& v); 00293 00294 //=============== set and get scale ============= 00298 void set_scale(const float& scale); 00299 00303 float get_scale() const; 00304 00308 void scale(const float& scale); 00309 00310 //=============== set and get post x mirror ============= 00314 bool get_mirror() const; 00315 00319 void set_mirror(const bool x_mirror); 00320 00321 //=============== other stuff ============================ 00327 void get_scale_and_mirror(float& scale, bool& x_mirror) const; 00328 00331 void to_identity(); 00332 00335 bool is_identity() const; 00336 00339 bool is_rot_identity() const; 00340 00347 void orthogonalize(); 00348 00352 float get_determinant() const; 00353 00356 void printme() const { 00357 printf("%8.6f %8.6f %8.6f %8.6f\n",matrix[0][0],matrix[0][1],matrix[0][2],matrix[0][3]); 00358 printf("%8.6f %8.6f %8.6f %8.6f\n",matrix[1][0],matrix[1][1],matrix[1][2],matrix[1][3]); 00359 printf("%8.6f %8.6f %8.6f %8.6f\n",matrix[2][0],matrix[2][1],matrix[2][2],matrix[2][3]); 00360 printf("%8.6f %8.6f %8.6f %8.6f\n",0.0,0.0,0.0,1.0); 00361 00362 } 00363 00364 //=============== get set matrix ============================ 00368 void set_matrix(const vector<float>& v); 00369 00373 vector<float> get_matrix() const; 00374 00378 vector<float> get_matrix_4x4() const; 00379 00383 void invert(); 00384 00388 Transform inverse() const; 00389 00392 void transpose_inplace(); 00393 00397 Transform transpose() const; 00398 00401 inline float at(int r,int c) const { return matrix[r][c]; } 00402 00405 inline void set(int r, int c, float value) { matrix[r][c] = value; } 00406 00410 inline float * operator[] (int i) { return matrix[i]; } 00411 00415 inline const float * operator[] (int i) const { return matrix[i]; } 00416 00422 inline Vec2f transform(const float& x, const float& y) const { 00423 // assert_valid_2d(); 00424 Vec2f ret; 00425 ret[0] = matrix[0][0]*x + matrix[0][1]*y + matrix[0][3]; 00426 ret[1] = matrix[1][0]*x + matrix[1][1]*y + matrix[1][3]; 00427 return ret; 00428 } 00429 00434 template<typename Type> 00435 inline Vec2f transform(const Vec2<Type>& v) const { 00436 return transform(v[0],v[1]); 00437 } 00438 00445 inline Vec3f transform(const float& x, const float& y, const float& z) const { 00446 // assert_consistent_type(THREED); 00447 Vec3f ret; 00448 ret[0] = matrix[0][0] * x + matrix[0][1] * y + matrix[0][2] * z + matrix[0][3]; 00449 ret[1] = matrix[1][0] * x + matrix[1][1] * y + matrix[1][2] * z + matrix[1][3]; 00450 ret[2] = matrix[2][0] * x + matrix[2][1] * y + matrix[2][2] * z + matrix[2][3]; 00451 return ret; 00452 } 00453 00458 template<typename Type> 00459 inline Vec3f transform(const Vec3<Type>& v) const { 00460 // assert_consistent_type(THREED); // Transform does the assertion 00461 return transform(v[0],v[1],v[2]); 00462 } 00463 00464 00470 inline Vec3f get_matrix3_row(int i) const { 00471 return Vec3f(matrix[i][0], matrix[i][1], matrix[i][2]); 00472 } 00473 00476 static int get_nsym(const string & sym); 00477 00482 Transform get_sym(const string & sym, int n) const; 00483 vector<Transform > get_sym_proj(const string & sym) const; 00484 00487 void copy_matrix_into_array(float* const) const; 00488 00493 Transform negate() const; 00494 00498 static Transform tet_3_to_2(); 00499 00503 static Transform icos_5_to_2(); 00504 00505 private: 00506 float matrix[3][4]; 00507 00508 void assert_valid_2d() const; 00509 00511 static vector<string> permissable_2d_not_rot; 00512 static vector<string> permissable_3d_not_rot; 00513 static map<string,vector<string> > permissable_rot_keys; 00514 00517 void init_permissable_keys(); 00518 00526 void detect_problem_keys(const Dict& d); 00527 00528 }; 00530 Transform operator*(const Transform & M2, const Transform & M1); 00531 00533 template<typename Type> 00534 Vec3f operator*( const Transform& M, const Vec3<Type> & v) 00535 { 00536 return M.transform(v); 00537 } 00538 00540 template<typename Type> 00541 Vec2f operator*( const Transform& M, const Vec2<Type> & v) 00542 { 00543 return M.transform(v); 00544 } 00545 00549 template<typename Type> 00550 Vec3f operator*(const Vec3<Type> & v, const Transform & M) 00551 { 00552 float x = v[0] * M[0][0] + v[1] * M[1][0] + v[2] * M[2][0] ; 00553 float y = v[0] * M[0][1] + v[1] * M[1][1] + v[2] * M[2][1]; 00554 float z = v[0] * M[0][2] + v[1] * M[1][2] + v[2] * M[2][2]; 00555 return Vec3f(x, y, z); 00556 } 00557 00558 template<typename type> 00559 void Transform::set_pre_trans(const type& v) { 00560 00561 Transform tmp; 00562 Dict rot = get_rotation("eman"); 00563 tmp.set_rotation(rot); 00564 00565 float scale = get_scale(); 00566 if (scale != 1.0 ) tmp.set_scale(scale); 00567 00568 Transform trans; 00569 trans.set_trans(v); 00570 00571 trans = tmp*trans; 00572 00573 Transform tmp2; 00574 tmp2.set_rotation(rot); 00575 tmp2.invert(); // invert 00576 if (scale != 1.0 ) tmp2.set_scale(1.0f/scale); 00577 00578 00579 trans = trans*tmp2; 00580 00581 set_trans(trans.get_trans()); 00582 } 00583 00627 // class Transform3D 00628 // { 00629 // public: 00630 // static const float ERR_LIMIT; 00631 // enum EulerType 00632 // { 00633 // UNKNOWN, 00634 // EMAN, 00635 // IMAGIC, 00636 // SPIN, 00637 // QUATERNION, 00638 // SGIROT, 00639 // SPIDER, 00640 // MRC, 00641 // XYZ, 00642 // MATRIX 00643 // }; 00644 // 00645 // /** Default constructor 00646 // * Internal matrix is the identity 00647 // */ 00648 // Transform3D(); 00649 // 00650 // /** Copy constructor 00651 // * @param rhs the object to be copied 00652 // */ 00653 // Transform3D( const Transform3D& rhs ); 00654 // 00655 // /** Construct a Transform3D object describing a rotation, assuming the EMAN Euler type 00656 // * @param az EMAN - az 00657 // * @param alt EMAN - alt 00658 // * @param phi EMAN - phi 00659 // */ 00660 // Transform3D(const float& az,const float& alt,const float& phi); // EMAN by default 00661 // 00662 // /** Construct a Transform3D object describing a rotation (assuming the EMAN Euler type) and 00663 // * a post translation 00664 // * @param az EMAN - az 00665 // * @param alt EMAN - alt 00666 // * @param phi EMAN - phi 00667 // * @param posttrans the post translation vector 00668 // */ 00669 // Transform3D(const float& az, const float& alt, const float& phi, const Vec3f& posttrans); 00670 // 00671 // /** Construct a Transform3D object describing a pre trans, a rotation 00672 // * assuming the EMAN Euler type) and a post translation 00673 // * @param pretrans the pre translation vector 00674 // * @param az EMAN - az 00675 // * @param alt EMAN - alt 00676 // * @param phi EMAN - phi 00677 // * @param posttrans the post translation vector 00678 // */ 00679 // Transform3D(const Vec3f & pretrans, const float& az,const float& alt,const float& phi, const Vec3f& posttrans); 00680 // 00681 // /** Construct a Transform3D object describing a rotation, using a specific Euler type. 00682 // * works for EMAN, SPIDER, MRC, IMAGIC and XYZ (Euler types required 3 parameters) 00683 // * @param euler_type the Euler type either EMAN, SPIDER, MRC, IMAGIC and XYZ 00684 // * @param a1 EMAN - az, SPIDER - phi, MRC - phi, IMAGIC - alpha, XYZ - xtilt 00685 // * @param a2 EMAN - alt, SPIDER - theta, MRC - theta, IMAGIC - beta, XYZ - ytilt 00686 // * @param a3 EMAN - phi, SPIDER - psi, MRC - omega, IMAGIC - gamma, XYZ - ztilt 00687 // */ 00688 // Transform3D(EulerType euler_type, const float& a1, const float& a2, const float& a3) ; 00689 // 00690 // /** Construct a Transform3D object describing a rotation, using a specific Euler type. 00691 // * Works for Euler types that require 4 parameters 00692 // * @param euler_type the Euler type either QUATERNION, SPIN or SGIROT 00693 // * @param a1 QUATERNION - e0, SPN and SGIROT - omega 00694 // * @param a2 QUATERNION - e1, SPN and SGIROT - n1 00695 // * @param a3 QUATERNION - e2, SPN and SGIROT - n2 00696 // * @param a4 QUATERNION - e3, SPN and SGIROT - n3 00697 // */ 00698 // Transform3D(EulerType euler_type, const float& a1, const float& a2, const float& a3, const float& a4) ; // o 00699 // 00700 // /** Construct a Transform3D object consisting only of a rotation, using a specific Euler type. 00701 // * Works for all Euler types 00702 // * @param euler_type any Euler type 00703 // * @param rotation a dictionary containing all key-entry pair required of the associated Euler type 00704 // */ 00705 // Transform3D(EulerType euler_type, const Dict& rotation); 00706 // 00707 // /** Construct a Transform3D object consisting only of a rotation by initializing the internal 00708 // * rotation matrix component wise 00709 // * @param mij the value to be placed in the internal transformation matrix at coordinate (i-1,j-1) 00710 // */ 00711 // Transform3D(const float& m11, const float& m12, const float& m13, 00712 // const float& m21, const float& m22, const float& m23, 00713 // const float& m31, const float& m32, const float& m33); 00714 // 00715 // /** Destructor 00716 // */ 00717 // ~Transform3D(); 00718 // 00719 // /** FIXME insert comments 00720 // */ 00721 // void apply_scale(const float& scale); 00722 // 00723 // /** FIXME insert comments 00724 // */ 00725 // void set_scale(const float& scale); 00726 // 00727 // /** Reorthogonalize the matrix 00728 // */ 00729 // void orthogonalize(); 00730 // 00731 // /** create the transpose in place 00732 // */ 00733 // void transpose(); 00734 // 00735 // void set_rotation(const float& az, const float& alt,const float& phi); 00736 // 00737 // /** Sets the rotation as defined by the EulerType 00738 // * works for EMAN, SPIDER, MRC, IMAGIC and XYZ 00739 // * @param euler_type the Euler type either EMAN, SPIDER, MRC, IMAGIC and XYZ 00740 // * @param a1 EMAN - az, SPIDER - phi, MRC - phi, IMAGIC - alpha, XYZ - xtilt 00741 // * @param a2 EMAN - alt, SPIDER - theta, MRC - theta, IMAGIC - beta, XYZ - ytilt 00742 // * @param a3 EMAN - phi, SPIDER - psi, MRC - omega, IMAGIC - gamma, XYZ - ztilt 00743 // */ 00744 // void set_rotation(EulerType euler_type,const float& a1,const float& a2,const float& a3); 00745 // 00746 // /** Set quaternion-based rotations 00747 // * Works for QUATERNION, SPIN and SGIROT 00748 // * @param euler_type the Euler type either QUATERNION, SPIN or SGIROT 00749 // * @param a1 QUATERNION - e0, SPN and SGIROT - omega 00750 // * @param a2 QUATERNION - e1, SPN and SGIROT - n1 00751 // * @param a3 QUATERNION - e2, SPN and SGIROT - n2 00752 // * @param a4 QUATERNION - e3, SPN and SGIROT - n3 00753 // */ 00754 // void set_rotation(EulerType euler_type,const float& a1,const float& a2,const float& a3, const float& a4); 00755 // 00756 // /** set the internal rotation matrix component wise 00757 // * @param mij the value to be placed in the internal transformation matrix at coordinate (i-1,j-1) 00758 // */ 00759 // void set_rotation(const float& m11, const float& m12, const float& m13, 00760 // const float& m21, const float& m22, const float& m23, 00761 // const float& m31, const float& m32, const float& m33); 00762 // 00766 // 00767 // /** Set a rotation using a specific Euler type and the dictionary interface 00768 // * Works for all Euler types 00769 // * @param euler_type any Euler type 00770 // * @param rotation a dictionary containing all key-entry pair required of the associated Euler type 00771 // */ 00772 // void set_rotation(EulerType euler_type, const Dict &rotation ); 00773 // 00774 // /** Get a rotation in any Euler format 00775 // * @param euler_type the requested Euler type 00776 // * @return a dictionary containing the key-entry pairs describing the rotations in terms of the requested Euler type 00777 // */ 00778 // Dict get_rotation(EulerType euler_type=EMAN) const; 00779 // 00780 // /** returns a rotation that maps a pair of unit vectors, a,b to a second pair A,B 00781 // * @param eahat, ebhat, eAhat, eBhat are all unit vectors 00782 // * @return a transform3D rotation 00783 // */ 00784 // void set_rotation(const Vec3f & eahat, const Vec3f & ebhat, 00785 // const Vec3f & eAhat, const Vec3f & eBhat); 00786 // /** returns the magnitude of the rotation 00787 // */ 00788 // float get_mag() const; 00789 // 00790 // /** returns the spin-axis (or finger) of the rotation 00791 // */ 00792 // Vec3f get_finger() const; 00793 // 00794 // /** Gets one of two pre translation vectors 00795 // * @param flag if 0 returns the pre translation vector, if 1 all translation is treated as pre 00796 // * @return the translation vector 00797 // */ 00798 // Vec3f get_pretrans( int flag=0) const; // flag=1 => all trans is pre 00799 // 00800 // /** Gets one of two post translation vectors. 00801 // * when the flag is 1 then the contents of the Transform3D matrix right column are returned 00802 // * @param flag if 0 returns the post translation vector, if 1 all translation is treated as post 00803 // * @return the translation vector 00804 // */ 00805 // Vec3f get_posttrans(int flag=0) const; // flag=1 => all trans is post 00806 // 00807 // /** Get the total translation as a post translation. Calls get_postrans(1) 00808 // * @return the translation vector 00809 // */ 00810 // Vec3f get_total_posttrans() const; 00811 // 00812 // /** Get the total translation as a pre translation. Calls get_pretrans(1) 00813 // * @return the translation vector 00814 // */ 00815 // Vec3f get_total_pretrans() const; 00816 // 00817 // /** This doesn't do anything, it returns an empty vector. Why is it being used? 00818 // */ 00819 // Vec3f get_center() const; // This doesn't do anything 00820 // 00821 // /** Get a matrix column as a Vec3f 00822 // * @param i the column number (starting at 0) 00823 // * @return the ith column 00824 // */ 00825 // Vec3f get_matrix3_col(int i) const; 00826 // 00827 // /** Get a matrix row as a Vec3f 00828 // * @param i the row number (starting at 0) 00829 // * @return the ith row 00830 // */ 00831 // Vec3f get_matrix3_row(int i) const; 00832 // 00833 // /** Perform a full transform a Vec3f using the internal transformation matrix 00834 // * @param v3f the vector to be transformed 00835 // * @return the transformed vector 00836 // */ 00837 // Vec3f transform(const Vec3f & v3f) const; 00838 // 00839 // /** Rotate a Vec3f using the internal rotation matrix 00840 // * @param v3f the vector to be rotated 00841 // * @return the rotated vector 00842 // */ 00843 // Vec3f rotate(const Vec3f & v3f) const; 00844 // 00845 // /** FIXME insert comments 00846 // */ 00847 // Transform3D inverseUsingAngs() const; 00848 // 00849 // /** FIXME insert comments 00850 // */ 00851 // Transform3D inverse() const; 00852 // 00853 // 00854 // /** Print the Transform3D matrix 00855 // */ 00856 // void printme() const { 00857 // for (int i=0; i<3; i++) { 00858 // printf("%6.15f\t%6.15f\t%6.15f\t%6.1f\n", 00859 // matrix[i][0],matrix[i][1],matrix[i][2],matrix[i][3]); 00860 // } 00861 // printf("%6.3f\t%6.3f\t%6.3f\t%6.3f\n",0.0,0.0,0.0,1.0); 00862 // printf("\n"); 00863 // } 00864 // 00865 // /** Get the value stored in the internal transformation matrix at at coordinate (r,c) 00866 // */ 00867 // inline float at(int r,int c) const { return matrix[r][c]; } 00868 // 00869 // /** Set the value stored in the internal transformation matrix at at coordinate (r,c) to value 00870 // */ 00871 // void set(int r, int c, float value) { matrix[r][c] = value; } 00872 // 00873 // /** Operator[] convenience 00874 // * so Transform3D[2][2] etc terminology can be used 00875 // */ 00876 // inline float * operator[] (int i) { return matrix[i]; } 00877 // 00878 // /** Operator[] convenience 00879 // * so Transform3D[2][2] etc terminology can be used 00880 // */ 00881 // inline const float * operator[] (int i) const { return matrix[i]; } 00882 // 00883 // static int get_nsym(const string & sym); 00884 // Transform3D get_sym(const string & sym, int n) const; 00885 // 00886 // /** Set functions FIXME insert more comments from here down 00887 // */ 00888 // void set_center(const Vec3f & center); 00889 // void set_pretrans(const Vec3f & pretrans); 00890 // void set_pretrans(const float& dx, const float& dy, const float& dz); 00891 // void set_pretrans(const float& dx, const float& dy); 00892 // void set_pretrans(const Vec2f& pretrans); 00893 // void set_posttrans(const Vec3f & posttrans); 00894 // void set_posttrans(const float& dx, const float& dy, const float& dz); 00895 // void set_posttrans(const float& dx, const float& dy); 00896 // void set_posttrans(const Vec2f& posttrans); 00897 // 00898 // void set_post_x_mirror(const bool b) { post_x_mirror = b; } 00899 // bool get_post_x_mirror() const { return post_x_mirror; } 00900 // 00901 // float get_scale() const; 00902 // 00903 // void to_identity(); 00904 // bool is_identity(); 00905 // 00906 // /** Convert a list of euler angles to a vector of Transform3D objects. 00907 // * 00908 // * @param[in] eulertype The type of Euler angles that is being passed in. 00909 // * @param[in] angles A flat vector of angles. 00910 // * 00911 // * @return Vector of pointers to Transform3D objects. 00912 // */ 00913 // static vector<Transform3D*> 00914 // angles2tfvec(EulerType eulertype, const vector<float> angles); 00915 // 00916 // /** This added by d.woolford, will eventually be removed by author 00917 // */ 00918 // void dsaw_zero_hack(){ 00919 // for (int j=0; j<4; ++j) { 00920 // for (int i=0; i<4; i++) { 00921 // if ( fabs(matrix[j][i]) < 0.000001 ) 00922 // matrix[j][i] = 0.0; 00923 // } 00924 // } 00925 // 00926 // } 00927 // 00928 // protected: 00929 // enum SymType 00930 // { CSYM, 00931 // DSYM, 00932 // TET_SYM, 00933 // ICOS_SYM, 00934 // OCT_SYM, 00935 // ISYM, 00936 // UNKNOWN_SYM 00937 // }; 00938 // 00939 // void init(); 00940 // 00941 // static SymType get_sym_type(const string & symname); 00942 // 00943 // float matrix[4][4]; 00944 // 00945 // bool post_x_mirror; 00946 // 00947 // Transform3D::EulerType s; 00948 // }; // ends Class 00949 // 00950 // Transform3D operator*(const Transform3D & M1, const Transform3D & M2); 00951 // Vec3f operator*(const Vec3f & v , const Transform3D & M); 00952 // Vec3f operator*(const Transform3D & M, const Vec3f & v ); 00953 00954 // template<typename Type> 00955 // Vec3f operator*(const Vec3<Type> & v, const Transform3D & M) // YYY 00956 // { 00958 // float x = v[0] * M[0][0] + v[1] * M[1][0] + v[2] * M[2][0] ; 00959 // float y = v[0] * M[0][1] + v[1] * M[1][1] + v[2] * M[2][1]; 00960 // float z = v[0] * M[0][2] + v[1] * M[1][2] + v[2] * M[2][2]; 00961 // return Vec3f(x, y, z); 00962 // } 00963 // 00964 // template<typename Type> 00965 // Vec3f operator*( const Transform3D & M, const Vec3<Type> & v) // YYY 00966 // { 00968 // float x = M[0][0] * v[0] + M[0][1] * v[1] + M[0][2] * v[2] + M[0][3]; 00969 // float y = M[1][0] * v[0] + M[1][1] * v[1] + M[1][2] * v[2] + M[1][3]; 00970 // float z = M[2][0] * v[0] + M[2][1] * v[1] + M[2][2] * v[2] + M[2][3]; 00971 // return Vec3f(x, y, z); 00972 // } 00973 // 00974 // 00975 // template<typename Type> 00976 // Vec2f operator*( const Transform3D & M, const Vec2<Type> & v) // YYY 00977 // { 00979 // float x = M[0][0] * v[0] + M[0][1] * v[1] + M[0][3] ; 00980 // float y = M[1][0] * v[0] + M[1][1] * v[1] + M[1][3]; 00981 // return Vec2f(x, y); 00982 // } 00983 00984 } // ends NameSpace EMAN 00985 00986 00987 00988 #endif 00989 00990 00991 /* vim: set ts=4 noet: */