00001
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
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
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
00168
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
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
00198
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
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
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
00347 hypothesized_line_ = new imp_line(A, B, C);
00348 }