00001
00002
00003
00004
00005
00006
00007 #ifndef BALL_DATATYPE_REGULARDATA3D_H
00008 #define BALL_DATATYPE_REGULARDATA3D_H
00009
00010 #ifndef BALL_MATHS_VECTOR3_H
00011 # include <BALL/MATHS/vector3.h>
00012 #endif
00013
00014 #ifndef BALL_SYSTEM_FILE_H
00015 # include <BALL/SYSTEM/file.h>
00016 #endif
00017
00018 #ifndef BALL_MATHS_COMMON_H
00019 # include <BALL/MATHS/common.h>
00020 #endif
00021
00022 #include <iostream>
00023 #include <fstream>
00024 #include <iterator>
00025 #include <algorithm>
00026
00027 namespace BALL
00028 {
00042 template <typename ValueType>
00043 class TRegularData3D
00044 {
00045 public:
00046
00047 BALL_CREATE(TRegularData3D<ValueType>)
00048
00049
00052
00054 class IndexType
00055 {
00056 public:
00057 inline IndexType() : x(0), y(0), z(0) {}
00058 inline IndexType(Position p) : x(p), y(p), z(p) {}
00059 inline IndexType(Position p, Position q, Position r) : x(p), y(q), z(r) {}
00060
00062 Position x;
00064 Position y;
00066 Position z;
00067 };
00068
00070 typedef std::vector<ValueType> VectorType;
00072 typedef TVector3<float> CoordinateType;
00074 typedef typename std::vector<ValueType>::iterator Iterator;
00076 typedef typename std::vector<ValueType>::const_iterator ConstIterator;
00078
00079
00080
00081 typedef ValueType value_type;
00082 typedef typename std::vector<ValueType>::iterator iterator;
00083 typedef typename std::vector<ValueType>::const_iterator const_iterator;
00084 typedef typename std::vector<ValueType>::reference reference;
00085 typedef typename std::vector<ValueType>::const_reference const_reference;
00086 typedef typename std::vector<ValueType>::pointer pointer;
00087 typedef typename std::vector<ValueType>::difference_type difference_type;
00088 typedef typename std::vector<ValueType>::size_type size_type;
00089
00093
00097 TRegularData3D();
00098
00101 TRegularData3D(const TRegularData3D<ValueType>& grid)
00102 throw(Exception::OutOfMemory);
00103
00106 TRegularData3D(const CoordinateType& origin, const CoordinateType& dimension, const CoordinateType& spacing)
00107 throw(Exception::OutOfMemory);
00108
00111 TRegularData3D(const CoordinateType& origin, const CoordinateType& x_axis,
00112 const CoordinateType& y_axis, const CoordinateType& z_axis, const IndexType& size)
00113 throw(Exception::OutOfMemory);
00114
00117 TRegularData3D
00118 (const IndexType& size,
00119 const CoordinateType& origin = CoordinateType(0.0),
00120 const CoordinateType& dimension = CoordinateType(1.0))
00121 throw(Exception::OutOfMemory);
00122
00125 virtual ~TRegularData3D();
00126
00130 virtual void clear();
00132
00136
00140 TRegularData3D& operator = (const TRegularData3D<ValueType>& data)
00141 throw(Exception::OutOfMemory);
00143
00144
00148
00154 bool operator == (const TRegularData3D<ValueType>& grid) const;
00155
00158 BALL_INLINE bool operator != (const TRegularData3D<ValueType>& grid) const { return !this->operator == (grid); }
00159
00161 BALL_INLINE bool empty() const { return data_.empty(); }
00162
00164 bool isInside(const CoordinateType& r) const;
00166
00168 BALL_INLINE bool isOrthogonal() const { return is_orthogonal_;}
00169
00173
00174 BALL_INLINE ConstIterator begin() const { return data_.begin(); }
00176 BALL_INLINE ConstIterator end() const { return data_.end(); }
00178 BALL_INLINE Iterator begin() { return data_.begin(); }
00180 BALL_INLINE Iterator end() { return data_.end(); }
00182
00186
00187
00188 BALL_INLINE size_type size() const { return data_.size(); }
00189 BALL_INLINE size_type max_size() const { return data_.max_size(); }
00190 BALL_INLINE void swap(TRegularData3D<ValueType>& grid) { std::swap(*this, grid); }
00191
00192
00194 const vector<ValueType>& getData() const;
00195
00199 const ValueType& getData(const IndexType& index) const
00200 throw(Exception::OutOfGrid);
00201
00205 ValueType& getData(const IndexType& index)
00206 throw(Exception::OutOfGrid);
00207
00211 const ValueType& getData(Position index) const
00212 throw(Exception::OutOfGrid);
00213
00217 ValueType& getData(Position index)
00218 throw(Exception::OutOfGrid);
00219
00224 const ValueType& operator [] (const IndexType& index) const
00225 {
00226 return data_[index.x + size_.x * index.y + index.z * size_.x * size_.y];
00227 }
00228
00233 ValueType& operator [] (const IndexType& index)
00234 {
00235 return data_[index.x + size_.x * index.y + index.z * size_.x * size_.y];
00236 }
00237
00242 const ValueType& operator [] (Position index) const { return data_[index]; }
00243
00248 ValueType& operator [] (Position index) { return data_[index]; }
00249
00260 ValueType operator () (const CoordinateType& x) const;
00261
00267 ValueType getInterpolatedValue(const CoordinateType& x) const
00268 throw(Exception::OutOfGrid);
00269
00275 const ValueType& getClosestValue(const CoordinateType& x) const
00276 throw(Exception::OutOfGrid);
00277
00283 ValueType& getClosestValue(const CoordinateType& x)
00284 throw(Exception::OutOfGrid);
00285
00291 IndexType getClosestIndex(const CoordinateType& v) const
00292 throw(Exception::OutOfGrid);
00293
00298 IndexType getLowerIndex(const CoordinateType& v) const
00299 throw(Exception::OutOfGrid);
00300
00306 inline const IndexType& getSize() const { return size_; }
00307
00312 inline const CoordinateType& getOrigin() const { return origin_; }
00313
00318 const CoordinateType& getSpacing() const { return spacing_; }
00321 void setOrigin(const CoordinateType& origin) { origin_ = origin; }
00322
00328 const CoordinateType& getDimension() const { return dimension_; }
00329
00338 void setDimension(const CoordinateType& dimension)
00339 {
00340 dimension_ = dimension;
00341 if (is_orthogonal_)
00342 {
00343 spacing_.x = dimension_.x / (double)(size_.x - 1);
00344 spacing_.y = dimension_.y / (double)(size_.y - 1);
00345 spacing_.z = dimension_.z / (double)(size_.z - 1);
00346 }
00347 }
00348
00363 void resize(const IndexType& size)
00364 throw(Exception::OutOfMemory);
00365
00377 void rescale(const IndexType& new_size)
00378 throw(Exception::OutOfMemory);
00379
00384 CoordinateType getCoordinates(const IndexType& index) const
00385 throw(Exception::OutOfGrid);
00386
00391 CoordinateType getCoordinates(Position index) const
00392 throw(Exception::OutOfGrid);
00393
00409 void getEnclosingIndices
00410 (const CoordinateType& r,
00411 Position& llf, Position& rlf, Position& luf, Position& ruf,
00412 Position& llb, Position& rlb, Position& lub, Position& rub) const
00413 throw(Exception::OutOfGrid);
00414
00418 void getEnclosingValues
00419 (const CoordinateType& r,
00420 ValueType& llf, ValueType& rlf, ValueType& luf, ValueType& ruf,
00421 ValueType& llb, ValueType& rlb, ValueType& lub, ValueType& rub) const
00422 throw(Exception::OutOfGrid);
00423
00427 ValueType calculateMean() const;
00428
00432 ValueType calculateSD() const;
00433
00438 void binaryWrite(const String& filename) const
00439 throw(Exception::FileNotFound);
00440
00447 void binaryWriteRaw(const String& filename) const
00448 throw(Exception::FileNotFound);
00449
00454 void binaryRead(const String& filename)
00455 throw(Exception::FileNotFound);
00457
00458 protected:
00459
00461 const CoordinateType mapToCartesian_(CoordinateType r) const
00462 {
00463 Vector3 result;
00464 r.x /= (size_.x - 1.);
00465 r.y /= (size_.y - 1.);
00466 r.z /= (size_.z - 1.);
00467
00468 result.x = mapping_[0] * r.x + mapping_[1] * r.y + mapping_[2] * r.z + origin_.x;
00469 result.y = mapping_[3] * r.x + mapping_[4] * r.y + mapping_[5] * r.z + origin_.y;
00470 result.z = mapping_[6] * r.x + mapping_[7] * r.y + mapping_[8] * r.z + origin_.z;
00471
00472 return result;
00473 }
00474
00476 const CoordinateType mapInverse_(CoordinateType r) const
00477 {
00478 r -= origin_;
00479
00480 Vector3 result;
00481 result.x = inverse_mapping_[0] * r.x + inverse_mapping_[1] * r.y + inverse_mapping_[2] * r.z;
00482 result.y = inverse_mapping_[3] * r.x + inverse_mapping_[4] * r.y + inverse_mapping_[5] * r.z;
00483 result.z = inverse_mapping_[6] * r.x + inverse_mapping_[7] * r.y + inverse_mapping_[8] * r.z;
00484
00485 result.x *= (size_.x - 1);
00486 result.y *= (size_.y - 1);
00487 result.z *= (size_.z - 1);
00488
00489 return result;
00490 }
00491
00493 VectorType data_;
00494
00496 CoordinateType origin_;
00497
00499 CoordinateType dimension_;
00500
00502 CoordinateType spacing_;
00503
00505 IndexType size_;
00506
00508 typedef struct { ValueType bt[1024]; } BlockValueType;
00509
00511 bool is_orthogonal_;
00512
00514 std::vector<double> mapping_;
00515 std::vector<double> inverse_mapping_;
00516 };
00517
00520 typedef TRegularData3D<float> RegularData3D;
00521
00522
00523 template <class ValueType>
00524 TRegularData3D<ValueType>::TRegularData3D()
00525 : data_(0),
00526 origin_(0.0),
00527 dimension_(0.0),
00528 spacing_(1.0),
00529 size_(0, 0, 0),
00530 is_orthogonal_(true)
00531 {
00532 }
00533
00534
00535 template <class ValueType>
00536 TRegularData3D<ValueType>::TRegularData3D
00537 (const TRegularData3D<ValueType>& data)
00538 throw(Exception::OutOfMemory)
00539 : data_(),
00540 origin_(data.origin_),
00541 dimension_(data.dimension_),
00542 spacing_(data.spacing_),
00543 size_(data.size_),
00544 is_orthogonal_(data.is_orthogonal_),
00545 mapping_(data.mapping_),
00546 inverse_mapping_(data.inverse_mapping_)
00547 {
00548 try
00549 {
00550 data_ = data.data_;
00551 }
00552 catch (std::bad_alloc&)
00553 {
00554 data_.resize(0);
00555 throw Exception::OutOfMemory(__FILE__, __LINE__, data.data_.size() * sizeof(ValueType));
00556 }
00557 }
00558
00559 template <class ValueType>
00560 TRegularData3D<ValueType>::TRegularData3D
00561 (const typename TRegularData3D<ValueType>::IndexType& size,
00562 const typename TRegularData3D<ValueType>::CoordinateType& origin,
00563 const typename TRegularData3D<ValueType>::CoordinateType& dimension)
00564 throw(Exception::OutOfMemory)
00565 : data_(),
00566 origin_(origin),
00567 dimension_(dimension),
00568 spacing_(0.0),
00569 size_(size),
00570 is_orthogonal_(true)
00571 {
00572
00573 spacing_.x = dimension_.x / (double)(size_.x - 1);
00574 spacing_.y = dimension_.y / (double)(size_.y - 1);
00575 spacing_.z = dimension_.z / (double)(size_.z - 1);
00576
00577
00578 size_type number_of_points = size_.x * size_.y * size_.z;
00579 try
00580 {
00581 data_.resize(number_of_points);
00582 }
00583 catch (std::bad_alloc&)
00584 {
00585 data_.resize(0);
00586 throw Exception::OutOfMemory(__FILE__, __LINE__, number_of_points * sizeof(ValueType));
00587 }
00588 }
00589
00590
00591 template <class ValueType>
00592 TRegularData3D<ValueType>::TRegularData3D
00593 (const typename TRegularData3D<ValueType>::CoordinateType& origin,
00594 const typename TRegularData3D<ValueType>::CoordinateType& dimension,
00595 const typename TRegularData3D<ValueType>::CoordinateType& spacing)
00596 throw(Exception::OutOfMemory)
00597 : data_(),
00598 origin_(origin),
00599 dimension_(dimension),
00600 spacing_(spacing),
00601 size_(0),
00602 is_orthogonal_(true)
00603 {
00604
00605 size_.x = (Size)(dimension_.x / spacing_.x + 0.5) + 1;
00606 size_.y = (Size)(dimension_.y / spacing_.y + 0.5) + 1;
00607 size_.z = (Size)(dimension_.z / spacing_.z + 0.5) + 1;
00608
00609
00610 size_type size = size_.x * size_.y * size_.z;
00611 try
00612 {
00613 data_ .resize(size);
00614 }
00615 catch (std::bad_alloc&)
00616 {
00617 data_.resize(0);
00618 throw Exception::OutOfMemory(__FILE__, __LINE__, size * sizeof(ValueType));
00619 }
00620
00621
00622 spacing_.x = dimension_.x / (double)(size_.x - 1);
00623 spacing_.y = dimension_.y / (double)(size_.y - 1);
00624 spacing_.z = dimension_.z / (double)(size_.z - 1);
00625 }
00626
00627 template <class ValueType>
00628 TRegularData3D<ValueType>::TRegularData3D
00629 (const typename TRegularData3D<ValueType>::CoordinateType& origin,
00630 const typename TRegularData3D<ValueType>::CoordinateType& x_axis,
00631 const typename TRegularData3D<ValueType>::CoordinateType& y_axis,
00632 const typename TRegularData3D<ValueType>::CoordinateType& z_axis,
00633 const typename TRegularData3D<ValueType>::IndexType& new_size)
00634 throw(Exception::OutOfMemory)
00635 : data_(),
00636 origin_(origin),
00637 dimension_(x_axis+y_axis+z_axis),
00638 spacing_(0.0),
00639 size_(new_size),
00640 is_orthogonal_(false)
00641 {
00642
00643 spacing_.x = x_axis.getLength() / (new_size.x - 1.);
00644 spacing_.y = y_axis.getLength() / (new_size.y - 1.);
00645 spacing_.z = z_axis.getLength() / (new_size.z - 1.);
00646
00647 size_type size = size_.x * size_.y * size_.z;
00648 try
00649 {
00650 data_.resize(size);
00651 }
00652 catch (std::bad_alloc&)
00653 {
00654 data_.resize(0);
00655 throw Exception::OutOfMemory(__FILE__, __LINE__, size * sizeof(ValueType));
00656 }
00657
00658
00659 mapping_.resize(9);
00660 inverse_mapping_.resize(9);
00661
00662 mapping_[0] = x_axis.x; mapping_[1] = y_axis.x; mapping_[2] = z_axis.x;
00663 mapping_[3] = x_axis.y; mapping_[4] = y_axis.y; mapping_[5] = z_axis.y;
00664 mapping_[6] = x_axis.z; mapping_[7] = y_axis.z; mapping_[8] = z_axis.z;
00665
00666
00667
00668
00669
00670 double a = mapping_[0]; double b = mapping_[1]; double c = mapping_[2];
00671 double d = mapping_[3]; double e = mapping_[4]; double f = mapping_[5];
00672 double g = mapping_[6]; double h = mapping_[7]; double i = mapping_[8];
00673
00674 double determinant = 1. / (a*(e*i - f*h) - b*(d*i - f*g) + c*(d*h - e*g));
00675
00676 inverse_mapping_[0] = determinant * (e*i - f*h);
00677 inverse_mapping_[1] = determinant * (b*i - c*h);
00678 inverse_mapping_[2] = determinant * (b*f - c*e);
00679
00680 inverse_mapping_[3] = determinant * (f*g - d*i);
00681 inverse_mapping_[4] = determinant * (a*i - c*g);
00682 inverse_mapping_[5] = determinant * (c*d - a*f);
00683
00684 inverse_mapping_[6] = determinant * (d*h - e*g);
00685 inverse_mapping_[7] = determinant * (b*g - a*h);
00686 inverse_mapping_[8] = determinant * (a*e - b*d);
00687 }
00688
00689 template <class ValueType>
00690 TRegularData3D<ValueType>::~TRegularData3D()
00691 {
00692 }
00693
00694 template <typename ValueType>
00695 BALL_INLINE
00696 TRegularData3D<ValueType>& TRegularData3D<ValueType>::operator =
00697 (const TRegularData3D<ValueType>& rhs)
00698 throw(Exception::OutOfMemory)
00699 {
00700
00701 if (&rhs != this)
00702 {
00703
00704
00705 origin_ = rhs.origin_;
00706 dimension_ = rhs.dimension_;
00707 spacing_ = rhs.spacing_;
00708 size_ = rhs.size_;
00709
00710 is_orthogonal_ = rhs.is_orthogonal_;
00711 mapping_ = rhs.mapping_;
00712 inverse_mapping_ = rhs.inverse_mapping_;
00713
00714 try
00715 {
00716 data_ = rhs.data_;
00717 }
00718 catch (std::bad_alloc&)
00719 {
00720 data_.resize(0);
00721 throw Exception::OutOfMemory(__FILE__, __LINE__, rhs.data_.size() * sizeof(ValueType));
00722 }
00723 }
00724
00725 return *this;
00726 }
00727
00728 template <typename ValueType>
00729 void TRegularData3D<ValueType>::resize(const typename TRegularData3D<ValueType>::IndexType& size)
00730 throw(Exception::OutOfMemory)
00731 {
00732 if (is_orthogonal_)
00733 {
00734
00735 if ((size.x == size_.x) && (size_.y == size.y) && (size_.z == size.z))
00736 {
00737 return;
00738 }
00739
00740
00741 if ((size.x == 0) || (size.y == 0) || (size.z == 0))
00742 {
00743 data_.resize(0);
00744 dimension_.set(0.0, 0.0, 0.0);
00745 return;
00746 }
00747
00748 size_type new_size = (size_type)(size.x * size.y * size.z);
00749
00750
00751 try
00752 {
00753
00754 std::vector<ValueType> old_data(data_);
00755
00756
00757 data_.resize(new_size);
00758
00759
00760 static ValueType default_value = (ValueType)0;
00761 for (size_type i = 0; i < new_size; i++)
00762 {
00763 size_type x = i % size.x;
00764 size_type y = (i % (size.x * size.y)) / size.x;
00765 size_type z = i / (size.x * size.y);
00766 if ((x >= size_.x) || (y >= size_.y) || (z >= size_.z))
00767 {
00768 data_[i] = default_value;
00769 }
00770 else
00771 {
00772 data_[i] = old_data[x + y * size_.x + z * size_.x * size_.y];
00773 }
00774 }
00775
00776
00777 if ((size_.x != 0) && (size_.y != 0) && (size_.z != 0))
00778 {
00779 dimension_.x *= (double)size.x / (double)size_.x;
00780 dimension_.y *= (double)size.y / (double)size_.y;
00781 dimension_.z *= (double)size.z / (double)size_.z;
00782 }
00783 size_ = size;
00784 }
00785 catch (std::bad_alloc&)
00786 {
00787 throw Exception::OutOfMemory(__FILE__, __LINE__, new_size * (Size)sizeof(ValueType));
00788 }
00789 }
00790 }
00791
00792 template <typename ValueType>
00793 void TRegularData3D<ValueType>::rescale(const typename TRegularData3D<ValueType>::IndexType& size)
00794 throw(Exception::OutOfMemory)
00795 {
00796 if (is_orthogonal_)
00797 {
00798
00799 if ((size.x == size_.x) && (size_.y == size.y) && (size_.z == size.z))
00800 {
00801 return;
00802 }
00803
00804
00805 if ((size.x == 0) || (size.y == 0) || (size.z == 0))
00806 {
00807 data_.resize(0);
00808 dimension_.set(0.0);
00809 return;
00810 }
00811
00812
00813 size_type new_size = (size_type)(size.x * size.y * size.z);
00814
00815
00816 try
00817 {
00818
00819 TRegularData3D<ValueType> old_data(*this);
00820
00821
00822 data_.resize(new_size);
00823 spacing_.x = dimension_.x / (double)(size.x - 1);
00824 spacing_.y = dimension_.y / (double)(size.y - 1);
00825 spacing_.z = dimension_.z / (double)(size.z - 1);
00826
00827
00828 size_ = size;
00829
00830
00831 for (size_type i = 0; i < data_.size(); i++)
00832 {
00833 try
00834 {
00835 data_[i] = old_data.getInterpolatedValue(getCoordinates(i));
00836 }
00837 catch (Exception::OutOfGrid&)
00838 {
00839 data_[i] = old_data.getClosestValue(getCoordinates(i));
00840 }
00841 }
00842 }
00843 catch (std::bad_alloc&)
00844 {
00845 throw Exception::OutOfMemory(__FILE__, __LINE__, new_size * (Size)sizeof(ValueType));
00846 }
00847 }
00848 }
00849
00850 template <class ValueType>
00851 BALL_INLINE
00852 bool TRegularData3D<ValueType>::isInside(const typename TRegularData3D<ValueType>::CoordinateType& r) const
00853 {
00854 if (is_orthogonal_)
00855 {
00856 return !((r.x > (origin_.x + dimension_.x ))
00857 || (r.y > (origin_.y + dimension_.y))
00858 || (r.z > (origin_.z + dimension_.z))
00859 || (r.x < origin_.x) || (r.y < origin_.y) || (r.z < origin_.z));
00860 }
00861 else
00862 {
00863
00864 CoordinateType ri = mapInverse_(r);
00865 ri.x = Maths::round(ri.x);
00866 ri.y = Maths::round(ri.y);
00867 ri.z = Maths::round(ri.z);
00868
00869 return !( (ri.x < 0) || (ri.y < 0) || (ri.z < 0)
00870 || (ri.x >= size_.x) || (ri.y >= size_.y) || (ri.z >= size_.z) );
00871 }
00872 }
00873
00874 template <class ValueType>
00875 BALL_INLINE
00876 const ValueType& TRegularData3D<ValueType>::getData
00877 (const typename TRegularData3D<ValueType>::IndexType& index) const
00878 throw(Exception::OutOfGrid)
00879 {
00880 size_type pos = index.x + index.y * size_.x + index.z * size_.x * size_.y;
00881 if (pos >= data_.size())
00882 {
00883 throw Exception::OutOfGrid(__FILE__, __LINE__);
00884 }
00885 return data_[pos];
00886 }
00887
00888 template <class ValueType>
00889 BALL_INLINE
00890 const vector<ValueType>& TRegularData3D<ValueType>::getData() const
00891 {
00892 return data_;
00893 }
00894
00895 template <typename ValueType>
00896 BALL_INLINE
00897 ValueType& TRegularData3D<ValueType>::getData
00898 (const typename TRegularData3D<ValueType>::IndexType& index)
00899 throw(Exception::OutOfGrid)
00900 {
00901 size_type pos = index.x + index.y * size_.x + index.z * size_.x * size_.y;
00902 if (pos >= data_.size())
00903 {
00904 throw Exception::OutOfGrid(__FILE__, __LINE__);
00905 }
00906 return data_[pos];
00907 }
00908
00909 template <class ValueType>
00910 BALL_INLINE
00911 const ValueType& TRegularData3D<ValueType>::getData(Position index) const
00912 throw(Exception::OutOfGrid)
00913 {
00914 if (index >= data_.size())
00915 {
00916 throw Exception::OutOfGrid(__FILE__, __LINE__);
00917 }
00918 return data_[index];
00919 }
00920
00921 template <class ValueType>
00922 BALL_INLINE
00923 ValueType& TRegularData3D<ValueType>::getData(Position index)
00924 throw(Exception::OutOfGrid)
00925 {
00926 if (index >= data_.size())
00927 {
00928 throw Exception::OutOfGrid(__FILE__, __LINE__);
00929 }
00930 return data_[index];
00931 }
00932
00933 template <class ValueType>
00934 BALL_INLINE
00935 typename TRegularData3D<ValueType>::CoordinateType TRegularData3D<ValueType>::getCoordinates
00936 (const typename TRegularData3D<ValueType>::IndexType& index) const
00937 throw(Exception::OutOfGrid)
00938 {
00939 if ((index.x >= size_.x) || (index.y >= size_.y) || (index.z >= size_.z))
00940 {
00941 throw Exception::OutOfGrid(__FILE__, __LINE__);
00942 }
00943
00944 if (is_orthogonal_)
00945 {
00946 CoordinateType r(origin_.x + index.x * spacing_.x,
00947 origin_.y + index.y * spacing_.y,
00948 origin_.z + index.z * spacing_.z);
00949 return r;
00950 }
00951 else
00952 {
00953 CoordinateType r(index.x, index.y, index.z);
00954 r = mapToCartesian_(r);
00955
00956 return r;
00957 }
00958 }
00959
00960 template <class ValueType>
00961 BALL_INLINE
00962 typename TRegularData3D<ValueType>::CoordinateType
00963 TRegularData3D<ValueType>::getCoordinates(Position position) const
00964 throw(Exception::OutOfGrid)
00965 {
00966 if (position >= data_.size())
00967 {
00968 throw Exception::OutOfGrid(__FILE__, __LINE__);
00969 }
00970
00971 Position x = (Position)(position % size_.x);
00972 Position y = (Position)((position % (size_.x * size_.y))/ size_.x);
00973 Position z = (Position)(position / (size_.x * size_.y));
00974
00975 if (is_orthogonal_)
00976 {
00977 return CoordinateType(origin_.x + (double)x * spacing_.x,
00978 origin_.y + (double)y * spacing_.y,
00979 origin_.z + (double)z * spacing_.z);
00980 }
00981 else
00982 {
00983 CoordinateType r(x,y,z);
00984 r = mapToCartesian_(r);
00985
00986 return r;
00987 }
00988 }
00989
00990 template <typename ValueType>
00991 BALL_INLINE
00992 void TRegularData3D<ValueType>::getEnclosingIndices
00993 (const typename TRegularData3D<ValueType>::CoordinateType& r,
00994 Position& llf, Position& rlf, Position& luf, Position& ruf,
00995 Position& llb, Position& rlb, Position& lub, Position& rub) const
00996 throw(Exception::OutOfGrid)
00997 {
00998 if (!isInside(r))
00999 {
01000 throw Exception::OutOfGrid(__FILE__, __LINE__);
01001 }
01002
01003
01004
01005 IndexType position;
01006 if (is_orthogonal_)
01007 {
01008 position.x = (Position)((r.x - origin_.x) / spacing_.x);
01009 position.y = (Position)((r.y - origin_.y) / spacing_.y);
01010 position.z = (Position)((r.z - origin_.z) / spacing_.z);
01011 }
01012 else
01013 {
01014 CoordinateType pos = mapInverse_(r);
01015 position.x = (Position) pos.x;
01016 position.y = (Position) pos.y;
01017 position.z = (Position) pos.z;
01018 }
01019
01020
01021
01022 llf = position.x + size_.x * position.y
01023 + size_.x * size_.y * position.z;
01024 rlf = llf + 1;
01025 luf = llf + size_.x;
01026 ruf = luf + 1;
01027 llb = llf + size_.x * size_.y;
01028 rlb = llb + 1;
01029 lub = llb + size_.x;
01030 rub = lub + 1;
01031 }
01032
01033 template <typename ValueType>
01034 BALL_INLINE
01035 void TRegularData3D<ValueType>::getEnclosingValues
01036 (const typename TRegularData3D<ValueType>::CoordinateType& r,
01037 ValueType& llf, ValueType& rlf, ValueType& luf, ValueType& ruf,
01038 ValueType& llb, ValueType& rlb, ValueType& lub, ValueType& rub) const
01039 throw(Exception::OutOfGrid)
01040 {
01041 if (!isInside(r))
01042 {
01043 throw Exception::OutOfGrid(__FILE__, __LINE__);
01044 }
01045
01046
01047 Position llf_idx, rlf_idx, luf_idx, ruf_idx, llb_idx, rlb_idx, lub_idx, rub_idx;
01048 getEnclosingIndices(r, llf_idx, rlf_idx, luf_idx, ruf_idx, llb_idx, rlb_idx, lub_idx, rub_idx);
01049
01050
01051 llf = data_[llf_idx];
01052 rlf = data_[rlf_idx];
01053 luf = data_[luf_idx];
01054 ruf = data_[ruf_idx];
01055 llb = data_[llb_idx];
01056 rlb = data_[rlb_idx];
01057 lub = data_[lub_idx];
01058 rub = data_[rub_idx];
01059 }
01060
01061 template <typename ValueType>
01062 BALL_INLINE
01063 ValueType TRegularData3D<ValueType>::getInterpolatedValue
01064 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01065 throw(Exception::OutOfGrid)
01066 {
01067 if (!isInside(r))
01068 {
01069 throw Exception::OutOfGrid(__FILE__, __LINE__);
01070 }
01071 return operator () (r);
01072 }
01073
01074 template <typename ValueType>
01075 BALL_INLINE
01076 ValueType TRegularData3D<ValueType>::operator ()
01077 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01078 {
01079 Position x;
01080 Position y;
01081 Position z;
01082 TVector3<double> r_0;
01083
01084 if (is_orthogonal_)
01085 {
01086 Vector3 h(r - origin_);
01087
01088 x = (Position)(h.x / spacing_.x);
01089 y = (Position)(h.y / spacing_.y);
01090 z = (Position)(h.z / spacing_.z);
01091
01092 while (x >= (size_.x - 1)) x--;
01093 while (y >= (size_.y - 1)) y--;
01094 while (z >= (size_.z - 1)) z--;
01095
01096 r_0.x = origin_.x + x*spacing_.x;
01097 r_0.y = origin_.y + y*spacing_.y;
01098 r_0.z = origin_.z + z*spacing_.z;
01099 }
01100 else
01101 {
01102 Vector3 pos = mapInverse_(r);
01103 x = (Position) pos.x;
01104 y = (Position) pos.y;
01105 z = (Position) pos.z;
01106
01107 while (x >= (size_.x - 1)) x--;
01108 while (y >= (size_.y - 1)) y--;
01109 while (z >= (size_.z - 1)) z--;
01110
01111
01112 Vector3 lower_pos(x,y,z);
01113 lower_pos = mapToCartesian_(lower_pos);
01114 r_0.x = lower_pos.x;
01115 r_0.y = lower_pos.y;
01116 r_0.z = lower_pos.z;
01117 }
01118
01119 Position Nx = size_.x;
01120 Position Nxy = size_.y * Nx;
01121 Position l = x + Nx * y + Nxy * z;
01122
01123 double dx = 1. - ((double)(r.x - r_0.x) / spacing_.x);
01124 double dy = 1. - ((double)(r.y - r_0.y) / spacing_.y);
01125 double dz = 1. - ((double)(r.z - r_0.z) / spacing_.z);
01126
01127 return data_[l] * dx * dy * dz
01128 + data_[l + 1] * (1. - dx) * dy * dz
01129 + data_[l + Nx] * dx * (1. - dy) * dz
01130 + data_[l + Nx + 1] * (1. - dx) * (1. - dy) * dz
01131 + data_[l + Nxy] * dx * dy * (1. - dz)
01132 + data_[l + Nxy + 1] * (1. - dx) * dy * (1. - dz)
01133 + data_[l + Nxy + Nx] * dx * (1. - dy) * (1. - dz)
01134 + data_[l + Nxy + Nx + 1] * (1. - dx) * (1. - dy) * (1. - dz);
01135 }
01136
01137 template <typename ValueType>
01138 BALL_INLINE
01139 typename TRegularData3D<ValueType>::IndexType TRegularData3D<ValueType>::getClosestIndex
01140 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01141 throw(Exception::OutOfGrid)
01142 {
01143 if (!isInside(r))
01144 {
01145 throw Exception::OutOfGrid(__FILE__, __LINE__);
01146 }
01147
01148 static IndexType position;
01149
01150 if (is_orthogonal_)
01151 {
01152 position.x = (Position)((r.x - origin_.x) / spacing_.x + 0.5);
01153 position.y = (Position)((r.y - origin_.y) / spacing_.y + 0.5);
01154 position.z = (Position)((r.z - origin_.z) / spacing_.z + 0.5);
01155 }
01156 else
01157 {
01158 Vector3 pos = mapInverse_(r);
01159 position.x = (Position) Maths::round(pos.x);
01160 position.y = (Position) Maths::round(pos.y);
01161 position.z = (Position) Maths::round(pos.z);
01162 }
01163
01164 return position;
01165 }
01166
01167 template <typename ValueType>
01168 BALL_INLINE
01169 typename TRegularData3D<ValueType>::IndexType TRegularData3D<ValueType>::getLowerIndex
01170 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01171 throw(Exception::OutOfGrid)
01172 {
01173 if (!isInside(r))
01174 {
01175 throw Exception::OutOfGrid(__FILE__, __LINE__);
01176 }
01177
01178 static IndexType position;
01179 if (is_orthogonal_)
01180 {
01181 position.x = (Position)((r.x - origin_.x) / spacing_.x);
01182 position.y = (Position)((r.y - origin_.y) / spacing_.y);
01183 position.z = (Position)((r.z - origin_.z) / spacing_.z);
01184 }
01185 else
01186 {
01187 Vector3 pos = mapInverse_(r);
01188 position.x = (Position)pos.x;
01189 position.y = (Position)pos.y;
01190 position.z = (Position)pos.z;
01191 }
01192
01193 return position;
01194 }
01195
01196 template <typename ValueType>
01197 BALL_INLINE
01198 const ValueType& TRegularData3D<ValueType>::getClosestValue
01199 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01200 throw(Exception::OutOfGrid)
01201 {
01202 if (!isInside(r))
01203 {
01204 throw Exception::OutOfGrid(__FILE__, __LINE__);
01205 }
01206
01207 static IndexType position;
01208
01209 if (is_orthogonal_)
01210 {
01211 position.x = (Position)((r.x - origin_.x) / spacing_.x + 0.5);
01212 position.y = (Position)((r.y - origin_.y) / spacing_.y + 0.5);
01213 position.z = (Position)((r.z - origin_.z) / spacing_.z + 0.5);
01214 }
01215 else
01216 {
01217 static Vector3 pos = mapInverse_(r);
01218 position.x = (Position) Maths::round(pos.x);
01219 position.y = (Position) Maths::round(pos.y);
01220 position.z = (Position) Maths::round(pos.z);
01221 }
01222
01223 return operator [] (position);
01224 }
01225
01226 template <typename ValueType>
01227 BALL_INLINE
01228 ValueType& TRegularData3D<ValueType>::getClosestValue
01229 (const typename TRegularData3D<ValueType>::CoordinateType& r)
01230 throw(Exception::OutOfGrid)
01231 {
01232 if (!isInside(r))
01233 {
01234 throw Exception::OutOfGrid(__FILE__, __LINE__);
01235 }
01236
01237 static IndexType position;
01238
01239 if (is_orthogonal_)
01240 {
01241 position.x = (Position)((r.x - origin_.x) / spacing_.x + 0.5);
01242 position.y = (Position)((r.y - origin_.y) / spacing_.y + 0.5);
01243 position.z = (Position)((r.z - origin_.z) / spacing_.z + 0.5);
01244 }
01245 else
01246 {
01247 static Vector3 pos = mapInverse_(r);
01248 position.x = (Position) Maths::round(pos.x);
01249 position.y = (Position) Maths::round(pos.y);
01250 position.z = (Position) Maths::round(pos.z);
01251 }
01252
01253
01254 return operator [] (position);
01255 }
01256
01257 template <typename ValueType>
01258 BALL_INLINE
01259 ValueType TRegularData3D<ValueType>::calculateMean() const
01260 {
01261 Position data_points = (size_.x * size_.y * size_.z);
01262 ValueType mean = 0;
01263 for (Position i = 0; i < data_points; i++)
01264 {
01265 mean += data_[i];
01266 }
01267 mean /= data_points;
01268 return mean;
01269 }
01270
01271 template <typename ValueType>
01272 BALL_INLINE
01273 ValueType TRegularData3D<ValueType>::calculateSD() const
01274 {
01275 Position data_points = (size_.x * size_.y * size_.z);
01276 ValueType stddev = 0;
01277 ValueType mean = this->calculateMean();
01278 for (Position i = 0; i < data_points; i++)
01279 {
01280 stddev += (pow(data_[i]-mean,2));
01281 }
01282 stddev /= (data_points-1);
01283 stddev = sqrt(stddev);
01284 return stddev;
01285 }
01286
01287 template <typename ValueType>
01288 void TRegularData3D<ValueType>::clear()
01289 {
01290 data_.resize(0);
01291
01292 origin_.set(0.0);
01293 dimension_.set(0.0);
01294 size_.x = 0;
01295 size_.y = 0;
01296 size_.z = 0;
01297 spacing_.set(1.0);
01298 is_orthogonal_ = true;
01299 }
01300
01301
01302 template <typename ValueType>
01303 bool TRegularData3D<ValueType>::operator == (const TRegularData3D<ValueType>& grid) const
01304 {
01305 return ((origin_ == grid.origin_)
01306 && (dimension_ == grid.dimension_)
01307 && (size_.x == grid.size_.x)
01308 && (size_.y == grid.size_.y)
01309 && (size_.z == grid.size_.z)
01310 && (data_ == grid.data_)
01311 && (is_orthogonal_ == grid.is_orthogonal_));
01312 }
01313
01314 template <typename ValueType>
01315 void TRegularData3D<ValueType>::binaryWrite(const String& filename) const
01316 throw(Exception::FileNotFound)
01317 {
01318 File outfile(filename, std::ios::out|std::ios::binary);
01319 if (!outfile.isValid()) throw Exception::FileNotFound(__FILE__, __LINE__, filename);
01320
01321 BinaryFileAdaptor< BlockValueType > adapt_block;
01322 BinaryFileAdaptor< ValueType > adapt_single;
01323
01324
01325
01326
01327 BinaryFileAdaptor<CoordinateType> adapt_coordinate;
01328 BinaryFileAdaptor<Size> adapt_size;
01329
01330 adapt_size.setData(data_.size());
01331 outfile << adapt_size;
01332
01333 adapt_coordinate.setData(origin_);
01334 outfile << adapt_coordinate;
01335
01336 adapt_coordinate.setData(dimension_);
01337 outfile << adapt_coordinate;
01338
01339 adapt_coordinate.setData(spacing_);
01340 outfile << adapt_coordinate;
01341
01342 BinaryFileAdaptor<IndexType> adapt_index;
01343 adapt_index.setData(size_);
01344 outfile << adapt_index;
01345
01346
01347 Index window_pos = 0;
01348
01349 while ( ((int)data_.size() - (1024 + window_pos)) >= 0 )
01350 {
01351 adapt_block.setData(* (BlockValueType*)&(data_[window_pos]));
01352 outfile << adapt_block;
01353 window_pos+=1024;
01354 }
01355
01356
01357 for (Size i=window_pos; i<data_.size(); i++)
01358 {
01359 adapt_single.setData(data_[i]);
01360 outfile << adapt_single;
01361 }
01362
01363
01364 outfile.close();
01365 }
01366
01367 template <typename ValueType>
01368 void TRegularData3D<ValueType>::binaryRead(const String& filename)
01369 throw(Exception::FileNotFound)
01370 {
01371 File infile(filename, std::ios::in|std::ios::binary);
01372 if (!infile.isValid()) throw Exception::FileNotFound(__FILE__, __LINE__, filename);
01373
01374 BinaryFileAdaptor< BlockValueType > adapt_block;
01375 BinaryFileAdaptor< ValueType > adapt_single;
01376
01377
01378
01379
01380 BinaryFileAdaptor<CoordinateType> adapt_coordinate;
01381 BinaryFileAdaptor<Size> adapt_size;
01382
01383 infile >> adapt_size;
01384 Size new_size = adapt_size.getData();
01385
01386 infile >> adapt_coordinate;
01387 origin_ = adapt_coordinate.getData();
01388
01389 infile >> adapt_coordinate;
01390 dimension_ = adapt_coordinate.getData();
01391
01392 infile >> adapt_coordinate;
01393 spacing_ = adapt_coordinate.getData();
01394
01395 BinaryFileAdaptor<IndexType> adapt_index;
01396 infile >> adapt_index;
01397 size_ = adapt_index.getData();
01398
01399 data_.resize(new_size);
01400
01401
01402 Index window_pos = 0;
01403
01404 while ( ((int)data_.size() - (1024 + window_pos)) >= 0 )
01405 {
01406 infile >> adapt_block;
01407 *(BlockValueType*)(&(data_[window_pos])) = adapt_block.getData();
01408
01409
01410
01411
01412
01413
01414 window_pos+=1024;
01415 }
01416
01417
01418 for (Size i=window_pos; i<data_.size(); i++)
01419 {
01420 infile >> adapt_single;
01421 data_[i] = adapt_single.getData();
01422 }
01423
01424
01425 infile.close();
01426 }
01427
01430
01431 template <typename ValueType>
01432 std::ostream& operator << (std::ostream& os, const TRegularData3D<ValueType>& grid)
01433 {
01434
01435 os << grid.getOrigin().x << " " << grid.getOrigin().y << " " << grid.getOrigin().z
01436 << std::endl
01437 << grid.getOrigin().x + grid.getDimension().x << " "
01438 << grid.getOrigin().y + grid.getDimension().y << " "
01439 << grid.getOrigin().z + grid.getDimension().z
01440 << std::endl
01441 << grid.getSize().x - 1 << " " << grid.getSize().y - 1 << " " << grid.getSize().z - 1
01442 << std::endl;
01443
01444
01445 std::copy(grid.begin(), grid.end(), std::ostream_iterator<ValueType>(os, "\n"));
01446
01447 return os;
01448 }
01449
01451 template <typename ValueType>
01452 std::istream& operator >> (std::istream& is, TRegularData3D<ValueType>& grid)
01453 {
01454 typename TRegularData3D<ValueType>::CoordinateType origin;
01455 typename TRegularData3D<ValueType>::CoordinateType dimension;
01456 typename TRegularData3D<ValueType>::IndexType size;
01457
01458 is >> origin.x >> origin.y >> origin.z;
01459 is >> dimension.x >> dimension.y >> dimension.z;
01460 is >> size.x >> size.y >> size.z;
01461
01462 dimension -= origin;
01463 size.x++;
01464 size.y++;
01465 size.z++;
01466
01467 grid.resize(size);
01468 grid.setOrigin(origin);
01469 grid.setDimension(dimension);
01470 std::copy(std::istream_iterator<ValueType>(is), std::istream_iterator<ValueType>(), grid.begin());
01471
01472 return is;
01473 }
01475
01476 }
01477
01478 #endif // BALL_DATATYPE_REGULARDATA3D_H