00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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;
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
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
00066 multimap<float,VT > neighbors;
00067 int mx0=-1;
00068 float dmax02=-1;
00069
00070 typename _Base::iteratorBoxConcentric p(cp);
00071 for(p=this->begin();p!=this->end();++p)
00072 {
00073
00074
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
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
00086
00087 if(neighbors.size()>=n)
00088 {
00089
00090 typename Maptyp::iterator it;uint i;
00091 for(it=neighbors.begin(),i=1;i<n;++i,it++){;}
00092 float dmax2=(*it).first;
00093
00094 if(neighbors.size()>n){it++;neighbors.erase(it,neighbors.end());}
00095
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
00106
00107
00108
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
00114 }
00115 }
00116 }
00117 if(neighbors.size()<n){ThrowError("NearestNeighbors found only:%d requested:%d",neighbors.size(),n);}
00118
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
00128 #ifdef NOTDEF
00129 VT NearestNeighbor(const Vect3Df centerR)
00130 {
00131
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
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
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
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
00164
00165 if(distMin2>=0)
00166 {
00167 float dmax2=distMin2;
00168
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
00179
00180
00181
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
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
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
00230 }
00231 };
00232 #endif// _Neighbors3D_hpp