00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00021 #ifndef _Container3D_internal
00022 #error Image3DIterators should only be included by Container3D.hpp
00023 #endif
00024
00025
00026
00027
00028
00029
00030 #if (__GNUC__==3 && __GNUC_MINOR__>=1) || __GNUC__>3
00031
00032 template<typename _Tp, typename _Distance>
00033 struct random_access_iterator {
00034 typedef random_access_iterator_tag iterator_category;
00035 typedef _Tp value_type;
00036 typedef _Distance difference_type;
00037 typedef _Tp* pointer;
00038 typedef _Tp& reference;
00039 };
00040
00041 #endif
00042
00043
00045 template<class Container3D,class _Ref,class _Ptr>
00046 class CTR3D_iteratorFast : public random_access_iterator<typename Container3D::value_type,size_t>
00047 {
00048 typedef CTR3D_iteratorFast<Container3D,_Ref,_Ptr> _Self;
00049 public:
00050 Container3D *ima;
00051 _Ptr pos;
00052 public:
00053 void AssertBounds()
00054 {
00055 if(pos<ima->begin().pos || pos>=ima->end().pos)
00056 {
00057 ThrowError("iteratorFast: out of bounds:pos:%x begin:%x end:%x\n",pos,ima->begin().pos,ima->end().pos);
00058 }
00059 }
00060 inline _Ref operator*(){return *pos;}
00061 double Progress() const {if(!this){return 0;}return (pos-ima->GetData())/(float)ima->GetNVoxels();}
00062 inline _Self operator++(int) {_Self __tmp=*this;pos++;return __tmp;}
00063 inline _Self &operator++() {pos++;return *this;}
00064 inline void operator+=(size_t m){pos+=m;}
00065 inline _Self operator+ (size_t m){_Self __tmp=*this;__tmp.pos+=m;return __tmp;}
00066 inline _Self operator- (size_t m){_Self __tmp=*this;__tmp.pos-=m;return __tmp;}
00067 inline _Self operator--(int) {_Self __tmp=*this;pos--;return __tmp;}
00068 inline _Self &operator--() {pos--;return *this;}
00069 inline void operator-=(size_t m){pos-=m;}
00070 inline int operator- (const _Self &other) const {return pos-other.pos;}
00071 inline bool operator< (const _Self &other) const {return pos< other.pos;}
00072 inline bool operator<=(const _Self &other) const {return pos<=other.pos;}
00073 inline bool operator> (const _Self &other) const {return pos> other.pos;}
00074 inline bool operator>=(const _Self &other) const {return pos>=other.pos;}
00075
00076 inline Vect3Di ComputePosition() const
00077 {
00078 int offset=pos-ima->GetData();
00079 Vect3Di res;
00080 res.z=offset/(ima->Height()*ima->Width());
00081 offset=offset%(ima->Height()*ima->Width());
00082 res.y=offset/ima->Width();
00083 res.x=offset%ima->Width();
00084 return res;
00085 }
00086 void operator+=(const Vect3Di &dV)
00087 {
00088 pos+=dV.x+ima->Width()*dV.y+ima->Width()*ima->Height()*dV.z;
00089 }
00090 inline void operator=(const Vect3Di &P)
00091 {
00092 pos=ima->GetData()+P.x+ima->Width()*P.y+ima->Width()*ima->Height()*P.z;
00093 }
00094 inline bool operator!=(const _Self &other){return pos!=other.pos; }
00095 inline bool operator==(const _Self &other){return pos==other.pos; }
00096 CTR3D_iteratorFast():ima(NULL),pos(NULL){}
00097 CTR3D_iteratorFast(Container3D *_ima,_Ptr _pos):ima(_ima),pos(_pos){}
00098 };
00099
00101
00102 template<class Container3D,class _Ref,class _Ptr>
00103 class CTR3D_iteratorXYZ : public CTR3D_iteratorFast<Container3D,_Ref,_Ptr>
00104 {
00105 typedef CTR3D_iteratorFast<Container3D,_Ref,_Ptr> _Base;
00106 typedef CTR3D_iteratorXYZ <Container3D,_Ref,_Ptr> _Self;
00107 void Reposition(){Vect3Di v=this->ComputePosition();x=v.x;y=v.y;z=v.z;}
00108 public:
00109 int x,y,z;
00110
00111 void AssertBounds()
00112 {
00113 if(!this->ima->IsInside(x,y,z) || this->pos<this->ima->GetData() || this->pos>=this->ima->GetData()+this->ima->GetNVoxels())
00114 {
00115 ThrowError("iteratorXYZ: out of bounds %d %d %d: image %d %d %d :pos:%x begin:%x end:%x\n",
00116 x,y,z,
00117 this->ima->Width(),this->ima->Height(),this->ima->Depth(),
00118 this->pos,this->ima->GetData(),this->ima->GetData()+this->ima->GetNVoxels());
00119 }
00120 }
00121
00122 inline _Self operator++(int){_Self __tmp=*this;++(*this);return __tmp;}
00123 inline _Self &operator++()
00124 {
00125 this->pos++;
00126 x++;
00127 if(x>=this->ima->Width())
00128 {
00129 x=0;
00130 y++;
00131 if(y>=this->ima->Height())
00132 {
00133 y=0;
00134 z++;
00135 }
00136 }
00137 return *this;
00138 }
00139 inline _Self operator--(int){_Self __tmp=*this;--(*this);return __tmp;}
00140 inline _Self &operator--()
00141 {
00142 this->pos--;
00143 x--;
00144 if(x<0)
00145 {
00146 x=this->ima->Width()-1;
00147 y--;
00148 if(y<0)
00149 {
00150 y=this->ima->Height()-1;
00151 z--;
00152 }
00153 }
00154 return *this;
00155 }
00157 inline Vect3Di Pos() const {return Vect3Di(x,y,z);}
00158
00159 inline void operator=(const Vect3Di &P)
00160 {
00161 x=P.x;
00162 y=P.y;
00163 z=P.z;
00164 this->pos=&(*this->ima)(P);
00165 }
00166
00167 inline void operator+=(size_t m){this->pos+=m;Reposition();}
00168 inline void operator-=(size_t m){this->pos-=m;Reposition();}
00169 inline _Self operator+ (size_t m){_Self __tmp=*this;__tmp.pos+=m;__tmp.Reposition();return __tmp;}
00170 inline _Self operator- (size_t m){_Self __tmp=*this;__tmp.pos-=m;__tmp.Reposition();return __tmp;}
00171
00172 void operator= (const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other)
00173 {
00174 this->ima=other.ima;
00175 this->pos=other.pos;
00176 if(this->pos==this->ima->GetData()){x=0;y=0;z=0;}
00177 else{Reposition();}
00178 }
00179 CTR3D_iteratorXYZ():_Base(){;}
00180 CTR3D_iteratorXYZ(const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other) : _Base(other)
00181 {
00182 operator=(other);
00183 }
00184 CTR3D_iteratorXYZ(Container3D *_ima,_Ptr _pos) : _Base(_ima,_pos)
00185 {
00186
00187 if(this->pos!=this->ima->GetData())
00188 {_Base::operator=(CTR3D_iteratorFast<Container3D,_Ref,_Ptr>(this->ima,this->pos).ComputePosition());}
00189 }
00190
00191 };
00192
00194
00195 template<class Container3D,class _Ref,class _Ptr>
00196 class CTR3D_iteratorZone : public CTR3D_iteratorXYZ<Container3D,_Ref,_Ptr>
00197 {
00198 typedef CTR3D_iteratorXYZ <Container3D,_Ref,_Ptr> _Base;
00199 typedef CTR3D_iteratorZone<Container3D,_Ref,_Ptr> _Self;
00200 public:
00201 RectZone3Di zone;
00202 double Progress(){return (this->pos-this->ima->GetData())/(float)zone.Volume();}
00203 void AssertBounds()
00204 {
00205 if(!this->ima->IsInside(this->x,this->y,this->z) || !this->zone.IsInside(this->x,this->y,this->z) ||
00206 this->pos<this->ima->GetData() || this->pos>=this->ima->GetData()+this->ima->GetNVoxels())
00207 {
00208 ThrowError("iteratorZone: out of bounds %d %d %d:zone:%d %d %d - %d %d %d: image %d %d %d : pos:%x begin:%x end:%x\n",
00209 this->x,this->y,this->z,
00210 zone.x0,zone.y0,zone.z0,
00211 zone.x1,zone.y1,zone.z1,
00212 this->ima->Width(),this->ima->Height(),this->ima->Depth(),
00213 this->pos,this->ima->GetData(),this->ima->GetData()+this->ima->GetNVoxels());
00214 }
00215 }
00216 inline _Self operator++(int){_Self __tmp=*this;++(*this);return __tmp;}
00217 inline _Self &operator++()
00218 {
00219 this->pos++;
00220 if(this->zone.ToNext(this->x,this->y,this->z))
00221 {
00222 if(this->zone.IsInside(this->x,this->y,this->z))
00223 {
00224 this->pos=&(*this->ima)(this->x,this->y,this->z);
00225 }
00226 else{this->pos=this->ima->GetDataEnd();}
00227 }
00228 return *this;
00229 }
00230 inline void operator--(int)
00231 {
00232 this->pos--;
00233 if(this->zone.ToPrev(this->x,this->y,this->z))
00234 {
00235 if(this->zone.IsInside(this->x,this->y,this->z))
00236 {
00237 this->pos=&(*this->ima)(this->x,this->y,this->z);
00238 }
00239 else{this->pos=NULL;}
00240 }
00241 }
00242
00243 inline void operator+=(size_t m){while (m--) operator++(0);}
00244 inline void operator-=(size_t m){while (m--) operator--(0);}
00245 inline _Self operator+ (size_t m){_Self __tmp=*this;__tmp+=m;return __tmp;}
00246 inline _Self operator- (size_t m){_Self __tmp=*this;__tmp-=m;return __tmp;}
00247
00248 void operator= (const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other)
00249 {
00250 this->ima=other.ima;
00251 this->pos=other.pos;
00252 if(!this->ima->IsInside(zone.GetP0()) || !this->ima->IsInside(zone.GetP1()))
00253 {
00254 ThrowError("iteratorZone zone does not fit in image");
00255 }
00256
00257 if(this->pos==this->ima->GetData()){this->zone.ToStart(this->x,this->y,this->z);}
00258 else{_Base::operator=(other.ComputePosition());}
00259 this->pos=&(*this->ima)(this->x,this->y,this->z);
00260 }
00261 CTR3D_iteratorZone():_Base(){}
00262
00263
00264
00265
00266 CTR3D_iteratorZone(const RectZone3Di &_zone):
00267 _Base(),zone(_zone)
00268 {
00269 }
00270 };
00271
00272
00273
00275 template<class Container3D,class _Ref,class _Ptr>
00276 class CTR3D_iteratorFastMasked : public CTR3D_iteratorFast<Container3D,_Ref,_Ptr>
00277 {
00278 typedef CTR3D_iteratorFast <Container3D,_Ref,_Ptr> _Base;
00279 typedef CTR3D_iteratorFastMasked<Container3D,_Ref,_Ptr> _Self;
00280 const byte *pmask;
00281 public:
00282 void AssertMasked()
00283 {
00284 if(*pmask==0)
00285 {
00286 ThrowError("iteratorFastMasked: mask at pos==0 :pos:%x begin:%x end:%x\n",_Base::pos,_Base::begin,_Base::end);
00287 }
00288 }
00289 inline _Self operator++(int){_Self __tmp=*this;++(*this);return __tmp;}
00290 inline _Self &operator++()
00291 {
00292
00293
00294
00295 if(!pmask){_Base::operator++(0);return *this;}
00296 do
00297 {
00298 pmask++;
00299 _Base::operator++(0);
00300 }while(_Base::pos!=this->ima->GetDataEnd() && !(*pmask));
00301 return *this;
00302 }
00303 inline _Self operator--(int){_Self __tmp=*this;--(*this);return __tmp;}
00304 inline _Self &operator--()
00305 {
00306
00307
00308
00309
00310 if(!pmask){_Base::operator--(0);return *this;}
00311 do
00312 {
00313 pmask--;
00314 _Base::operator--(0);
00315 }while(!(*pmask) && _Base::pos!=this->ima->GetData());
00316 return *this;
00317 }
00318
00319
00320 inline void operator+=(size_t m){while (m--) operator++(0);}
00321 inline void operator-=(size_t m){while (m--) operator--(0);}
00322 inline _Self operator+ (size_t m){_Self __tmp=*this;__tmp+=m;return __tmp;}
00323 inline _Self operator- (size_t m){_Self __tmp=*this;__tmp-=m;return __tmp;}
00324
00325 void operator=(const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other)
00326 {
00327 _Base::operator=(other);
00328 if(this->ima->HasMask())
00329 {
00330 pmask=this->ima->Mask().GetData();
00331 if(!(*pmask)){operator++();}
00332 }
00333 else
00334 {pmask=NULL;}
00335 }
00336
00337 CTR3D_iteratorFastMasked():_Base(),pmask(NULL){}
00338 CTR3D_iteratorFastMasked(const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other):
00339 _Base()
00340 {
00341 operator=(other);
00342 }
00343 };
00344
00345
00347
00348 template<class Container3D,class _Ref,class _Ptr>
00349 class CTR3D_iteratorXYZMasked : public CTR3D_iteratorXYZ<Container3D,_Ref,_Ptr>
00350 {
00351 typedef CTR3D_iteratorXYZ <Container3D,_Ref,_Ptr> _Base;
00352 typedef CTR3D_iteratorXYZMasked<Container3D,_Ref,_Ptr> _Self;
00353 const byte *pmask;
00354 public:
00355 inline _Self operator++(int){_Self __tmp=*this;++(*this);return __tmp;}
00356 inline _Self &operator++()
00357 {
00358
00359
00360
00361 if(!pmask){_Base::operator++(0);return *this;}
00362 do
00363 {
00364 pmask++;
00365 _Base::operator++(0);
00366 }while(!(*pmask) && _Base::pos!=this->ima->GetDataEnd());
00367 return *this;
00368 }
00369 inline _Self operator--(int){_Self __tmp=*this;--(*this);return __tmp;}
00370 inline _Self &operator--()
00371 {
00372
00373
00374
00375
00376 if(!pmask){_Base::operator--(0);return *this;}
00377 do
00378 {
00379 pmask--;
00380 _Base::operator--(0);
00381 }while(!(*pmask) && _Base::pos!=this->ima->GetData());
00382 return *this;
00383 }
00384
00385 inline void operator=(const Vect3Di &P)
00386 {
00387 ThrowError("iteratorXYZMasked operator=V unimplemented");
00388 }
00389
00390 inline void operator+=(size_t m){while (m--) operator++(0);}
00391 inline void operator-=(size_t m){while (m--) operator--(0);}
00392 inline _Self operator+ (size_t m){_Self __tmp=*this;__tmp+=m;return __tmp;}
00393 inline _Self operator- (size_t m){_Self __tmp=*this;__tmp-=m;return __tmp;}
00394
00395 void operator= (const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other)
00396 {
00397 _Base::operator=(other);
00398 if(this->ima->HasMask())
00399 {
00400 pmask=this->ima->Mask().GetData();
00401 if(!(*pmask)){operator++();}
00402 }
00403 else
00404 {pmask=NULL;}
00405 }
00406 CTR3D_iteratorXYZMasked():_Base(),pmask(NULL){;}
00407 CTR3D_iteratorXYZMasked(const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other):
00408 _Base()
00409 {
00410 operator=(other);
00411 }
00412 };
00413
00415
00416 template<class Container3D,class _Ref,class _Ptr>
00417 class CTR3D_iteratorBoxConcentric : public CTR3D_iteratorFast<Container3D,_Ref,_Ptr>
00418 {
00419 typedef CTR3D_iteratorFast <Container3D,_Ref,_Ptr> _Base;
00420 typedef CTR3D_iteratorBoxConcentric<Container3D,_Ref,_Ptr> _Self;
00421 public:
00422
00423 RectZone3Di currentBox;
00424 RectZone3Di imazone;
00425 int x,y,z;
00426 void AssertBounds()
00427 {
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 }
00439 inline _Self operator++(int){_Self __tmp=*this;++(*this);return __tmp;}
00440 inline _Self &operator++()
00441 {
00442 #ifdef SAFE_DEBUG
00443 AssertBounds();
00444 #endif
00445
00446 do{currentBox.ToNextOnSurface(x,y,z);}
00447 while(!imazone.IsInside(x,y,z) && currentBox.IsInside(x,y,z));
00448
00449 if(currentBox.IsInside(x,y,z))
00450 {
00451 this->pos=&(*this->ima)(x,y,z);
00452 }
00453 else
00454 {
00455
00456 currentBox=RectZone3Di(currentBox.GetP0()-Vect3Di(1,1,1),currentBox.GetP1()+Vect3Di(1,1,1));
00457
00458 if(currentBox.IsInside(imazone.GetP0()) && !currentBox.IsOnSurface(imazone.GetP0()) &&
00459 currentBox.IsInside(imazone.GetP1()) && !currentBox.IsOnSurface(imazone.GetP1()) )
00460 {this->pos=this->ima->GetDataEnd();return *this;}
00461
00462 currentBox.ToStart(x,y,z);
00463 while(!imazone.IsInside(x,y,z) ){currentBox.ToNextOnSurface(x,y,z);}
00464 this->pos=&(*this->ima)(x,y,z);
00465 }
00466 return *this;
00467 }
00468 inline deprecated Vect3Di V() const {return Vect3Di(x,y,z);}
00469 inline Vect3Di Pos() const {return Vect3Di(x,y,z);}
00470 inline _Ref operator*()
00471 {
00472 #ifdef SAFE_DEBUG
00473 AssertBounds();
00474 #endif
00475 return *this->pos;
00476 }
00477 void operator= (const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other)
00478 {
00479 _Base::operator=(other);
00480 if(this->pos!=this->ima->GetData()){ThrowError("BoxConcentric::operator= jump to rand this->pos unimplemented");}
00481 this->imazone=this->ima->GetZone();
00482 currentBox.ToStart(x,y,z);
00483 if(!imazone.IsInside(x,y,z))
00484 {
00485 Vect3Di p=Vect3Di(x,y,z);
00486 Vect3Di cp=imazone.ClosestPoint(p);
00487 Vect3Di dp=p-cp;
00488 int mx=max(abs(dp.x),max(abs(dp.y),abs(dp.z)));
00489 dp=Vect3Di(mx,mx,mx);
00490 currentBox=RectZone3Di(p-dp,p+dp);
00491 currentBox.ToStart(x,y,z);
00492 while(!imazone.IsInside(x,y,z) ){currentBox.ToNextOnSurface(x,y,z);}
00493 }
00494 this->pos=&(*this->ima)(x,y,z);
00495 }
00496 CTR3D_iteratorBoxConcentric():_Base(){}
00497 CTR3D_iteratorBoxConcentric(const Vect3Di &p0):
00498 _Base(),currentBox(p0,p0),imazone(0,0,0,0,0,0)
00499 {
00500 }
00501 };
00502