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