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

Container3DIterators.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  */
00021 #ifndef _Container3D_internal
00022 #error Image3DIterators should only be included by Container3D.hpp
00023 #endif
00024 
00025 // **************************************************
00026 // ****************** iterators *********************
00027 // **************************************************
00028 
00029 // FIXME!! this is a temporary fix for gcc>=3.1
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     // jump to new location
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         // optionally move xyz if pos is not at begining of ima
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         // if iter fast is begining of image put it at begining of zone
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 //      CTR3D_iteratorZone(const CTR3D_iteratorFast<Container3D,_Ref,_Ptr> &other) : _Base()
00263 //      {
00264 //          operator=(other);
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         // for lazy programers that don't want to write masked and unmasked versions
00293         // of their algorithms... 
00294         // this works on unmasked images too but warning, this is a litle bit slower
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         // waring: this is dangerous beacause there is no 100% safe way of checking if we are under begining
00307         // for lazy programers that don't want to write masked and unmasked versions
00308         // of their algorithms... 
00309         // this works on unmasked images too but warning, this is a litle bit slower
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         // for lazy programers that don't want to write masked and unmasked versions
00359         // of their algorithms... 
00360         // this works on unmasked images too but warning, this is a litle bit slower
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         // waring: this is dangerous beacause there is no 100% safe way of checking if we are under begining
00373         // for lazy programers that don't want to write masked and unmasked versions
00374         // of their algorithms... 
00375         // this works on unmasked images too but warning, this is a litle bit slower
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     // jump to new location
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     // intersection of current box and image box
00423     RectZone3Di currentBox;
00424     RectZone3Di imazone;
00425     int x,y,z;
00426     void AssertBounds()
00427     {       
00428 //          if(!ima->IsInside(x,y,z)  || !zone.IsInside(x,y,z) || 
00429 //             pos<ima->GetData() || pos>=ima->GetData()+ima->GetNVoxels())
00430 //          {
00431 //              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",
00432 //                       x,y,z,
00433 //                       zone.x0,zone.y0,zone.z0,
00434 //                       zone.x1,zone.y1,zone.z1,
00435 //                       ima->Width(),ima->Height(),ima->Depth(),
00436 //                       pos,ima->GetData(),ima->GetData()+ima->GetNVoxels());
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         // go to next point on current box that's inside image
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             // finished this box, now find next concentric box
00456             currentBox=RectZone3Di(currentBox.GetP0()-Vect3Di(1,1,1),currentBox.GetP1()+Vect3Di(1,1,1));
00457             // check if this was last box
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             // place current pos at first point in box that's ok
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);} // deprecated : use Pos()
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 

Generated on Fri Jun 17 13:35:56 2005 for ImLib3D by  doxygen 1.4.2