00001
00002 #ifndef vgl_rotation_3d_h_
00003 #define vgl_rotation_3d_h_
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <vnl/vnl_vector_fixed.h>
00022 #include <vnl/vnl_matrix_fixed.h>
00023 #include <vnl/vnl_quaternion.h>
00024 #include <vnl/vnl_cross.h>
00025 #include <vnl/vnl_math.h>
00026 #include <vcl_cmath.h>
00027 #include <vgl/vgl_fwd.h>
00028 #include <vgl/vgl_point_3d.h>
00029 #include <vgl/vgl_homg_point_3d.h>
00030 #include <vgl/algo/vgl_h_matrix_3d.h>
00031 #include <vgl/vgl_tolerance.h>
00032 #include <vcl_vector.h>
00033 #include <vcl_iostream.h>
00034
00035 template <class T>
00036 class vgl_rotation_3d
00037 {
00038 public:
00039
00040
00041
00042 vgl_rotation_3d() : q_(0,0,0,1) {}
00043
00044
00045 vgl_rotation_3d( const vnl_quaternion<T>& q ) : q_(q) { q_.normalize(); }
00046
00047
00048 vgl_rotation_3d( const T& rx, const T& ry, const T& rz ) : q_(rx,ry,rz) {}
00049
00050
00051 explicit vgl_rotation_3d( const vnl_vector_fixed<T,3>& rvector )
00052 {
00053 T mag = rvector.magnitude();
00054 if (mag > T(0))
00055 q_ = vnl_quaternion<T>(rvector/mag,mag);
00056 else
00057 q_ = vnl_quaternion<T>(0,0,0,1);
00058 }
00059
00060
00061 explicit vgl_rotation_3d( const vnl_matrix_fixed<T,3,3>& matrix )
00062 : q_(matrix.transpose()) {}
00063
00064
00065 explicit vgl_rotation_3d( const vgl_h_matrix_3d<T>& h )
00066 : q_(h.get_upper_3x3_matrix().transpose()) { assert(h.is_rotation()); }
00067
00068
00069
00070 vgl_rotation_3d(const vnl_vector_fixed<T,3>& a,
00071 const vnl_vector_fixed<T,3>& b)
00072 {
00073 vnl_vector_fixed<T,3> c = vnl_cross_3d(a, b);
00074 double aa = 0.0; if (dot_product(a, b) < 0) { aa = vnl_math::pi; c=-c; }
00075 double cmag = static_cast<double>(c.magnitude())
00076 / static_cast<double>(a.magnitude())
00077 / static_cast<double>(b.magnitude());
00078
00079 if (cmag>1.0) cmag=1.0;
00080
00081 if (cmag<vgl_tolerance<double>::position)
00082 {
00083 if (aa!=vnl_math::pi) {
00084 q_ = vnl_quaternion<T>(0, 0, 0, 1);
00085 return;
00086 }
00087 else {
00088
00089 double ax = static_cast<double>(a[0]),ay = static_cast<double>(a[1]),
00090 az = static_cast<double>(a[2]);
00091 vnl_vector_fixed<T,3> v(T(0));
00092 double amin = ax; v[0]=T(1);
00093 if (ay<amin) { amin = ay; v[0]=T(0); v[1]=T(1); }
00094 if (az<amin) { v[0]=T(0); v[1]=T(0); v[2]=T(1); }
00095
00096 vnl_vector_fixed<T,3> pi_axis = vnl_cross_3d(v, a);
00097 q_ = vnl_quaternion<T>(pi_axis/pi_axis.magnitude(), aa);
00098 return;
00099 }
00100 }
00101 double angl = vcl_asin(cmag)+aa;
00102 q_ = vnl_quaternion<T>(c/c.magnitude(), angl);
00103 }
00104
00105
00106
00107 explicit vgl_rotation_3d(const vgl_vector_3d<T>& a,
00108 const vgl_vector_3d<T>& b)
00109 {
00110 vnl_vector_fixed<T,3> na(a.x(), a.y(), a.z());
00111 vnl_vector_fixed<T,3> nb(b.x(), b.y(), b.z());
00112 *this = vgl_rotation_3d<T>(na, nb);
00113 }
00114
00115
00116
00117
00118 vnl_quaternion<T> as_quaternion() const
00119 {
00120 return q_;
00121 }
00122
00123
00124
00125
00126
00127
00128 vnl_vector_fixed<T,3> as_euler_angles() const
00129 {
00130 return q_.rotation_euler_angles();
00131 }
00132
00133
00134
00135
00136 vnl_vector_fixed<T,3> as_rodrigues() const
00137 {
00138 double ang = q_.angle();
00139 if (ang == 0.0)
00140 return vnl_vector_fixed<T,3>(T(0));
00141 return q_.axis()*T(ang);
00142 }
00143
00144
00145 vnl_matrix_fixed<T,3,3> as_matrix() const
00146 {
00147 return q_.rotation_matrix_transpose().transpose();
00148 }
00149
00150
00151 vgl_h_matrix_3d<T> as_h_matrix_3d() const
00152 {
00153 return vgl_h_matrix_3d<T>(q_.rotation_matrix_transpose_4().transpose());
00154 }
00155
00156
00157 vnl_vector_fixed<T,3> axis() const { return q_.axis(); }
00158
00159
00160 double angle() const { return q_.angle(); }
00161
00162
00163
00164
00165 void set_identity() { q_[0]=0; q_[1]=0; q_[2]=0; q_[3]=1; }
00166
00167
00168 vgl_rotation_3d<T> inverse() const { return vgl_rotation_3d<T>(q_.conjugate()); }
00169
00170 vgl_rotation_3d<T> transpose() const
00171 { return this->inverse(); }
00172
00173
00174 vgl_rotation_3d<T> operator*( const vgl_rotation_3d<T>& first_rotation ) const
00175 {
00176 return vgl_rotation_3d<T>( q_*first_rotation.q_ );
00177 }
00178
00179
00180 vgl_homg_point_3d<T> operator*( const vgl_homg_point_3d<T>& p ) const
00181 {
00182 vnl_vector_fixed<T,3> rp = q_.rotate(vnl_vector_fixed<T,3>(p.x(),p.y(),p.z()));
00183 return vgl_homg_point_3d<T>(rp[0],rp[1],rp[2],p.w());
00184 }
00185
00186
00187 vgl_homg_plane_3d<T> operator*( const vgl_homg_plane_3d<T>& p ) const
00188 {
00189 vnl_vector_fixed<T,3> rp = q_.rotate(vnl_vector_fixed<T,3>(p.a(),p.b(),p.c()));
00190 return vgl_homg_plane_3d<T>(rp[0],rp[1],rp[2],p.d());
00191 }
00192
00193
00194 vgl_homg_line_3d_2_points<T> operator*( const vgl_homg_line_3d_2_points<T>& l ) const
00195 {
00196 return vgl_homg_line_3d_2_points<T>(this->operator*(l.point_finite()),
00197 this->operator*(l.point_infinite()));
00198 }
00199
00200
00201 vgl_point_3d<T> operator*( const vgl_point_3d<T>& p ) const
00202 {
00203 vnl_vector_fixed<T,3> rp = q_.rotate(vnl_vector_fixed<T,3>(p.x(),p.y(),p.z()));
00204 return vgl_point_3d<T>(rp[0],rp[1],rp[2]);
00205 }
00206
00207
00208 vgl_plane_3d<T> operator*( const vgl_plane_3d<T>& p ) const
00209 {
00210 vnl_vector_fixed<T,3> rp = q_.rotate(vnl_vector_fixed<T,3>(p.a(),p.b(),p.c()));
00211 return vgl_plane_3d<T>(rp[0],rp[1],rp[2],p.d());
00212 }
00213
00214
00215 vgl_line_3d_2_points<T> operator*( const vgl_line_3d_2_points<T>& l ) const
00216 {
00217 return vgl_line_3d_2_points<T>(this->operator*(l.point1()),
00218 this->operator*(l.point2()));
00219 }
00220
00221
00222 vgl_line_segment_3d<T> operator*( const vgl_line_segment_3d<T>& l ) const
00223 {
00224 return vgl_line_segment_3d<T>(this->operator*(l.point1()),
00225 this->operator*(l.point2()));
00226 }
00227
00228
00229 vgl_vector_3d<T> operator*( const vgl_vector_3d<T>& v ) const
00230 {
00231 vnl_vector_fixed<T,3> rv = q_.rotate(vnl_vector_fixed<T,3>(v.x(),v.y(),v.z()));
00232 return vgl_vector_3d<T>(rv[0],rv[1],rv[2]);
00233 }
00234
00235
00236 vnl_vector_fixed<T, 3> operator*( const vnl_vector_fixed<T,3>& v ) const
00237 {
00238 return q_.rotate(v);
00239 }
00240
00241
00242 bool operator==(vgl_rotation_3d<T> const& r) const { return q_ == r.as_quaternion(); }
00243
00244 protected:
00245
00246 vnl_quaternion<T> q_;
00247 };
00248
00249
00250
00251
00252
00253 template <class T>
00254 vcl_ostream& operator<<(vcl_ostream& s, vgl_rotation_3d<T> const& R)
00255 {
00256 return s << R.as_quaternion();
00257 }
00258
00259
00260
00261
00262
00263
00264 template <class T> inline
00265 void vgl_rotate_3d(const vgl_rotation_3d<T>& rot, vcl_vector<vgl_homg_point_3d<T> >& pts)
00266 {
00267 vnl_matrix_fixed<T,3,3> R = rot.as_3matrix();
00268 for (typename vcl_vector<vgl_homg_point_3d<T> >::iterator itr = pts.begin();
00269 itr != pts.end(); ++itr)
00270 {
00271 vgl_homg_point_3d<T>& p = *itr;
00272 p.set(R[0][0]*p.x()+R[0][1]*p.y()+R[0][2]*p.z(),
00273 R[1][0]*p.x()+R[1][1]*p.y()+R[1][2]*p.z(),
00274 R[2][0]*p.x()+R[2][1]*p.y()+R[2][2]*p.z(), p.w());
00275 }
00276 }
00277
00278 #endif // vgl_rotation_3d_h_