00001
00002
00003
00004
00005
00006
00007 #ifndef BALL_DATATYPE_REGULARDATA1D_H
00008 #define BALL_DATATYPE_REGULARDATA1D_H
00009
00010 #ifndef BALL_COMMON_H
00011 # include <BALL/common.h>
00012 #endif
00013
00014 #ifndef BALL_SYSTEM_FILE_H
00015 # include <BALL/SYSTEM/file.h>
00016 #endif
00017
00018 #include <vector>
00019 #include <iostream>
00020 #include <fstream>
00021 #include <iterator>
00022 #include <algorithm>
00023
00024 namespace BALL
00025 {
00037 template <typename ValueType>
00038 class TRegularData1D
00039 {
00040 public:
00041
00042 BALL_CREATE(TRegularData1D<ValueType>)
00043
00044
00047
00049 typedef Position IndexType;
00051 typedef std::vector<ValueType> VectorType;
00053 typedef double CoordinateType;
00055 typedef typename std::vector<ValueType>::iterator Iterator;
00057 typedef typename std::vector<ValueType>::const_iterator ConstIterator;
00059
00060
00061
00062 typedef ValueType value_type;
00063 typedef typename std::vector<ValueType>::iterator iterator;
00064 typedef typename std::vector<ValueType>::const_iterator const_iterator;
00065 typedef typename std::vector<ValueType>::reference reference;
00066 typedef typename std::vector<ValueType>::const_reference const_reference;
00067 typedef typename std::vector<ValueType>::pointer pointer;
00068 typedef typename std::vector<ValueType>::difference_type difference_type;
00069 typedef typename std::vector<ValueType>::size_type size_type;
00070
00074
00076 TRegularData1D();
00077
00079 TRegularData1D(const TRegularData1D& data)
00080 throw(Exception::OutOfMemory);
00081
00083 TRegularData1D(const CoordinateType& origin, const CoordinateType& dimension, const CoordinateType& spacing)
00084 throw(Exception::OutOfMemory);
00085
00087 TRegularData1D(const IndexType& size)
00088 throw(Exception::OutOfMemory);
00089
00091 TRegularData1D(const VectorType& data, const CoordinateType& origin = 0.0, const CoordinateType& dimension = 1.0)
00092 throw(Exception::OutOfMemory);
00093
00095 virtual ~TRegularData1D();
00096
00098 virtual void clear();
00100
00101
00105
00109 TRegularData1D& operator = (const TRegularData1D<ValueType>& data)
00110 throw(Exception::OutOfMemory);
00111
00115 TRegularData1D& operator = (const VectorType& data)
00116 throw(Exception::OutOfMemory);
00117
00119
00123
00124 bool operator == (const TRegularData1D& data) const;
00125
00127 BALL_INLINE bool operator != (const TRegularData1D& data) const { return !this->operator == (data); }
00128
00130 BALL_INLINE bool empty() const { return data_.empty(); }
00131
00133 bool isInside(const CoordinateType& x) const;
00135
00139
00140 BALL_INLINE ConstIterator begin() const { return data_.begin(); }
00142 BALL_INLINE ConstIterator end() const { return data_.end(); }
00144 BALL_INLINE Iterator begin() { return data_.begin(); }
00146 BALL_INLINE Iterator end() { return data_.end(); }
00148
00152
00153
00154 BALL_INLINE size_type size() const { return data_.size(); }
00155 BALL_INLINE size_type max_size() const { return data_.max_size(); }
00156 BALL_INLINE void swap(TRegularData1D<ValueType>& data) { std::swap(*this, data); }
00157
00161 const ValueType& getData(const IndexType& index) const
00162 throw(Exception::OutOfGrid);
00163
00167 ValueType& getData(const IndexType& index)
00168 throw(Exception::OutOfGrid);
00169
00174 const ValueType& operator [] (const IndexType& index) const { return data_[index]; }
00175
00180 ValueType& operator [] (const IndexType& index) { return data_[index]; }
00181
00190 ValueType operator () (const CoordinateType& x) const;
00191
00197 ValueType getInterpolatedValue(const CoordinateType& x) const
00198 throw(Exception::OutOfGrid);
00199
00206 void getEnclosingIndices(const CoordinateType& x, Position& lower, Position& upper) const
00207 throw(Exception::OutOfGrid);
00208
00209
00213 void getEnclosingValues(const CoordinateType& x, ValueType& lower, ValueType& upper) const
00214 throw(Exception::OutOfGrid);
00215
00220 CoordinateType getCoordinates(const IndexType& index) const
00221 throw(Exception::OutOfGrid);
00222
00228 IndexType getClosestIndex(const CoordinateType& x) const
00229 throw(Exception::OutOfGrid);
00230
00236 IndexType getLowerIndex(const CoordinateType& x) const
00237 throw(Exception::OutOfGrid);
00238
00244 const ValueType& getClosestValue(const CoordinateType& x) const
00245 throw(Exception::OutOfGrid);
00246
00252 ValueType& getClosestValue(const CoordinateType& x)
00253 throw(Exception::OutOfGrid);
00254
00256 BALL_INLINE IndexType getSize() const { return (IndexType)data_.size(); }
00257
00262 BALL_INLINE const CoordinateType& getOrigin() const { return origin_; }
00263
00268 BALL_INLINE const CoordinateType& getSpacing() const { return spacing_; }
00269
00272 BALL_INLINE void setOrigin(const CoordinateType& origin) { origin_ = origin; }
00273
00279 BALL_INLINE const CoordinateType& getDimension() const { return dimension_; }
00280
00286 BALL_INLINE void setDimension(const CoordinateType& dimension) { dimension_ = dimension; }
00287
00299 void resize(const IndexType& size)
00300 throw(Exception::OutOfMemory);
00301
00310 void rescale(const IndexType& new_size)
00311 throw(Exception::OutOfMemory);
00312
00316 void binaryWrite(const String& filename) const
00317 throw(Exception::FileNotFound);
00318
00322 void binaryRead(const String& filename)
00323 throw(Exception::FileNotFound);
00325
00326 protected:
00328 CoordinateType origin_;
00329
00331 CoordinateType dimension_;
00332
00334 CoordinateType spacing_;
00335
00337 VectorType data_;
00338
00340 typedef struct { ValueType bt[1024]; } BlockValueType;
00341 };
00342
00345 typedef TRegularData1D<float> RegularData1D;
00346
00347 template <typename ValueType>
00348 TRegularData1D<ValueType>::TRegularData1D()
00349 : origin_(0.0),
00350 dimension_(0.0),
00351 spacing_(1.0),
00352 data_()
00353 {
00354 }
00355
00356 template <typename ValueType>
00357 TRegularData1D<ValueType>::~TRegularData1D()
00358 {
00359 }
00360
00361 template <typename ValueType>
00362 TRegularData1D<ValueType>::TRegularData1D(const TRegularData1D<ValueType>& data)
00363 throw(Exception::OutOfMemory)
00364 : origin_(data.origin_),
00365 dimension_(data.dimension_),
00366 spacing_(data.spacing_),
00367 data_()
00368 {
00369
00370 try
00371 {
00372 data_ = data.data_;
00373 }
00374 catch (std::bad_alloc&)
00375 {
00376 throw Exception::OutOfMemory(__FILE__, __LINE__, data.size() * sizeof(ValueType));
00377 }
00378 }
00379
00380 template <typename ValueType>
00381 TRegularData1D<ValueType>::TRegularData1D
00382 (const typename TRegularData1D<ValueType>::CoordinateType& origin,
00383 const typename TRegularData1D<ValueType>::CoordinateType& dimension,
00384 const typename TRegularData1D<ValueType>::CoordinateType& spacing)
00385 throw(Exception::OutOfMemory)
00386 : origin_(origin),
00387 dimension_(dimension),
00388 spacing_(spacing),
00389 data_()
00390 {
00391
00392 size_type size = (size_type)(dimension_ / spacing_ + 1.0);
00393
00394
00395 try
00396 {
00397 data_.resize(size);
00398 }
00399 catch (std::bad_alloc&)
00400 {
00401 throw Exception::OutOfMemory(__FILE__, __LINE__, size * sizeof(ValueType));
00402 }
00403 }
00404
00405 template <typename ValueType>
00406 TRegularData1D<ValueType>::TRegularData1D
00407 (const typename TRegularData1D<ValueType>::VectorType& data,
00408 const typename TRegularData1D<ValueType>::CoordinateType& origin,
00409 const typename TRegularData1D<ValueType>::CoordinateType& dimension)
00410 throw(Exception::OutOfMemory)
00411 : origin_(origin),
00412 dimension_(dimension),
00413 spacing_(dimension / ((double)data.size()-1)),
00414 data_()
00415 {
00416
00417 try
00418 {
00419 data_ = data;
00420 }
00421 catch (std::bad_alloc&)
00422 {
00423 throw Exception::OutOfMemory(__FILE__, __LINE__, data.size() * sizeof(ValueType));
00424 }
00425 }
00426
00427
00428 template <class ValueType>
00429 TRegularData1D<ValueType>::TRegularData1D
00430 (const typename TRegularData1D<ValueType>::IndexType& size)
00431 throw(Exception::OutOfMemory)
00432 : origin_(0.0),
00433 dimension_(1.0),
00434 data_()
00435 {
00436
00437 spacing_ = dimension_ / (double)(size - 1);
00438
00439 try
00440 {
00441 data_.resize(size);
00442 }
00443 catch (std::bad_alloc&)
00444 {
00445 data_.resize(0);
00446 throw Exception::OutOfMemory(__FILE__, __LINE__, size * sizeof(ValueType));
00447 }
00448 }
00449
00450 template <typename ValueType>
00451 void TRegularData1D<ValueType>::clear()
00452 {
00453
00454
00455 static ValueType default_value = ValueType();
00456 std::fill(data_.begin(), data_.end(), default_value);
00457 }
00458
00459 template <typename ValueType>
00460 TRegularData1D<ValueType>& TRegularData1D<ValueType>::operator = (const TRegularData1D<ValueType>& rhs)
00461 throw(Exception::OutOfMemory)
00462 {
00463
00464 origin_ = rhs.origin_;
00465 dimension_ = rhs.dimension_;
00466 spacing_ = rhs.spacing_;
00467 try
00468 {
00469 data_ = rhs.data_;
00470 }
00471 catch (std::bad_alloc&)
00472 {
00473 data_.resize(0);
00474 throw Exception::OutOfMemory(__FILE__, __LINE__, rhs.size() * sizeof(ValueType));
00475 }
00476
00477 return *this;
00478 }
00479
00480 template <typename ValueType>
00481 TRegularData1D<ValueType>& TRegularData1D<ValueType>::operator = (const VectorType& rhs)
00482 throw(Exception::OutOfMemory)
00483 {
00484
00485 try
00486 {
00487 data_ = rhs;
00488 }
00489 catch (std::bad_alloc&)
00490 {
00491 data_.resize(0);
00492 throw Exception::OutOfMemory(__FILE__, __LINE__, rhs.size() * sizeof(ValueType));
00493 }
00494
00495 return *this;
00496 }
00497
00498 template <typename ValueType>
00499 bool TRegularData1D<ValueType>::operator == (const TRegularData1D<ValueType>& data) const
00500 {
00501 return (origin_ == data.origin_
00502 && dimension_ == data.dimension_
00503 && data_ == data.data_);
00504 }
00505
00506 template <class ValueType>
00507 BALL_INLINE
00508 bool TRegularData1D<ValueType>::isInside(const typename TRegularData1D<ValueType>::CoordinateType& r) const
00509 {
00510 return ((r >= origin_) && (r <= (origin_ + dimension_)));
00511 }
00512
00513 template <typename ValueType>
00514 BALL_INLINE
00515 const ValueType& TRegularData1D<ValueType>::getData(const IndexType& index) const
00516 throw(Exception::OutOfGrid)
00517 {
00518 if (index >= data_.size())
00519 {
00520 throw Exception::OutOfGrid(__FILE__, __LINE__);
00521 }
00522 return data_[index];
00523 }
00524
00525 template <typename ValueType>
00526 BALL_INLINE
00527 ValueType& TRegularData1D<ValueType>::getData(const IndexType& index)
00528 throw(Exception::OutOfGrid)
00529 {
00530 if (index >= data_.size())
00531 {
00532 throw Exception::OutOfGrid(__FILE__, __LINE__);
00533 }
00534 return data_[index];
00535 }
00536
00537 template <typename ValueType>
00538 void TRegularData1D<ValueType>::getEnclosingIndices
00539 (const typename TRegularData1D<ValueType>::CoordinateType& x,
00540 Position& lower, Position& upper) const
00541 throw(Exception::OutOfGrid)
00542 {
00543 if (!isInside(x) || (data_.size() < 2))
00544 {
00545 throw Exception::OutOfGrid(__FILE__, __LINE__);
00546 }
00547 lower = (Position)floor((x - origin_) / spacing_);
00548 if (lower == data_.size() - 1)
00549 {
00550
00551 lower = data_.size() - 2;
00552 }
00553 upper = lower + 1;
00554 }
00555
00556 template <typename ValueType>
00557 void TRegularData1D<ValueType>::getEnclosingValues
00558 (const typename TRegularData1D<ValueType>::CoordinateType& x,
00559 ValueType& lower, ValueType& upper) const
00560 throw(Exception::OutOfGrid)
00561 {
00562 Position lower_index;
00563 Position upper_index;
00564 getEnclosingIndices(x, lower_index, upper_index);
00565 lower = data_[lower_index];
00566 upper = data_[upper_index];
00567 }
00568
00569 template <typename ValueType>
00570 BALL_INLINE
00571 ValueType TRegularData1D<ValueType>::getInterpolatedValue(const CoordinateType& x) const
00572 throw(Exception::OutOfGrid)
00573 {
00574 if (!isInside(x))
00575 {
00576 throw Exception::OutOfGrid(__FILE__, __LINE__);
00577 }
00578 return operator () (x);
00579 }
00580
00581 template <typename ValueType>
00582 BALL_INLINE
00583 typename TRegularData1D<ValueType>::CoordinateType TRegularData1D<ValueType>::getCoordinates
00584 (const typename TRegularData1D<ValueType>::IndexType& index) const
00585 throw(Exception::OutOfGrid)
00586 {
00587 if ((index >= data_.size()) || (data_.size() == 0))
00588 {
00589 throw Exception::OutOfGrid(__FILE__, __LINE__);
00590 }
00591
00592 return (CoordinateType)(origin_ + (double)index / ((double)data_.size()-1) * dimension_);
00593 }
00594
00595 template <typename ValueType>
00596 BALL_INLINE
00597 typename TRegularData1D<ValueType>::IndexType TRegularData1D<ValueType>::getClosestIndex(const CoordinateType& x) const
00598 throw(Exception::OutOfGrid)
00599 {
00600 if ((x < origin_) || (x > (origin_ + dimension_)))
00601 {
00602 throw Exception::OutOfGrid(__FILE__, __LINE__);
00603 }
00604
00605 return (IndexType)(size_type)floor((x - origin_) / spacing_ + 0.5);
00606 }
00607
00608 template <typename ValueType>
00609 BALL_INLINE
00610 typename TRegularData1D<ValueType>::IndexType TRegularData1D<ValueType>::getLowerIndex(const CoordinateType& x) const
00611 throw(Exception::OutOfGrid)
00612 {
00613 if ((x < origin_) || (x > (origin_ + dimension_)))
00614 {
00615 throw Exception::OutOfGrid(__FILE__, __LINE__);
00616 }
00617
00618 return (IndexType)(size_type)floor((x - origin_) / spacing_);
00619 }
00620
00621 template <typename ValueType>
00622 BALL_INLINE
00623 const ValueType& TRegularData1D<ValueType>::getClosestValue(const CoordinateType& x) const
00624 throw(Exception::OutOfGrid)
00625 {
00626 if ((x < origin_) || (x > (origin_ + dimension_)))
00627 {
00628 throw Exception::OutOfGrid(__FILE__, __LINE__);
00629 }
00630
00631
00632 size_type index = (size_type)floor((x - origin_) / spacing_ + 0.5);
00633 return data_[index];
00634 }
00635
00636 template <typename ValueType>
00637 BALL_INLINE
00638 ValueType& TRegularData1D<ValueType>::getClosestValue(const CoordinateType& x)
00639 throw(Exception::OutOfGrid)
00640 {
00641 if ((x < origin_) || (x > (origin_ + dimension_)))
00642 {
00643 throw Exception::OutOfGrid(__FILE__, __LINE__);
00644 }
00645
00646
00647 size_type index = (size_type)floor((x - origin_) / spacing_ + 0.5);
00648 return data_[index];
00649 }
00650
00651 template <typename ValueType>
00652 BALL_INLINE
00653 ValueType TRegularData1D<ValueType>::operator () (const CoordinateType& x) const
00654 {
00655 size_type left_index = (size_type)floor((x - origin_) / spacing_);
00656 if (left_index == data_.size() - 1)
00657 {
00658
00659 return data_[data_.size() - 1];
00660 }
00661
00662
00663 double d = 1.0 - (((x - origin_) - (double)left_index * spacing_) / spacing_);
00664 return data_[left_index] * d + (1.0 - d) * data_[left_index + 1];
00665 }
00666
00667 template <typename ValueType>
00668 void TRegularData1D<ValueType>::resize
00669 (const typename TRegularData1D<ValueType>::IndexType& new_size)
00670 throw(Exception::OutOfMemory)
00671 {
00672
00673 if (data_.size() > 0)
00674 {
00675 dimension_ *= (double)new_size / (double)data_.size();
00676 }
00677
00678
00679 try
00680 {
00681 data_.resize(new_size);
00682 }
00683 catch (std::bad_alloc&)
00684 {
00685
00686 data_.resize(0);
00687 throw Exception::OutOfMemory(__FILE__, __LINE__, new_size * sizeof(ValueType));
00688 }
00689 }
00690
00691 template <typename ValueType>
00692 void TRegularData1D<ValueType>::rescale
00693 (const typename TRegularData1D<ValueType>::IndexType& new_size)
00694 throw(Exception::OutOfMemory)
00695 {
00696
00697 if (new_size == (IndexType)data_.size())
00698 {
00699 return;
00700 }
00701
00702
00703 try
00704 {
00705
00706 if (data_.size() == 0)
00707 {
00708
00709 data_.resize(new_size);
00710 return;
00711 }
00712
00713
00714
00715 if ((data_.size() == 1) && (new_size > 1))
00716 {
00717 ValueType old_value = data_[0];
00718 data_.resize(new_size);
00719 for (IndexType i = 1; i < new_size; i++)
00720 {
00721 data_[i] = old_value;
00722 }
00723
00724 return;
00725 }
00726
00727
00728
00729 VectorType new_data(new_size);
00730 CoordinateType factor1 = (CoordinateType)data_.size() / (CoordinateType)new_size;
00731 CoordinateType factor2 = (CoordinateType)(data_.size() - 1) / (new_size - 1);
00732
00733 for (Size i = 0; i < new_size; i++)
00734 {
00735
00736
00737 IndexType old_idx = (IndexType)((CoordinateType)i * factor1);
00738
00739
00740 if (old_idx >= (data_.size() - 1))
00741 {
00742 old_idx = data_.size() - 2;
00743 }
00744 CoordinateType factor3 = (CoordinateType)i * factor2 - (CoordinateType)old_idx;
00745 new_data[i] = data_[old_idx] * (1 - factor3) + factor3 * data_[old_idx + 1];
00746 }
00747
00748
00749 data_ = new_data;
00750 }
00751 catch (std::bad_alloc&)
00752 {
00753
00754 data_.resize(0);
00755 throw Exception::OutOfMemory(__FILE__, __LINE__, new_size * sizeof(ValueType));
00756 }
00757 }
00758
00761
00762 template <typename ValueType>
00763 std::ostream& operator << (std::ostream& os, const TRegularData1D<ValueType>& data)
00764 {
00765
00766 os << data.getOrigin() << std::endl
00767 << data.getOrigin() + data.getDimension() << std::endl
00768 << data.getSize() - 1 << std::endl;
00769
00770
00771 std::copy(data.begin(), data.end(), std::ostream_iterator<ValueType>(os, "\n"));
00772 return os;
00773 }
00774
00776 template <typename ValueType>
00777 std::istream& operator >> (std::istream& is, TRegularData1D<ValueType>& grid)
00778 {
00779 typename TRegularData1D<ValueType>::CoordinateType origin;
00780 typename TRegularData1D<ValueType>::CoordinateType dimension;
00781 typename TRegularData1D<ValueType>::IndexType size;
00782
00783 is >> origin;
00784 is >> dimension;
00785 is >> size;
00786
00787 dimension -= origin;
00788 size++;
00789
00790 grid.resize(size);
00791 grid.setOrigin(origin);
00792 grid.setDimension(dimension);
00793
00794 std::copy(std::istream_iterator<ValueType>(is),
00795 std::istream_iterator<ValueType>(),
00796 grid.begin());
00797
00798
00799 return is;
00800 }
00801
00802 template <typename ValueType>
00803 void TRegularData1D<ValueType>::binaryWrite(const String& filename) const
00804 throw(Exception::FileNotFound)
00805 {
00806 File outfile(filename, std::ios::out|std::ios::binary);
00807 if (!outfile.isValid())
00808 {
00809 throw Exception::FileNotFound(__FILE__, __LINE__, filename);
00810 }
00811
00812 BinaryFileAdaptor<BlockValueType> adapt_block;
00813 BinaryFileAdaptor<ValueType> adapt_single;
00814
00815
00816 BinaryFileAdaptor<CoordinateType> adapt_coordinate;
00817 BinaryFileAdaptor<Size> adapt_size;
00818
00819 adapt_size.setData(data_.size());
00820 outfile << adapt_size;
00821
00822 adapt_coordinate.setData(origin_);
00823 outfile << adapt_coordinate;
00824
00825 adapt_coordinate.setData(dimension_);
00826 outfile << adapt_coordinate;
00827
00828 adapt_coordinate.setData(spacing_);
00829 outfile << adapt_coordinate;
00830
00831
00832 Index window_pos = 0;
00833 while (((int)data_.size() - (1024 + window_pos)) >= 0 )
00834 {
00835 adapt_block.setData(*(BlockValueType*)&(data_[window_pos]));
00836 outfile << adapt_block;
00837 window_pos += 1024;
00838 }
00839
00840
00841 for (Size i = window_pos; i < data_.size(); i++)
00842 {
00843 adapt_single.setData(data_[i]);
00844 outfile << adapt_single;
00845 }
00846
00847
00848 outfile.close();
00849 }
00850
00851 template <typename ValueType>
00852 void TRegularData1D<ValueType>::binaryRead(const String& filename)
00853 throw(Exception::FileNotFound)
00854 {
00855 File infile(filename, std::ios::in|std::ios::binary);
00856 if (!infile.isValid()) throw Exception::FileNotFound(__FILE__, __LINE__, filename);
00857
00858 BinaryFileAdaptor<BlockValueType> adapt_block;
00859 BinaryFileAdaptor<ValueType> adapt_single;
00860
00861
00862 BinaryFileAdaptor<CoordinateType> adapt_coordinate;
00863 BinaryFileAdaptor<Size> adapt_size;
00864
00865 infile >> adapt_size;
00866 Size new_size = adapt_size.getData();
00867
00868 infile >> adapt_coordinate;
00869 origin_ = adapt_coordinate.getData();
00870
00871 infile >> adapt_coordinate;
00872 dimension_ = adapt_coordinate.getData();
00873
00874 infile >> adapt_coordinate;
00875 spacing_ = adapt_coordinate.getData();
00876
00877 data_.resize(new_size);
00878
00879
00880 Index window_pos = 0;
00881
00882 while ( ((int)data_.size() - (1024 + window_pos)) >= 0 )
00883 {
00884 infile >> adapt_block;
00885 *(BlockValueType*)(&(data_[window_pos])) = adapt_block.getData();
00886
00887
00888
00889
00890
00891
00892 window_pos+=1024;
00893 }
00894
00895
00896 for (Size i=window_pos; i<data_.size(); i++)
00897 {
00898 infile >> adapt_single;
00899 data_[i] = adapt_single.getData();
00900 }
00901
00902
00903 infile.close();
00904 }
00905 }
00906
00907 #endif // BALL_DATATYPE_REGULARDATA1D_H