contrib/gel/vifa/vifa_coll_lines.cxx
Go to the documentation of this file.
00001 // This is gel/vifa/vifa_coll_lines.cxx
00002 #include "vifa_coll_lines.h"
00003 #include <vcl_cmath.h>
00004 #include <vnl/vnl_math.h>
00005 #include <vsol/vsol_point_2d.h>
00006 #include <vtol/vtol_face.h>
00007 
00008 // Static initialization
00009 int  vifa_coll_lines::serial_num_ = 0;
00010 
00011 vifa_coll_lines::vifa_coll_lines(vtol_edge_2d_sptr  e,
00012                                  double             cutoff_angle_deg,
00013                                  double             endpt_distance,
00014                                  bool               discard_flag)
00015 {
00016   vsol_point_2d_sptr p1 = e->curve()->p0();
00017   vsol_point_2d_sptr p2 = e->curve()->p1();
00018 
00019   hypothesized_line_ = new imp_line(p1->get_p(), p2->get_p());
00020   contributors_.push_back(e);
00021   projected_length_cutoff_ = vcl_cos(cutoff_angle_deg * vnl_math::pi_over_180);
00022   endpt_distance_ = endpt_distance;
00023   id_ = vifa_coll_lines::serial_num_++;
00024   discard_flag_ = discard_flag;
00025 }
00026 
00027 vifa_coll_lines::~vifa_coll_lines(void)
00028 {
00029   hypothesized_line_ = 0;
00030 }
00031 
00032 bool vifa_coll_lines::get_discard_flag(void) const
00033 {
00034   return discard_flag_;
00035 }
00036 
00037 int vifa_coll_lines::get_id(void) const
00038 {
00039   return id_;
00040 }
00041 
00042 double vifa_coll_lines::get_measure(const vtol_edge_2d&  e) const
00043 {
00044   return get_measure(e, *hypothesized_line_);
00045 }
00046 
00047 double vifa_coll_lines::get_projected_length(const vtol_edge_2d&  e) const
00048 {
00049   double  v1;
00050   double  v2;
00051 
00052   return vifa_coll_lines::get_projected_length(e,
00053                                                *hypothesized_line_,
00054                                                v1,
00055                                                v2);
00056 }
00057 
00058 edge_2d_list& vifa_coll_lines::get_contributors(void)
00059 {
00060   return contributors_;
00061 }
00062 
00063 face_list* vifa_coll_lines::get_contributor_faces(void)
00064 {
00065   face_list*  ret = new face_list;
00066 
00067   for (edge_2d_iterator e = contributors_.begin();
00068        e != contributors_.end(); ++e)
00069   {
00070     face_list faces; (*e)->faces(faces);
00071 
00072     for (face_iterator f_it = faces.begin(); f_it != faces.end(); ++f_it)
00073     {
00074       vtol_face_sptr  nbr_face = *f_it;
00075       bool      add_me = true;
00076 
00077       // Make sure the contributor face is 2-D
00078       if (nbr_face->cast_to_face_2d())
00079       {
00080         for (face_iterator f = ret->begin(); f != ret->end(); ++f)
00081         {
00082           if (**f == *nbr_face)
00083           {
00084             add_me = false;
00085             break;
00086           }
00087         }
00088 
00089         if (add_me)
00090         {
00091           ret->push_back(nbr_face);
00092         }
00093       }
00094     }
00095   }
00096 
00097   return ret;
00098 }
00099 
00100 void vifa_coll_lines::lms_fit(const vcl_vector<double>&  x,
00101                               const vcl_vector<double>&  y,
00102                               double&                    A,
00103                               double&                    B,
00104                               double&                    C)
00105 {
00106   double  sum_x_sq = 0.0;
00107   double  sum_x = 0.0;
00108   double  sum_xy = 0.0;
00109   double  sum_y = 0.0;
00110   double  n = 0.0;
00111 
00112   vcl_vector<double>::const_iterator  xi = x.begin();
00113   vcl_vector<double>::const_iterator  yi = y.begin();
00114   for (; xi != x.end(); ++xi, ++yi)
00115   {
00116     sum_x_sq += (*xi * (*xi));
00117     sum_x += *xi;
00118     sum_y += *yi;
00119     sum_xy += *xi * (*yi);
00120     n++;
00121   }
00122 
00123   double  f1 = n - ((sum_x * sum_x) / sum_x_sq);
00124   double  f2 = sum_y - (sum_x * sum_xy / sum_x_sq);
00125   double  b = f2 / f1;
00126   double  m = (sum_xy - (sum_x * b)) / sum_x_sq;
00127 
00128   A = m;
00129   C = b;
00130   B = -1;
00131 }
00132 
00133 void vifa_coll_lines::add_and_update(vtol_edge_2d_sptr  e)
00134 {
00135   contributors_.push_back(e);
00136   this->fit_line();
00137 }
00138 
00139 double vifa_coll_lines::spanning_length(void)
00140 {
00141   vgl_point_2d<double> p1;
00142   vgl_point_2d<double> p2;
00143 
00144   return spanning_length(p1, p2);
00145 }
00146 
00147 double vifa_coll_lines::spanning_length(vgl_point_2d<double>&  p1,
00148                                         vgl_point_2d<double>&  p2)
00149 {
00150   double  min_x=0.0, min_y=0.0, min_d;
00151   double  max_x=0.0, max_y=0.0, max_d= -1.0;
00152 
00153   for (edge_2d_iterator e = contributors_.begin();
00154        e != contributors_.end(); ++e)
00155   {
00156     vsol_point_2d_sptr v1 = (*e)->curve()->p0();
00157     vsol_point_2d_sptr v2 = (*e)->curve()->p1();
00158 
00159     for (int i = 0; i < 2; i++)
00160     {
00161       vsol_point_2d_sptr v = (i == 0) ? v1 : v2;
00162       double            x;
00163       double            y;
00164 
00165       hypothesized_line_->project_2d_pt(v->x(), v->y(), x, y);
00166 
00167       //vcl_cout << "    ---> " << v->x() << ", " << v->y() <<
00168       //  " projects to " << x << ", " << y << vcl_endl;
00169 
00170       double  d = vcl_sqrt((x * x) + (y * y));
00171       if (d > max_d)
00172       {
00173         max_d = d;
00174         max_x = x;
00175         max_y = y;
00176       }
00177     }
00178   }
00179 
00180   //vcl_cout << "  -> span: p1 is " << max_x << " , " << max_y << " ( " << max_d << " )\n";
00181 
00182   min_d = max_d;
00183   for (edge_2d_iterator e = contributors_.begin();
00184        e != contributors_.end(); ++e)
00185   {
00186     vsol_point_2d_sptr v1 = (*e)->curve()->p0();
00187     vsol_point_2d_sptr v2 = (*e)->curve()->p1();
00188 
00189     for (int i = 0; i < 2; i++)
00190     {
00191       vsol_point_2d_sptr v = (i == 0) ? v1 : v2;
00192       double            x;
00193       double            y;
00194 
00195       hypothesized_line_->project_2d_pt(v->x(), v->y(), x, y);
00196 
00197       //vcl_cout << "    ---> " << v->x() << ", " << v->y() <<
00198       //  " projects to " << x << ", " << y << vcl_endl;
00199 
00200       double  dx = x - max_x;
00201       double  dy = y - max_y;
00202       double  d = vcl_sqrt((dx * dx) + (dy * dy));
00203 
00204       if (d > min_d)
00205       {
00206         min_d = d;
00207         min_x = x;
00208         min_y = y;
00209       }
00210     }
00211   }
00212 
00213   //vcl_cout << "  -> span: p2 is " << min_x << " , " << min_y << " ( " << min_d << " )\n";
00214 
00215   double  dx = max_x - min_x;
00216   double  dy = max_y - min_y;
00217   p1 = vgl_point_2d<double>(min_x, min_y);
00218   p2 = vgl_point_2d<double>(max_x, max_y);
00219 
00220   return vcl_sqrt((dx * dx) + (dy * dy));
00221 }
00222 
00223 double vifa_coll_lines::support_length(void)
00224 {
00225   double  len = 0.0;
00226   for (edge_2d_iterator e = contributors_.begin();
00227        e != contributors_.end(); ++e)
00228   {
00229     len += this->get_projected_length(**e);
00230   }
00231 
00232   return len;
00233 }
00234 
00235 bool vifa_coll_lines::contains(const vtol_edge&  edgeref)
00236 {
00237   for (edge_2d_iterator e = contributors_.begin();
00238        e != contributors_.end(); ++e)
00239   {
00240     if (**e == edgeref)
00241     {
00242       return true;
00243     }
00244   }
00245 
00246   return false;
00247 }
00248 
00249 // *****************************************************************************
00250 //                                Private API's
00251 // *****************************************************************************
00252 
00253 double vifa_coll_lines::get_projected_length(const vtol_edge_2d&  e,
00254                                              const imp_line&      hyp_line,
00255                                              double&              v1_dist,
00256                                              double&              v2_dist)
00257 {
00258   vsol_point_2d_sptr v1 = e.curve()->p0();
00259   vsol_point_2d_sptr v2 = e.curve()->p1();
00260   double            x1;
00261   double            y1;
00262   double            x2;
00263   double            y2;
00264 
00265   hyp_line.project_2d_pt(v1->x(), v1->y(), x1, y1);
00266   hyp_line.project_2d_pt(v2->x(), v2->y(), x2, y2);
00267 
00268   double  dx = x2 - x1;
00269   double  dy = y2 - y1;
00270   double  midpt_dist = vcl_sqrt((dx * dx) + (dy * dy));
00271 
00272   dx = x1 - v1->x();
00273   dy = y1 - v1->y();
00274   v1_dist = vcl_sqrt((dx * dx) + (dy * dy));
00275 
00276   dx = x2 - v2->x();
00277   dy = y2 - v2->y();
00278   v2_dist = vcl_sqrt((dx * dx) + (dy * dy));
00279 
00280   return midpt_dist;
00281 }
00282 
00283 double vifa_coll_lines::get_midpt_dist(const vtol_edge_2d&  e,
00284                                        const imp_line&      hyp_line)
00285 {
00286   vsol_point_2d_sptr v1 = e.curve()->p0();
00287   vsol_point_2d_sptr v2 = e.curve()->p1();
00288   double            midx = (v1->x() + v2->x()) / 2;
00289   double            midy = (v1->y() + v2->y()) / 2;
00290   double            mx;
00291   double            my;
00292 
00293   hyp_line.project_2d_pt(midx, midy, mx, my);
00294 
00295   double  mid_dx = mx - midx;
00296   double  mid_dy = my - midy;
00297   return vcl_sqrt((mid_dx * mid_dx) + (mid_dy * mid_dy));
00298 }
00299 
00300 
00301 double vifa_coll_lines::get_measure(const vtol_edge_2d&  e,
00302                                     const imp_line&      hyp_line)  const
00303 {
00304   double    v1_dist;
00305   double    v2_dist;
00306   double    proj_len = vifa_coll_lines::get_projected_length(e,
00307                                                              hyp_line,
00308                                                              v1_dist,
00309                                                              v2_dist);
00310   bool    angle_fits = (proj_len / e.curve()->length() >
00311                         projected_length_cutoff_);
00312   bool    vertices_are_close = ((v1_dist < endpt_distance_) &&
00313                                 (v2_dist < endpt_distance_));
00314   double    rv = 100000;
00315 
00316   if (vertices_are_close || angle_fits)
00317   {
00318     rv = vifa_coll_lines::get_midpt_dist(e, hyp_line);
00319   }
00320 
00321   return rv;
00322 }
00323 
00324 void vifa_coll_lines::fit_line(void)
00325 {
00326   vcl_vector<double>  x;
00327   vcl_vector<double>  y;
00328   double              A;
00329   double              B;
00330   double              C;
00331 
00332   for (edge_2d_iterator e = contributors_.begin();
00333        e != contributors_.end(); ++e)
00334   {
00335     vsol_point_2d_sptr v1 = (*e)->curve()->p0();
00336     vsol_point_2d_sptr v2 = (*e)->curve()->p1();
00337 
00338     x.push_back(v1->x());
00339     x.push_back(v2->x());
00340     y.push_back(v1->y());
00341     y.push_back(v2->y());
00342   }
00343 
00344   vifa_coll_lines::lms_fit(x, y, A, B, C);
00345 
00346   // Smart pointer will unref previous hypothesized_line_
00347   hypothesized_line_ = new imp_line(A, B, C);
00348 }