contrib/brl/bbas/bsol/bsol_point_index_3d.cxx
Go to the documentation of this file.
00001 #include "bsol_point_index_3d.h"
00002 //:
00003 // \file
00004 #include <vsol/vsol_point_3d.h>
00005 #include <vsol/vsol_box_3d.h>
00006 #include "bsol_algs.h"
00007 #ifdef DEBUG
00008 #include <vcl_iostream.h>
00009 #endif
00010 
00011 static void clear_flag(vsol_point_3d_sptr& p)
00012 {
00013   p->unset_user_flag(VSOL_FLAG1);
00014 }
00015 
00016 static void set_flag(vsol_point_3d_sptr & p)
00017 {
00018   p->set_user_flag(VSOL_FLAG1);
00019 }
00020 
00021 static bool flag(vsol_point_3d_sptr const& p)
00022 {
00023   return p->get_user_flag(VSOL_FLAG1);
00024 }
00025 
00026 //------------------------------------------------------------------------
00027 // Constructors
00028 //------------------------------------------------------------------------
00029 
00030 bsol_point_index_3d::bsol_point_index_3d()
00031 {
00032   nrows_ = 0;
00033   ncols_ = 0;
00034   nslabs_ = 0;
00035   b_box_ = (vsol_box_3d*)0;
00036 }
00037 
00038 bsol_point_index_3d::bsol_point_index_3d(int nrows, int ncols, int nslabs,
00039                                          vsol_box_3d_sptr const& bb)
00040 {
00041   nrows_ = nrows;
00042   ncols_ = ncols;
00043   nslabs_ = nslabs;
00044   //initialize the array
00045   point_array_.resize(nrows, ncols);
00046   for (int r = 0; r<nrows; r++)
00047     for (int c = 0; c<ncols; c++)
00048     {
00049       vcl_vector<vcl_vector<vsol_point_3d_sptr> >* v =
00050         new vcl_vector<vcl_vector<vsol_point_3d_sptr> >(nslabs);
00051       point_array_[r][c] = v;
00052     //  v->clear();
00053     }
00054   b_box_ = bb;
00055   double w = b_box_->width(), h = b_box_->height(), d = b_box_->depth();
00056   row_spacing_ = 1;
00057   col_spacing_ = 1;
00058   slab_spacing_ = 1;
00059   if (nrows)
00060     row_spacing_ = h/nrows;
00061   if (ncols)
00062     col_spacing_ = w/ncols;
00063   if (nslabs)
00064     slab_spacing_ = d/nslabs;
00065 }
00066 
00067 bsol_point_index_3d::
00068 bsol_point_index_3d(int nrows, int ncols, int nslabs,
00069                     vcl_vector<vsol_point_3d_sptr> const& points)
00070 {
00071   nrows_ = nrows;
00072   ncols_ = ncols;
00073   nslabs_ = nslabs;
00074   //initialize the array
00075   point_array_.resize(nrows, ncols);
00076   for (int r = 0; r<nrows; r++)
00077     for (int c = 0; c<ncols; c++)
00078     {
00079       vcl_vector<vcl_vector<vsol_point_3d_sptr> >* v =
00080         new vcl_vector<vcl_vector<vsol_point_3d_sptr> >(nslabs);
00081       point_array_[r][c] = v;
00082       //  v->clear();
00083     }
00084   vbl_bounding_box<double,3> box = bsol_algs::bounding_box(points);
00085   b_box_ = new vsol_box_3d(box);
00086   double w = b_box_->width(), h = b_box_->height(), d = b_box_->depth();
00087   row_spacing_ = 1;
00088   col_spacing_ = 1;
00089   slab_spacing_ = 1;
00090   if (nrows)
00091     row_spacing_ = h/nrows;
00092   if (ncols)
00093     col_spacing_ = w/ncols;
00094   if (nslabs)
00095     slab_spacing_ = d/nslabs;
00096 
00097   this->add_points(points);
00098 }
00099 
00100 // Destructor
00101 bsol_point_index_3d::~bsol_point_index_3d()
00102 {
00103   for (int r = 0; r<nrows_; r++)
00104     for (int c = 0; c<ncols_; c++)
00105       delete point_array_[r][c];
00106 }
00107 
00108 void bsol_point_index_3d::origin(double& x0, double& y0, double& z0)
00109 {
00110   if (!b_box_) { x0 = y0 = z0 = 0; return; }
00111   x0 = b_box_->get_min_x();
00112   y0 = b_box_->get_min_y();
00113   z0 = b_box_->get_min_z();
00114 }
00115 
00116 int
00117 bsol_point_index_3d::n_points(const int row, const int col, const int slab)
00118 {
00119   if (row<0||row>=nrows_||col<0||col>=ncols_||slab<0||slab>=nslabs_)
00120     return 0;
00121   int n = (*(point_array_[row][col]))[slab].size();
00122   return n;
00123 }
00124 
00125 int
00126 bsol_point_index_3d::n_points(const double x, const double y, const double z)
00127 {
00128   int row=0, col=0, slab=0;
00129   if (!trans(x, y, z, row, col, slab))
00130     return 0;
00131   if (row<0||row>=nrows_||col<0||col>=ncols_||slab<0||slab>=nslabs_)
00132     return 0;
00133   return (*(point_array_[row][col]))[slab].size();
00134 }
00135 
00136 int bsol_point_index_3d::n_points()
00137 {
00138   int n = 0;
00139   for (int r=0; r<nrows_; r++)
00140     for (int c=0; c<ncols_; c++)
00141       for (int s=0; s<nslabs_; s++)
00142         n += n_points(r, c, s);
00143   return n;
00144 }
00145 
00146 vcl_vector<vsol_point_3d_sptr> bsol_point_index_3d::points(const int row, const int col,
00147                                                            const int slab)
00148 {
00149   vcl_vector<vsol_point_3d_sptr> out;
00150   if (row<0||row>=nrows_||col<0||col>=ncols_||slab<0||slab>=nslabs_)
00151     return out;
00152   return (*(point_array_[row][col]))[slab];
00153 }
00154 
00155 //:offset to origin of bounds and convert to cell integer coordinates
00156 bool bsol_point_index_3d::trans(const double x, const double y,
00157                                 const double z,
00158                                 int& row, int& col, int& slab)
00159 {
00160   if (!bsol_algs::in(b_box_, x, y, z))
00161     return false;
00162   col = (int)((x-b_box_->get_min_x())/col_spacing_);
00163   row = (int)((y-b_box_->get_min_y())/row_spacing_);
00164   slab = (int)((z-b_box_->get_min_z())/slab_spacing_);
00165   return true;
00166 }
00167 
00168 //---------------------------------------------------------------------
00169 //: Add a point to the index.
00170 //  Should check for duplicate points, but not doing that right now.
00171 //---------------------------------------------------------------------
00172 bool bsol_point_index_3d::add_point(vsol_point_3d_sptr const& p)
00173 {
00174   double x = p->x(), y = p->y(), z = p->z();
00175   int row=0, col=0, slab=0;
00176   if (!trans(x, y, z, row, col, slab))
00177     return false;
00178   if (row<0||row>=nrows_||col<0||col>=ncols_||slab<0||slab>=nslabs_)
00179     return false;
00180    vcl_vector<vcl_vector<vsol_point_3d_sptr> >* v = point_array_[row][col];
00181    (*v)[slab].push_back(p);
00182   return true;
00183 }
00184 
00185 bool bsol_point_index_3d::add_points(vcl_vector<vsol_point_3d_sptr> const& points)
00186 {
00187   bool ok = true;
00188   for (vcl_vector<vsol_point_3d_sptr>::const_iterator pit = points.begin();
00189        pit != points.end(); pit++)
00190     if (!this->add_point(*pit))
00191       ok = false;
00192   return ok;
00193 }
00194 
00195 bool bsol_point_index_3d::find_point(vsol_point_3d_sptr const& p)
00196 {
00197   int row=0, col=0, slab = 0;
00198   if (!this->trans(p->x(), p->y(), p->z(),row, col, slab))
00199     return false;
00200   if (row<0||row>=nrows_||col<0||col>=ncols_||slab<0||slab>=nslabs_)
00201     return false;
00202   vcl_vector<vsol_point_3d_sptr>& points = (*(point_array_[row][col]))[slab];
00203   for (vcl_vector<vsol_point_3d_sptr>::iterator pit = points.begin();
00204        pit!=points.end(); pit++)
00205     if ((*pit)==p)
00206       return true;
00207   return false;
00208 }
00209 
00210 //:find the points within a box
00211 bool bsol_point_index_3d::in_box(vsol_box_3d_sptr const& box,
00212                                  vcl_vector<vsol_point_3d_sptr>& points)
00213 {
00214   if (!box)
00215     return false;
00216   double xmin = box->get_min_x(),
00217     ymin = box->get_min_y(), zmin = box->get_min_z();
00218   double xmax = box->get_max_x(),
00219     ymax = box->get_max_y(), zmax = box->get_max_z();
00220   int row_min = 0, col_min = 0, slab_min = 0;
00221   int row_max = 0, col_max = 0, slab_max = 0;
00222   trans(xmin, ymin, zmin, row_min, col_min, slab_min);
00223   trans(xmax, ymax, zmax, row_max, col_max, slab_max);
00224   if (row_min<0)
00225     row_min = 0;
00226   if (col_min<0)
00227     col_min = 0;
00228   if (slab_min<0)
00229     slab_min = 0;
00230   if (row_max>nrows_)
00231     row_max = nrows_-1;
00232   if (col_max>=ncols_)
00233     col_max = ncols_-1;
00234   if (slab_max>=nslabs_)
00235     slab_max = nslabs_-1;
00236   for (int r=row_min; r<row_max; r++)
00237     for (int c=col_min; c<col_max; c++)
00238       for (int s=slab_min; s<slab_max; s++)
00239       {
00240         vcl_vector<vsol_point_3d_sptr>& pts = (*(point_array_[r][c]))[s];
00241         for (vcl_vector<vsol_point_3d_sptr>::iterator pit = pts.begin();
00242              pit != pts.end(); pit++)
00243           points.push_back(*pit);
00244       }
00245   return true;
00246 }
00247 
00248 //:find the points within a radius of p
00249 bool bsol_point_index_3d::in_radius(const double radius,
00250                                     vsol_point_3d_sptr const& p,
00251                                     vcl_vector<vsol_point_3d_sptr>& points)
00252 {
00253   if (!p)
00254     return false;
00255   bool found_points = false;
00256   // find the cell corresponding to p
00257   double x = p->x(), y = p->y(), z = p->z();
00258   int row = 0, col = 0, slab = 0;
00259   this->trans(x, y, z, row, col, slab);
00260   //get points from surrounding cells
00261   int row_radius = int(radius/row_spacing_),
00262       col_radius = int(radius/col_spacing_),
00263       slab_radius = int(radius/slab_spacing_);
00264   //include points near cell boundaries
00265   row_radius++; col_radius++;
00266   for (int ro = -row_radius; ro<=row_radius; ro++)
00267     for (int co = -col_radius; co<=col_radius; co++)
00268       for (int so = -slab_radius; so<=slab_radius; so++)
00269       {
00270         int r = row+ro, c = col+co, s = slab + so;
00271         if (r<0||r>=nrows_||c<0||c>=ncols_||s<0||s>=nslabs_)
00272           continue;
00273         vcl_vector<vsol_point_3d_sptr>& points_in_cell =
00274           (*(point_array_[r][c]))[s];
00275         int n = points_in_cell.size();
00276         if (!n)
00277           continue;
00278         for (int i=0; i<n; i++)
00279           if (!flag(points_in_cell[i]))
00280           {
00281             points.push_back(points_in_cell[i]);
00282             found_points = true;
00283           }
00284       }
00285   return found_points;
00286 }
00287 
00288 //:find the closest point with the specified radius.  If none return false.
00289 bool bsol_point_index_3d::closest_in_radius(const double radius,
00290                                             vsol_point_3d_sptr const& p,
00291                                             vsol_point_3d_sptr& point)
00292 {
00293   vcl_vector<vsol_point_3d_sptr> points;
00294   this->in_radius(radius, p, points);
00295   double d = 0;
00296   point = bsol_algs::closest_point(p, points, d);
00297   if (!point||d>radius)
00298     return false;
00299 #ifdef DEBUG
00300   vcl_cout << "p("<< p->x() << ' ' << p->y()<< "):P(" << point->x() << ' ' << point->y() << "):" << d << vcl_endl;
00301 #endif
00302   return true;
00303 }
00304 
00305 void bsol_point_index_3d::clear()
00306 {
00307   for (int r =0; r<nrows_; r++)
00308     for (int c = 0; c<ncols_; c++)
00309       for (int s = 0; c<nslabs_; c++)
00310         (*(point_array_[r][c]))[s].clear();
00311 }
00312 
00313 bool bsol_point_index_3d::mark_point(vsol_point_3d_sptr& p)
00314 {
00315   if (!p||!this->find_point(p))
00316     return false;
00317   set_flag(p);
00318   return true;
00319 }
00320 
00321 bool bsol_point_index_3d::unmark_point(vsol_point_3d_sptr& p)
00322 {
00323   if (!p||!this->find_point(p))
00324     return false;
00325   clear_flag(p);
00326   return true;
00327 }
00328 
00329 bool bsol_point_index_3d::marked(vsol_point_3d_sptr const& p)
00330 {
00331   if (!p||!this->find_point(p))
00332     return false;
00333   return flag(p);
00334 }
00335 
00336 vcl_vector<vsol_point_3d_sptr> bsol_point_index_3d::points()
00337 {
00338   vcl_vector<vsol_point_3d_sptr> out;
00339   for (int r=0; r<nrows_; r++)
00340     for (int c=0; c<ncols_; c++)
00341       for (int s=0; s<nslabs_; s++)
00342       {
00343         vcl_vector<vsol_point_3d_sptr>& points = (*(point_array_[r][c]))[s];
00344         for (vcl_vector<vsol_point_3d_sptr>::iterator pit = points.begin();
00345              pit!= points.end(); pit++)
00346           out.push_back(*pit);
00347       }
00348   return out;
00349 }
00350 
00351 void bsol_point_index_3d::clear_marks()
00352 {
00353   for (int r=0; r<nrows_; ++r)
00354     for (int c=0; c<ncols_; ++c)
00355       for (int s=0; s<nslabs_; ++s)
00356         for (vcl_vector<vsol_point_3d_sptr>::iterator pit = (*(point_array_[r][c]))[s].begin();
00357              pit != (*(point_array_[r][c]))[s].end(); ++pit)
00358           clear_flag(*pit);
00359 }
00360 
00361 vsol_box_3d_sptr bsol_point_index_3d::
00362 index_cell(const int row, const int col, const int slab)
00363 {
00364   vsol_box_3d_sptr box = new vsol_box_3d;
00365   if (row<0||row>=nrows_||col<0||col>=ncols_||slab<0||slab>=nslabs_)
00366     return box;
00367   //the cell origin
00368   double x0, y0, z0;
00369   this->origin(x0, y0, z0);
00370   double xmin = col_spacing_*col   + x0;
00371   double ymin = row_spacing_*row   + y0;
00372   double zmin = slab_spacing_*slab + z0;
00373   box->add_point(xmin, ymin, zmin);
00374   box->add_point(xmin+col_spacing_, ymin+row_spacing_, zmin+slab_spacing_);
00375   return box;
00376 }
00377 
00378 vsol_box_3d_sptr bsol_point_index_3d::
00379 index_cell(const double x, const double y, const double z)
00380 {
00381   vsol_box_3d_sptr null;
00382   int row=0, col=0, slab=0;
00383   if (!trans(x, y, z, row, col, slab))
00384     return null;
00385   if (row<0||row>=nrows_||col<0||col>=ncols_||slab<0||slab>=nslabs_)
00386     return null;
00387   return this->index_cell(row, col, slab);
00388 }
00389 
00390 vsol_box_3d_sptr bsol_point_index_3d::point_bounds()
00391 {
00392   vsol_box_3d_sptr box = new vsol_box_3d();
00393   for (int r=0; r<nrows_; r++)
00394     for (int c=0; c<ncols_; c++)
00395       for (int s=0; s<nslabs_; s++)
00396       {
00397         vcl_vector<vsol_point_3d_sptr>& points = (*(point_array_[r][c]))[s];
00398         for (vcl_vector<vsol_point_3d_sptr>::iterator pit = points.begin();
00399              pit!= points.end(); pit++)
00400           box->add_point((*pit)->x(), (*pit)->y(), (*pit)->z());
00401       }
00402   return box;
00403 }