[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [IMP-dev] [IMP-commits] r903 - in trunk/modules/misc: include pyext src test/transformation



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: ">
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.htm
+
+    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
">
https://salilab.org/mailman/listinfo/imp-commits