contrib/mul/msm/msm_points.cxx
Go to the documentation of this file.
00001 #include "msm_points.h"
00002 //:
00003 // \file
00004 // \brief Set of 2D points, stored in a vnl_vector (x0,y0,x1,y1...)
00005 // \author Tim Cootes
00006 
00007 #include <vcl_iostream.h>
00008 #include <vsl/vsl_indent.h>
00009 #include <vsl/vsl_binary_io.h>
00010 #include <vnl/io/vnl_io_vector.h>
00011 #include <vgl/vgl_point_2d.h>
00012 #include <vcl_cstdlib.h>  // for vcl_atoi() & vcl_abort()
00013 
00014 
00015 //=======================================================================
00016 // Dflt ctor
00017 //=======================================================================
00018 
00019 msm_points::msm_points()
00020 {
00021 }
00022 
00023 msm_points::msm_points(unsigned n)
00024 {
00025   v_.set_size(n*2); v_.fill(0.0);
00026 }
00027 
00028 //=======================================================================
00029 // Destructor
00030 //=======================================================================
00031 
00032 msm_points::~msm_points()
00033 {
00034 }
00035 
00036 //: Set to hold n points (initially all (x,y))
00037 void msm_points::set_size(unsigned n, double x, double y)
00038 {
00039   if (n==size()) return;
00040   v_.set_size(n*2);
00041   double* v=v_.data_block();
00042   double* v_end=v+2*n;
00043   for (;v!=v_end;v+=2) 
00044   {
00045     v[0]=x; v[1]=y;
00046   }
00047 }
00048 
00049 //: Set this to be equal to supplied points
00050 void msm_points::set_points(const vcl_vector<vgl_point_2d<double> >& pts)
00051 {
00052   unsigned n=pts.size();
00053   v_.set_size(2*n);
00054   double* v=v_.data_block();
00055   vcl_vector<vgl_point_2d<double> >::const_iterator p = pts.begin();
00056   for (;p!=pts.end();v+=2,++p)
00057   {
00058     v[0] = p->x();
00059     v[1] = p->y();
00060   }
00061 }
00062 
00063 //: Copy points into pts
00064 void msm_points::get_points(vcl_vector<vgl_point_2d<double> >& pts) const
00065 {
00066   pts.resize(size());
00067   const double* v=v_.data_block();
00068   vcl_vector<vgl_point_2d<double> >::iterator p = pts.begin();
00069   for (;p!=pts.end();v+=2,++p)
00070   {
00071     p->x()=v[0];
00072     p->y()=v[1];
00073   }
00074 }
00075 
00076 //: Return centre of gravity of points
00077 vgl_point_2d<double> msm_points::cog() const
00078 {
00079   const double* v=v_.data_block();
00080   unsigned n=size();
00081   const double* end_v=v+2*n;
00082   double cx=0.0,cy=0.0;
00083   for (;v!=end_v;v+=2) { cx+=v[0]; cy+=v[1]; }
00084   if (n>0) { cx/=n; cy/=n; }
00085   return vgl_point_2d<double>(cx,cy);
00086 }
00087 
00088 //: Return RMS of distance of points to CoG.
00089 double msm_points::scale() const
00090 {
00091   vgl_point_2d<double> c;
00092   double s;
00093   get_cog_and_scale(c,s);
00094   return s;
00095 }
00096 
00097 //: Compute centre of gravity and RMS distance to CoG
00098 void msm_points::get_cog_and_scale(vgl_point_2d<double>& cog, double& scale) const
00099 {
00100   unsigned n=size();
00101   if (n==0) { cog=vgl_point_2d<double>(0,0); scale=0; return; }
00102 
00103   const double* v=v_.data_block();
00104   const double* end_v=v+2*n;
00105 
00106   // compute sum and sum of squares of elements
00107   double sx=0.0,s2x=0.0,sy=0.0,s2y=0.0;
00108   for (;v!=end_v;v+=2)
00109   {
00110     sx+=v[0];  s2x+=v[0]*v[0];
00111     sy+=v[1];  s2y+=v[1]*v[1];
00112   }
00113 
00114   double cx=sx/n, cy=sy/n;
00115   double L2=(s2x+s2y)/n-cx*cx-cy*cy;
00116   scale = 0.0;
00117   if (L2>0) scale=vcl_sqrt(L2);
00118   cog=vgl_point_2d<double>(cx,cy);
00119 }
00120 
00121 //: Scale current points by s about the origin
00122 void msm_points::scale_by(double s)
00123 {
00124   if (s==1.0) return;
00125   v_*=s;
00126 }
00127 
00128 //: Translate current points by (tx,ty)
00129 void msm_points::translate_by(double tx, double ty)
00130 {
00131   if (tx==0.0 && ty==0.0) return;
00132   double* v=v_.data_block();
00133   double* end_v=v+2*size();
00134   for (;v!=end_v;v+=2)
00135   {
00136     v[0]+=tx;
00137     v[1]+=ty;
00138   }
00139 }
00140 
00141 //: Transform current points with similarity transform
00142 void msm_points::transform_by(double a, double b, double tx, double ty)
00143 {
00144   double* v=v_.data_block();
00145   double* end_v=v+2*size();
00146   for (;v!=end_v;v+=2)
00147   {
00148     double x=v[0],y=v[1];
00149     v[0]=a*x-b*y+tx;
00150     v[1]=b*x+a*y+ty;
00151   }
00152 }
00153 
00154 //: Transform current points with t
00155 void msm_points::transform_by(const vimt_transform_2d& t)
00156 {
00157   double* v=v_.data_block();
00158   double* end_v=v+2*size();
00159   for (;v!=end_v;v+=2)
00160   {
00161     vgl_point_2d<double> p = t(v[0],v[1]);
00162     v[0]=p.x(); v[1]=p.y();
00163   }
00164 }
00165 
00166 //: Bounding box of points
00167 void msm_points::get_bounds(vgl_point_2d<double>& b_lo,
00168                             vgl_point_2d<double>& b_hi) const
00169 {
00170   if (size()==0)
00171   {
00172     b_lo=vgl_point_2d<double>(0,0);
00173     b_hi=vgl_point_2d<double>(0,0);
00174     return;
00175   }
00176 
00177   const double* v=v_.data_block();
00178   const double* end_v=v+2*size();
00179   b_lo=vgl_point_2d<double>(v[0],v[1]);
00180   b_hi=b_lo;
00181   for (;v!=end_v;v+=2)
00182   {
00183     if (v[0]<b_lo.x()) b_lo.x()=v[0];
00184     if (v[0]>b_hi.x()) b_hi.x()=v[0];
00185     if (v[1]<b_lo.y()) b_lo.y()=v[1];
00186     if (v[1]>b_hi.y()) b_hi.y()=v[1];
00187   }
00188 }
00189 
00190 //: Return bounding box of points
00191 vgl_box_2d<double> msm_points::bounds() const
00192 {
00193   vgl_point_2d<double> blo,bhi;
00194   get_bounds(blo,bhi);
00195   return vgl_box_2d<double>(blo,bhi);
00196 }
00197 
00198 //: Equality test
00199 bool msm_points::operator==(const msm_points& points) const
00200 {
00201   if (points.v_.size()!=v_.size()) return false;
00202   if (size()==0) return true;
00203   double ssd=vnl_vector_ssd(points.v_,v_);
00204   return (vcl_fabs(ssd/size())<1e-3);
00205 }
00206 
00207 // ===============================================================
00208 // ========= Text IO =============================================
00209 
00210 //: Write out points to named text file
00211 //  Returns true if successful.
00212 bool msm_points::write_text_file(const vcl_string& path) const
00213 {
00214   vcl_ofstream afs(path.c_str(),vcl_ios_out);
00215   if (!afs) return false;
00216 
00217   unsigned n = size();
00218   const double* v = v_.data_block();
00219   afs << "version: 1\nn_points: " << n << "\n{" << '\n';
00220   for (unsigned i=0;i<n;++i)
00221   {
00222     // Write out elements of point on a single line
00223     afs << v[2*i] << ' ' << v[2*i+1] << '\n';
00224   }
00225   afs << '}' << '\n';
00226 
00227   afs.close();
00228 
00229   return true;
00230 }
00231 
00232 static bool read_points(vcl_istream& afs,
00233                         vnl_vector<double>& vec, unsigned n)
00234 {
00235   if (n>999999)
00236   {
00237     vcl_cerr << "msm_points read_points() :\n"
00238              << "Bizarre number of points specified : " << n << vcl_endl;
00239     return false;
00240   }
00241 
00242   vec.set_size(2*n);
00243   double* v = vec.data_block();
00244   for (unsigned i=0;i<n;i++,v+=2)
00245   {
00246     if (afs.eof())
00247     {
00248       vcl_cerr << "msm_points read_points() :\n"
00249                << "EOF reached after reading "
00250                << i << " of " << n << " points.\n";
00251       return false;
00252     }
00253     afs>>v[0]>>v[1];
00254   }
00255 
00256   return true;
00257 }
00258 
00259 //: Read in points from named text file
00260 //  Returns true if successful.
00261 bool msm_points::read_text_file(const vcl_string& path)
00262 {
00263   vcl_ifstream afs( path.c_str(), vcl_ios_in );
00264   if (!afs) return false;
00265 
00266   vnl_vector<double> vec;  // New data
00267   vcl_string label;
00268   afs >> label;
00269   if (label != "version:")
00270   {
00271     // Attempt to load in old format
00272     int n = vcl_atoi(label.c_str());
00273     if (n>0)
00274     {
00275       return read_points(afs, v_, n);
00276     }
00277 
00278     vcl_cerr << "Expecting <version:> got <" << label << vcl_endl;
00279     return false;
00280   }
00281 
00282   int ver;
00283   afs >> ver;
00284   if (ver!=1)
00285   {
00286     vcl_cerr << "msm_points::read_text_file() :\n"
00287              << "Cannot cope with version number " << ver << vcl_endl;
00288     return false;
00289   }
00290 
00291   // Possible extra data - ignore it
00292   int image_nx, image_ny, image_nz;
00293   int n = -1;
00294 
00295   afs >> label;
00296   while (!afs.eof()  && label != "}")
00297   {
00298     if (label.size()>=2 && label[0]=='/' && label[1]=='/')
00299     {
00300       // Comment: Read to the end of the line
00301       char buf[256];
00302       afs.get(buf,256);
00303     }
00304     else
00305     if (label=="image_size_x:")
00306       afs>>image_nx;
00307     else if (label=="image_size_y:")
00308       afs>>image_ny;
00309     else if (label=="image_size_z:")
00310       afs>>image_nz;
00311     else if (label=="n_points:")
00312       afs>>n;
00313     else if (label=="{")
00314     {
00315       if (!read_points(afs, v_, n))
00316         return false;
00317     }
00318     else
00319     {
00320       vcl_cerr << "Unexpected label: <" << label << vcl_endl;
00321       return false;
00322     }
00323 
00324     afs>>label;
00325   }
00326 
00327   return true;
00328 }
00329 
00330 
00331 //=======================================================================
00332 // Method: version_no
00333 //=======================================================================
00334 
00335 short msm_points::version_no() const
00336 {
00337   return 1;
00338 }
00339 
00340 //=======================================================================
00341 // Method: is_a
00342 //=======================================================================
00343 
00344 vcl_string msm_points::is_a() const
00345 {
00346   return vcl_string("msm_points");
00347 }
00348 
00349 //=======================================================================
00350 // Method: print
00351 //=======================================================================
00352 
00353   // required if data is present in this class
00354 void msm_points::print_summary(vcl_ostream& os) const
00355 {
00356   os << size() << " pts: ";
00357   for (unsigned i=0;i<size();++i)
00358     os << '(' << v_[2*i] << ',' << v_[2*i+1] << ')';
00359 }
00360 
00361 //=======================================================================
00362 // Method: save
00363 //=======================================================================
00364 
00365   // required if data is present in this class
00366 void msm_points::b_write(vsl_b_ostream& bfs) const
00367 {
00368   vsl_b_write(bfs,version_no());
00369   vsl_b_write(bfs,v_);
00370 }
00371 
00372 //=======================================================================
00373 // Method: load
00374 //=======================================================================
00375 
00376   // required if data is present in this class
00377 void msm_points::b_read(vsl_b_istream& bfs)
00378 {
00379   short version;
00380   vsl_b_read(bfs,version);
00381   switch (version)
00382   {
00383     case (1):
00384       vsl_b_read(bfs,v_);
00385       break;
00386     default:
00387       vcl_cerr << "msm_points::b_read() :\n"
00388                << "Unexpected version number " << version << vcl_endl;
00389       vcl_abort();
00390   }
00391 }
00392 
00393 
00394 //=======================================================================
00395 // Associated function: operator<<
00396 //=======================================================================
00397 
00398 void vsl_b_write(vsl_b_ostream& bfs, const msm_points& b)
00399 {
00400   b.b_write(bfs);
00401 }
00402 
00403 //=======================================================================
00404 // Associated function: operator>>
00405 //=======================================================================
00406 
00407 void vsl_b_read(vsl_b_istream& bfs, msm_points& b)
00408 {
00409   b.b_read(bfs);
00410 }
00411 
00412 //=======================================================================
00413 // Associated function: operator<<
00414 //=======================================================================
00415 
00416 vcl_ostream& operator<<(vcl_ostream& os,const msm_points& b)
00417 {
00418   os << b.is_a() << ": ";
00419   vsl_indent_inc(os);
00420   b.print_summary(os);
00421   vsl_indent_dec(os);
00422   return os;
00423 }
00424 
00425 //: Stream output operator for class reference
00426 void vsl_print_summary(vcl_ostream& os,const msm_points& b)
00427 {
00428  os << b;
00429 }