easy-iso

Iso-surface extraction from volume data
git clone https://git.0xfab.ch/easy-iso.git
Log | Files | Refs | Submodules | README | LICENSE

Matrix3D.h (5273B)


      1 // File       : Matrix3D.h
      2 // Date       : Wed Nov 23 14:45:22 2016
      3 // Author     : Fabian Wermelinger
      4 // Description: 3D Matrix
      5 // Copyright 2016 ETH Zurich. All Rights Reserved.
      6 #ifndef MATRIX3D_H_L9MVKQGE
      7 #define MATRIX3D_H_L9MVKQGE
      8 
      9 #include <cassert>
     10 #include <cstdlib>
     11 #include <cstddef>
     12 #include <cstring>
     13 #include <iostream>
     14 
     15 template <typename T, int XS=0, int XE=0, int YS=0, int YE=0, int ZS=0, int ZE=0>
     16 class Matrix3D
     17 {
     18 public:
     19     static constexpr int XSTART = XS;
     20     static constexpr int XEND   = XE;
     21     static constexpr int YSTART = YS;
     22     static constexpr int YEND   = YE;
     23     static constexpr int ZSTART = ZS;
     24     static constexpr int ZEND   = ZE;
     25 
     26     Matrix3D() : m_Nx(0), m_Ny(0), m_Nz(0), m_allocated(false), m_data(nullptr) { }
     27 
     28     Matrix3D(const int Nx, const int Ny, const int Nz, const T* const data = nullptr) :
     29         m_Nx(0), m_Ny(0), m_Nz(0), m_allocated(false), m_data(nullptr)
     30     {
     31         alloc(Nx, Ny, Nz, data);
     32     }
     33 
     34     Matrix3D(const Matrix3D& rhs) :
     35         m_Nx(0), m_Ny(0), m_Nz(0), m_allocated(false), m_data(nullptr)
     36     {
     37         if (rhs.m_allocated)
     38         {
     39             m_data = _alloc(rhs.m_Nx, rhs.m_Ny, rhs.m_Nz);
     40             _copy(rhs.m_data);
     41         }
     42     }
     43 
     44     Matrix3D(Matrix3D&& rhs) :
     45         m_Nx(rhs.m_Nx), m_Ny(rhs.m_Ny), m_Nz(rhs.m_Nz),
     46         m_XS(rhs.m_XS), m_XE(rhs.m_XE), m_Xpitch(rhs.m_Xpitch), m_Npitched(rhs.m_Npitched),
     47         m_allocated(rhs.m_allocated), m_data(std::move(rhs.m_data))
     48     { }
     49 
     50     ~Matrix3D() { if (m_allocated) free(m_data); }
     51 
     52     Matrix3D& operator=(const Matrix3D& rhs)
     53     {
     54         if (this != &rhs)
     55         {
     56             _reset();
     57             if (rhs.m_allocated)
     58             {
     59                 m_data = _alloc(rhs.m_Nx, rhs.m_Ny, rhs.m_Nz);
     60                 _copy(rhs.m_data);
     61             }
     62         }
     63         return *this;
     64     }
     65 
     66     Matrix3D& operator=(Matrix3D&& rhs)
     67     {
     68         if (this != &rhs)
     69         {
     70             _reset();
     71             if (rhs.m_allocated)
     72             {
     73                 m_Nx = rhs.m_Nx;
     74                 m_Ny = rhs.m_Ny;
     75                 m_Nz = rhs.m_Nz;
     76                 m_XS = rhs.m_XS;
     77                 m_XE = rhs.m_XE;
     78                 m_Xpitch = rhs.m_Xpitch;
     79                 m_Npitched = rhs.m_Npitched;
     80                 m_allocated = rhs.m_allocated;
     81                 m_data = std::move(rhs.m_data);
     82                 rhs.m_allocated = false;
     83             }
     84         }
     85         return *this;
     86     }
     87 
     88     T operator()(const int ix, const int iy, const int iz) const
     89     {
     90         assert(m_allocated);
     91         assert(ix >= XS && ix < m_Nx+XE);
     92         assert(iy >= YS && iy < m_Ny+YE);
     93         assert(iz >= ZS && iz < m_Nz+ZE);
     94         return m_data[(ix-XS) + m_Xpitch*(iy-YS) + m_Xpitch*(m_Ny+YE-YS)*(iz-ZS)];
     95     }
     96 
     97     T& operator()(const int ix, const int iy, const int iz)
     98     {
     99         assert(m_allocated);
    100         assert(ix >= XS && ix < m_Nx+XE);
    101         assert(iy >= YS && iy < m_Ny+YE);
    102         assert(iz >= ZS && iz < m_Nz+ZE);
    103         return m_data[(ix-XS) + m_Xpitch*(iy-YS) + m_Xpitch*(m_Ny+YE-YS)*(iz-ZS)];
    104     }
    105 
    106     inline void alloc(const int Nx, const int Ny, const int Nz, const T* const data = nullptr)
    107     {
    108         if (m_allocated) free(m_data);
    109         m_data = _alloc(Nx, Ny, Nz);
    110 
    111         if (data)
    112         {
    113             for (int iz = 0; iz < m_Nz; ++iz)
    114                 for (int iy = 0; iy < m_Ny; ++iy)
    115                     {
    116                         const T* const src = data + m_Nx*iy + m_Nx*m_Ny*iz;
    117                         T* dst = &(this->operator()(0,iy,iz));
    118                         memcpy(dst, src, m_Nx*sizeof(T));
    119                     }
    120         }
    121     }
    122 
    123     inline int Nx() const { return m_Nx; }
    124     inline int Ny() const { return m_Ny; }
    125     inline int Nz() const { return m_Nz; }
    126 
    127 private:
    128     int m_Nx;
    129     int m_Ny;
    130     int m_Nz;
    131     int m_XS, m_XE, m_Xpitch;
    132     size_t m_Npitched;
    133     bool m_allocated;
    134     T* m_data;
    135 
    136     inline T* _alloc(const int Nx, const int Ny, const int Nz)
    137     {
    138         m_Nx = Nx;
    139         m_Ny = Ny;
    140         m_Nz = Nz;
    141         const int alignedElements = _ALIGN_/sizeof(T);
    142         m_XS = alignedElements * ((XS - (alignedElements-1))/alignedElements);
    143         m_XE = alignedElements * ((XE + (alignedElements-1))/alignedElements);
    144         m_Xpitch = m_Nx+m_XE-m_XS;
    145         m_Npitched = static_cast<size_t>(m_Xpitch) * static_cast<size_t>(m_Ny+YE-YS) * static_cast<size_t>(m_Nz+ZE-ZS);
    146 
    147         void* pmem;
    148         if (posix_memalign(&pmem, _ALIGN_, m_Npitched*sizeof(T)))
    149         {
    150             std::cerr << "ERROR: Matrix3D: can not allocate memory" << std::endl;
    151             abort();
    152         }
    153         memset(pmem, 0, m_Npitched*sizeof(T));
    154         m_allocated = true;
    155         return (T*)pmem;
    156     }
    157 
    158     inline void _copy(const T* const base)
    159     {
    160         const size_t Nslice = static_cast<size_t>(m_Xpitch) * (m_Ny+YE-YS);
    161         for (int iz = 0; iz < m_Nz+ZE-ZS; ++iz)
    162         {
    163             const T* const src = base + Nslice*iz;
    164             T* dst = m_data + Nslice*iz;
    165             memcpy(dst, src, Nslice*sizeof(T));
    166         }
    167     }
    168 
    169     inline void _reset()
    170     {
    171         if (m_allocated) free(m_data);
    172         m_Nx = m_Ny = m_Nz = m_XS = m_XE = m_Xpitch = m_Npitched = 0;
    173         m_allocated = false;
    174         m_data = nullptr;
    175     }
    176 };
    177 
    178 #endif /* MATRIX3D_H_L9MVKQGE */