trackball.cpp
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00040 
00041 #include <algorithm>
00042 #include <limits>
00043 #include <pcl/apps/point_cloud_editor/common.h>
00044 #include <pcl/apps/point_cloud_editor/trackball.h>
00045 
00046 TrackBall::TrackBall() : quat_(1.0f), origin_x_(0), origin_y_(0), origin_z_(0)
00047 {
00048   radius_sqr_ = (TRACKBALL_RADIUS_SCALE * static_cast<float>(WINDOW_WIDTH)) *
00049                 (TRACKBALL_RADIUS_SCALE * static_cast<float>(WINDOW_WIDTH));
00050 }
00051 
00052 TrackBall::TrackBall(const TrackBall &copy) :
00053   quat_(copy.quat_), origin_x_(copy.origin_x_), origin_y_(copy.origin_y_),
00054   origin_z_(copy.origin_z_), radius_sqr_(copy.radius_sqr_)
00055 {
00056   
00057 }
00058 
00059 TrackBall::~TrackBall()
00060 {
00061     
00062 }
00063 
00064 TrackBall&
00065 TrackBall::operator=(const TrackBall &rhs)
00066 {
00067   quat_ = rhs.quat_;
00068   origin_x_ = rhs.origin_x_;
00069   origin_y_ = rhs.origin_y_;
00070   origin_z_ = rhs.origin_z_;
00071   radius_sqr_ = rhs.radius_sqr_;
00072   return *this;
00073 }
00074 
00075 void
00076 TrackBall::start(int s_x, int s_y)
00077 {
00078   getPointFromScreenPoint(s_x, s_y, origin_x_, origin_y_, origin_z_);
00079 }
00080 
00081 void
00082 normalize(float x, float y, float z, float &nx, float &ny, float &nz)
00083 {
00084     float inv_len = 1.0f / std::sqrt(x * x + y * y + z * z);
00085     nx = x * inv_len;
00086     ny = y * inv_len;
00087     nz = z * inv_len;
00088 }
00089 
00090 boost::math::quaternion<float>
00091 normalizeQuaternion(const boost::math::quaternion<float> &q)
00092 {
00093     float w = q.R_component_1();
00094     float x = q.R_component_2();
00095     float y = q.R_component_3();
00096     float z = q.R_component_4();
00097     float inv_len = 1.0f / std::sqrt(w * w + x * x + y * y + z * z);
00098     return boost::math::quaternion<float>(w * inv_len, x * inv_len, y * inv_len,
00099                                           z * inv_len);
00100 }
00101 
00102 boost::math::quaternion<float>
00103 quaternionFromAngleAxis(float angle, float x, float y, float z)
00104 {
00105   float s = std::sin(0.5f * angle);
00106   float qw = std::cos(0.5f * angle);
00107   float qx = x * s;
00108   float qy = y * s;
00109   float qz = z * s;
00110   return normalizeQuaternion(boost::math::quaternion<float>(qw, qx, qy, qz));
00111 }
00112 
00113 boost::math::quaternion<float>
00114 multiplyQuaternion(const boost::math::quaternion<float> &lhs,
00115                    const boost::math::quaternion<float> &rhs)
00116 {
00117     float lw = lhs.R_component_1();
00118     float lx = lhs.R_component_2();
00119     float ly = lhs.R_component_3();
00120     float lz = lhs.R_component_4();
00121     
00122     float rw = rhs.R_component_1();
00123     float rx = rhs.R_component_2();
00124     float ry = rhs.R_component_3();
00125     float rz = rhs.R_component_4();
00126     
00127     float tw = lw * rw - lx * rx - ly * ry - lz * rz;
00128     float tx = lw * rx + lx * rw - ly * rz + lz * ry;
00129     float ty = lw * ry + lx * rz + ly * rw - lz * rx;
00130     float tz = lw * rz - lx * ry + ly * rx + lz * rw;
00131     
00132     return boost::math::quaternion<float>(tw, tx, ty, tz);
00133 }
00134 
00135 void
00136 TrackBall::update(int s_x, int s_y)
00137 {
00138   float cur_x, cur_y, cur_z;
00139   getPointFromScreenPoint(s_x, s_y, cur_x, cur_y, cur_z);
00140     
00141   float d_x = cur_x - origin_x_;
00142   float d_y = cur_y - origin_y_;
00143   float d_z = cur_z - origin_z_;
00144 
00145   float dot = d_x * d_x + d_y * d_y + d_z * d_z;
00146   if (dot < std::numeric_limits<float>::epsilon())
00147   {
00148     quat_ = boost::math::quaternion<float>(1.0f);
00149     return;
00150   }
00151   float nc_x, nc_y, nc_z;
00152   float no_x, no_y, no_z;
00153   normalize(cur_x, cur_y, cur_z, nc_x, nc_y, nc_z);
00154   normalize(origin_x_, origin_y_, origin_z_, no_x, no_y, no_z);
00155     
00156   // compute the angle of rotation
00157   float angle = std::acos(nc_x * no_x + nc_y * no_y + nc_z * no_z);
00158 
00159   // compute the axis of rotation
00160   float cross_x = nc_y * no_z - nc_z * no_y;
00161   float cross_y = nc_z * no_x - nc_x * no_z;
00162   float cross_z = nc_x * no_y - nc_y * no_x;
00163     
00164   // reuse of nc_*
00165   normalize(cross_x, cross_y, cross_z, nc_x, nc_y, nc_z);
00166 
00167   quat_ = quaternionFromAngleAxis(angle, nc_x, nc_y, nc_z);
00168   if (quat_.R_component_1() != quat_.R_component_1())
00169     quat_ = boost::math::quaternion<float>(1.0f);
00170 
00171   origin_x_ = cur_x;
00172   origin_y_ = cur_y;
00173   origin_z_ = cur_z;
00174 }
00175 
00176 void
00177 TrackBall::getRotationMatrix(float (&rot)[MATRIX_SIZE])
00178 {
00179   // This function is based on quaternion_to_R3_rotation from
00180   // http://www.boost.org/doc/libs/1_41_0/libs/math/quaternion/HSO3.hpp
00181     
00182   float a = quat_.R_component_1();
00183   float b = quat_.R_component_2();
00184   float c = quat_.R_component_3();
00185   float d = quat_.R_component_4();
00186     
00187   float aa = a*a;
00188   float ab = a*b;
00189   float ac = a*c;
00190   float ad = a*d;
00191   float bb = b*b;
00192   float bc = b*c;
00193   float bd = b*d;
00194   float cc = c*c;
00195   float cd = c*d;
00196   float dd = d*d;
00197     
00198   setIdentity(rot);
00199   float n = aa + bb + cc + dd;
00200     
00201   if (n <= std::numeric_limits<float>::epsilon())
00202     return;
00203 
00204   // fill the upper 3x3
00205   rot[0] = (aa + bb - cc - dd);
00206   rot[1] = 2 * (-ad + bc);
00207   rot[2] = 2 * (ac + bd);
00208   rot[MATRIX_SIZE_DIM+0] = 2 * (ad + bc);
00209   rot[MATRIX_SIZE_DIM+1] = (aa - bb + cc - dd);
00210   rot[MATRIX_SIZE_DIM+2] = 2 * (-ab + cd);
00211   rot[2*MATRIX_SIZE_DIM+0] = 2 * (-ac + bd);
00212   rot[2*MATRIX_SIZE_DIM+1] = 2 * (ab + cd);
00213   rot[2*MATRIX_SIZE_DIM+2] = (aa - bb - cc + dd);
00214 }
00215 
00216 void
00217 TrackBall::reset()
00218 {
00219   quat_ = boost::math::quaternion<float>(1.0f);
00220 }
00221 
00222 void
00223 TrackBall::getPointFromScreenPoint(int s_x, int s_y,
00224                                    float &x, float &y, float &z)
00225 {
00226   // See http://www.opengl.org/wiki/Trackball for more info
00227     
00228   x = static_cast<float>(s_x) - (static_cast<float>(WINDOW_WIDTH) * 0.5f);
00229   y = (static_cast<float>(WINDOW_HEIGHT) * 0.5f) - static_cast<float>(s_y);
00230   float d = x * x + y * y;
00231   if (d > 0.5f * radius_sqr_)
00232   {
00233     // use hyperbolic sheet
00234     z = (0.5f * radius_sqr_) / std::sqrt(d);
00235     return;
00236   }
00237   // use sphere
00238   z = std::sqrt(radius_sqr_ - d);
00239 }
00240 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:36:35