arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

nrro.h

Go to the documentation of this file.
00001 //------------------------------------------------------------------------
00002 //
00003 //   Joe Kniss
00004 //     9-17-02
00005 //                   ________    ____   ___ 
00006 //                  |        \  /    | /  /
00007 //                  +---+     \/     |/  /
00008 //                  +--+|  |\    /|     < 
00009 //                  |  ||  | \  / |  |\  \ 
00010 //                  |      |  \/  |  | \  \ 
00011 //                   \_____|      |__|  \__\
00012 //                       Copyright  2002 
00013 //                      Joe Michael Kniss
00014 //                   <<< jmk@cs.utah.edu >>>
00015 //               "All Your Base are Belong to Us"
00016 //-------------------------------------------------------------------------
00017 
00018 //nrro.h
00019 
00020 /// nrro, a nrrd object wrapper.
00021 
00022 #ifndef __NRRO_DOT_H
00023 #define __NRRO_DOT_H
00024 
00025 #include <nrrd.h>
00026 #include <arrayGutz.h>
00027 #include <mathGutz.h>
00028 #include <smartptr.h>
00029 #include <iostream>
00030 #include <vector>
00031 #include <string>
00032 #include "nrroKernel.h"
00033 
00034 #define MAX_NRRO_ARRAY_DIM 8
00035 
00036 class NrroProbe;
00037 
00038 /////////////////////////////////////////////////////////////////////////
00039 /// NRRO,  NRRd Object, "Not Really Raster Object"
00040 ///
00041 ///  TODO: move to GUTZ ??? \n
00042 ///  TODO: only node centered data?
00043 ///        this means that a axis of length 1 has spatial size 0 ...
00044 ///        no matter the spacing!
00045 ///
00046 ///
00047 /////////////////////////////////////////////////////////////////////////
00048 
00049 class Nrro : public gutz::Counted {
00050 public:
00051    Nrro(); //<Empty Nrro 
00052    Nrro(int typeEnum, int sx);  //< 1D
00053    Nrro(int typeEnum, int sx, int sy); //< 2D
00054    Nrro(int typeEnum, int sx, int sy, int sz); //< 3D
00055    Nrro(int typeEnum, int sx, int sy, int sz, int sw); //< 4D
00056    Nrro(int typeEnum, int s1, int s2, int s3, int s4, int s5); //< 5D
00057    Nrro(int typeEnum, int dim, int sz[]); //< ND
00058    Nrro(const Nrro &n); //<Copy Constructor
00059    Nrro(const char* nrrdFileName, bool proxy = false);//<Read Nrrd from file
00060    Nrro(Nrrd* n); //<Wrap a Nrrd in a Nrro
00061    virtual ~Nrro(); //<Destruction
00062 
00063    ////////////////////////////////////////////////////
00064    /// assignment
00065    void operator=(const Nrro &n);
00066 
00067    ////////////////////////////////////////////////////
00068    /// does this nrro contain any usefull information?
00069    bool          isValid() const    {return _valid;}
00070    ////////////////////////////////////////////////////
00071    ///@name Modified - should be Depricated
00072    ///@{
00073 
00074    /// has it been changed?
00075    bool          isModified() const           {return _modified;}
00076    void          setModified(bool mod = true) {_modified = mod;}
00077    
00078    ///@}
00079 
00080    /// bring it up to date. isModified() will be false after.
00081    /// Updates: strides, extended format, minmax
00082    /// only worry about this if you change something about this
00083    /// nrro, like values or it's size.
00084    virtual void  update();
00085 
00086    /////////////////////////////////////////////////////
00087    ///@name Kinds of Nrros 
00088    /// for more symantic meaning, 
00089    /// without subclassing, this might not be a good idea?
00090    /// This class tries to be smart about guessing what
00091    /// kind of nrrd it is, see <nrroKind.cpp> for rules
00092    /// These can be "or'ed" together for instance: 
00093    /// \code IMAGE | TIME_SERIES | PROXY \endcode 
00094    ///  is a movie (time series image) with no data, 
00095    ///  just info on it's size and dimensions etc....
00096    ///@{
00097 
00098    enum  NRRO_KINDS{
00099       KIND_NOT_SET = 0,     ///< We dont know, and haven't even guessed yet
00100       KIND_UNKNOWN = 1<<0,  ///< just a Nrro, no symantics, default if no guess 
00101       IMAGE        = 1<<1,  ///< a 2D image, may have multiple channels
00102       VOLUME       = 1<<2,  ///< a 3D volume (mutually exclusive with IMAGE)
00103       TIME_SERIES  = 1<<3,  ///< a time series of ...
00104       PROXY        = 1<<4,  ///< no data read, just info on the volume 
00105       KIND_LAST    = 1<<5 | 1<<0
00106    };
00107    int       getKind() const   {return _kind;}
00108    /// guess what kind of data we have
00109    int       guessKind() const; 
00110    /// set the kind of data, 
00111    ///  to make it a proxy try:
00112    /// setKind(getKind() | Nrro::PROXY);
00113    ///  to make it "not" a PROXY try
00114    /// setKind(getKind() & (~Nrro::PROXY))
00115    void      setKind(int kind) {_kind = kind;}
00116    /// print kind to std::err
00117    void      printKind() const;
00118 
00119    ///@}
00120    /////////////////////////////////////////////////////
00121 
00122    /////////////////////////////////////////////////////
00123    ///@name Nrro Types
00124    ///@{
00125 
00126    /// Let's go ahead and redefine all of the nrrd types
00127    /// ... so we don't have to dig through all of gk's .h
00128    /// use Nrro::CHAR, for example
00129    enum  NRRO_TYPES  {
00130       UNKNOWN     = nrrdTypeUnknown,
00131       CHAR        = nrrdTypeChar,
00132       UCHAR       = nrrdTypeUChar,
00133       SHORT       = nrrdTypeShort,
00134       USHORT      = nrrdTypeUShort,
00135       INT         = nrrdTypeInt,
00136       UINT        = nrrdTypeUInt,
00137       FLOAT       = nrrdTypeFloat,
00138       DOUBLE      = nrrdTypeDouble,
00139       BLOCK       = nrrdTypeBlock,
00140       TYPE_LAST   = nrrdTypeLast
00141    }; /////////////////////////////////////////////////
00142    ////////////////////////////////////////////////////
00143    /// Type of nrrd contained here.
00144    ///   From nrrdEnums.h, same as above
00145    /// You'll need this to get the correct iterator.
00146    int           getType()  const {if(_nrrd)return _nrrd->type; return UNKNOWN;}
00147    void          printType() const;
00148 
00149    ///@}
00150    /////////////////////////////////////////////////////
00151 
00152 
00153    ////////////////////////////////////////////////////
00154    ///@name  Read & Save
00155    ///@{
00156 
00157    ///read returns 0 if read, 1 if error
00158    /// proxy nrro's don't have data, just dimension and type info
00159    virtual int   readNrrd(const char *nrrdFileName, bool proxy = false);
00160    ///save returns 0 if read, 1 if error
00161    virtual int   saveNrrd(const char *nrrdFileName);
00162 
00163    ///@}
00164    ////////////////////////////////////////////////////
00165 
00166    //////////////////////////////////////////////////
00167    ///@name get/set the nrrd for direct nrrd hacking! 
00168    ///   Yummy, be very carefull here
00169    ///@{
00170    Nrrd*         getNrrd()  const {assert(_nrrd); return _nrrd;}
00171    void          setNrrd(Nrrd *n);
00172    ///@}
00173 
00174    //////////////////////////////////////////////////
00175    ///@name get the data for even more direct hacking um..
00176    ///@{
00177    void*         getData() const  {return _nrrd->data;}
00178    ///@}
00179 
00180    ////////////////////////////////////////////////////
00181    ///@name Dimensions & axis info
00182    ///@{
00183 
00184    /// how many axies does this object contain?
00185    int  dim() const              {return _nrrd->dim;}
00186    /// how many values along an axis?
00187    int  dim(int a) const         {return _nrrd->axis[a].size;}
00188    /// how many values are not from pading?
00189    int  dimNPad(int a) const     {return _pads[a].y - _pads[a].x + 1;}
00190    /// what is the physical length of the axis?
00191    float         axisSize(int a) const    {return float(dim(a)-1) * axisSpacing(a);}
00192    /// what is the physical length, ignoring paded values?
00193    float         axisSizeNPad(int a) const;
00194    /// what is the physical spacing between values along an axis
00195    float         axisSpacing(int a) const {return float(_nrrd->axis[a].spacing);}
00196    void          setAxisSpacing(int a, float s) {_nrrd->axis[a].spacing = s;}
00197    /// what is the name of the axis
00198    char*         axisName(int a) const    {return _nrrd->axis[a].label;}
00199    /// what are the units of the axis
00200    char*         axisUnit(int a) const    {return _nrrd->axis[a].unit;}
00201    /// ranges of unpadded values along an axis
00202    gutz::vec2ui  axisValNPad(int a) const {return _pads[a];}
00203    /// total size of data
00204    int  size() const;
00205    /// strides for accessing fast!
00206    int           getStride(int a) const   { return _strides[a]; }
00207    /// min/max values in nrro, r.x = min, r.y = max <nrroGinsu.cpp>
00208    gutz::vec2d   getMinMax() const { return _minmax; }
00209 
00210    ///@}
00211    ////////////////////////////////////////////////////
00212 
00213    ////////////////////////////////////////////////////
00214    ///@name Position & size
00215    /// only meaningfull if nrro has a spatial position & size
00216    ///@{
00217    gutz::vec3f   getPos() const           {return _pos;}
00218    void          setPos(gutz::vec3f pos)  {_pos = pos;}
00219    /// ignores padded part, doesn't work for time series 4D vols
00220    gutz::vec3f   getSizeV3() const;
00221    ///@}
00222 
00223    ////////////////////////////////////////////////////
00224    ////////////////////////////////////////////////////
00225    ///@name Ginsu : Slice and Dice 
00226    ///   see nrroGinsu.cpp
00227    ///@{
00228 
00229    ////////////////////////////////////////////////////
00230    /// Quantize, set min/max if you want to, otherwise
00231    ///   we'll figure out what they are
00232    gutz::SmartPtr<Nrro> quantize(int bits, double min = AIR_NAN, double max = AIR_NAN);
00233 
00234    ////////////////////////////////////////////////////
00235    /// slice, get a slice on axis at pos
00236    gutz::SmartPtr<Nrro>  slice(int axis, int pos);
00237 
00238    ////////////////////////////////////////////////////
00239    /// crop, 
00240    ///   set axis pos to -1 if you want it left unchanged
00241    gutz::SmartPtr<Nrro>  crop(int min[], int max[]);
00242 
00243    ////////////////////////////////////////////////////
00244    /// pad, pad out the volume.
00245    enum NRRO_BOUNDARY_BEHAVIORS{  //< what to do at the boundary when padding
00246       PAD   = nrrdBoundaryPad,    //< padd with a specified value
00247       BLEED = nrrdBoundaryBleed,  //< bleed boundary values
00248       WRAP  = nrrdBoundaryWrap    //< wrap to other side of axis
00249    }; 
00250    /// be sure that min and max are valid values, 
00251    ///  "-1" for min would pad back 1 voxel!!!!
00252    gutz::SmartPtr<Nrro>  pad(int min[], int max[], int bound = PAD, double padval = 0.0);
00253 
00254    ///////////////////////////////////////////////////
00255    /// pad and or crop to exact size
00256    gutz::SmartPtr<Nrro> cropPad(int min[], int max[], int bound = PAD, double padval = 0.0);
00257 
00258    ///////////////////////////////////////////////////
00259    /// resample. 
00260    /// if dims[1] == -1 leave the axis alone
00261    /// can use any kind of kernel, 
00262    /// if dims[i] == dim(i) than filter axis, but don't resize
00263    /// if typeOut == UKNOWN than output the same type of nrro
00264    gutz::SmartPtr<Nrro>  resample(int dims[], 
00265                                   const NrroKernel &kern = CatmulRomKernel,
00266                                   int bound = BLEED,
00267                                   int typeOut = UNKNOWN);
00268    gutz::SmartPtr<Nrro>  resample(float pct = 1.0f);
00269       
00270    ///////////////////////////////////////////////////
00271    /// insert axis
00272    int  insertAxis(unsigned int axis);   
00273 
00274    ///@}
00275    ////////////////////////////////////////////////////
00276 
00277    ////////////////////////////////////////////////////
00278    /// This makes all kinds of nrros multi-channel.
00279    /// - Images       3D: N channels + 2 spatial axes
00280    /// - Time Images  4D: N channels + 2 spatial + 1 time
00281    /// - Volumes      4D: N channels + 3 spatial axes
00282    /// - Time Volumes 5D: N channels + 3 spatial + 1 time
00283    /// - Unknown kinds are left alone. <nrroKind.cpp>
00284    int forceMultiChannel(); 
00285 
00286    ////////////////////////////////////////////////////
00287    ///@name Name 
00288    ///   like a comment, but, well, a name
00289    ///@{
00290    std::string   getName() const           {return _name;}
00291    void          setName(std::string name) {_name = name;}
00292    ///@}
00293 
00294    ////////////////////////////////////////////////////
00295    /// Print out what the nrro is, stderr right now
00296    void printInfo() const;
00297 
00298    ////////////////////////////////////////////////////
00299    ///@name comments
00300    ///  see nrroComment.cpp \n
00301    ///   can also be manipulated using "keys" which use
00302    ///   simple text strings as identifiers, 
00303    ///   This is how we extend the nrrd format, we save
00304    ///   things like the position, and pads in comments.
00305    ///  You must make sure key/comment pairs have valid
00306    ///  strings for both key and comment, if not, you
00307    ///  could get duplicate empty key/comment pairs
00308    ///@{
00309    int          numComments() const;
00310    std::string  getComment(int i);
00311    std::string  getComment(const std::string key);
00312    void         addComment(const std::string comment);
00313    void         addComment(const std::string key, const std::string comment);
00314    void         setComment(int i, const std::string comment);
00315    void         setComment(const std::string key, const std::string comment);
00316    ///@}
00317    
00318    /////////////////////////////////////////////////////
00319    /// ignore this class, it just represents a double
00320    /// for assignment.
00321    ///
00322    ///  This class represents un-typed data elements,
00323    /// local accessors [v() & ()] are pure doubles (LCD)
00324    /// they will be slow, you should use iterators for
00325    /// speed
00326    class __dbl {
00327    public:
00328       __dbl(Nrro *n, int pos) : _n(n), _pos(pos) {}
00329       ~__dbl(){}
00330       double operator=(const __dbl &vp);
00331       /// repeats, avoid upcast for simple assignments
00332       double         operator=(double v)          {return assn<double>(v);}
00333       float          operator=(float v)           {return assn<float>(v);}
00334       unsigned short operator=(unsigned short v)  {return assn<unsigned short>(v);}
00335       short          operator=(short v)           {return assn<short>(v);}
00336       unsigned int   operator=(unsigned int v)    {return assn<unsigned int>(v);}
00337       int            operator=(int v)             {return assn<int>(v);}
00338       char           operator=(char v)            {return assn<char>(v);}
00339       double         operator+=(double v)         {return assn<double>(val() + v);}
00340       double         operator-=(double v)         {return assn<double>(val() - v);}
00341       double         operator++()                 {return assn<double>(val() + 1);}
00342       double         operator--()                 {return assn<double>(val() - 1);}
00343       double         val() const;
00344       template<class T>
00345          T assn(T val);
00346       /// danger danger, auto typecast to double, fail safe
00347       operator double() const {return val();}
00348    protected:
00349       Nrro *_n;
00350       int   _pos;
00351    };
00352 
00353    /////////////////////////////////////////////////////
00354    ///@name Accessors.
00355    /// ()/v() access, use either v(), or operator(), 
00356    ///   they are the same thing. example: 
00357    /// \code
00358    /// Nrro n;  n(1,3,5) = n(3,1,5); /// set index[5][1][3] to value at index...
00359    /// \endcode
00360    /// or use the alias for clean looking SmartPointer code: 
00361    /// \code
00362    /// NrroSP n; n->v(1,3,5) = n->v(3,1,5); /// same as above
00363    /// \endcode
00364    /// you have accessors from 1 to 6 dimensions.
00365    /// remeber () access is fliped from c arrays (x,y,z) vs. [z][y][x]
00366    ///@{
00367    double v(int i1) const                        {return val<double>(i1);}
00368    double operator()(int i1) const               {return v(i1);}
00369    __dbl v(int i1)                               {return __dbl(this,i1);}
00370    __dbl operator()(int i1)                      {return v(i1);}
00371    double v(int i1, int i2) const                {return val<double>(a(i1, i2));}
00372    double operator()(int i1, int i2) const       {return v(i1, i2);}
00373    __dbl v(int i1, int i2)                       {return __dbl(this,a(i1,i2));}
00374    __dbl operator()(int i1, int i2)              {return v(i1,i2);}
00375    double v(int i1, int i2, int i3, int i4=0) const;
00376    double operator()(int i1, int i2, int i3, int i4=0) const {return v(i1,i2,i3,i4);}
00377    __dbl v(int i1, int i2, int i3, int i4=0); 
00378    __dbl operator()(int i1, int i2, int i3, int i4=0) {return v(i1,i2,i3,i4);} 
00379    double v(int i1, int i2, int i3, int i4, int i5, int i6=0) const;
00380    double operator()(int i1, int i2, int i3, int i4, int i5, int i6=0) const;
00381    __dbl v(int i1, int i2, int i3, int i4, int i5, int i6=0);
00382    __dbl operator()(int i1, int i2, int i3, int i4, int i5, int i6=0);
00383    template<class T>
00384    T val(int pos) const; //< const 1D value getter
00385    /// fast addressing
00386    int a(int i1, int i2=0) const                       {return i1 + i2*getStride(1);}
00387    int a(int i1,int i2, int i3, int i4=0) const;
00388    int a(int i1, int i2, int i3, int i4, int i5, int i6=0) const;
00389    ///@}
00390 
00391    ////////////////////////////////////////////////////
00392    /// Iterator, generic type, use gen functions
00393    /// TODO: need to make a const iterator too!, I think it works
00394    /// NOTE: this includes a -> that gives you the nrro
00395    /// so, this suffices as a typed nrro object. 
00396    /// NOTE: if you use an iterator internal to this object
00397    /// you shoud increment your ref count before use, then
00398    /// decrement after, to avoid having it nuke you!!!
00399    template<class T>
00400    class NrroIter {
00401    public:
00402       NrroIter(Nrro *n, int pos = 0);
00403       NrroIter(const NrroIter &ni);
00404       virtual ~NrroIter(){}
00405       T &operator*()                            {return *_d;}
00406       const T &operator*() const                {return *_d;}
00407       Nrro *operator->()                        {return _n.getPtr();}
00408       const Nrro *operator->() const            {return _n.getPtr();}
00409       NrroIter &operator=(const NrroIter &ni);  //< below
00410       NrroIter &operator=(int pos)              {_d = _n.getData() + pos;  return *this;}
00411       const NrroIter &operator+=(int dpos) const{_d += dpos; _pos += dpos; return *this;}
00412       NrroIter &operator+=(int dpos)            {_d += dpos; _pos += dpos; return *this;}
00413       const NrroIter &operator-=(int dpos) const{_d -= dpos; _pos -= dpos; return *this;}
00414       NrroIter &operator-=(int dpos)            {_d -= dpos; _pos -= dpos; return *this;}
00415       bool operator==(const NrroIter &ni) const;//< below
00416       bool operator!=(const NrroIter &ni) const {return (! (*this) == ni );}
00417       bool operator>(const NrroIter &ni) const  {return _pos > ni._pos;}
00418       bool operator<(const NrroIter &ni) const  {return _pos < ni._pos;}
00419       bool operator>=(const NrroIter &ni) const {return _pos >= ni._pos;}
00420       bool operator<=(const NrroIter &ni) const {return _pos <= ni._pos;}
00421       bool isValid() const                      
00422            {return ((_pos >= 0) && (_pos < int(_n->size())));}
00423       const NrroIter &operator++() const        {++_d; ++_pos; return *this;}
00424       NrroIter &operator++()                    {++_d; ++_pos; return *this;}
00425       const NrroIter  operator++(int) const     
00426            {NrroIter<T> tmp = *this; ++(*this); return tmp;}
00427       NrroIter  operator++(int)                 
00428            {NrroIter<T> tmp = *this; ++(*this); return tmp;}
00429       const NrroIter &operator--() const        {--_d; --_pos; return *this;}
00430       NrroIter &operator--()                    {--_d; --_pos; return *this;}
00431       const NrroIter  operator--(int) const     
00432            {NrroIter<T> tmp = *this; --*this; return tmp;}
00433       NrroIter  operator--(int)                 
00434            {NrroIter<T> tmp = *this; --*this; return tmp;}
00435       const NrroIter operator+(int dpos) const  
00436            {return NrroIter<T>(const_cast<Nrro*>(_n.getPtr()),_pos+dpos); } 
00437       NrroIter operator+(int dpos)              {return NrroIter<T>(_n,_pos+dpos); } 
00438       const NrroIter operator-(int dpos) const  
00439            {return NrroIter<T>(const_cast<Nrro*>(_n.getPtr()),_pos-dpos); }
00440       NrroIter operator-(int dpos)              {return NrroIter<T>(_n,_pos-dpos); }
00441       /// difference of Iterators
00442       int       operator-(const NrroIter &ni) const {return _pos - ni._pos; }
00443       /// this accesses in 1D from current Iterator position
00444       T        &operator[](int pos)             {return (*(*this + pos));}
00445       T         operator[](int pos) const       {return (*(*this + pos));}
00446       /// ()accessors are backwards from []ops, ie. (x,y,z,w) vs [w][z][y][x]
00447       /// they access from begining of nrro data array, not current iter pos
00448       T         operator()(int i1) const        {return ((T*)(_n->getData()))[i1];}
00449       T        &operator()(int i1)              {return ((T*)(_n->getData()))[i1];}
00450       T         operator()(int i1, int i2) const;
00451       T        &operator()(int i1, int i2);
00452       T         operator()(int i1, int i2, int i3, int i4=0) const;
00453       T        &operator()(int i1, int i2, int i3, int i4=0);
00454       T         operator()(int i1, int i2, int i3, int i4, int i5, int i6=0) const;
00455       T        &operator()(int i1, int i2, int i3, int i4, int i5, int i6=0);
00456       int       pos() const {return _pos;}
00457    protected:
00458       gutz::SmartPtr<Nrro> _n;
00459       mutable int    _pos;
00460       mutable T*     _d;
00461    private:
00462       NrroIter(); //not used
00463    };
00464 
00465    ////////////////////////////////////////////////////
00466    ///@name Get Iterators
00467    /// sorry but you have to explicitly ask for the right type:
00468    /// NrroIter<char> niter = nrro->begin<char>()
00469    /// see nrroDispatch.h for some short cuts to grabbing the right type
00470    ///@{
00471    template<class T>
00472       NrroIter<T> begin() { return NrroIter<T>(this, 0); }
00473    template<class T>
00474       NrroIter<T> last() { return NrroIter<T>(this, int(size())-1); }
00475    template<class T>
00476       const NrroIter<T> end() const { return NrroIter<T>(this,int(size())); }
00477    ///@}
00478 
00479    ////////////////////////////////////////////////////
00480    /// set the strides, for fast access, usually you won't have to 
00481    /// worry about this, when things change internally, this is 
00482    /// called automatically, if you muck with the dimensions yourself
00483    /// be sure to update the strides
00484    virtual void setStrides();
00485 
00486 
00487 protected:
00488    /// initiallize member variables
00489    virtual void initMembers();
00490    /// erase the nrrd and other stuff
00491    virtual void erase();
00492    /// copy a nrro object
00493    virtual void copy(const Nrro &n);
00494    /// send a real error message
00495    inline
00496       void NrroErr(const char *s, const char *s2=0) const;
00497    /// message for debugging purposes
00498    inline
00499       void NrroDbg(const char *s, const char *s2=0) const;
00500 
00501    ////////////////////////////////////////////////////
00502    /// Extended features: <nrroExtended.cpp>
00503    /// this next one updates the extended nrrd format
00504    /// by adding things like pos and pads to the comments
00505    /// these can be read in with the nrro after it has
00506    /// been saved. These don't actually write the nrro
00507    /// to disk, they just update the comment fields
00508    virtual void    readExtended();
00509    virtual void    writeExtended();
00510 
00511    ////////////////////////////////
00512    ///  DATA
00513    ////////////////////////////////
00514 
00515    /// the nrrd struct, from teem
00516    Nrrd  *_nrrd;
00517 
00518    ////////////////////////////////
00519    ///  Extended format data
00520    ///  see <nrroExtended.cpp>
00521    ////////////////////////////////
00522 
00523    /// Symantics - Kind of Nrro 
00524    int    _kind;
00525    virtual void writeKind();
00526    virtual void readKind();
00527 
00528    /// if padded, where is the "real" data
00529    gutz::arrayo1v2ui _pads;
00530    virtual void writePads();
00531    virtual void readPads();
00532 
00533    /// what is the spatial position of this data,
00534    /// may not always be relevant
00535    gutz::vec3f  _pos;
00536    virtual void writePos();
00537    virtual void readPos();
00538 
00539    /// does he have a name
00540    std::string _name;
00541    virtual void writeName();
00542    virtual void readName();
00543 
00544    ////////////////////////////////
00545    ///  Other data
00546    ///  just some stuff we need to
00547    ///  keep track of while the 
00548    ///  nrro is in use
00549    ////////////////////////////////
00550 
00551    /// strides for easy/fast access
00552    int    _strides[MAX_NRRO_ARRAY_DIM];
00553 
00554    /// does this guy actuall contain something usefull?
00555    bool   _valid;
00556    bool   _modified;
00557 
00558    /// original file name
00559    std::string _fileName;
00560 
00561    /// cache some slow to compute, but likely static 
00562    /// values
00563    void updateMinMax();
00564    gutz::vec2d   _minmax; //< min and max values in double
00565    unsigned int  _size;   //< total # of elements
00566 private:
00567 
00568 };
00569 
00570 //////////////////////////////////////////////////////////////////////////
00571 /// Pre defined containers
00572 //////////////////////////////////////////////////////////////////////////
00573 
00574 typedef gutz::SmartPtr<Nrro>          NrroSP;
00575 typedef std::vector<NrroSP>           NrroSPVec;
00576 typedef std::vector<NrroSP>::iterator NrroSPVecIter;
00577 
00578 //////////////////////////////////////////////////////////////////////////
00579 /// Extended format keys, <nrroExtended.cpp>
00580 //////////////////////////////////////////////////////////////////////////
00581 extern const std::string NRRO_KIND_KEY;
00582 extern const std::string NRRO_PADS_KEY;
00583 extern const std::string NRRO_POS_KEY;
00584 extern const std::string NRRO_NAME_KEY;
00585 
00586 //////////////////////////////////////////////////////////////////////////
00587 //////////////////////////////////////////////////////////////////////////
00588 /// some implementation
00589 //////////////////////////////////////////////////////////////////////////
00590 //////////////////////////////////////////////////////////////////////////
00591 /// send a real error message
00592 inline
00593 void Nrro::NrroErr(const char *s, const char *s2) const
00594 {
00595    std::cerr << " -";
00596    if(!_name.empty())
00597       std::cerr << _name;
00598    else
00599       std::cerr << "Un-named Nrro";
00600    std::cerr << std::endl;
00601 
00602    std::cerr << "Error, Nrro::" << s;
00603    if(s2) std::cerr << " : " << s2;
00604    std::cerr << std::endl;
00605 }
00606 /// message for debugging purposes
00607 inline
00608 void Nrro::NrroDbg(const char *s, const char *s2) const
00609 {
00610 #ifdef _DEBUG
00611    std::cerr << " -";
00612    if(!_name.empty())
00613       std::cerr << _name;
00614    else
00615       std::cerr << "Un-named Nrro";
00616    std::cerr << std::endl;
00617 
00618    std::cerr << "Debug, Nrro::" << s;
00619    if(s2) std::cerr << " : " << s2;
00620    std::cerr << std::endl;
00621 #endif
00622 }
00623 
00624 //////////////////////////////////////////////////////////////////////////
00625 //////////////////////////////////////////////////////////////////////////
00626 /// Public inlines
00627 //////////////////////////////////////////////////////////////////////////
00628 //////////////////////////////////////////////////////////////////////////
00629 
00630 //////////////////////////////////////////////////////////////////////////
00631 /// Accessors
00632 //////////////////////////////////////////////////////////////////////////
00633 
00634 template <class T>
00635 inline 
00636 T Nrro::val(int pos) const //< 1D value getter
00637 {
00638    switch(getType())
00639    {
00640    case Nrro::CHAR:
00641       return T( ( ((char*)getData())[pos] ) );
00642       break;
00643    case Nrro::UCHAR:
00644       return T( ( ((unsigned char*)getData())[pos] ) );
00645       break;
00646    case Nrro::SHORT:
00647       return T( ( ((short*)getData())[pos] ) );
00648       break;
00649    case Nrro::USHORT:
00650       return T( ( ((unsigned short*)getData())[pos] ) );
00651       break;
00652    case Nrro::INT:
00653       return T( ( ((int*)getData())[pos]) );
00654       break;
00655    case Nrro::UINT:
00656       return T( ( ((unsigned int*)getData())[pos] ) );
00657       break;
00658    case Nrro::FLOAT:
00659       return T( ( ((float*)getData())[pos] ) );
00660       break;
00661    case Nrro::DOUBLE:
00662       return T( ( ((double*)getData())[pos] ) );
00663       break;
00664    }
00665    return 0.0;
00666 }
00667 
00668 inline
00669 int Nrro::a(int i1,int i2, int i3, int i4) const
00670 {
00671    return a(i1,i2) + i3*getStride(2) + i4*getStride(3);
00672 }
00673 
00674 inline
00675 double Nrro::v(int i1, int i2, int i3, int i4) const
00676 {
00677    return val<double>(a(i1,i2,i3,i4));
00678 }
00679 
00680 inline
00681 Nrro::__dbl Nrro::v(int i1, int i2, int i3, int i4)
00682 {
00683    return __dbl(this,a(i1,i2,i3,i4));
00684 }
00685 
00686 inline
00687 int Nrro::a(int i1, int i2, int i3, int i4, int i5, int i6) const
00688 {
00689    return a(i1,i2,i3,i4) + i5*getStride(4) + i6*getStride(5);
00690 }
00691 
00692 inline
00693 double Nrro::v(int i1, int i2, int i3, int i4, int i5, int i6) const
00694 {
00695    return val<double>(a(i1,i2,i3,i4,i5,i6));
00696 }
00697 
00698 inline
00699 Nrro::__dbl Nrro::v(int i1, int i2, int i3, int i4, int i5, int i6)
00700 {
00701    return __dbl(this,a(i1,i2,i3,i4,i5,i6));
00702 }
00703 
00704 inline
00705 double Nrro::operator()(int i1, int i2, int i3, int i4, int i5, int i6) const
00706 {
00707    return v(i1,i2,i3,i4,i5,i6);
00708 }
00709 
00710 inline
00711 Nrro::__dbl Nrro::operator()(int i1, int i2, int i3, int i4, int i5, int i6)
00712 {
00713    return v(i1,i2,i3,i4,i5,i6);
00714 }
00715 
00716 //////////////////////////////////////////////////////////////////////////
00717 /// value proxy
00718 //////////////////////////////////////////////////////////////////////////
00719 inline
00720 double Nrro::__dbl::val() const
00721 {
00722    return _n->val<double>(_pos);
00723 }
00724 
00725 inline
00726 double Nrro::__dbl::operator=(const __dbl &vp)
00727 {
00728    return operator=(vp.val());
00729 }
00730 
00731 /// here is why I bothered to template this:
00732 /// if you maybe know the type, you can assign it without
00733 /// an upcast and then a down cast, for instance:
00734 /// n.assn<char>(10); /// the nrro has char data
00735 /// this is just a minor speed issue, 
00736 /// but probably worth the effort.
00737 /// TODO: use arrays of pointers instead of switches!!!
00738 template<class T>
00739 inline
00740 T Nrro::__dbl::assn(T val)
00741 {
00742    ///Yuk, you are doing this switch every assignment!!,
00743    /// and access too for that matter, slow slow.
00744    switch(_n->getType())
00745    {
00746    case Nrro::CHAR:
00747       /// to type cast reslut to requested type <class T>..
00748       /// cast (void*) data ptr to the real data type ptr,
00749       /// increment position to where it needs to be,
00750       /// de-reference ptr, and assign the value.
00751       /// cast reslut to <class T>
00752       /// castT( (dref((cast to (real)) + offset) ) = val)
00753       return T( (*( ((char*)_n->getData()) + _pos) ) = (char)val );
00754       break;
00755    case Nrro::UCHAR:
00756       return T((*(((char*)_n->getData()) + _pos)) = (char)val);
00757       break;
00758    case Nrro::SHORT:
00759       return T((*(((short*)_n->getData()) + _pos)) = (short)val);
00760       break;
00761    case Nrro::USHORT:
00762       return T((*(((unsigned short*)_n->getData()) + _pos)) = (unsigned short)val);
00763       break;
00764    case Nrro::INT:
00765       return T((*(((int*)_n->getData()) + _pos)) = (int)val);
00766       break;
00767    case Nrro::UINT:
00768       return T((*(((unsigned int*)_n->getData()) + _pos)) = (unsigned int)val);
00769       break;
00770    case Nrro::FLOAT:
00771       return T((*(((float*)_n->getData()) + _pos)) = (float)val);
00772       break;
00773    case Nrro::DOUBLE:
00774       return T((*(((double*)_n->getData()) + _pos)) = val);
00775       break;
00776    }
00777    return val;
00778 }
00779 
00780 //////////////////////////////////////////////////////////////////////////
00781 /// Iterator implementation
00782 //////////////////////////////////////////////////////////////////////////
00783 template<class T>
00784 Nrro::NrroIter<T>::
00785 NrroIter(Nrro *n, int pos)
00786 : _pos(pos), _n(gutz::SmartPtr<Nrro>(n))
00787 {
00788    if(!n)
00789    {
00790       std::cerr << "NrroIter::NrroIter(), null nrro!!!" << std::endl;
00791       _d = 0;
00792    }
00793    else
00794    {
00795       _d = (T*)(n->getData());
00796    }
00797 }
00798 
00799 template<class T>
00800 Nrro::NrroIter<T>::
00801 NrroIter(const NrroIter &ni)
00802 : _d(ni._d), _pos(ni._pos), _n(ni._n)
00803 {}
00804 
00805 template<class T>
00806 Nrro::NrroIter<T> &Nrro::NrroIter<T>::
00807 operator=(const NrroIter<T> &ni)
00808 {
00809    _d = ni._d;
00810    _n = ni._n;
00811    _pos = ni._pos;
00812    return this;
00813 }
00814 
00815 template<class T>
00816 bool Nrro::NrroIter<T>::
00817 operator==(const NrroIter<T> &ni) const
00818 {
00819    if(ni._pos != _pos) return false;
00820    if(ni._n != _n) return false;
00821    return true;
00822 }
00823 
00824 template<class T>
00825 inline
00826 T &Nrro::NrroIter<T>::
00827 operator()(int i1, int i2, int i3, int i4, int i5, int i6)
00828 {
00829    return ((T*)(_n->getData()))[ _n->a(i1,i2,i3,i4,i5,i6) ];
00830 }
00831 
00832 template<class T>
00833 inline
00834 T Nrro::NrroIter<T>::
00835 operator()(int i1, int i2, int i3, int i4, int i5, int i6) const
00836 {
00837    return ((T*)(_n->getData()))[ _n->a(i1,i2,i3,i4,i5,i6) ];
00838 }
00839 
00840 template<class T>
00841 inline
00842 T &Nrro::NrroIter<T>::
00843 operator()(int i1, int i2)
00844 {
00845    return ((T*)(_n->getData()))[ _n->a(i1,i2) ];
00846 }
00847 
00848 template<class T>
00849 inline
00850 T Nrro::NrroIter<T>::
00851 operator()(int i1, int i2) const
00852 {
00853    return ((T*)(_n->getData()))[ _n->a(i1,i2) ];
00854 }
00855 
00856 template<class T>
00857 inline
00858 T &Nrro::NrroIter<T>::
00859 operator()(int i1, int i2, int i3, int i4)
00860 {
00861    return *(((T*)(_n->getData()))+_n->a(i1,i2,i3,i4)); 
00862 }
00863 
00864 template<class T>
00865 inline
00866 T Nrro::NrroIter<T>::
00867 operator()(int i1, int i2, int i3, int i4) const
00868 {
00869    return *(((T*)(_n->getData())) + _n->a(i1,i2,i3,i4)); 
00870 }
00871 
00872 //template<class T, int TYPEENUM>
00873 //const NrroIter<T> end() const;
00874 
00875 #endif
00876 

Send questions, comments, and bug reports to:
jmk