contrib/gel/vsol/vsol_digital_curve_2d.cxx
Go to the documentation of this file.
00001 // This is gel/vsol/vsol_digital_curve_2d.cxx
00002 #include "vsol_digital_curve_2d.h"
00003 //:
00004 // \file
00005 #include <vsol/vsol_point_2d.h>
00006 #include <vcl_iostream.h>
00007 #include <vgl/vgl_point_2d.h>
00008 #include <vgl/vgl_closest_point.h>
00009 #include <vsl/vsl_vector_io.h>
00010 #include <vcl_cmath.h>
00011 #include <vcl_cassert.h>
00012 
00013 //***************************************************************************
00014 // Initialization
00015 //***************************************************************************
00016 
00017 //---------------------------------------------------------------------------
00018 //: Default Constructor
00019 //---------------------------------------------------------------------------
00020 vsol_digital_curve_2d::vsol_digital_curve_2d()
00021  : vsol_curve_2d(), samples_()
00022 {
00023 }
00024 
00025 //---------------------------------------------------------------------------
00026 //: Constructor from a vcl_vector of points
00027 //---------------------------------------------------------------------------
00028 
00029 vsol_digital_curve_2d::vsol_digital_curve_2d(const vcl_vector<vsol_point_2d_sptr> &samples)
00030  : vsol_curve_2d(), samples_(samples)
00031 {
00032 }
00033 
00034 //---------------------------------------------------------------------------
00035 // Copy constructor
00036 //---------------------------------------------------------------------------
00037 vsol_digital_curve_2d::vsol_digital_curve_2d(const vsol_digital_curve_2d &other)
00038   : vsol_curve_2d(other), samples_()
00039 {
00040   for ( vcl_vector<vsol_point_2d_sptr>::const_iterator itr=other.samples_.begin();
00041         itr != other.samples_.end();  ++itr )
00042     this->samples_.push_back(new vsol_point_2d(**itr));
00043 }
00044 
00045 //---------------------------------------------------------------------------
00046 // Destructor
00047 //---------------------------------------------------------------------------
00048 vsol_digital_curve_2d::~vsol_digital_curve_2d()
00049 {
00050 }
00051 
00052 //---------------------------------------------------------------------------
00053 //: Clone `this': creation of a new object and initialization
00054 // See Prototype pattern
00055 //---------------------------------------------------------------------------
00056 vsol_spatial_object_2d* vsol_digital_curve_2d::clone(void) const
00057 {
00058   return new vsol_digital_curve_2d(*this);
00059 }
00060 
00061 //***************************************************************************
00062 // Access
00063 //***************************************************************************
00064 
00065 //---------------------------------------------------------------------------
00066 //: Return the first point of `this'
00067 //---------------------------------------------------------------------------
00068 vsol_point_2d_sptr vsol_digital_curve_2d::p0(void) const
00069 {
00070   if ( samples_.empty() )
00071     return NULL;
00072 
00073   return samples_.front();
00074 }
00075 
00076 //---------------------------------------------------------------------------
00077 //: Return the last point of `this'
00078 //---------------------------------------------------------------------------
00079 vsol_point_2d_sptr vsol_digital_curve_2d::p1(void) const
00080 {
00081   if ( samples_.empty() )
00082     return NULL;
00083 
00084   return samples_.back();
00085 }
00086 
00087 //---------------------------------------------------------------------------
00088 //: Return point `i'
00089 //  REQUIRE: valid_index(i)
00090 //---------------------------------------------------------------------------
00091 vsol_point_2d_sptr vsol_digital_curve_2d::point(const int i) const
00092 {
00093   // require
00094   assert(valid_index(i));
00095 
00096   return samples_[i];
00097 }
00098 
00099 //---------------------------------------------------------------------------
00100 //: Interpolate a point on the curve given a floating point index
00101 //  Linear interpolation is used for now
00102 //---------------------------------------------------------------------------
00103 vgl_point_2d<double>
00104 vsol_digital_curve_2d::interp(double index) const
00105 {
00106   assert(index >= 0.0);
00107   assert(index <= double(samples_.size()-1));
00108 
00109   int i1 = (int)vcl_floor(index);
00110   if ( vcl_floor(index) == index )
00111     return samples_[i1]->get_p();
00112 
00113   int i2 = (int)vcl_ceil(index);
00114   double f = index - vcl_floor(index);
00115 
00116   vgl_point_2d<double> p1 = samples_[i1]->get_p();
00117   vgl_point_2d<double> p2 = samples_[i2]->get_p();
00118   return p1 + f*(p2-p1);
00119 }
00120 
00121 
00122 //***************************************************************************
00123 // Comparison
00124 //***************************************************************************
00125 
00126 //---------------------------------------------------------------------------
00127 //: Has `this' the same points than `other' in the same order ?
00128 //---------------------------------------------------------------------------
00129 bool vsol_digital_curve_2d::operator==(const vsol_digital_curve_2d &other) const
00130 {
00131   if (this==&other)
00132     return true;
00133   //check endpoint equality since that is cheaper then checking each vertex
00134   //and if it fails we are done
00135   bool epts_eq = vsol_curve_2d::endpoints_equal(other);
00136   if (!epts_eq)
00137     return false;
00138   //Do the polylines have the same number of vertices?
00139   if (samples_.size()!=other.samples_.size())
00140     return false;
00141   //The easy tests are done.  Now compare each vertex
00142   int n = samples_.size();
00143   for (int i=0; i<n; i++)
00144     if (*(samples_[i])!=*(other.samples_[i]))
00145       return false;
00146   return true;
00147 }
00148 
00149 //: spatial object equality
00150 
00151 bool vsol_digital_curve_2d::operator==(const vsol_spatial_object_2d& obj) const
00152 {
00153   return
00154     obj.cast_to_curve() && obj.cast_to_curve()->cast_to_digital_curve() &&
00155     *this == *obj.cast_to_curve()->cast_to_digital_curve();
00156 }
00157 
00158 //***************************************************************************
00159 // Status report
00160 //***************************************************************************
00161 
00162 
00163 //---------------------------------------------------------------------------
00164 //: Return the length of `this'
00165 //---------------------------------------------------------------------------
00166 double vsol_digital_curve_2d::length(void) const
00167 {
00168   double curve_length = 0.0;
00169   for ( vcl_vector<vsol_point_2d_sptr>::const_iterator itr=samples_.begin();
00170         itr+1 != samples_.end();  ++itr )
00171   {
00172     curve_length += ((*(itr+1))->get_p() - (*itr)->get_p()).length();
00173   }
00174   return curve_length;
00175 }
00176 
00177 
00178 //---------------------------------------------------------------------------
00179 //: Compute the bounding box of `this'
00180 //---------------------------------------------------------------------------
00181 void vsol_digital_curve_2d::compute_bounding_box(void) const
00182 {
00183   // valid under linear interpolation
00184   set_bounding_box(samples_[0]->x(), samples_[0]->y());
00185   for (unsigned int i=1; i<samples_.size(); ++i)
00186     add_to_bounding_box(samples_[i]->x(), samples_[i]->y());
00187 }
00188 
00189 //***************************************************************************
00190 // Status setting
00191 //***************************************************************************
00192 
00193 //---------------------------------------------------------------------------
00194 //: Set the first point of the curve
00195 // Require: in(new_p0)
00196 //---------------------------------------------------------------------------
00197 void vsol_digital_curve_2d::set_p0(const vsol_point_2d_sptr &new_p0)
00198 {
00199   samples_.front() = new_p0;
00200 }
00201 
00202 //---------------------------------------------------------------------------
00203 //: Set the last point of the curve
00204 // Require: in(new_p1)
00205 //---------------------------------------------------------------------------
00206 void vsol_digital_curve_2d::set_p1(const vsol_point_2d_sptr &new_p1)
00207 {
00208   samples_.back() = new_p1;
00209 }
00210 
00211 //---------------------------------------------------------------------------
00212 //: Add another point to the curve
00213 //---------------------------------------------------------------------------
00214 void vsol_digital_curve_2d::add_vertex(const vsol_point_2d_sptr &new_p)
00215 {
00216   samples_.push_back(new_p);
00217 }
00218 
00219 //----------------------------------------------------------------
00220 // ================   Binary I/O Methods ========================
00221 //----------------------------------------------------------------
00222 
00223 //: Binary save self to stream.
00224 void vsol_digital_curve_2d::b_write(vsl_b_ostream &os) const
00225 {
00226   vsl_b_write(os, version());
00227   vsl_b_write(os, samples_);
00228 }
00229 
00230 
00231 //: Binary load self from stream
00232 void vsol_digital_curve_2d::b_read(vsl_b_istream &is)
00233 {
00234   if (!is)
00235     return;
00236 
00237   short ver;
00238   vsl_b_read(is, ver);
00239   switch (ver)
00240   {
00241    default:
00242     assert(!"vsol_digital_curve_2d I/O version should be 1");
00243    case 1:
00244     vsl_b_read(is, samples_);
00245   }
00246 }
00247 
00248 
00249 //: Return IO version number;
00250 short vsol_digital_curve_2d::version() const
00251 {
00252   return 1;
00253 }
00254 
00255 //: Print an ascii summary to the stream
00256 void vsol_digital_curve_2d::print_summary(vcl_ostream &os) const
00257 {
00258   os << *this;
00259 }
00260 
00261 
00262 //----------------------------------------------------------------
00263 // ================  External Methods ========================
00264 //----------------------------------------------------------------
00265 
00266 
00267 //: Binary save vsol_digital_curve_2d to stream.
00268 void
00269 vsl_b_write(vsl_b_ostream &os, const vsol_digital_curve_2d* p)
00270 {
00271   if (p==0) {
00272     vsl_b_write(os, false); // Indicate null pointer stored
00273   }
00274   else {
00275     vsl_b_write(os,true); // Indicate non-null pointer stored
00276     p->b_write(os);
00277   }
00278 }
00279 
00280 
00281 //: Binary load vsol_digital_curve_2d from stream.
00282 void
00283 vsl_b_read(vsl_b_istream &is, vsol_digital_curve_2d* &p)
00284 {
00285   delete p;
00286   bool not_null_ptr;
00287   vsl_b_read(is, not_null_ptr);
00288   if (not_null_ptr) {
00289     p = new vsol_digital_curve_2d();
00290     p->b_read(is);
00291   }
00292   else
00293     p = 0;
00294 }
00295 
00296 void vsol_digital_curve_2d::describe(vcl_ostream &strm, int blanking) const
00297 {
00298   if (blanking < 0) blanking = 0; while (blanking--) strm << ' ';
00299   strm << "[vsol_digital_curve_2d";
00300   for (unsigned int i=0; i<size(); ++i)
00301     strm << ' ' << *(point(i));
00302   strm << ']' << vcl_endl;
00303 }
00304 
00305 
00306 //: Return the floating point index of the point on the curve nearest to \p pt
00307 double closest_index(const vgl_point_2d<double>& pt,
00308                      const vsol_digital_curve_2d_sptr& curve)
00309 {
00310   const unsigned int n = curve->size();
00311   double *px = new double[n], *py = new double[n];
00312   for (unsigned int i=0; i<n; ++i)
00313     px[i]=curve->point(i)->x(), py[i]=curve->point(i)->y();
00314   double x, y;
00315   int index=vgl_closest_point_to_non_closed_polygon(x,y,px,py,n,pt.x(),pt.y());
00316   double dx = px[index+1]-px[index], dy = py[index+1]-py[index];
00317   double f = dx==0 ? (dy==0 ? 0.5 : (y-py[index])/dy) : (x-px[index])/dx;
00318   delete [] px; delete[] py;
00319   return f + index;
00320 }
00321 
00322 
00323 //: Split the input curve into two pieces at the floating point index
00324 bool split(const vsol_digital_curve_2d_sptr &input,
00325            double index,
00326            vsol_digital_curve_2d_sptr &output1,
00327            vsol_digital_curve_2d_sptr &output2)
00328 {
00329   const int n = input->size();
00330   if (index <= 0.0 || index >= double(n-1))
00331     return false;
00332 
00333   vcl_vector<vsol_point_2d_sptr> vec1, vec2;
00334   vgl_point_2d<double> break_point = input->interp(index);
00335   vec2.push_back(new vsol_point_2d(break_point));
00336   for (int i=0; i<n; ++i) {
00337     if ( double(i) < index )
00338       vec1.push_back(input->point(i));
00339     if ( double(i) > index )
00340       vec2.push_back(input->point(i));
00341     // if index == i then ignore this point
00342   }
00343   vec1.push_back(new vsol_point_2d(break_point));
00344 
00345   output1 = new vsol_digital_curve_2d(vec1);
00346   output2 = new vsol_digital_curve_2d(vec2);
00347   return true;
00348 }