contrib/brl/bbas/bsol/bsol_algs.cxx
Go to the documentation of this file.
00001 #include "bsol_algs.h"
00002 //:
00003 // \file
00004 
00005 #include <vcl_compiler.h>
00006 #ifdef VCL_VC_6
00007 //Get rid of warning generated by fault deep inside MS supplied library
00008 # pragma warning(disable:4018 )
00009 #endif
00010 
00011 #include <vnl/vnl_numeric_traits.h>
00012 #include <vsol/vsol_point_2d_sptr.h>
00013 #include <vsol/vsol_point_2d.h>
00014 #include <vsol/vsol_point_3d.h>
00015 #include <vsol/vsol_line_2d.h>
00016 #include <vsol/vsol_box_2d.h>
00017 #include <vsol/vsol_box_3d.h>
00018 #include <vsol/vsol_polygon_2d.h>
00019 #include <vsol/vsol_digital_curve_2d.h>
00020 #include <vgl/vgl_point_2d.h>
00021 #include <vgl/vgl_homg_point_2d.h>
00022 #include <vgl/vgl_box_2d.h>
00023 #include <vgl/vgl_intersection.h>
00024 #include <vgl/algo/vgl_convex_hull_2d.h>
00025 
00026 // Destructor
00027 bsol_algs::~bsol_algs()
00028 {
00029 }
00030 
00031 //-----------------------------------------------------------------------------
00032 //: Compute a bounding box for a set of vsol_point_2ds.
00033 //-----------------------------------------------------------------------------
00034 vbl_bounding_box<double,2> bsol_algs::
00035 bounding_box(vcl_vector<vsol_point_2d_sptr> const& points)
00036 {
00037   vbl_bounding_box<double, 2> b;
00038   for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = points.begin();
00039        pit != points.end(); pit++)
00040     b.update((*pit)->x(), (*pit)->y());
00041   return b;
00042 }
00043 
00044 //-----------------------------------------------------------------------------
00045 //: Compute a bounding box for a set of vsol_line_2ds.
00046 //-----------------------------------------------------------------------------
00047 vbl_bounding_box<double,2>  bsol_algs::
00048 bounding_box(vcl_vector<vsol_line_2d_sptr> const & lines)
00049 {
00050   vbl_bounding_box<double, 2> b;
00051   for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = lines.begin();
00052        lit != lines.end(); lit++)
00053   {
00054     vsol_point_2d_sptr p0 = (*lit)->p0();
00055     vsol_point_2d_sptr p1 = (*lit)->p1();
00056     b.update(p0->x(), p0->y());
00057     b.update(p1->x(), p1->y());
00058   }
00059   return b;
00060 }
00061 
00062 //-----------------------------------------------------------------------------
00063 //: Compute a bounding box for a set of vsol_point_3ds.
00064 //-----------------------------------------------------------------------------
00065 vbl_bounding_box<double,3> bsol_algs::
00066 bounding_box(vcl_vector<vsol_point_3d_sptr> const& points)
00067 {
00068   vbl_bounding_box<double, 3> b;
00069   for (vcl_vector<vsol_point_3d_sptr>::const_iterator pit = points.begin();
00070        pit != points.end(); pit++)
00071     b.update((*pit)->x(), (*pit)->y(), (*pit)->z());
00072   return b;
00073 }
00074 
00075 //-----------------------------------------------------------------------------
00076 //: Determine if a point is inside a bounding box
00077 //-----------------------------------------------------------------------------
00078 bool bsol_algs::in(vsol_box_2d_sptr const & b, double x, double y)
00079 {
00080   if (!b)
00081     return false;
00082   double xmin = b->get_min_x(), ymin = b->get_min_y();
00083   double xmax = b->get_max_x(), ymax = b->get_max_y();
00084   return x >= xmin && x <= xmax
00085       && y >= ymin && y <= ymax;
00086 }
00087 
00088 //: returns true if the boxes a and b intersect
00089 bool bsol_algs::meet(vsol_box_2d_sptr const & a, vsol_box_2d_sptr const & b)
00090 {
00091   double min_x_a = a->get_min_x(), max_x_a = a->get_max_x();
00092   double min_y_a = a->get_min_y(), max_y_a = a->get_max_y();
00093   double min_x_b = b->get_min_x(), max_x_b = b->get_max_x();
00094   double min_y_b = b->get_min_y(), max_y_b = b->get_max_y();
00095   return min_x_b <= max_x_a && min_x_a <= max_x_b
00096       && min_y_b <= max_y_a && min_y_a <= max_y_b;
00097 }
00098 
00099 //: find the intersection of two boxes. Return false if no intersection
00100 bool bsol_algs::intersection(vsol_box_2d_sptr const & a,
00101                              vsol_box_2d_sptr const & b,
00102                              vsol_box_2d_sptr& a_int_b)
00103 {
00104   vgl_point_2d<double> a_min(a->get_min_x(), a->get_min_y());
00105   vgl_point_2d<double> a_max(a->get_max_x(), a->get_max_y());
00106   vgl_box_2d<double> vga(a_min, a_max);
00107 
00108   vgl_point_2d<double> b_min(b->get_min_x(), b->get_min_y());
00109   vgl_point_2d<double> b_max(b->get_max_x(), b->get_max_y());
00110   vgl_box_2d<double> vgb(b_min, b_max);
00111   vgl_box_2d<double> temp = vgl_intersection(vga, vgb);
00112   if (temp.is_empty())
00113     return false;
00114   a_int_b = new vsol_box_2d();
00115   a_int_b->add_point(temp.min_x(), temp.min_y());
00116   a_int_b->add_point(temp.max_x(), temp.max_y());
00117   return true;
00118 }
00119 
00120 //: find the convex union of two boxes. Always return true
00121 bool bsol_algs::box_union(vsol_box_2d_sptr const & a,
00122                           vsol_box_2d_sptr const & b,
00123                           vsol_box_2d_sptr& a_union_b)
00124 {
00125   if (!a||!b)
00126     return false;
00127   double x_min_a = a->get_min_x(), y_min_a = a->get_min_y();
00128   double x_max_a = a->get_max_x(), y_max_a = a->get_max_y();
00129   double x_min_b = b->get_min_x(), y_min_b = b->get_min_y();
00130   double x_max_b = b->get_max_x(), y_max_b = b->get_max_y();
00131   double x_min=x_min_a, y_min = y_min_a;
00132   double x_max=x_max_a, y_max = y_max_a;
00133   if (x_min_b<x_min)
00134     x_min = x_min_b;
00135   if (y_min_b<y_min)
00136     y_min = y_min_b;
00137   if (x_max_b>x_max)
00138     x_max = x_max_b;
00139   if (y_max_b>y_max)
00140     y_max = y_max_b;
00141   a_union_b = new vsol_box_2d();
00142   a_union_b->add_point(x_min, y_min);
00143   a_union_b->add_point(x_max, y_max);
00144   return true;
00145 }
00146 
00147 //-----------------------------------------------------------------------------
00148 //: expand or contract a box with the supplied absolute margin
00149 //-----------------------------------------------------------------------------
00150 bool bsol_algs::box_with_margin(vsol_box_2d_sptr const & b,
00151                                 const double margin,
00152                                 vsol_box_2d_sptr& bmod)
00153 {
00154   if (!b)
00155     return false;
00156   double x_min = b->get_min_x(), y_min = b->get_min_y();
00157   double x_max = b->get_max_x(), y_max = b->get_max_y();
00158   double width = x_max-x_min, height = y_max-y_min;
00159   //See if the margin for contraction is too large, i.e. margin is negative
00160   if ((width+2*margin)<0)
00161     return false;
00162   if ((height+2*margin)<0)
00163     return false;
00164   bmod = new vsol_box_2d();
00165   bmod->add_point(x_min-margin, y_min-margin);
00166   bmod->add_point(x_max+margin, y_max+margin);
00167   return true;
00168 }
00169 
00170 //-----------------------------------------------------------------------------
00171 //: Compute the convex hull of a set of polygons
00172 //-----------------------------------------------------------------------------
00173 bool bsol_algs::hull_of_poly_set(vcl_vector<vsol_polygon_2d_sptr> const& polys,
00174                                  vsol_polygon_2d_sptr& hull)
00175 {
00176   if (!polys.size())
00177     return false;
00178   vcl_vector<vgl_point_2d<double> > points;
00179   for (vcl_vector<vsol_polygon_2d_sptr>::const_iterator pit = polys.begin();
00180        pit != polys.end(); pit++)
00181   {
00182     if (!(*pit))
00183       return false;
00184     for (unsigned int i=0; i<(*pit)->size(); ++i)
00185       points.push_back(vgl_point_2d<double>((*pit)->vertex(i)->x(),
00186                                             (*pit)->vertex(i)->y()));
00187   }
00188   vgl_convex_hull_2d<double> ch(points);
00189   vgl_polygon<double> h = ch.hull();
00190   hull = bsol_algs::poly_from_vgl(h);
00191   return true;
00192 }
00193 
00194 //-----------------------------------------------------------------------------
00195 //: Determine if a point is inside a bounding box
00196 //-----------------------------------------------------------------------------
00197 bool bsol_algs::in(vsol_box_3d_sptr const & b,
00198                    double x, double y, double z)
00199 {
00200   if (!b)
00201     return false;
00202   double xmin = b->get_min_x(), ymin = b->get_min_y(), zmin = b->get_min_z();
00203   double xmax = b->get_max_x(), ymax = b->get_max_y(), zmax = b->get_max_z();
00204   return x >= xmin && x <= xmax
00205       && y >= ymin && y <= ymax
00206       && z >= zmin && z <= zmax;
00207 }
00208 
00209 vsol_polygon_2d_sptr bsol_algs::poly_from_box(vsol_box_2d_sptr const& box)
00210 {
00211   vcl_vector<vsol_point_2d_sptr> pts;
00212   vsol_point_2d_sptr pa = new vsol_point_2d(box->get_min_x(), box->get_min_y());
00213   vsol_point_2d_sptr pb = new vsol_point_2d(box->get_max_x(), box->get_min_y());
00214   vsol_point_2d_sptr pc = new vsol_point_2d(box->get_max_x(), box->get_max_y());
00215   vsol_point_2d_sptr pd = new vsol_point_2d(box->get_min_x(), box->get_max_y());
00216   pts.push_back(pa);   pts.push_back(pb);
00217   pts.push_back(pc);   pts.push_back(pd); //pts.push_back(pa);
00218   return new vsol_polygon_2d(pts);
00219 }
00220 
00221 //: construct a vsol_polygon from a vgl_polygon
00222 vsol_polygon_2d_sptr bsol_algs::poly_from_vgl(vgl_polygon<double> const& poly)
00223 {
00224   vsol_polygon_2d_sptr out;
00225   vcl_vector<vsol_point_2d_sptr> pts;
00226   if (poly.num_sheets() != 1)
00227     return out;
00228   vcl_vector<vgl_point_2d<double> > sheet = poly[0];
00229   for (vcl_vector<vgl_point_2d<double> >::iterator pit = sheet.begin();
00230        pit != sheet.end(); pit++)
00231   {
00232     vsol_point_2d_sptr p = new vsol_point_2d((*pit).x(), (*pit).y());
00233     pts.push_back(p);
00234   }
00235   out = new vsol_polygon_2d(pts);
00236   return out;
00237 }
00238 
00239 vgl_polygon<double>
00240 bsol_algs::vgl_from_poly(vsol_polygon_2d_sptr const& poly)
00241 {
00242   vgl_polygon<double> vp(1);
00243   if (!poly)
00244     return vp;
00245   unsigned nverts = poly->size();
00246   for (unsigned i = 0; i<nverts; ++i)
00247   {
00248     double x = poly->vertex(i)->x(), y = poly->vertex(i)->y();
00249     vp.push_back(x, y);
00250   }
00251   return vp;
00252 }
00253 
00254 //: find the closest point to p in a set of points
00255 vsol_point_2d_sptr
00256 bsol_algs::closest_point(vsol_point_2d_sptr const& p,
00257                          vcl_vector<vsol_point_2d_sptr> const& point_set,
00258                          double& d)
00259 {
00260   vsol_point_2d_sptr cp;
00261   int n = point_set.size();
00262   if (!p||!n)
00263     return cp;
00264   double dmin_sq = vnl_numeric_traits<double>::maxval;
00265   double x = p->x(), y = p->y();
00266   for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = point_set.begin();
00267        pit!=point_set.end(); pit++)
00268   {
00269     double xs = (*pit)->x(), ys = (*pit)->y();
00270     double dsq = (x-xs)*(x-xs)+(y-ys)*(y-ys);
00271     if (dsq<dmin_sq)
00272     {
00273       dmin_sq = dsq;
00274       cp = *pit;
00275     }
00276   }
00277   d = vcl_sqrt(dmin_sq);
00278   return cp;
00279 }
00280 
00281 vsol_point_3d_sptr
00282 bsol_algs::closest_point(vsol_point_3d_sptr const& p,
00283                          vcl_vector<vsol_point_3d_sptr> const& point_set,
00284                          double& d)
00285 {
00286   d = 0;
00287   vsol_point_3d_sptr cp;
00288   int n = point_set.size();
00289   if (!p||!n)
00290     return cp;
00291   double dmin_sq = vnl_numeric_traits<double>::maxval;
00292   double x = p->x(), y = p->y(), z = p->z();
00293   for (vcl_vector<vsol_point_3d_sptr>::const_iterator pit = point_set.begin();
00294        pit!=point_set.end(); pit++)
00295   {
00296     double xs = (*pit)->x(), ys = (*pit)->y(), zs = (*pit)->z();
00297     double dsq = (x-xs)*(x-xs) + (y-ys)*(y-ys) + (z-zs)*(z-zs);
00298     if (dsq<dmin_sq)
00299     {
00300       dmin_sq = dsq;
00301       cp = *pit;
00302     }
00303   }
00304   d = vcl_sqrt(dmin_sq);
00305   return cp;
00306 }
00307 
00308 //: Transform a vsol_polygon_2d with a general homography.
00309 //  Return false if any of the points are turned into ideal points
00310 //  since vsol geometry is assumed finite.
00311 bool bsol_algs::homography(vsol_polygon_2d_sptr const& p,
00312                            vgl_h_matrix_2d<double> const& H,
00313                            vsol_polygon_2d_sptr& Hp)
00314 {
00315   const int n = p->size();
00316   vcl_vector<vsol_point_2d_sptr> pts;
00317   const double tol = 1e-06;
00318   for (int i = 0; i<n; i++)
00319   {
00320     vsol_point_2d_sptr v = p->vertex(i);
00321     vgl_homg_point_2d<double> hp(v->x(), v->y());
00322     vgl_homg_point_2d<double> Hhp = H(hp);
00323     if (Hhp.ideal(tol))
00324       return false;
00325     vgl_point_2d<double> q(Hhp);
00326     vsol_point_2d_sptr qs = new vsol_point_2d(q.x(), q.y());
00327     pts.push_back(qs);
00328   }
00329   Hp = new vsol_polygon_2d(pts);
00330   return true;
00331 }
00332 
00333 //: Transform a vsol_polygon_2d with a point specified as the center of the transformation.
00334 //  i.e. vertices of the polygon are translated so that the specified point is the origin.
00335 /// The transformation is then applied and the point coordinates added back in afterwards.
00336 vsol_polygon_2d_sptr bsol_algs::
00337 transform_about_point(vsol_polygon_2d_sptr const& p,
00338                       vsol_point_2d_sptr const& c,
00339                       vgl_h_matrix_2d<double> const& H)
00340 {
00341   const int n = p->size();
00342   vcl_vector<vsol_point_2d_sptr> pts;
00343   for (int i = 0; i<n; i++)
00344   {
00345     vsol_point_2d_sptr v = p->vertex(i);
00346     //Remove the centroid
00347     vgl_homg_point_2d<double> hp(v->x() - c->x(), v->y() - c->y());
00348     vgl_homg_point_2d<double> Hhp = H(hp);
00349     vgl_point_2d<double> q(Hhp);
00350     //add it back in
00351     vsol_point_2d_sptr qs = new vsol_point_2d(q.x() + c->x(), q.y() + c->y());
00352     pts.push_back(qs);
00353   }
00354   return new vsol_polygon_2d(pts);
00355 }
00356 
00357 //: Transform a vsol_polygon_2d with a homography
00358 //  Apply the transform with the centroid of the polygon as the
00359 //  origin and then translate by the centroid location vector
00360 vsol_polygon_2d_sptr bsol_algs::
00361 transform_about_centroid(vsol_polygon_2d_sptr const& p,
00362                          vgl_h_matrix_2d<double> const& H)
00363 {
00364   vsol_point_2d_sptr c = p->centroid();
00365   return bsol_algs::transform_about_point(p, c, H);
00366 }
00367 
00368 bool bsol_algs::homography(vsol_box_2d_sptr const& b,
00369                            vgl_h_matrix_2d<double> const& H,
00370                            vsol_box_2d_sptr& Hb)
00371 {
00372   vsol_polygon_2d_sptr p = bsol_algs::poly_from_box(b);
00373   vsol_polygon_2d_sptr Hp;
00374   if (!homography(p, H, Hp))
00375     return false;
00376   Hb = Hp->get_bounding_box();
00377   return true;
00378 }
00379 
00380 void bsol_algs::tangent(vsol_digital_curve_2d_sptr const& dc, unsigned index,
00381                         double& dx, double& dy)
00382 {
00383   dx = 0; dy = 0;
00384   if (!dc)
00385     return;
00386   unsigned n = dc->size();
00387   //cases
00388   if (index>=n)
00389     return;
00390   if (index == 0)// first point on curve
00391   {
00392     vsol_point_2d_sptr p_n0 = dc->point(0);
00393     vsol_point_2d_sptr p_n1 = dc->point(1);
00394     dx = p_n1->x()-p_n0->x();
00395     dy = p_n1->y()-p_n0->y();
00396     return;
00397   }
00398 
00399   if (index == n-1)// last point on curve
00400   {
00401     vsol_point_2d_sptr p_n1 = dc->point(n-1);
00402     vsol_point_2d_sptr p_n2 = dc->point(n-2);
00403     dx = p_n1->x()-p_n2->x();
00404     dy = p_n1->y()-p_n2->y();
00405     return;
00406   }
00407   //the normal case
00408   vsol_point_2d_sptr p_m1 = dc->point(index-1);
00409   vsol_point_2d_sptr p_p1 = dc->point(index+1);
00410   dx = p_p1->x()-p_m1->x();
00411   dy = p_p1->y()-p_m1->y();
00412 }
00413 
00414 void bsol_algs::print(vsol_box_2d_sptr const& b)
00415 {
00416   if (!b)
00417     return;
00418   vcl_cout << *b << '\n';
00419 }
00420 
00421 void bsol_algs::print(vsol_box_3d_sptr const& b)
00422 {
00423   if (!b)
00424     return;
00425   double xmin = b->get_min_x(), ymin = b->get_min_y(), zmin = b->get_min_z();
00426   double xmax = b->get_max_x(), ymax = b->get_max_y(), zmax = b->get_max_z();
00427 
00428   vcl_cout << "vsol_box_2d[(" << xmin << ' ' << ymin << ' ' << zmin << ")<("
00429            << xmax << ' ' << ymax << ' ' << zmax << ")]\n";
00430 }
00431 
00432 void bsol_algs::print(vsol_point_2d_sptr const& p)
00433 {
00434   if (!p)
00435     return;
00436   vcl_cout << *p << '\n';
00437 }
00438 
00439 void bsol_algs::print(vsol_point_3d_sptr const& p)
00440 {
00441   if (!p)
00442     return;
00443   vcl_cout << "vsol_point_3d[ " << p->x() << ' ' << p->y() << ' '
00444            << p->z() <<  " ]\n";
00445 }