PrCellStructure.C

00001 //===========================================================================
00002 // GoTools - SINTEF Geometry Tools version 1.1
00003 //
00004 // GoTools module: parametrization
00005 //
00006 // Copyright (C) 2000-2005 SINTEF ICT, Applied Mathematics, Norway.
00007 //
00008 // This program is free software; you can redistribute it and/or          
00009 // modify it under the terms of the GNU General Public License            
00010 // as published by the Free Software Foundation version 2 of the License. 
00011 //
00012 // This program is distributed in the hope that it will be useful,        
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of         
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
00015 // GNU General Public License for more details.                           
00016 //
00017 // You should have received a copy of the GNU General Public License      
00018 // along with this program; if not, write to the Free Software            
00019 // Foundation, Inc.,                                                      
00020 // 59 Temple Place - Suite 330,                                           
00021 // Boston, MA  02111-1307, USA.                                           
00022 //
00023 // Contact information: E-mail: tor.dokken@sintef.no                      
00024 // SINTEF ICT, Department of Applied Mathematics,                         
00025 // P.O. Box 124 Blindern,                                                 
00026 // 0314 Oslo, Norway.                                                     
00027 //
00028 // Other licenses are also available for this software, notably licenses
00029 // for:
00030 // - Building commercial software.                                        
00031 // - Building software whose source code you wish to keep private.        
00032 //===========================================================================
00033 #include <PrCellStructure.h>
00034 #include <queue>
00035 using std::cout;
00036 using std::endl;
00037 
00038 
00039 class HeapNode {
00040 
00041 public:
00042   int     idx_;
00043   double  key_;
00044 
00045   HeapNode( int idx, double key) { idx_ = idx; key_ = key;}
00046   ~HeapNode(){}
00047 
00048   bool operator >   ( const HeapNode& x) const { return (this->key_
00049 >   x.key_);}
00050   bool operator >=  ( const HeapNode& x) const { return (this->key_
00051 >=  x.key_);}
00052 };
00053 typedef std::priority_queue< HeapNode, vector<HeapNode>, std::greater<HeapNode> > HeapType;
00054 
00055 // PRIVATE MEMBER FUNCTIONS
00056 
00057 //-----------------------------------------------------------------------------
00058 void PrCellStructure::makeCellStructure()
00059 //-----------------------------------------------------------------------------
00060 {
00061   // Find bounding box
00062   double maxarr[3];
00063   min_[0] = xyz_[0].x();
00064   maxarr[0] = xyz_[0].x();
00065   min_[1] = xyz_[0].y();
00066   maxarr[1] = xyz_[0].y();
00067   min_[2] = xyz_[0].z();
00068   maxarr[2] = xyz_[0].z();
00069   int i;
00070   int xyz_size = xyz_.size();
00071   for(i=1; i< xyz_size; i++)
00072   {
00073     if(xyz_[i].x() < min_[0]) min_[0] = xyz_[i].x();
00074     else if(xyz_[i].x() > maxarr[0]) maxarr[0] = xyz_[i].x();
00075 
00076     if(xyz_[i].y() < min_[1]) min_[1] = xyz_[i].y();
00077     else if(xyz_[i].y() > maxarr[1]) maxarr[1] = xyz_[i].y();
00078 
00079     if(xyz_[i].z() < min_[2]) min_[2] = xyz_[i].z();
00080     else if(xyz_[i].z() > maxarr[2]) maxarr[2] = xyz_[i].z();
00081   }
00082 
00083 
00084   // Choose a good cell size;
00085   cell_size_ = std::max( (maxarr[0] - min_[0]) / (double)max_no_cells_,
00086                    (maxarr[1] - min_[1]) / (double)max_no_cells_ );
00087   cell_size_ = std::max( cell_size_,
00088                    (maxarr[2] - min_[2]) / (double)max_no_cells_ );
00089   
00090 
00091   // Decide how many cells are needed in each direction
00092   ncells_[0] = (int)((maxarr[0] - min_[0]) / cell_size_) + 1;
00093   ncells_[1] = (int)((maxarr[1] - min_[1]) / cell_size_) + 1;
00094   ncells_[2] = (int)((maxarr[2] - min_[2]) / cell_size_) + 1;
00095 
00096 
00097   //allocate space for cells
00098   ind_.resize(ncells_[0]*ncells_[1]*ncells_[2]);
00099 
00100   // Now start filling in the cell information
00101   int ii,i1,j1,k1;
00102   for(i=0; i< xyz_size; i++)
00103   {
00104     // Find which cell the point lies in
00105     whichCell(xyz_[i],i1,j1,k1);
00106     //cout << oform("(i1,j1,k1) = (%d,%d,%d)\n",i1,j1,k1);
00107     ii = getI(i1,j1,k1);
00108     //cout << oform("ii = %d\n",ii);
00109     ind_[ii].push_back(i);
00110   }
00111 
00112   size_t min_num = xyz_.size();
00113   int ind_size = ind_.size();
00114   size_t max_num = 0;
00115   for (i=0; i<ind_size; i++ )
00116   {
00117     if(ind_[i].size() > max_num) max_num = ind_[i].size();
00118     else if(ind_[i].size() < min_num) min_num = ind_[i].size();
00119   }
00120 
00121 
00122 }
00123 
00124 // PUBLIC MEMBER FUNCTIONS
00125 
00126 //-----------------------------------------------------------------------------
00127 PrCellStructure::PrCellStructure(int n, double* xyz_points, int max_no_cells)
00128 //-----------------------------------------------------------------------------
00129 {
00130   xyz_.resize(n);
00131   int j;
00132   for(j=0; j< n; j++)
00133   {
00134     xyz_[j].x() = xyz_points[3*j];
00135     xyz_[j].y() = xyz_points[3*j+1];
00136     xyz_[j].z() = xyz_points[3*j+2];
00137   }
00138   max_no_cells_ = max_no_cells;
00139   makeCellStructure();
00140 }
00141 
00142 //-----------------------------------------------------------------------------
00143 void PrCellStructure::attach(int n, const double* xyz_points)
00144 //-----------------------------------------------------------------------------
00145 {
00146   xyz_.resize(n);
00147   int j;
00148   for(j=0; j< n; j++)
00149   {
00150     xyz_[j].x() = xyz_points[3*j];
00151     xyz_[j].y() = xyz_points[3*j+1];
00152     xyz_[j].z() = xyz_points[3*j+2];
00153   }
00154   makeCellStructure();
00155 }
00156 
00157 //----------------------------------------------------------------------------
00158 void
00159 PrCellStructure::getBall(const Vector3D& p, double radius,
00160                                vector<int>& neighbours, int notP) const
00161 //-----------------------------------------------------------------------------
00162 //   Return all points within the ball of radius radius around
00163 //   the point p. Don't include p itself if notP = 1.
00164 { 
00165   neighbours.clear();
00166   double r2 = radius * radius, dist2;
00167   // find which cell p lies in:
00168   int i1,j1,k1;
00169   whichCell(p,i1,j1,k1);
00170   int imin[3],imax[3];
00171   int diff = (int)(radius/cell_size_) + 1;
00172   imin[0] = std::max(i1-diff,0);
00173   imax[0] = std::min(i1+diff,ncells_[0]-1);
00174   imin[1] = std::max(j1-diff,0);
00175   imax[1] = std::min(j1+diff,ncells_[1]-1);
00176   imin[2] = std::max(k1-diff,0);
00177   imax[2] = std::min(k1+diff,ncells_[2]-1);
00178 
00179   int iq,ii;
00180   for(int k=imin[2]; k<=imax[2]; k++)
00181     for(int j=imin[1]; j<=imax[1]; j++)
00182       for(int i=imin[0]; i<=imax[0]; i++)
00183       {
00184         ii = getI(i,j,k);
00185         for(size_t ell=0; ell<ind_[ii].size(); ell++)
00186         {
00187           iq = ind_[ii][ell];
00188           dist2 = xyz_[iq].dist2(p);
00189           if(dist2 <= r2)
00190           {
00191             if(notP == 0 || dist2 > 0) neighbours.push_back(iq);
00192           }
00193         }
00194       }
00195 }
00196 
00197 
00198 //----------------------------------------------------------------------------
00199 void
00200 PrCellStructure::getKNearest(const Vector3D& p, int k,
00201                                vector<int>& neighbours, int notP) const
00202 //-----------------------------------------------------------------------------
00203 //   Return k nearest points to the point p.
00204 //   Don't include p itself if notP = 1.
00205 {
00206   neighbours.clear();
00207   if(k > int(xyz_.size()) - 1) return; // max k is xyz_.size() - 1
00208 
00209   // The following method is not optimal.
00210   // One should grow out in layers of cubes rather than in
00211   // larger and larger spheres, but this'll do as a first try.
00212 
00213   double r = cell_size_;
00214 
00215   vector<int> current_nghrs;
00216   getBall(p,r,current_nghrs,notP);
00217  
00218   while(int(current_nghrs.size()) < k)
00219   {
00220     r *= 2.0;
00221     getBall(p,r,current_nghrs,notP);
00222   }
00223 
00224   // Now we've got too many points in current_nghrs.
00225   // We now sort the points in distance from p and keep the
00226   // nearest k.
00227 
00228 
00229   int n = current_nghrs.size();
00230   double dist2;
00231 //  PrHeap heap(n);
00232 //  std::priority_queue< HeapNode , std::vector<HeapNode>, std::greater<HeapNode> > heap(n);
00233   HeapType heap;
00234   int i;
00235   for(i = 0; i < n; i++)
00236   {
00237     dist2 = xyz_[current_nghrs[i]].dist2(p);
00238     heap.push(HeapNode(i,dist2));
00239   }
00240 
00241   int index;
00242   for(i = 0; i < k; i++)
00243   {
00244     index = heap.top().idx_;
00245     heap.pop();
00246 //    heap.pop(key,index);
00247         // numbers are popped in increasing order
00248     //s_o << "  " << key << "  " << index << endl;
00249     neighbours.push_back(current_nghrs[index]);
00250   }
00251 }
00252 
00253 
00254 //----------------------------------------------------------------------------
00255 void
00256 PrCellStructure::getIJK(int ii, int& i, int& j, int& k) const
00257 //-----------------------------------------------------------------------------
00258 {
00259   k = ii / (ncells_[0] * ncells_[1]);
00260   int jj = ii - k * (ncells_[0] * ncells_[1]);
00261   j = jj / ncells_[0];
00262   i = jj - j * ncells_[0];
00263 }
00264 
00265 //----------------------------------------------------------------------------
00266 void
00267 PrCellStructure::whichCell(const Vector3D& xyz, int& i, int& j, int& k) const
00268 //-----------------------------------------------------------------------------
00269 {
00270   i = (int)((xyz.x() - min_[0]) / cell_size_);
00271   j = (int)((xyz.y() - min_[1]) / cell_size_);
00272   k = (int)((xyz.z() - min_[2]) / cell_size_);
00273 }
00274 
00275 //-----------------------------------------------------------------------------
00276 void PrCellStructure::print(ostream& os)
00277 //-----------------------------------------------------------------------------
00278 {
00279   os << xyz_.size() << endl;
00280   size_t i;
00281   for(i=0; i<xyz_.size(); i++)
00282   {
00283     os << xyz_[i].x() << " " << xyz_[i].y() << " " << xyz_[i].z() << "\n";
00284   }
00285 }
00286 
00287 //-----------------------------------------------------------------------------
00288 void PrCellStructure::scan(istream& is)
00289 //-----------------------------------------------------------------------------
00290 {
00291   int numpnts;
00292   is >> numpnts;
00293   xyz_.resize(numpnts);
00294   int i;
00295   for(i=0; i<numpnts; i++)
00296   {
00297     is >> xyz_[i].x() >> xyz_[i].y() >> xyz_[i].z();
00298   }
00299   makeCellStructure();
00300 }
00301 

Generated on Tue Jun 12 11:05:05 2007 for GoTools Parametrization Library by  doxygen 1.5.1