Couple quick comments: - we are mostly avoiding abbreviations, so get_trans should probably be "get_translation". It is a bit weird just having that (and no get_matrix or "get_rotation") - The function on Rotation3D shouldn't be mult (since it isn't necessarily multiplication as it is not necessarily a matrix). "transform" taken from Transformation3D or "rotate" are probably the best options. - I still don't like exposing the various methods on Matrix3D having to do with rotation. I think they should be hidden (and some classes made friends if outside classes need them).
Otherwise, looks good. THanks.
On Nov 29, 2008, at 6:14 PM, Notification of IMP commits wrote:
> Author: kerenl@SALILAB.ORG > Date: 2008-11-29 18:14:37 -0800 (Sat, 29 Nov 2008) > New Revision: 903 > > Modified: > trunk/modules/misc/include/Rotation3D.h > trunk/modules/misc/include/Transformation3D.h > trunk/modules/misc/pyext/misc.i > trunk/modules/misc/src/SConscript > trunk/modules/misc/test/transformation/ > test_particles_transformation.py > trunk/modules/misc/test/transformation/test_rigid_transformation.py > Log: > Update interface for Rotation3D class > > Modified: trunk/modules/misc/include/Rotation3D.h > =================================================================== > --- trunk/modules/misc/include/Rotation3D.h 2008-11-29 04:49:09 UTC > (rev 902) > +++ trunk/modules/misc/include/Rotation3D.h 2008-11-30 02:14:37 UTC > (rev 903) > @@ -9,122 +9,98 @@ > #define IMPMISC_ROTATION_3D_H > > #include "misc_exports.h" > - > -#include "Matrix3D.h" > +#include "IMP/Vector3D.h" > +#include <iostream> > IMPMISC_BEGIN_NAMESPACE > > //! 3D rotation class. > -/** Holds a 3-dimensional rotation compactly using a quaternions (4 > numbers). > - For a given axis and angle, one can easily construct the > corresponding > - quaternion, and conversely, for a given quaternion one can > easily read > - off the axis and the angle. > - Another advantage is robustness to rounding errors. > - The quaternions representation does not harm the performance > too much. > +/** Holds a three dimensional rotation compactly using a quaternion > (4 numbers). > + Advantages using quaternion: > + 1. Easy convertion between axis/angle to quaternion reprsentation > + 2. Robustness to rounding errors. > + 3. Is not subject to "Gimbal lock" (i.e. attempts to rotate an > + object fail to appear as expected, due to the order in which > the > + rotations are performed) like Euler angles. > + 4. Can be interpolated > + 5. The quaternions representation does not harm the performance > too much. > + http://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/index... > + > + Currently the rotation can be initialized from either: > + XYZ Euler angles > + Rotation Matrix > + Quaternion > */ > > class IMPMISCEXPORT Rotation3D { > public: > - Rotation3D(){ > - } > - //! Initialize a rotation in x-y-z order from three angles > - /** \param[in] xr Rotation around the X axis in radians > - \param[in] yr Rotation around the Y axis in radians > - \param[in] zr Rotation around the Z axis in radians > - */ > - Rotation3D(Float xr, Float yr, Float zr) { > - init_angles(xr,yr,zr); > + Rotation3D():a_(0.0),b_(0.0),c_(0.0),d_(0.0) {} > + Rotation3D(Float a, Float b, Float c, Float d){ > + a_=a;b_=b;c_=c;d_=d; > } > - //! Initialize a rotation in x-y-z order from three identical > angles > - /** \param[in] e_angle Rotation around first the X axis, Y axis > and Z axis > - in radians > - */ > - Rotation3D(Float e_angle){ > - init_angles(e_angle, e_angle, e_angle); > + //! Rotation by vector multiplication > + Vector3D mult(const Vector3D &o) const { > + return Vector3D((a_*a_+b_*b_-c_*c_-d_*d_)*o[0] + > + 2*(b_*c_-a_*d_)*o[1] + 2*(b_*d_+a_*c_)*o[2], > + 2*(b_*c_+a_*d_)*o[0] + > + (a_*a_-b_*b_+c_*c_-d_*d_)*o[1] + 2*(c_*d_- > a_*b_)*o[2], > + 2*(b_*d_-a_*c_)*o[0] + > + 2*(c_*d_+a_*b_)*o[1] + (a_*a_-b_*b_-c_*c_ > +d_*d_)*o[2]); > } > - Matrix3D get_matrix() const { > - const Float a = quat_[0]; > - const Float b = quat_[1]; > - const Float c = quat_[2]; > - const Float d = quat_[3]; > - return Matrix3D(a*a+b*b-c*c-d*d, 2*(b*c-a*d) , 2*(b*d+a*c), > - 2*(b*c+a*d) , a*a-b*b+c*c-d*d, 2*(c*d-a*b), > - 2*(b*d-a*c) , 2*(c*d+a*b) , a*a-b*b-c*c+d*d); > + void show(std::ostream& out = std::cout) const { > + out <<a_<<"|"<<b_<<"|"<<c_<<"|"<<d_<<'\n'; > } > - //! Rotation by vector multiplication > - Vector3D operator*(const Vector3D &o) const { > - const Float a = quat_[0]; > - const Float b = quat_[1]; > - const Float c = quat_[2]; > - const Float d = quat_[3]; > - return Vector3D((a*a+b*b-c*c-d*d)*o[0] + 2*(b*c-a*d)*o[1] + 2*(b*d > +a*c)*o[2], > - 2*(b*c+a*d)*o[0] + (a*a-b*b+c*c-d*d)*o[1] + > 2*(c*d-a*b)*o[2], > - 2*(b*d-a*c)*o[0] + 2*(c*d+a*b)*o[1] + (a*a-b*b-c*c > +d*d)*o[2]); > - } > - //! Returns the rotation around the x-axis for a rotational > matrix assuming > - //! rotations are performed in the order of x-y-z. > - Float rotX() const{ > - return atan2(matrix32(), matrix33()); > - } > +private: > + Float a_,b_,c_,d_; > +}; > > - //! Returns the rotation around the y-axis for a rotational > matrix assuming > - //! rotations are performed in the order of x-y-z. > - Float rotY() const{ > - return atan2(matrix31(), sqrt(sqr(matrix21())+sqr(matrix11()))); > - } > > - //! Returns the rotation around the z-axis for a rotational > matrix assuming > - //! rotations are performed in the order of x-y-z. > - Float rotZ() const{ > - return atan2(matrix21(), matrix11()); > - } > +//! Initialize a rotation in x-y-z order from three angles > +/** \param[in] xr Rotation around the X axis in radians > + \param[in] yr Rotation around the Y axis in radians > + \param[in] zr Rotation around the Z axis in radians > + \note The three rotations are represented in the original > (fixed) > + coordinate frame. http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles > +*/ > +inline Rotation3D rotation_from_fixed_xyz(Float xr,Float yr, Float > zr) > +{ > + Float a,b,c,d; > + Float cx = cos(xr); Float cy = cos(yr); Float cz = cos(zr); > + Float sx = sin(xr); Float sy = sin(yr); Float sz = sin(zr); > + Float m00 = cz*cy; > + Float m11 = -sy*sx*sz + cx*cz; > + Float m22 = cy*cx; > + a = sqrt(1+m00+m11+m22)/2.0; > + b = sqrt(1+m00-m11-m22)/2.0; > + c = sqrt(1-m00+m11-m22)/2.0; > + d = sqrt(1-m00-m11+m22)/2.0; > + if (cy*sx + sy*cx*sz + sx*cz < 0.0) b = -b; > + if (sz*sx - sy*cx*cz - sy < 0.0) c = -c; > + if (sz*cy + sy*sx*cz + sz*cx < 0.0) d = -d; > + return Rotation3D(a,b,c,d); > +} > > -private: > - void init_angles(Float xr, Float yr, Float zr) { > - Float cx = cos(xr); Float cy = cos(yr); Float cz = cos(zr); > - Float sx = sin(xr); Float sy = sin(yr); Float sz = sin(zr); > - Float m00 = cz*cy; > - Float m11 = -sy*sx*sz + cx*cz; > - Float m22 = cy*cx; > - quat_[0] = sqrt(1+m00+m11+m22)/2.0; > - quat_[1] = sqrt(1+m00-m11-m22)/2.0; > - quat_[2] = sqrt(1-m00+m11-m22)/2.0; > - quat_[3] = sqrt(1-m00-m11+m22)/2.0; > - if (cy*sx + sy*cx*sz + sx*cz < 0.0) quat_[1] = -quat_[1]; > - if (sz*sx - sy*cx*cz - sy < 0.0) quat_[2] = -quat_[2]; > - if (sz*cy + sy*sx*cz + sz*cx < 0.0) quat_[3] = -quat_[3]; > - } > +inline Rotation3D rotation_from_mat(Float m11,Float m12,Float m13, > + Float m21,Float m22,Float m23, > + Float m31,Float m32,Float m33) { > + Float a,b,c,d; > + a = fabs(1+m11+m22+m33)/4; > + b = fabs(1+m11-m22-m33)/4; > + c = fabs(1-m11+m22-m33)/4; > + d = fabs(1-m11-m22+m33)/4; > > - Float matrix11() const { > - return sqr(quat_[0]) + sqr(quat_[1]) - sqr(quat_[2]) - > sqr(quat_[3]); > - } > - Float matrix12() const { > - return 2*(quat_[1]*quat_[2] - quat_[0]*quat_[3]); > - } > - Float matrix13() const{ > - return 2*(quat_[2]*quat_[3] + quat_[0]*quat_[2]); > - } > - Float matrix21() const { > - return 2*(quat_[1]*quat_[2] + quat_[0]*quat_[3]); > - } > - Float matrix22() const { > - return sqr(quat_[0]) - sqr(quat_[1]) + sqr(quat_[2]) - > sqr(quat_[3]); > - } > - Float matrix23() const { > - return 2*(quat_[2]*quat_[3] - quat_[0]*quat_[1]); > - } > - Float matrix31() const { > - return 2*(quat_[1]*quat_[3] - quat_[0]*quat_[2]); > - } > - Float matrix32() const { > - return 2*(quat_[2]*quat_[3] + quat_[0]*quat_[1]); > - } > - Float matrix33() const { > - return sqr(quat_[0]) - sqr(quat_[1]) - sqr(quat_[2]) + > sqr(quat_[3]); > - } > + // make sure quat is normalized. > + Float sum = a+b+c+d; > + a = sqrt(a/sum); > + b = sqrt(b/sum); > + c = sqrt(c/sum); > + d = sqrt(d/sum); > > -private: > - Float sqr(Float a)const{return a*a;} > - Float quat_[4]; > -}; > + if (m32-m23 < 0.0) b=-b; > + if (m13-m31 < 0.0) c=-c; > + if (m21-m12 < 0.0) d=-d; > +} > +/* > +Rotation3D rotation_from_axis_angle(Vector3D axis, Float a){} > +*/ > IMPMISC_END_NAMESPACE > #endif /* IMPMISC_ROTATION_3D_H */ > > Modified: trunk/modules/misc/include/Transformation3D.h > =================================================================== > --- trunk/modules/misc/include/Transformation3D.h 2008-11-29 > 04:49:09 UTC (rev 902) > +++ trunk/modules/misc/include/Transformation3D.h 2008-11-30 > 02:14:37 UTC (rev 903) > @@ -23,24 +23,23 @@ > public: > // public for swig > typedef Transformation3D This; > - Transformation3D():rot_(1.0),trans_(){ > + Transformation3D():rot_(),trans_(){ > } > - > Transformation3D(const Rotation3D& r, const Vector3D& t) > - : rot_(r.get_matrix()), trans_(t){} > + : rot_(r), trans_(t){} > //! transform > Vector3D transform(const Vector3D &o) const { > - return (rot_ * o) + trans_; > + return rot_.mult(o) + trans_; > } > Vector3D get_trans()const{return trans_;} > - Matrix3D get_mat()const{return rot_;} > + // Matrix3D get_mat()const{return rot_;} > void show(std::ostream& out = std::cout) const { > rot_.show(out); > out<<" || "<<trans_<<"\n"; > } > private: > Vector3D trans_; //tranlation > - Matrix3D rot_; //rotation > + Rotation3D rot_; //rotation > }; > > IMPMISC_END_NAMESPACE > > Modified: trunk/modules/misc/pyext/misc.i > =================================================================== > --- trunk/modules/misc/pyext/misc.i 2008-11-29 04:49:09 UTC (rev 902) > +++ trunk/modules/misc/pyext/misc.i 2008-11-30 02:14:37 UTC (rev 903) > @@ -1,11 +1,11 @@ > %module(directors="1") IMP_misc > > %{ > -#include "IMP/misc.h" > -#include "IMP/core.h" > #include "IMP.h" > +#include "IMP/misc.h" > %} > > + > %include "kernel/pyext/IMP_macros.i" > %include "kernel/pyext/IMP_exceptions.i" > > @@ -17,7 +17,6 @@ > > /* Get definitions of kernel base classes (but do not wrap) */ > %import "kernel/pyext/IMP.i" > -%import "modules/core/pyext/core.i" > > namespace IMP { > typedef VectorD<3> Vector3D; > @@ -37,8 +36,6 @@ > %include "IMP/misc/RefineOncePairScore.h" > %include "IMP/misc/TunnelSingletonScore.h" > %include "IMP/misc/LowestRefinedPairScore.h" > -%include "IMP/misc/Matrix3D.h" > %include "IMP/misc/Rotation3D.h" > %include "IMP/misc/Transformation3D.h" > -%include "IMP/misc/ParticleFunction.h" > -%include "IMP/misc/TransformationFunction.h" > +%include "IMP/misc/TransformationFunction.h" > \ No newline at end of file > > Modified: trunk/modules/misc/src/SConscript > =================================================================== > --- trunk/modules/misc/src/SConscript 2008-11-29 04:49:09 UTC (rev > 902) > +++ trunk/modules/misc/src/SConscript 2008-11-30 02:14:37 UTC (rev > 903) > @@ -4,11 +4,11 @@ > files = [ > 'ChildrenParticleRefiner.cpp', > 'LowestRefinedPairScore.cpp', > - 'Matrix3D.cpp', > 'RefineOncePairScore.cpp', > 'Rotation3D.cpp', > 'Transformation3D.cpp', > 'TunnelSingletonScore.cpp', > + 'Rotation3D.cpp','Transformation3D.cpp' > ] > > # Build and install the shared library: > > Modified: trunk/modules/misc/test/transformation/ > test_particles_transformation.py > =================================================================== > --- trunk/modules/misc/test/transformation/ > test_particles_transformation.py 2008-11-29 04:49:09 UTC (rev 902) > +++ trunk/modules/misc/test/transformation/ > test_particles_transformation.py 2008-11-30 02:14:37 UTC (rev 903) > @@ -27,7 +27,8 @@ > > 82.603,46.874,76.53)) > def test_transformation(self): > """Test the TransformationFunction class""" > - > t > = > IMP > .misc > .Transformation3D > (IMP.misc.Rotation3D(0.2,0.8,-0.4),IMP.Vector3D(20.0,-12.4,18.6)) > + r = IMP.misc.rotation_from_fixed_xyz(0.2,0.8,-0.4) > + t=IMP.misc.Transformation3D(r,IMP.Vector3D(20.0,-12.4,18.6)) > tf=IMP.misc.TransformationFunction(t) > r = tf.apply(self.particles) > tp=[] > > Modified: trunk/modules/misc/test/transformation/ > test_rigid_transformation.py > =================================================================== > --- trunk/modules/misc/test/transformation/ > test_rigid_transformation.py 2008-11-29 04:49:09 UTC (rev 902) > +++ trunk/modules/misc/test/transformation/ > test_rigid_transformation.py 2008-11-30 02:14:37 UTC (rev 903) > @@ -16,7 +16,8 @@ > > def test_transformation(self): > """Check that the rotation function is ok""" > - > t > = > IMP > .misc > .Transformation3D > (IMP.misc.Rotation3D(0.2,0.8,-0.4),IMP.Vector3D(20.0,-12.4,18.6)) > + rt = IMP.misc.rotation_from_fixed_xyz(0.2,0.8,-0.4) > + t=IMP.misc.Transformation3D(rt,IMP.Vector3D(20.0,-12.4,18.6)) > v1_t = t.transform(self.v1) > v2_t = t.transform(self.v2) > v1_t_res=IMP.Vector3D(-62.517,86.209, 41.139) > > _______________________________________________ > IMP-commits mailing list > IMP-commits@salilab.org > https://salilab.org/mailman/listinfo/imp-commits