contrib/mul/mfpf/mfpf_pose.h
Go to the documentation of this file.
00001 #ifndef mfpf_pose_h_
00002 #define mfpf_pose_h_
00003 //:
00004 // \file
00005 // \brief Defines position and scale/orientation of an object
00006 // \author Tim Cootes
00007 
00008 
00009 #include <vsl/vsl_binary_io.h>
00010 #include <vcl_iostream.h>
00011 #include <vcl_cstdlib.h>
00012 #include <vcl_cmath.h>
00013 #include <vcl_vector.h>
00014 #include <vgl/vgl_point_2d.h>
00015 #include <vgl/vgl_vector_2d.h>
00016 
00017 //: Feature point, scale and orientation
00018 //  Basis for object given by u(),v().
00019 //  Thus point (i,j) in model given by p()+i*u() + j*v() in world;
00020 class mfpf_pose
00021 {
00022   //: Position
00023   vgl_point_2d<double> p_;
00024 
00025   //: Scale and orientation defined by basis vector
00026   vgl_vector_2d<double> u_;
00027  public:
00028   //: Position
00029   const vgl_point_2d<double>& p() const { return p_; }
00030 
00031   //: Position
00032   vgl_point_2d<double>& p() { return p_; }
00033 
00034   //: Scale and orientation defined by basis vector
00035   const vgl_vector_2d<double>& u() const { return u_; }
00036 
00037   //: Vector of same size, orthogonal to u()
00038   vgl_vector_2d<double> v() const
00039   { return vgl_vector_2d<double>(-u_.y(),u_.x()); }
00040 
00041   //: Scale and orientation defined by basis vector
00042   vgl_vector_2d<double>& u() { return u_; }
00043 
00044   //: Constructor
00045   mfpf_pose(const vgl_point_2d<double>& p,
00046             const vgl_vector_2d<double>& u) : p_(p),u_(u) {}
00047 
00048   //: Constructor.  Defines translation (px,py), basis vector (ux,uy)
00049   mfpf_pose(double px, double py, double ux, double uy)
00050     : p_(px,py),u_(ux,uy) {}
00051 
00052   //: Default constructor
00053   mfpf_pose() : p_(0,0),u_(1,0) {}
00054 
00055   //: Square of scaling factor applied by this pose
00056   double sqr_scale() const { return u_.x()*u_.x()+u_.y()*u_.y(); }
00057 
00058   //: Scaling applied by this pose
00059   double scale() const
00060   { double s2 = u_.x()*u_.x()+u_.y()*u_.y();
00061     return s2>0.0 ? vcl_sqrt(s2) : 0.0;
00062   }
00063 
00064   //: Apply pose transformation (map from ref frame to pose)
00065   vgl_point_2d<double> operator()(double x, double y) const
00066   {  return vgl_point_2d<double>(p_.x()+x*u_.x()-y*u_.y(),
00067                                  p_.y()+x*u_.y()+y*u_.x()); }
00068 
00069   //: Apply pose transformation (map from ref frame to pose)
00070   vgl_point_2d<double> operator()(const vgl_point_2d<double>& q) const
00071   {  return vgl_point_2d<double>(p_.x()+q.x()*u_.x()-q.y()*u_.y(),
00072                                  p_.y()+q.x()*u_.y()+q.y()*u_.x()); }
00073 
00074   //: Apply inverse of pose transformation (map from pose frame -> ref)
00075   vgl_point_2d<double> apply_inverse(double x, double y) const
00076   {
00077     double dx=x-p_.x(), dy=y-p_.y(),s2=sqr_scale();
00078     return vgl_point_2d<double>((dx*u_.x()+dy*u_.y())/s2,
00079                                 (dy*u_.x()-dx*u_.y())/s2);
00080   }
00081 
00082   //: Apply inverse of pose transformation (map from pose frame -> ref)
00083   vgl_point_2d<double> apply_inverse(const vgl_point_2d<double>& q) const
00084   {
00085     double dx=q.x()-p_.x(), dy=q.y()-p_.y(),s2=sqr_scale();
00086     return vgl_point_2d<double>((dx*u_.x()+dy*u_.y())/s2,
00087                                 (dy*u_.x()-dx*u_.y())/s2);
00088   }
00089 
00090   //: Return pose in co-ordinates defined by this pose.
00091   //  I.e., pose(p) == *this(rel_pose(pose)(p))
00092   mfpf_pose rel_pose(const mfpf_pose& pose) const
00093   {
00094     vgl_point_2d<double> p1 = apply_inverse(pose.p());
00095     vgl_vector_2d<double> u1 = apply_inverse(pose.p()+pose.u())-p1;
00096     return mfpf_pose(p1,u1);
00097   }
00098 
00099   //: Return pose applying inverse of this pose
00100   mfpf_pose inverse() const
00101   {
00102     vgl_point_2d<double> p1 = apply_inverse(0,0);
00103     double s2=sqr_scale();
00104     vgl_vector_2d<double> u1(u_.x()/s2,-u_.y()/s2);
00105     return mfpf_pose(p1,u1);
00106   }
00107 };
00108 
00109 inline bool operator==(const mfpf_pose& p1,
00110                        const mfpf_pose& p2)
00111 {
00112   const double tol=1e-6;
00113   return vcl_fabs(p1.p().x()-p2.p().x())<tol &&
00114          vcl_fabs(p1.p().y()-p2.p().y())<tol &&
00115          vcl_fabs(p1.u().x()-p2.u().x())<tol &&
00116          vcl_fabs(p1.u().y()-p2.u().y())<tol;
00117 }
00118 
00119 inline bool operator!=(const mfpf_pose& p1,
00120                        const mfpf_pose& p2)
00121 { return !(p1==p2); }
00122 
00123 //: Return a measure of difference of position for two poses
00124 //  Object assumed to have radius r.
00125 //  Returns estimate of square of largest difference in
00126 //  position for a point on the object (typically an extremal point)
00127 inline double mfpf_max_sqr_diff(const mfpf_pose& p1,
00128                                 const mfpf_pose& p2, double r)
00129 {
00130   double dx = vcl_fabs(p1.p().x()-p2.p().x())
00131               + r*vcl_fabs(p1.u().x()-p2.u().x());
00132   double dy = vcl_fabs(p1.p().y()-p2.p().y())
00133               + r*vcl_fabs(p1.u().y()-p2.u().y());
00134   return dx*dx+dy*dy;
00135 }
00136 
00137 inline vcl_ostream& operator<<(vcl_ostream& os,
00138                                const mfpf_pose& p)
00139 {
00140   os<<"{("<<p.p().x()<<','<<p.p().y()<<") u:"
00141     <<p.u().x()<<','<<p.u().y()<<")}";
00142   return os;
00143 }
00144 
00145 //: Treating poses as transformations, return p12=p1.p2.
00146 //  I.e., p12(x) = p1(p2(x))
00147 inline mfpf_pose operator*(const mfpf_pose& p1, const mfpf_pose& p2)
00148 {
00149   vgl_point_2d<double> q = p1(p2.p());
00150   return mfpf_pose(q,p1(p2.p()+p2.u())-q);
00151 }
00152 
00153 inline void vsl_b_write(vsl_b_ostream& bfs,
00154                         const mfpf_pose& p)
00155 {
00156   vsl_b_write(bfs,short(1));  // Version number
00157   vsl_b_write(bfs,p.p().x());
00158   vsl_b_write(bfs,p.p().y());
00159   vsl_b_write(bfs,p.u().x());
00160   vsl_b_write(bfs,p.u().y());
00161 }
00162 
00163 inline void vsl_b_read(vsl_b_istream& bfs, mfpf_pose& p)
00164 {
00165   short version;
00166   vsl_b_read(bfs,version);
00167   double ux,uy;
00168   switch (version)
00169   {
00170     case (1):
00171       vsl_b_read(bfs,p.p().x());
00172       vsl_b_read(bfs,p.p().y());
00173       vsl_b_read(bfs,ux);
00174       vsl_b_read(bfs,uy);
00175       p.u()=vgl_vector_2d<double>(ux,uy);
00176       break;
00177     default:
00178       vcl_cerr << "I/O ERROR: vsl_b_read(bfs,mfpf_pose):\n"
00179                << "           Unexpected version number " << version << '\n';
00180       vcl_abort();
00181   }
00182 }
00183 
00184 //: Write vector of feature points to stream
00185 inline void vsl_b_write(vsl_b_ostream& bfs,
00186                         const vcl_vector<mfpf_pose>& p)
00187 {
00188   vsl_b_write(bfs,short(1));  // Version number
00189   vsl_b_write(bfs,unsigned(p.size()));
00190   for (unsigned i=0;i<p.size();++i)
00191     vsl_b_write(bfs,p[i]);
00192 }
00193 
00194 //: Read in vector of feature points from stream
00195 inline void vsl_b_read(vsl_b_istream& bfs,
00196                        vcl_vector<mfpf_pose>& p)
00197 {
00198   short version;
00199   vsl_b_read(bfs,version);
00200   unsigned n;
00201   switch (version)
00202   {
00203     case (1):
00204       vsl_b_read(bfs,n);
00205       p.resize(n);
00206       for (unsigned i=0;i<n;++i) vsl_b_read(bfs,p[i]);
00207       break;
00208     default:
00209       vcl_cerr << "vsl_b_read(bfs,vcl_vector<mfpf_pose>): "
00210                << "Unexpected version number " << version << vcl_endl;
00211       vcl_abort();
00212   }
00213 }
00214 
00215 #endif // mfpf_pose_h_
00216