contrib/gel/vifa/vifa_line_cover.cxx
Go to the documentation of this file.
00001 // This is gel/vifa/vifa_line_cover.cxx
00002 #include "vifa_line_cover.h"
00003 //:
00004 // \file
00005 
00006 #include <vcl_algorithm.h>
00007 #include <vgl/vgl_point_2d.h>
00008 #include <vgl/vgl_vector_2d.h>
00009 
00010 //-----------------------------------------------------------
00011 //: Constructors
00012 
00013 vifa_line_cover::
00014 vifa_line_cover()
00015 {
00016   line_ = NULL;
00017   index_ = NULL;
00018   max_extent_ = NULL;
00019   min_extent_ = NULL;
00020   dim_ =0;
00021 }
00022 
00023 vifa_line_cover::
00024 vifa_line_cover(imp_line_sptr  prototype_line,
00025                 int            indexdimension)
00026 {
00027   line_ = prototype_line;
00028   dim_ = indexdimension;
00029   index_ = new int[dim_];
00030   max_extent_ = new double[dim_];
00031   min_extent_ = new double[dim_];
00032   for (int i = 0; i < dim_; i++)
00033   {
00034     index_[i] = 0;
00035     max_extent_[i] = -1E6;
00036     min_extent_[i] = 1E6;
00037   }
00038 }
00039 
00040 //------------------------------------------------------------
00041 //: Destructor
00042 vifa_line_cover::
00043 ~vifa_line_cover()
00044 {
00045   delete [] index_;
00046   delete [] max_extent_;
00047   delete [] min_extent_;
00048 }
00049 
00050 //------------------------------------------------------------
00051 //: Insert a line in the index. The line is inserted in each index bin it covers.
00052 void vifa_line_cover::
00053 InsertLine(imp_line_sptr  l)
00054 {
00055   int  rdim1 = dim_ - 1;
00056 
00057   // Find the 2-D projection of l onto the prototype line
00058   // That is, find the parameter bounds
00059   vgl_point_2d<double>  sp;
00060   vgl_point_2d<double>  ep;
00061   sp = l->point1();
00062   ep = l->point2();
00063   double  ts = line_->find_t(sp);
00064   double  te = line_->find_t(ep);
00065 
00066   // Get properly ordered and limited parameter bounds
00067   int ist;
00068   int iend;
00069   if (ts < te)
00070   {
00071     if (ts < 0)
00072       ts = 0;
00073     if (te > 1.0)
00074       te = 1.0;
00075 
00076     ist = (int)(rdim1 * ts);
00077     iend = (int)(rdim1 * te);
00078   }
00079   else
00080   {
00081     if (te < 0)
00082       te = 0;
00083     if (ts > 1.0)
00084       ts = 1.0;
00085 
00086     ist = (int)(rdim1 * te);
00087     iend = (int)(rdim1 * ts);
00088   }
00089 
00090   // Next accumulate the bins for each line coverage
00091   for (int i = ist; i <= iend; i++)
00092   {
00093     index_[i]++;
00094     double          t = (double)i / (double)rdim1;
00095     vgl_point_2d<double>  pos = line_->find_at_t(t);
00096 
00097     vgl_point_2d<double>  p = l->project_2d_pt(pos);
00098     double          d = this->get_signed_distance(p);
00099 
00100     min_extent_[i] = vcl_min(min_extent_[i], d);
00101     max_extent_[i] = vcl_max(max_extent_[i], d);
00102   }
00103 }
00104 
00105 //---------------------------------------------------------------
00106 //: Get the average coverage along the line.
00107 //  Normalized by the full bounding box diagonal.  Coverage must be
00108 //   greater than one line in order to indicate mutual coverage
00109 double vifa_line_cover::
00110 GetCoverage()
00111 {
00112   int  sum = 0;
00113   for (int i = 0; i < dim_; i++)
00114   {
00115     int  nlines = index_[i];
00116     if (nlines > 1)
00117       sum += (nlines - 1);
00118   }
00119 
00120   return (double)sum / dim_;
00121 }
00122 
00123 //---------------------------------------------------------------
00124 //: Get the average coverage along the line.
00125 //  Coverage must be greater than one line in order to indicate mutual coverage
00126 double vifa_line_cover::
00127 GetDenseCoverage()
00128 {
00129   double  cov = this->GetCoverage();
00130   double  cover_extent = double(this->get_index_max() - this->get_index_min());
00131   if (cover_extent <= 0)
00132     return 0.0;
00133   else
00134     return (dim_ * cov) / cover_extent;
00135 }
00136 
00137 
00138 //-------------------------------------------------------------
00139 //: Get coverage relative to the total perimeter of indexed lines
00140 //
00141 double vifa_line_cover::
00142 GetCustomCoverage(const double  norm)
00143 {
00144   double  total_cover = this->GetCoverage() * dim_;
00145   if (norm <= 0)
00146     return 0.0;
00147   else
00148     return total_cover / norm;
00149 }
00150 //---------------------------------------------------------------
00151 //: Get extent of image space where parallel lines overlap under projection onto the prototype.
00152 void vifa_line_cover::
00153 GetExtent(imp_line_sptr&  lmin,
00154           imp_line_sptr&  lmax)
00155 {
00156   if (!line_)
00157   {
00158     lmin = NULL;
00159     lmax = NULL;
00160     return;
00161   }
00162 
00163   int    st = get_index_min();
00164   int    en = get_index_max();
00165   double  min_ex = 1E6;
00166   double  max_ex = -1E6;
00167 
00168   // Scan for the max and min lateral extents
00169   for (int i = st; i <= en; i++)
00170   {
00171     min_ex = vcl_min(min_extent_[i], min_ex);
00172     max_ex = vcl_max(max_extent_[i], max_ex);
00173   }
00174 
00175   // Construct min and max bounding lines
00176   lmin = get_offset_line(st, en, min_ex);
00177   lmax = get_offset_line(st, en, max_ex);
00178 }
00179 
00180 int vifa_line_cover::
00181 get_index_min()
00182 {
00183   for (int i = 1; (i < dim_); i++)
00184   {
00185     if (index_[i] > 1)
00186       return i;
00187   }
00188 
00189   return 0;
00190 }
00191 
00192 int vifa_line_cover::
00193 get_index_max()
00194 {
00195   for (int i = dim_ - 1; i > 0; --i)
00196   {
00197     if (index_[i] > 1)
00198       return i;
00199   }
00200   return 0;
00201 }
00202 
00203 // Signed distance (algebraic dist) of a point from the prototype line
00204 double vifa_line_cover::
00205 get_signed_distance(vgl_point_2d<double> const &  p)
00206 {
00207   double  a = line_->a(), b = line_->b(), c = line_->c();
00208   double  d = a * p.x() + b * p.y() + c;
00209   return d;
00210 }
00211 
00212 // Get a bounded ImplicitLine which is offset from the prototype line
00213 // by the signed distance, d.
00214 imp_line_sptr vifa_line_cover::
00215 get_offset_line(int    start,
00216                 int    end,
00217                 double d)
00218 {
00219   // The normal vector
00220   vgl_vector_2d<double>  n = line_->normal();
00221 
00222   // The end points on the prototype line
00223   double  ts = (double)start / double(dim_ - 1);
00224   vgl_point_2d<double>  ps = line_->find_at_t(ts);
00225   double  te = (double)end / double(dim_ - 1);
00226   vgl_point_2d<double>  pe = line_->find_at_t(te);
00227 
00228   n *= d; // Extend the normal
00229   ps += n; // The offset start point
00230   pe += n; // The offset end point
00231   imp_line_sptr  il = new imp_line(ps, pe);
00232   return il;
00233 }