Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

Neighbors3D.hpp

Go to the documentation of this file.
00001 /* ImLib3D
00002  * Copyright (c) 2001, ULP-IPB Strasbourg.
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or (at
00007  * your option) any later version.
00008  * 
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00020 #ifndef _Neighbors3D_hpp
00021 #define _Neighbors3D_hpp
00022 
00023 #include<ImLib3D/Image3D.hpp>
00024 #include<ImLib3D/CppTools.hpp>
00025 #include<ImLib3D/Vect3D.hpp>
00026 #include<vector>
00027 #include<map>
00028 #include<algorithm>
00029 
00030 
00031 
00032 template<class Typ>
00033 class Neighbors3D : public Container3D< vector< pair< Vect3Df , Typ > > >
00034 {
00035     RectZone3Df *support;// cache ptr to property, for faster acces
00036 public:
00037     typedef Container3D< vector< pair< Vect3Df , Typ > > > _Base;
00038     typedef pair<Vect3Df,Typ> VT;
00039     typedef vector<VT > Im3DValue;
00040     Vect3Df RPosToIPos(const Vect3Df &p)
00041     {
00042         return this->Support().SelfCoords(p)%(Vect3Df)this->SizeV();
00043     }
00044     RectZone3Df NeighborZoneF(const Vect3Df center,double radius)
00045     {
00046         Vect3Df r(radius,radius,radius);
00047         return RectZone3Df(RPosToIPos(center-r),
00048                            RPosToIPos(center+r));
00049     }
00050     RectZone3Di NeighborZone(const Vect3Df center,double radius)
00051     {
00052         RectZone3Df fzone=NeighborZoneF(center,radius);
00053         RectZone3Df imzone(Vect3Df(0,0,0),(Vect3Df)this->SizeV()-Vect3Df(1,1,1));
00054         RectZone3Df t=fzone.Intersection(imzone);
00055         return RectZone3Di((int)t.x0,(int)t.y0,(int)t.z0,
00056                            (int)ceil(t.x1),(int)ceil(t.y1),(int)ceil(t.z1 ));
00057     }
00058     Im3DValue NearestNeighbors(const Vect3Df centerR,uint n=1)
00059     {
00060         // center point in image coords
00061         Vect3Df centerI(RPosToIPos(centerR));
00062         typedef pair<float,VT> ppair;
00063         Vect3Di cp((int)centerI.x,(int)centerI.y,(int)centerI.z);
00064         typedef multimap<float,VT > Maptyp;
00065         // list of candidate neighbors
00066         multimap<float,VT > neighbors;
00067         int mx0=-1;
00068         float dmax02=-1;
00069         // walk the voxels concentrically, starting from center
00070         typename _Base::iteratorBoxConcentric p(cp);
00071         for(p=this->begin();p!=this->end();++p)
00072         {
00073 //              p.Pos().Show("p:","\n");
00074             // check if we've gone far enough
00075             Vect3Di dp=p.Pos()-cp;
00076             int mx=max(abs(dp.x),max(abs(dp.y),abs(dp.z)));
00077             if(mx0>=0 && mx>mx0){break;}
00078             // incorporate this voxel's particles to the sorted candidate nn list
00079             for(uint i=0;i<(*p).size();i++)
00080             {
00081                 VT neighbor=(*p)[i];
00082                 float dist2=neighbor.first.Distance2(centerR);
00083                 neighbors.insert(ppair(dist2,neighbor));
00084             }
00085             // if we have enough neighbors, see how far away we have to go
00086             // to be sure we've got them all
00087             if(neighbors.size()>=n)
00088             {
00089                 // find distance of current n'th nearest neighbor
00090                 typename Maptyp::iterator it;uint i;
00091                 for(it=neighbors.begin(),i=1;i<n;++i,it++){;}
00092                 float dmax2=(*it).first;
00093                 // trash all other neigbors >n 
00094                 if(neighbors.size()>n){it++;neighbors.erase(it,neighbors.end());}
00095                 // see how far we must go
00096                 if(dmax02<0 || dmax2<dmax02)
00097                 {
00098                     dmax02=dmax2;
00099                     float dmax=sqrt(dmax2);
00100                     Vect3Df vmax(dmax,dmax,dmax);
00101                     Vect3Df pminI=RPosToIPos(centerR-vmax);
00102                     Vect3Df pmaxI=RPosToIPos(centerR+vmax);
00103                     Vect3Di pmin((int)pminI.x,(int)pminI.y,(int)pminI.z);
00104                     Vect3Di pmax((int)pmaxI.x,(int)pmaxI.y,(int)pmaxI.z);
00105 //                      pminI.Show("pminI:","\n");
00106 //                      pmaxI.Show("pmaxI:","\n");
00107 //                      pmin.Show("pmin :","\n");
00108 //                      pmax.Show("pmax :","\n");
00109                     Vect3Di dp=pmin-cp;
00110                     mx0=max(abs(dp.x),max(abs(dp.y),abs(dp.z)));
00111                     dp=pmax-cp;
00112                     mx0=max(mx0,max(abs(dp.x),max(abs(dp.y),abs(dp.z))));
00113 //                      mprintf("dmax:%f mx0:%d cp:%d %d %d\n",dmax,mx0,cp.x,cp.y,cp.z);
00114                 }
00115             }
00116         }
00117         if(neighbors.size()<n){ThrowError("NearestNeighbors found only:%d requested:%d",neighbors.size(),n);}
00118 //          mprintf("found %d neighbors. requested %d\n",neighbors.size(),n);
00119         vector<VT> res;
00120         res.reserve(n);
00121         typename Maptyp::iterator it;
00122         uint i;
00123         for(it=neighbors.begin(),i=0;i<n;++i,it++){res.push_back((*it).second);}
00124         return res;
00125     }
00126 
00127 //FIXME, needs testing
00128 #ifdef NOTDEF 
00129     VT NearestNeighbor(const Vect3Df centerR)
00130     {
00131         // center point in image coords
00132         Vect3Df centerI(RPosToIPos(centerR));
00133         typedef pair<float,VT> ppair;
00134         Vect3Di cp((int)centerI.x,(int)centerI.y,(int)centerI.z);
00135         Vect3Df nearest;
00136         float distMin2=-1;
00137         VT res;
00138 
00139         int mx0=-1;
00140         float dmax02=-1;
00141         bool talk=false;
00142         if(!(rand()%10000)){talk=true;}
00143         
00144         if(talk){centerI.Show("nearest neighbor at:","\n");}
00145         // walk the voxels concentrically, starting from center
00146         typename ImageType::iteratorBoxConcentric p(cp);
00147         for(p=this->begin();p!=this->end();++p)
00148         {
00149             if(talk)p.Pos().Show("starting box p:","\n");
00150             if(talk)printf("number of points here:%d min:%f\n",(*p).size(),distMin2);
00151             // check if we've gone far enough
00152             Vect3Di dp=p.Pos()-cp;
00153             int mx=max(abs(dp.x),max(abs(dp.y),abs(dp.z)));
00154             if(mx0>=0 && mx>mx0){break;}
00155             // incorporate this voxel's particles to the sorted candidate nn list
00156             for(uint i=0;i<(*p).size();i++)
00157             {
00158                 const VT &neighbor=(*p)[i];
00159                 float dist2=neighbor.first.Distance2(centerR);
00160                 if(talk){neighbor.first.Show(SPrintf("%f:",dist2),"\n");}
00161                 if(dist2<distMin2 || distMin2<0){nearest=neighbor.first;distMin2=dist2;res=neighbor;}
00162             }
00163             // if we have enough neighbors, see how far away we have to go
00164             // to be sure we've got them all
00165             if(distMin2>=0)
00166             {
00167                 float dmax2=distMin2;
00168                 // see how far we must go
00169                 if(dmax02<0 || dmax2<dmax02)
00170                 {
00171                     dmax02=dmax2;
00172                     float dmax=sqrt(dmax2);
00173                     Vect3Df vmax(dmax,dmax,dmax);
00174                     Vect3Df pminI=RPosToIPos(centerR-vmax);
00175                     Vect3Df pmaxI=RPosToIPos(centerR+vmax);
00176                     Vect3Di pmin((int)pminI.x,(int)pminI.y,(int)pminI.z);
00177                     Vect3Di pmax((int)pmaxI.x,(int)pmaxI.y,(int)pmaxI.z);
00178 //                      pminI.Show("pminI:","\n");
00179 //                      pmaxI.Show("pmaxI:","\n");
00180 //                      pmin.Show("pmin :","\n");
00181 //                      pmax.Show("pmax :","\n");
00182                     Vect3Di dp=pmin-cp;
00183                     mx0=max(abs(dp.x),max(abs(dp.y),abs(dp.z)));
00184                     dp=pmax-cp;
00185                     mx0=max(mx0,max(abs(dp.x),max(abs(dp.y),abs(dp.z))));
00186 //                      mprintf("dmax:%f mx0:%d cp:%d %d %d\n",dmax,mx0,cp.x,cp.y,cp.z);
00187                 }
00188             }
00189         }
00190         if(distMin2<0){ThrowError("NearestNeighbors found no neighbors");}
00191         return res;
00192     }
00193 #endif// NOTDEF 
00194     Im3DValue Neighbors(const Vect3Df center,double radius)
00195     {
00196         typename _Base::iteratorZone pi(NeighborZone(center,radius));
00197         Im3DValue res;
00198         double radius2=radius*radius;
00199         for(pi=this->begin();pi!=this->end();++pi)
00200         {
00201             Im3DValue &candidates=*pi;
00202             for(uint i=0;i<candidates.size();i++)
00203             {
00204                 if(candidates[i]->position.Distance2(center)<=radius2)
00205                 {
00206                     res.push_back(candidates[i]);
00207                 }
00208             }
00209         }
00210         return res;
00211     }
00212     void Remove(const Vect3Df &pos,Typ v){Remove(VT(pos,v));}
00213     void Remove(const VT &p)
00214     {
00215         Im3DValue &voxel=Get(p.first);
00216         typename Im3DValue::iterator f=find(voxel.begin(),voxel.end(),p);
00217         if(f==voxel.end()){ThrowError("Neighbors3D::Remove not found");}
00218         voxel.erase(f);
00219     }
00220     // FIXME FIXME, rarelly fails Get? (on optimize compile)
00221     void Insert(const VT &p){Get(p.first).push_back(p);}
00222     void Insert(const Vect3Df &pos,Typ v){Get(pos).push_back(VT(pos,v));}
00223     Im3DValue &Get(Vect3Di P){Vect3Df p1=RPosToIPos(P);return (*this)((int)p1.x,(int)p1.y,(int)p1.z);}
00224     Im3DValue &Get(Vect3Df P){Vect3Df p1=RPosToIPos(P);return (*this)((int)p1.x,(int)p1.y,(int)p1.z);}
00225     Neighbors3D(RectZone3Df _support,int _width, int _height, int _depth):
00226         Container3D<Im3DValue>(_width,_height,_depth)
00227     {
00228         AddSupport(_support.GetP0(),_support.GetP1());
00229 //          properties.support=new Support3D<Container3D<Im3DValue> >(this,support.GetP0(),support.GetP1());
00230     }
00231 };
00232 #endif// _Neighbors3D_hpp

Generated on Fri Jun 17 13:36:06 2005 for ImLib3D by  doxygen 1.4.2