00001 #ifndef OPENTISSUE_CORE_CONTAINERS_GRID_GRID_H
00002 #define OPENTISSUE_CORE_CONTAINERS_GRID_GRID_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/containers/grid/util/grid_iterators.h>
00013 #include <OpenTissue/utility/utility_copy.h>
00014 #include <OpenTissue/core/math/math_constants.h>
00015
00016 #include <cmath>
00017 #include <limits>
00018 #include <cassert>
00019 #include <algorithm>
00020
00021 namespace OpenTissue
00022 {
00023 namespace grid
00024 {
00025 template < typename T, typename math_types_ >
00026 class Grid
00027 {
00028 public:
00029
00030 typedef OpenTissue::grid::Grid<T, math_types_> grid_type;
00031 typedef T value_type;
00032 typedef math_types_ math_types;
00033
00034 typedef typename math_types::index_vector3_type index_vector;
00035
00036 typedef OpenTissue::grid::detail::Iterator< grid_type, value_type &, value_type *> iterator;
00037 typedef OpenTissue::grid::detail::Iterator< const grid_type, value_type const &, value_type const *> const_iterator;
00038
00039 typedef OpenTissue::grid::detail::IndexIterator< grid_type, value_type &, value_type *> index_iterator;
00040 typedef OpenTissue::grid::detail::IndexIterator< const grid_type, value_type const &, value_type const *> const_index_iterator;
00041
00042 protected:
00043
00044 typedef typename math_types::vector3_type vector3_type;
00045 typedef typename math_types::real_type real_type;
00046 typedef typename math_types::value_traits value_traits;
00047
00048 protected:
00049
00050 vector3_type m_min_coord;
00051 vector3_type m_max_coord;
00052 size_t m_N;
00053 size_t m_I;
00054 size_t m_J;
00055 size_t m_K;
00056 vector3_type m_delta;
00057 value_type * m_value;
00058 value_type * m_value_end;
00059 value_type m_infinity;
00060
00061 public:
00062
00063 iterator begin() { return iterator( this, m_value ); }
00064 const_iterator begin() const { return const_iterator( this, m_value ); }
00065 iterator end() { return iterator( this, m_value_end ); }
00066 const_iterator end() const { return const_iterator( this, m_value_end ); }
00067
00068 Grid()
00069 : m_min_coord(value_traits::zero(),value_traits::zero(),value_traits::zero())
00070 , m_max_coord(value_traits::zero(),value_traits::zero(),value_traits::zero())
00071 , m_N(0)
00072 , m_I(0)
00073 , m_J(0)
00074 , m_K(0)
00075 , m_delta(value_traits::zero(),value_traits::zero(),value_traits::zero())
00076 , m_value(0)
00077 , m_value_end(0)
00078 , m_infinity( math::detail::highest<T>() )
00079 {}
00080
00086 Grid(value_type const & unused_val)
00087 : m_min_coord(value_traits::zero(),value_traits::zero(),value_traits::zero())
00088 , m_max_coord(value_traits::zero(),value_traits::zero(),value_traits::zero())
00089 , m_I(0)
00090 , m_J(0)
00091 , m_K(0)
00092 , m_delta(value_traits::zero(),value_traits::zero(),value_traits::zero())
00093 , m_value(0)
00094 , m_value_end(0)
00095 {
00096 m_infinity = unused_val;
00097 }
00098
00099 Grid(grid_type const & G)
00100 : m_min_coord(value_traits::zero(),value_traits::zero(),value_traits::zero())
00101 , m_max_coord(value_traits::zero(),value_traits::zero(),value_traits::zero())
00102 , m_I(0)
00103 , m_J(0)
00104 , m_K(0)
00105 , m_delta(value_traits::zero(),value_traits::zero(),value_traits::zero())
00106 , m_value(0)
00107 , m_value_end(0)
00108 , m_infinity( G.unused() )
00109 {
00110 *this = G;
00111 }
00112
00113 ~Grid()
00114 {
00115 if(m_value)
00116 delete [] m_value;
00117 }
00118
00119 grid_type & operator=(grid_type const & G)
00120 {
00121 bool should_allocate = false;
00122
00123 if(m_I != G.m_I)
00124 should_allocate = true;
00125 if(m_J != G.m_J)
00126 should_allocate = true;
00127 if(m_K != G.m_K)
00128 should_allocate = true;
00129
00130 if(should_allocate)
00131 create(G.m_min_coord, G.m_max_coord, G.m_I, G.m_J, G.m_K);
00132
00133 OpenTissue::utility::copy(G.begin(), G.end(), begin());
00134
00135 return (*this);
00136 }
00137
00138 public:
00139
00150 void create(
00151 vector3_type const & min_coord
00152 , vector3_type const & max_coord
00153 , size_t const & Ival
00154 , size_t const & Jval
00155 , size_t const & Kval
00156 )
00157 {
00158 size_t new_size = Ival*Jval*Kval;
00159
00160 if(m_N != new_size && m_value)
00161 {
00162 delete [] m_value;
00163 m_value = 0;
00164 }
00165 m_I = Ival;
00166 m_J = Jval;
00167 m_K = Kval;
00168 m_N = new_size;
00169 m_min_coord = min_coord;
00170 m_max_coord = max_coord;
00171 m_delta(0) = (m_max_coord(0)-m_min_coord(0))/(m_I-1);
00172 m_delta(1) = (m_max_coord(1)-m_min_coord(1))/(m_J-1);
00173 m_delta(2) = (m_max_coord(2)-m_min_coord(2))/(m_K-1);
00174 if(!m_value)
00175 {
00176 std::cout << "-- OpenTissue::Grid::Create() : Trying to allocate " << m_I << "x" << m_J << "x" << m_K << " map of size " << m_N*sizeof(T) << " bytes... ";
00177 m_value = new T[m_N];
00178 m_value_end = m_value+m_N;
00179 std::cout << "Success!" << std::endl;
00180 }
00181 clear();
00182 }
00183
00194 void create(
00195 size_t I_val
00196 , size_t J_val
00197 , size_t K_val
00198 , real_type dx_val
00199 , real_type dy_val
00200 , real_type dz_val
00201 )
00202 {
00203 using std::max;
00204
00205 real_type w = I_val * dx_val / value_traits::two();
00206 real_type h = J_val * dy_val / value_traits::two();
00207 real_type d = K_val * dz_val / value_traits::two();
00208 vector3_type min_coord_value( -w, -h, -d );
00209 vector3_type max_coord_value( w, h, d );
00210
00211 real_type factor = max( w, max( h, d ) );
00212
00213 min_coord_value /= factor;
00214 max_coord_value /= factor;
00215
00216 create( min_coord_value, max_coord_value, I_val, J_val, K_val );
00217 }
00218
00222 void clear()
00223 {
00224 assert(m_value || !"Grid::clear(): data value pointer was NULL");
00225 std::fill(begin(), end(), m_infinity);
00226 }
00227
00228 void set_spacing(real_type const & new_dx, real_type const & new_dy, real_type const & new_dz)
00229 {
00230 real_type span_x = (m_I-1) * new_dx;
00231 m_max_coord(0) = span_x / value_traits::two();
00232 m_min_coord(0) = -m_max_coord(0);
00233 m_delta(0) = new_dx;
00234
00235 real_type span_y = (m_J-1)*new_dy;
00236 m_max_coord(1) = span_y/value_traits::two();
00237 m_min_coord(1) = -m_max_coord(1);
00238 m_delta(1) = new_dy;
00239
00240 real_type span_z = (m_K-1)*new_dz;
00241 m_max_coord(2) = span_z/value_traits::two();
00242 m_min_coord(2) = -m_max_coord(2);
00243 m_delta(2) = new_dz;
00244 }
00245
00246 public:
00247
00248 value_type & get_value(size_t const & i, size_t const & j, size_t const & k) const
00249 {
00250 int ii = (i%m_I);
00251 if(ii<0)
00252 ii += m_I;
00253 int jj = (j%m_J);
00254 if(jj<0)
00255 jj += m_J;
00256 int kk = (k%m_K);
00257 if(kk<0)
00258 kk += m_K;
00259 long idx = (kk*m_J + jj)*m_I + ii;
00260 return m_value[idx];
00261 }
00262
00263 value_type & get_value(size_t const & linear_index) const
00264 {
00265 assert(linear_index>=0 || !"Grid::get_value(): index was out of range");
00266 assert(linear_index<this->size() || !"Grid::get_value(): index was out of range");
00267 return m_value[linear_index];
00268 }
00269
00270 value_type & operator() (size_t const & i,size_t const & j,size_t const & k) { return this->get_value(i,j,k); }
00271 value_type const & operator() (size_t const & i,size_t const & j,size_t const & k) const { return this->get_value(i,j,k); }
00272
00273 value_type & operator() (size_t const & linear_index) { return this->get_value( linear_index ); }
00274 value_type const & operator() (size_t const & linear_index) const { return this->get_value( linear_index ); }
00275
00276 value_type & operator() (index_vector const& iv) { return this->get_value( iv(0), iv(1), iv(2) ); }
00277
00278 value_type const & operator() (index_vector const& iv) const { return this->get_value( iv(0), iv(1), iv(2) ); }
00279
00280
00281 real_type width() const { return m_max_coord(0) - m_min_coord(0); }
00282 real_type height() const { return m_max_coord(1) - m_min_coord(1); }
00283 real_type depth() const { return m_max_coord(2) - m_min_coord(2); }
00284
00285 real_type & dx() { return m_delta(0); }
00286 real_type & dy() { return m_delta(1); }
00287 real_type & dz() { return m_delta(2); }
00288
00289 real_type const & dx() const { return m_delta(0); }
00290 real_type const & dy() const { return m_delta(1); }
00291 real_type const & dz() const { return m_delta(2); }
00292
00293 size_t I() const { return m_I; }
00294 size_t J() const { return m_J; }
00295 size_t K() const { return m_K; }
00296 size_t size() const { return m_N; }
00297
00298 vector3_type const & min_coord() const { return m_min_coord; }
00299 vector3_type const & max_coord() const { return m_max_coord; }
00300 real_type const & min_coord(size_t const & idx) const { return m_min_coord(idx); }
00301 real_type const & max_coord(size_t const & idx) const { return m_max_coord(idx); }
00302
00303 value_type unused() const { return m_infinity; }
00304
00305 value_type infinity() const { return m_infinity; }
00306
00307 bool valid() const { return (m_value!=0); }
00308
00309 bool empty() const { return ( size()==0 ); }
00310
00311 value_type * data() { return m_value; }
00312
00313 value_type const * data() const { return m_value; }
00314
00315 };
00316
00324 template< typename T, typename M >
00325 T min_element(OpenTissue::grid::Grid<T,M> const & G)
00326 {
00327 T const * value = G.data();
00328 T min_value = OpenTissue::math::detail::highest<T>();
00329 for(size_t idx=0; idx<G.size(); ++idx, ++value)
00330 {
00331 if( *value!=G.unused() && *value<min_value )
00332 min_value = *value;
00333 }
00334 return min_value;
00335 }
00336
00344 template< typename T, typename M >
00345 T max_element(OpenTissue::grid::Grid<T,M> const & G)
00346 {
00347 T const * value = G.data();
00348 T max_value = OpenTissue::math::detail::lowest<T>();
00349
00350 for(size_t idx=0;idx<G.size();++idx,++value)
00351 {
00352 if(*value!=G.unused() && *value>max_value)
00353 max_value = *value;
00354 }
00355 return max_value;
00356 }
00357
00366 template<typename T, typename M>
00367 Grid<T,M> & fabs(Grid<T,M> & G)
00368 {
00369 using std::fabs;
00370
00371 T * value = G.data();
00372 for(size_t idx=0;idx<G.size();++idx,++value)
00373 {
00374 if(*value!=G.unused())
00375 *value = fabs(*value);
00376 }
00377 return G;
00378 }
00379
00390 template<typename T,typename M>
00391 Grid<T,M> & negate(Grid<T,M> & G)
00392 {
00393 T * value = G.data();
00394 for(size_t idx=0;idx<G.size();++idx,++value)
00395 {
00396 if(*value!=G.unused())
00397 *value = -(*value);
00398 }
00399 return G;
00400 }
00401
00402 template<typename T,typename M>
00403 Grid<T,M> & scale(Grid<T,M> & G, T fac)
00404 {
00405 T * value = G.data();
00406 for(size_t idx=0;idx<G.size();++idx,++value)
00407 {
00408 if(*value!=G.unused())
00409 *value = fac*(*value);
00410 }
00411 return G;
00412 }
00413
00414 }
00415 }
00416
00417
00418 #endif