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
00170
00171 BALL_INLINE ConstIterator begin() const { return data_.begin(); }
00173 BALL_INLINE ConstIterator end() const { return data_.end(); }
00175 BALL_INLINE Iterator begin() { return data_.begin(); }
00177 BALL_INLINE Iterator end() { return data_.end(); }
00179
00183
00184
00185 BALL_INLINE size_type size() const { return data_.size(); }
00186 BALL_INLINE size_type max_size() const { return data_.max_size(); }
00187 BALL_INLINE void swap(TRegularData3D<ValueType>& grid) { std::swap(*this, grid); }
00188
00189
00191 const vector<ValueType>& getData() const;
00192
00196 const ValueType& getData(const IndexType& index) const
00197 throw(Exception::OutOfGrid);
00198
00202 ValueType& getData(const IndexType& index)
00203 throw(Exception::OutOfGrid);
00204
00208 const ValueType& getData(Position index) const
00209 throw(Exception::OutOfGrid);
00210
00214 ValueType& getData(Position index)
00215 throw(Exception::OutOfGrid);
00216
00221 const ValueType& operator [] (const IndexType& index) const
00222 {
00223 return data_[index.x + size_.x * index.y + index.z * size_.x * size_.y];
00224 }
00225
00230 ValueType& operator [] (const IndexType& index)
00231 {
00232 return data_[index.x + size_.x * index.y + index.z * size_.x * size_.y];
00233 }
00234
00239 const ValueType& operator [] (Position index) const { return data_[index]; }
00240
00245 ValueType& operator [] (Position index) { return data_[index]; }
00246
00257 ValueType operator () (const CoordinateType& x) const;
00258
00264 ValueType getInterpolatedValue(const CoordinateType& x) const
00265 throw(Exception::OutOfGrid);
00266
00272 const ValueType& getClosestValue(const CoordinateType& x) const
00273 throw(Exception::OutOfGrid);
00274
00280 ValueType& getClosestValue(const CoordinateType& x)
00281 throw(Exception::OutOfGrid);
00282
00288 IndexType getClosestIndex(const CoordinateType& v) const
00289 throw(Exception::OutOfGrid);
00290
00295 IndexType getLowerIndex(const CoordinateType& v) const
00296 throw(Exception::OutOfGrid);
00297
00303 inline const IndexType& getSize() const { return size_; }
00304
00309 inline const CoordinateType& getOrigin() const { return origin_; }
00310
00315 const CoordinateType& getSpacing() const { return spacing_; }
00318 void setOrigin(const CoordinateType& origin) { origin_ = origin; }
00319
00325 const CoordinateType& getDimension() const { return dimension_; }
00326
00335 void setDimension(const CoordinateType& dimension)
00336 {
00337 dimension_ = dimension;
00338 if (is_orthogonal_)
00339 {
00340 spacing_.x = dimension_.x / (double)(size_.x - 1);
00341 spacing_.y = dimension_.y / (double)(size_.y - 1);
00342 spacing_.z = dimension_.z / (double)(size_.z - 1);
00343 }
00344 }
00345
00360 void resize(const IndexType& size)
00361 throw(Exception::OutOfMemory);
00362
00374 void rescale(const IndexType& new_size)
00375 throw(Exception::OutOfMemory);
00376
00381 CoordinateType getCoordinates(const IndexType& index) const
00382 throw(Exception::OutOfGrid);
00383
00388 CoordinateType getCoordinates(Position index) const
00389 throw(Exception::OutOfGrid);
00390
00406 void getEnclosingIndices
00407 (const CoordinateType& r,
00408 Position& llf, Position& rlf, Position& luf, Position& ruf,
00409 Position& llb, Position& rlb, Position& lub, Position& rub) const
00410 throw(Exception::OutOfGrid);
00411
00415 void getEnclosingValues
00416 (const CoordinateType& r,
00417 ValueType& llf, ValueType& rlf, ValueType& luf, ValueType& ruf,
00418 ValueType& llb, ValueType& rlb, ValueType& lub, ValueType& rub) const
00419 throw(Exception::OutOfGrid);
00420
00425 void binaryWrite(const String& filename) const
00426 throw(Exception::FileNotFound);
00427
00434 void binaryWriteRaw(const String& filename) const
00435 throw(Exception::FileNotFound);
00436
00441 void binaryRead(const String& filename)
00442 throw(Exception::FileNotFound);
00444
00445 protected:
00446
00448 const CoordinateType mapToCartesian_(CoordinateType r) const
00449 {
00450 Vector3 result;
00451 r.x /= (size_.x - 1.);
00452 r.y /= (size_.y - 1.);
00453 r.z /= (size_.z - 1.);
00454
00455 result.x = mapping_[0] * r.x + mapping_[1] * r.y + mapping_[2] * r.z + origin_.x;
00456 result.y = mapping_[3] * r.x + mapping_[4] * r.y + mapping_[5] * r.z + origin_.y;
00457 result.z = mapping_[6] * r.x + mapping_[7] * r.y + mapping_[8] * r.z + origin_.z;
00458
00459 return result;
00460 }
00461
00463 const CoordinateType mapInverse_(CoordinateType r) const
00464 {
00465 r -= origin_;
00466
00467 Vector3 result;
00468 result.x = inverse_mapping_[0] * r.x + inverse_mapping_[1] * r.y + inverse_mapping_[2] * r.z;
00469 result.y = inverse_mapping_[3] * r.x + inverse_mapping_[4] * r.y + inverse_mapping_[5] * r.z;
00470 result.z = inverse_mapping_[6] * r.x + inverse_mapping_[7] * r.y + inverse_mapping_[8] * r.z;
00471
00472 result.x *= (size_.x - 1);
00473 result.y *= (size_.y - 1);
00474 result.z *= (size_.z - 1);
00475
00476 return result;
00477 }
00478
00480 VectorType data_;
00481
00483 CoordinateType origin_;
00484
00486 CoordinateType dimension_;
00487
00489 CoordinateType spacing_;
00490
00492 IndexType size_;
00493
00495 typedef struct { ValueType bt[1024]; } BlockValueType;
00496
00498 bool is_orthogonal_;
00499
00501 std::vector<double> mapping_;
00502 std::vector<double> inverse_mapping_;
00503 };
00504
00507 typedef TRegularData3D<float> RegularData3D;
00508
00509
00510 template <class ValueType>
00511 TRegularData3D<ValueType>::TRegularData3D()
00512 : data_(0),
00513 origin_(0.0),
00514 dimension_(0.0),
00515 spacing_(1.0),
00516 size_(0, 0, 0),
00517 is_orthogonal_(true)
00518 {
00519 }
00520
00521
00522 template <class ValueType>
00523 TRegularData3D<ValueType>::TRegularData3D
00524 (const TRegularData3D<ValueType>& data)
00525 throw(Exception::OutOfMemory)
00526 : data_(),
00527 origin_(data.origin_),
00528 dimension_(data.dimension_),
00529 spacing_(data.spacing_),
00530 size_(data.size_),
00531 is_orthogonal_(data.is_orthogonal_),
00532 mapping_(data.mapping_),
00533 inverse_mapping_(data.inverse_mapping_)
00534 {
00535 try
00536 {
00537 data_ = data.data_;
00538 }
00539 catch (std::bad_alloc&)
00540 {
00541 data_.resize(0);
00542 throw Exception::OutOfMemory(__FILE__, __LINE__, data.data_.size() * sizeof(ValueType));
00543 }
00544 }
00545
00546 template <class ValueType>
00547 TRegularData3D<ValueType>::TRegularData3D
00548 (const typename TRegularData3D<ValueType>::IndexType& size,
00549 const typename TRegularData3D<ValueType>::CoordinateType& origin,
00550 const typename TRegularData3D<ValueType>::CoordinateType& dimension)
00551 throw(Exception::OutOfMemory)
00552 : data_(),
00553 origin_(origin),
00554 dimension_(dimension),
00555 spacing_(0.0),
00556 size_(size),
00557 is_orthogonal_(true)
00558 {
00559
00560 spacing_.x = dimension_.x / (double)(size_.x - 1);
00561 spacing_.y = dimension_.y / (double)(size_.y - 1);
00562 spacing_.z = dimension_.z / (double)(size_.z - 1);
00563
00564
00565 size_type number_of_points = size_.x * size_.y * size_.z;
00566 try
00567 {
00568 data_.resize(number_of_points);
00569 }
00570 catch (std::bad_alloc&)
00571 {
00572 data_.resize(0);
00573 throw Exception::OutOfMemory(__FILE__, __LINE__, number_of_points * sizeof(ValueType));
00574 }
00575 }
00576
00577
00578 template <class ValueType>
00579 TRegularData3D<ValueType>::TRegularData3D
00580 (const typename TRegularData3D<ValueType>::CoordinateType& origin,
00581 const typename TRegularData3D<ValueType>::CoordinateType& dimension,
00582 const typename TRegularData3D<ValueType>::CoordinateType& spacing)
00583 throw(Exception::OutOfMemory)
00584 : data_(),
00585 origin_(origin),
00586 dimension_(dimension),
00587 spacing_(spacing),
00588 size_(0),
00589 is_orthogonal_(true)
00590 {
00591
00592 size_.x = (Size)(dimension_.x / spacing_.x + 0.5) + 1;
00593 size_.y = (Size)(dimension_.y / spacing_.y + 0.5) + 1;
00594 size_.z = (Size)(dimension_.z / spacing_.z + 0.5) + 1;
00595
00596
00597 size_type size = size_.x * size_.y * size_.z;
00598 try
00599 {
00600 data_ .resize(size);
00601 }
00602 catch (std::bad_alloc&)
00603 {
00604 data_.resize(0);
00605 throw Exception::OutOfMemory(__FILE__, __LINE__, size * sizeof(ValueType));
00606 }
00607
00608
00609 spacing_.x = dimension_.x / (double)(size_.x - 1);
00610 spacing_.y = dimension_.y / (double)(size_.y - 1);
00611 spacing_.z = dimension_.z / (double)(size_.z - 1);
00612 }
00613
00614 template <class ValueType>
00615 TRegularData3D<ValueType>::TRegularData3D
00616 (const typename TRegularData3D<ValueType>::CoordinateType& origin,
00617 const typename TRegularData3D<ValueType>::CoordinateType& x_axis,
00618 const typename TRegularData3D<ValueType>::CoordinateType& y_axis,
00619 const typename TRegularData3D<ValueType>::CoordinateType& z_axis,
00620 const typename TRegularData3D<ValueType>::IndexType& new_size)
00621 throw(Exception::OutOfMemory)
00622 : data_(),
00623 origin_(origin),
00624 dimension_(x_axis+y_axis+z_axis),
00625 spacing_(0.0),
00626 size_(new_size),
00627 is_orthogonal_(false)
00628 {
00629
00630 spacing_.x = x_axis.getLength() / (new_size.x - 1.);
00631 spacing_.y = y_axis.getLength() / (new_size.y - 1.);
00632 spacing_.z = z_axis.getLength() / (new_size.z - 1.);
00633
00634 size_type size = size_.x * size_.y * size_.z;
00635 try
00636 {
00637 data_.resize(size);
00638 }
00639 catch (std::bad_alloc&)
00640 {
00641 data_.resize(0);
00642 throw Exception::OutOfMemory(__FILE__, __LINE__, size * sizeof(ValueType));
00643 }
00644
00645
00646 mapping_.resize(9);
00647 inverse_mapping_.resize(9);
00648
00649 mapping_[0] = x_axis.x; mapping_[1] = y_axis.x; mapping_[2] = z_axis.x;
00650 mapping_[3] = x_axis.y; mapping_[4] = y_axis.y; mapping_[5] = z_axis.y;
00651 mapping_[6] = x_axis.z; mapping_[7] = y_axis.z; mapping_[8] = z_axis.z;
00652
00653
00654
00655
00656
00657 double a = mapping_[0]; double b = mapping_[1]; double c = mapping_[2];
00658 double d = mapping_[3]; double e = mapping_[4]; double f = mapping_[5];
00659 double g = mapping_[6]; double h = mapping_[7]; double i = mapping_[8];
00660
00661 double determinant = 1. / (a*(e*i - f*h) - b*(d*i - f*g) + c*(d*h - e*g));
00662
00663 inverse_mapping_[0] = determinant * (e*i - f*h);
00664 inverse_mapping_[1] = determinant * (b*i - c*h);
00665 inverse_mapping_[2] = determinant * (b*f - c*e);
00666
00667 inverse_mapping_[3] = determinant * (f*g - d*i);
00668 inverse_mapping_[4] = determinant * (a*i - c*g);
00669 inverse_mapping_[5] = determinant * (c*d - a*f);
00670
00671 inverse_mapping_[6] = determinant * (d*h - e*g);
00672 inverse_mapping_[7] = determinant * (b*g - a*h);
00673 inverse_mapping_[8] = determinant * (a*e - b*d);
00674 }
00675
00676 template <class ValueType>
00677 TRegularData3D<ValueType>::~TRegularData3D()
00678 {
00679 }
00680
00681 template <typename ValueType>
00682 BALL_INLINE
00683 TRegularData3D<ValueType>& TRegularData3D<ValueType>::operator =
00684 (const TRegularData3D<ValueType>& rhs)
00685 throw(Exception::OutOfMemory)
00686 {
00687
00688 if (&rhs != this)
00689 {
00690
00691
00692 origin_ = rhs.origin_;
00693 dimension_ = rhs.dimension_;
00694 spacing_ = rhs.spacing_;
00695 size_ = rhs.size_;
00696
00697 is_orthogonal_ = rhs.is_orthogonal_;
00698 mapping_ = rhs.mapping_;
00699 inverse_mapping_ = rhs.inverse_mapping_;
00700
00701 try
00702 {
00703 data_ = rhs.data_;
00704 }
00705 catch (std::bad_alloc&)
00706 {
00707 data_.resize(0);
00708 throw Exception::OutOfMemory(__FILE__, __LINE__, rhs.data_.size() * sizeof(ValueType));
00709 }
00710 }
00711
00712 return *this;
00713 }
00714
00715 template <typename ValueType>
00716 void TRegularData3D<ValueType>::resize(const typename TRegularData3D<ValueType>::IndexType& size)
00717 throw(Exception::OutOfMemory)
00718 {
00719 if (is_orthogonal_)
00720 {
00721
00722 if ((size.x == size_.x) && (size_.y == size.y) && (size_.z == size.z))
00723 {
00724 return;
00725 }
00726
00727
00728 if ((size.x == 0) || (size.y == 0) || (size.z == 0))
00729 {
00730 data_.resize(0);
00731 dimension_.set(0.0, 0.0, 0.0);
00732 return;
00733 }
00734
00735 size_type new_size = (size_type)(size.x * size.y * size.z);
00736
00737
00738 try
00739 {
00740
00741 std::vector<ValueType> old_data(data_);
00742
00743
00744 data_.resize(new_size);
00745
00746
00747 static ValueType default_value = (ValueType)0;
00748 for (size_type i = 0; i < new_size; i++)
00749 {
00750 size_type x = i % size.x;
00751 size_type y = (i % (size.x * size.y)) / size.x;
00752 size_type z = i / (size.x * size.y);
00753 if ((x >= size_.x) || (y >= size_.y) || (z >= size_.z))
00754 {
00755 data_[i] = default_value;
00756 }
00757 else
00758 {
00759 data_[i] = old_data[x + y * size_.x + z * size_.x * size_.y];
00760 }
00761 }
00762
00763
00764 if ((size_.x != 0) && (size_.y != 0) && (size_.z != 0))
00765 {
00766 dimension_.x *= (double)size.x / (double)size_.x;
00767 dimension_.y *= (double)size.y / (double)size_.y;
00768 dimension_.z *= (double)size.z / (double)size_.z;
00769 }
00770 size_ = size;
00771 }
00772 catch (std::bad_alloc&)
00773 {
00774 throw Exception::OutOfMemory(__FILE__, __LINE__, new_size * (Size)sizeof(ValueType));
00775 }
00776 }
00777 }
00778
00779 template <typename ValueType>
00780 void TRegularData3D<ValueType>::rescale(const typename TRegularData3D<ValueType>::IndexType& size)
00781 throw(Exception::OutOfMemory)
00782 {
00783 if (is_orthogonal_)
00784 {
00785
00786 if ((size.x == size_.x) && (size_.y == size.y) && (size_.z == size.z))
00787 {
00788 return;
00789 }
00790
00791
00792 if ((size.x == 0) || (size.y == 0) || (size.z == 0))
00793 {
00794 data_.resize(0);
00795 dimension_.set(0.0);
00796 return;
00797 }
00798
00799
00800 size_type new_size = (size_type)(size.x * size.y * size.z);
00801
00802
00803 try
00804 {
00805
00806 TRegularData3D<ValueType> old_data(*this);
00807
00808
00809 data_.resize(new_size);
00810 spacing_.x = dimension_.x / (double)(size.x - 1);
00811 spacing_.y = dimension_.y / (double)(size.y - 1);
00812 spacing_.z = dimension_.z / (double)(size.z - 1);
00813
00814
00815 size_ = size;
00816
00817
00818 for (size_type i = 0; i < data_.size(); i++)
00819 {
00820 try
00821 {
00822 data_[i] = old_data.getInterpolatedValue(getCoordinates(i));
00823 }
00824 catch (Exception::OutOfGrid&)
00825 {
00826 data_[i] = old_data.getClosestValue(getCoordinates(i));
00827 }
00828 }
00829 }
00830 catch (std::bad_alloc&)
00831 {
00832 throw Exception::OutOfMemory(__FILE__, __LINE__, new_size * (Size)sizeof(ValueType));
00833 }
00834 }
00835 }
00836
00837 template <class ValueType>
00838 BALL_INLINE
00839 bool TRegularData3D<ValueType>::isInside(const typename TRegularData3D<ValueType>::CoordinateType& r) const
00840 {
00841 if (is_orthogonal_)
00842 {
00843 return !((r.x > (origin_.x + dimension_.x ))
00844 || (r.y > (origin_.y + dimension_.y))
00845 || (r.z > (origin_.z + dimension_.z))
00846 || (r.x < origin_.x) || (r.y < origin_.y) || (r.z < origin_.z));
00847 }
00848 else
00849 {
00850
00851 CoordinateType ri = mapInverse_(r);
00852 ri.x = Maths::round(ri.x);
00853 ri.y = Maths::round(ri.y);
00854 ri.z = Maths::round(ri.z);
00855
00856 return !( (ri.x < 0) || (ri.y < 0) || (ri.z < 0)
00857 || (ri.x >= size_.x) || (ri.y >= size_.y) || (ri.z >= size_.z) );
00858 }
00859 }
00860
00861 template <class ValueType>
00862 BALL_INLINE
00863 const ValueType& TRegularData3D<ValueType>::getData
00864 (const typename TRegularData3D<ValueType>::IndexType& index) const
00865 throw(Exception::OutOfGrid)
00866 {
00867 size_type pos = index.x + index.y * size_.x + index.z * size_.x * size_.y;
00868 if (pos >= data_.size())
00869 {
00870 throw Exception::OutOfGrid(__FILE__, __LINE__);
00871 }
00872 return data_[pos];
00873 }
00874
00875 template <class ValueType>
00876 BALL_INLINE
00877 const vector<ValueType>& TRegularData3D<ValueType>::getData() const
00878 {
00879 return data_;
00880 }
00881
00882 template <typename ValueType>
00883 BALL_INLINE
00884 ValueType& TRegularData3D<ValueType>::getData
00885 (const typename TRegularData3D<ValueType>::IndexType& index)
00886 throw(Exception::OutOfGrid)
00887 {
00888 size_type pos = index.x + index.y * size_.x + index.z * size_.x * size_.y;
00889 if (pos >= data_.size())
00890 {
00891 throw Exception::OutOfGrid(__FILE__, __LINE__);
00892 }
00893 return data_[pos];
00894 }
00895
00896 template <class ValueType>
00897 BALL_INLINE
00898 const ValueType& TRegularData3D<ValueType>::getData(Position index) const
00899 throw(Exception::OutOfGrid)
00900 {
00901 if (index >= data_.size())
00902 {
00903 throw Exception::OutOfGrid(__FILE__, __LINE__);
00904 }
00905 return data_[index];
00906 }
00907
00908 template <class ValueType>
00909 BALL_INLINE
00910 ValueType& TRegularData3D<ValueType>::getData(Position index)
00911 throw(Exception::OutOfGrid)
00912 {
00913 if (index >= data_.size())
00914 {
00915 throw Exception::OutOfGrid(__FILE__, __LINE__);
00916 }
00917 return data_[index];
00918 }
00919
00920 template <class ValueType>
00921 BALL_INLINE
00922 typename TRegularData3D<ValueType>::CoordinateType TRegularData3D<ValueType>::getCoordinates
00923 (const typename TRegularData3D<ValueType>::IndexType& index) const
00924 throw(Exception::OutOfGrid)
00925 {
00926 if ((index.x >= size_.x) || (index.y >= size_.y) || (index.z >= size_.z))
00927 {
00928 throw Exception::OutOfGrid(__FILE__, __LINE__);
00929 }
00930
00931 if (is_orthogonal_)
00932 {
00933 CoordinateType r(origin_.x + index.x * spacing_.x,
00934 origin_.y + index.y * spacing_.y,
00935 origin_.z + index.z * spacing_.z);
00936 return r;
00937 }
00938 else
00939 {
00940 CoordinateType r(index.x, index.y, index.z);
00941 r = mapToCartesian_(r);
00942
00943 return r;
00944 }
00945 }
00946
00947 template <class ValueType>
00948 BALL_INLINE
00949 typename TRegularData3D<ValueType>::CoordinateType
00950 TRegularData3D<ValueType>::getCoordinates(Position position) const
00951 throw(Exception::OutOfGrid)
00952 {
00953 if (position >= data_.size())
00954 {
00955 throw Exception::OutOfGrid(__FILE__, __LINE__);
00956 }
00957
00958 Position x = (Position)(position % size_.x);
00959 Position y = (Position)((position % (size_.x * size_.y))/ size_.x);
00960 Position z = (Position)(position / (size_.x * size_.y));
00961
00962 if (is_orthogonal_)
00963 {
00964 return CoordinateType(origin_.x + (double)x * spacing_.x,
00965 origin_.y + (double)y * spacing_.y,
00966 origin_.z + (double)z * spacing_.z);
00967 }
00968 else
00969 {
00970 CoordinateType r(x,y,z);
00971 r = mapToCartesian_(r);
00972
00973 return r;
00974 }
00975 }
00976
00977 template <typename ValueType>
00978 BALL_INLINE
00979 void TRegularData3D<ValueType>::getEnclosingIndices
00980 (const typename TRegularData3D<ValueType>::CoordinateType& r,
00981 Position& llf, Position& rlf, Position& luf, Position& ruf,
00982 Position& llb, Position& rlb, Position& lub, Position& rub) const
00983 throw(Exception::OutOfGrid)
00984 {
00985 if (!isInside(r))
00986 {
00987 throw Exception::OutOfGrid(__FILE__, __LINE__);
00988 }
00989
00990
00991
00992 IndexType position;
00993 if (is_orthogonal_)
00994 {
00995 position.x = (Position)((r.x - origin_.x) / spacing_.x);
00996 position.y = (Position)((r.y - origin_.y) / spacing_.y);
00997 position.z = (Position)((r.z - origin_.z) / spacing_.z);
00998 }
00999 else
01000 {
01001 CoordinateType pos = mapInverse_(r);
01002 position.x = (Position) pos.x;
01003 position.y = (Position) pos.y;
01004 position.z = (Position) pos.z;
01005 }
01006
01007
01008
01009 llf = position.x + size_.x * position.y
01010 + size_.x * size_.y * position.z;
01011 rlf = llf + 1;
01012 luf = llf + size_.x;
01013 ruf = luf + 1;
01014 llb = llf + size_.x * size_.y;
01015 rlb = llb + 1;
01016 lub = llb + size_.x;
01017 rub = lub + 1;
01018 }
01019
01020 template <typename ValueType>
01021 BALL_INLINE
01022 void TRegularData3D<ValueType>::getEnclosingValues
01023 (const typename TRegularData3D<ValueType>::CoordinateType& r,
01024 ValueType& llf, ValueType& rlf, ValueType& luf, ValueType& ruf,
01025 ValueType& llb, ValueType& rlb, ValueType& lub, ValueType& rub) const
01026 throw(Exception::OutOfGrid)
01027 {
01028 if (!isInside(r))
01029 {
01030 throw Exception::OutOfGrid(__FILE__, __LINE__);
01031 }
01032
01033
01034 Position llf_idx, rlf_idx, luf_idx, ruf_idx, llb_idx, rlb_idx, lub_idx, rub_idx;
01035 getEnclosingIndices(r, llf_idx, rlf_idx, luf_idx, ruf_idx, llb_idx, rlb_idx, lub_idx, rub_idx);
01036
01037
01038 llf = data_[llf_idx];
01039 rlf = data_[rlf_idx];
01040 luf = data_[luf_idx];
01041 ruf = data_[ruf_idx];
01042 llb = data_[llb_idx];
01043 rlb = data_[rlb_idx];
01044 lub = data_[lub_idx];
01045 rub = data_[rub_idx];
01046 }
01047
01048 template <typename ValueType>
01049 BALL_INLINE
01050 ValueType TRegularData3D<ValueType>::getInterpolatedValue
01051 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01052 throw(Exception::OutOfGrid)
01053 {
01054 if (!isInside(r))
01055 {
01056 throw Exception::OutOfGrid(__FILE__, __LINE__);
01057 }
01058 return operator () (r);
01059 }
01060
01061 template <typename ValueType>
01062 BALL_INLINE
01063 ValueType TRegularData3D<ValueType>::operator ()
01064 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01065 {
01066 Position x;
01067 Position y;
01068 Position z;
01069 TVector3<double> r_0;
01070
01071 if (is_orthogonal_)
01072 {
01073 Vector3 h(r - origin_);
01074
01075 x = (Position)(h.x / spacing_.x);
01076 y = (Position)(h.y / spacing_.y);
01077 z = (Position)(h.z / spacing_.z);
01078
01079 while (x >= (size_.x - 1)) x--;
01080 while (y >= (size_.y - 1)) y--;
01081 while (z >= (size_.z - 1)) z--;
01082
01083 r_0.x = origin_.x + x*spacing_.x;
01084 r_0.y = origin_.y + y*spacing_.y;
01085 r_0.z = origin_.z + z*spacing_.z;
01086 }
01087 else
01088 {
01089 Vector3 pos = mapInverse_(r);
01090 x = (Position) pos.x;
01091 y = (Position) pos.y;
01092 z = (Position) pos.z;
01093
01094 while (x >= (size_.x - 1)) x--;
01095 while (y >= (size_.y - 1)) y--;
01096 while (z >= (size_.z - 1)) z--;
01097
01098
01099 Vector3 lower_pos(x,y,z);
01100 lower_pos = mapToCartesian_(lower_pos);
01101 r_0.x = lower_pos.x;
01102 r_0.y = lower_pos.y;
01103 r_0.z = lower_pos.z;
01104 }
01105
01106 Position Nx = size_.x;
01107 Position Nxy = size_.y * Nx;
01108 Position l = x + Nx * y + Nxy * z;
01109
01110 double dx = 1. - ((double)(r.x - r_0.x) / spacing_.x);
01111 double dy = 1. - ((double)(r.y - r_0.y) / spacing_.y);
01112 double dz = 1. - ((double)(r.z - r_0.z) / spacing_.z);
01113
01114 return data_[l] * dx * dy * dz
01115 + data_[l + 1] * (1. - dx) * dy * dz
01116 + data_[l + Nx] * dx * (1. - dy) * dz
01117 + data_[l + Nx + 1] * (1. - dx) * (1. - dy) * dz
01118 + data_[l + Nxy] * dx * dy * (1. - dz)
01119 + data_[l + Nxy + 1] * (1. - dx) * dy * (1. - dz)
01120 + data_[l + Nxy + Nx] * dx * (1. - dy) * (1. - dz)
01121 + data_[l + Nxy + Nx + 1] * (1. - dx) * (1. - dy) * (1. - dz);
01122 }
01123
01124 template <typename ValueType>
01125 BALL_INLINE
01126 typename TRegularData3D<ValueType>::IndexType TRegularData3D<ValueType>::getClosestIndex
01127 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01128 throw(Exception::OutOfGrid)
01129 {
01130 if (!isInside(r))
01131 {
01132 throw Exception::OutOfGrid(__FILE__, __LINE__);
01133 }
01134
01135 static IndexType position;
01136
01137 if (is_orthogonal_)
01138 {
01139 position.x = (Position)((r.x - origin_.x) / spacing_.x + 0.5);
01140 position.y = (Position)((r.y - origin_.y) / spacing_.y + 0.5);
01141 position.z = (Position)((r.z - origin_.z) / spacing_.z + 0.5);
01142 }
01143 else
01144 {
01145 Vector3 pos = mapInverse_(r);
01146 position.x = (Position) Maths::round(pos.x);
01147 position.y = (Position) Maths::round(pos.y);
01148 position.z = (Position) Maths::round(pos.z);
01149 }
01150
01151 return position;
01152 }
01153
01154 template <typename ValueType>
01155 BALL_INLINE
01156 typename TRegularData3D<ValueType>::IndexType TRegularData3D<ValueType>::getLowerIndex
01157 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01158 throw(Exception::OutOfGrid)
01159 {
01160 if (!isInside(r))
01161 {
01162 throw Exception::OutOfGrid(__FILE__, __LINE__);
01163 }
01164
01165 static IndexType position;
01166 if (is_orthogonal_)
01167 {
01168 position.x = (Position)((r.x - origin_.x) / spacing_.x);
01169 position.y = (Position)((r.y - origin_.y) / spacing_.y);
01170 position.z = (Position)((r.z - origin_.z) / spacing_.z);
01171 }
01172 else
01173 {
01174 Vector3 pos = mapInverse_(r);
01175 position.x = (Position)pos.x;
01176 position.y = (Position)pos.y;
01177 position.z = (Position)pos.z;
01178 }
01179
01180 return position;
01181 }
01182
01183 template <typename ValueType>
01184 BALL_INLINE
01185 const ValueType& TRegularData3D<ValueType>::getClosestValue
01186 (const typename TRegularData3D<ValueType>::CoordinateType& r) const
01187 throw(Exception::OutOfGrid)
01188 {
01189 if (!isInside(r))
01190 {
01191 throw Exception::OutOfGrid(__FILE__, __LINE__);
01192 }
01193
01194 static IndexType position;
01195
01196 if (is_orthogonal_)
01197 {
01198 position.x = (Position)((r.x - origin_.x) / spacing_.x + 0.5);
01199 position.y = (Position)((r.y - origin_.y) / spacing_.y + 0.5);
01200 position.z = (Position)((r.z - origin_.z) / spacing_.z + 0.5);
01201 }
01202 else
01203 {
01204 static Vector3 pos = mapInverse_(r);
01205 position.x = (Position) Maths::round(pos.x);
01206 position.y = (Position) Maths::round(pos.y);
01207 position.z = (Position) Maths::round(pos.z);
01208 }
01209
01210 return operator [] (position);
01211 }
01212
01213 template <typename ValueType>
01214 BALL_INLINE
01215 ValueType& TRegularData3D<ValueType>::getClosestValue
01216 (const typename TRegularData3D<ValueType>::CoordinateType& r)
01217 throw(Exception::OutOfGrid)
01218 {
01219 if (!isInside(r))
01220 {
01221 throw Exception::OutOfGrid(__FILE__, __LINE__);
01222 }
01223
01224 static IndexType position;
01225
01226 if (is_orthogonal_)
01227 {
01228 position.x = (Position)((r.x - origin_.x) / spacing_.x + 0.5);
01229 position.y = (Position)((r.y - origin_.y) / spacing_.y + 0.5);
01230 position.z = (Position)((r.z - origin_.z) / spacing_.z + 0.5);
01231 }
01232 else
01233 {
01234 static Vector3 pos = mapInverse_(r);
01235 position.x = (Position) Maths::round(pos.x);
01236 position.y = (Position) Maths::round(pos.y);
01237 position.z = (Position) Maths::round(pos.z);
01238 }
01239
01240
01241 return operator [] (position);
01242 }
01243
01244
01245 template <typename ValueType>
01246 void TRegularData3D<ValueType>::clear()
01247 {
01248 data_.resize(0);
01249
01250 origin_.set(0.0);
01251 dimension_.set(0.0);
01252 size_.x = 0;
01253 size_.y = 0;
01254 size_.z = 0;
01255 spacing_.set(1.0);
01256 is_orthogonal_ = true;
01257 }
01258
01259
01260 template <typename ValueType>
01261 bool TRegularData3D<ValueType>::operator == (const TRegularData3D<ValueType>& grid) const
01262 {
01263 return ((origin_ == grid.origin_)
01264 && (dimension_ == grid.dimension_)
01265 && (size_.x == grid.size_.x)
01266 && (size_.y == grid.size_.y)
01267 && (size_.z == grid.size_.z)
01268 && (data_ == grid.data_)
01269 && (is_orthogonal_ == grid.is_orthogonal_));
01270 }
01271
01272 template <typename ValueType>
01273 void TRegularData3D<ValueType>::binaryWrite(const String& filename) const
01274 throw(Exception::FileNotFound)
01275 {
01276 File outfile(filename, std::ios::out|std::ios::binary);
01277 if (!outfile.isValid()) throw Exception::FileNotFound(__FILE__, __LINE__, filename);
01278
01279 BinaryFileAdaptor< BlockValueType > adapt_block;
01280 BinaryFileAdaptor< ValueType > adapt_single;
01281
01282
01283
01284
01285 BinaryFileAdaptor<CoordinateType> adapt_coordinate;
01286 BinaryFileAdaptor<Size> adapt_size;
01287
01288 adapt_size.setData(data_.size());
01289 outfile << adapt_size;
01290
01291 adapt_coordinate.setData(origin_);
01292 outfile << adapt_coordinate;
01293
01294 adapt_coordinate.setData(dimension_);
01295 outfile << adapt_coordinate;
01296
01297 adapt_coordinate.setData(spacing_);
01298 outfile << adapt_coordinate;
01299
01300 BinaryFileAdaptor<IndexType> adapt_index;
01301 adapt_index.setData(size_);
01302 outfile << adapt_index;
01303
01304
01305 Index window_pos = 0;
01306
01307 while ( ((int)data_.size() - (1024 + window_pos)) >= 0 )
01308 {
01309 adapt_block.setData(* (BlockValueType*)&(data_[window_pos]));
01310 outfile << adapt_block;
01311 window_pos+=1024;
01312 }
01313
01314
01315 for (Size i=window_pos; i<data_.size(); i++)
01316 {
01317 adapt_single.setData(data_[i]);
01318 outfile << adapt_single;
01319 }
01320
01321
01322 outfile.close();
01323 }
01324
01325 template <typename ValueType>
01326 void TRegularData3D<ValueType>::binaryRead(const String& filename)
01327 throw(Exception::FileNotFound)
01328 {
01329 File infile(filename, std::ios::in|std::ios::binary);
01330 if (!infile.isValid()) throw Exception::FileNotFound(__FILE__, __LINE__, filename);
01331
01332 BinaryFileAdaptor< BlockValueType > adapt_block;
01333 BinaryFileAdaptor< ValueType > adapt_single;
01334
01335
01336
01337
01338 BinaryFileAdaptor<CoordinateType> adapt_coordinate;
01339 BinaryFileAdaptor<Size> adapt_size;
01340
01341 infile >> adapt_size;
01342 Size new_size = adapt_size.getData();
01343
01344 infile >> adapt_coordinate;
01345 origin_ = adapt_coordinate.getData();
01346
01347 infile >> adapt_coordinate;
01348 dimension_ = adapt_coordinate.getData();
01349
01350 infile >> adapt_coordinate;
01351 spacing_ = adapt_coordinate.getData();
01352
01353 BinaryFileAdaptor<IndexType> adapt_index;
01354 infile >> adapt_index;
01355 size_ = adapt_index.getData();
01356
01357 data_.resize(new_size);
01358
01359
01360 Index window_pos = 0;
01361
01362 while ( ((int)data_.size() - (1024 + window_pos)) >= 0 )
01363 {
01364 infile >> adapt_block;
01365 *(BlockValueType*)(&(data_[window_pos])) = adapt_block.getData();
01366
01367
01368
01369
01370
01371
01372 window_pos+=1024;
01373 }
01374
01375
01376 for (Size i=window_pos; i<data_.size(); i++)
01377 {
01378 infile >> adapt_single;
01379 data_[i] = adapt_single.getData();
01380 }
01381
01382
01383 infile.close();
01384 }
01385
01388
01389 template <typename ValueType>
01390 std::ostream& operator << (std::ostream& os, const TRegularData3D<ValueType>& grid)
01391 {
01392
01393 os << grid.getOrigin().x << " " << grid.getOrigin().y << " " << grid.getOrigin().z
01394 << std::endl
01395 << grid.getOrigin().x + grid.getDimension().x << " "
01396 << grid.getOrigin().y + grid.getDimension().y << " "
01397 << grid.getOrigin().z + grid.getDimension().z
01398 << std::endl
01399 << grid.getSize().x - 1 << " " << grid.getSize().y - 1 << " " << grid.getSize().z - 1
01400 << std::endl;
01401
01402
01403 std::copy(grid.begin(), grid.end(), std::ostream_iterator<ValueType>(os, "\n"));
01404
01405 return os;
01406 }
01407
01409 template <typename ValueType>
01410 std::istream& operator >> (std::istream& is, TRegularData3D<ValueType>& grid)
01411 {
01412 typename TRegularData3D<ValueType>::CoordinateType origin;
01413 typename TRegularData3D<ValueType>::CoordinateType dimension;
01414 typename TRegularData3D<ValueType>::IndexType size;
01415
01416 is >> origin.x >> origin.y >> origin.z;
01417 is >> dimension.x >> dimension.y >> dimension.z;
01418 is >> size.x >> size.y >> size.z;
01419
01420 dimension -= origin;
01421 size.x++;
01422 size.y++;
01423 size.z++;
01424
01425 grid.resize(size);
01426 grid.setOrigin(origin);
01427 grid.setDimension(dimension);
01428 std::copy(std::istream_iterator<ValueType>(is), std::istream_iterator<ValueType>(), grid.begin());
01429
01430 return is;
01431 }
01433
01434 }
01435
01436 #endif // BALL_DATATYPE_REGULARDATA3D_H