00001
00002
00003
00004
00005
00006
00007 #ifndef BALL_MATHS_TFFT2D_H
00008 #define BALL_MATHS_TFFT2D_H
00009
00010 #ifndef BALL_COMMON_EXCEPTION_H
00011 # include <BALL/COMMON/exception.h>
00012 #endif
00013
00014 #ifndef BALL_DATATYPE_REGULARDATA2D_H
00015 # include <BALL/DATATYPE/regularData2D.h>
00016 #endif
00017
00018 #ifndef BALL_MATHS_VECTOR2_H
00019 # include <BALL/MATHS/vector2.h>
00020 #endif
00021
00022 #include <math.h>
00023 #include <complex>
00024 #include <fftw3.h>
00025
00026 #include <BALL/MATHS/fftwCommon.h>
00027
00028
00029 namespace BALL
00030 {
00042 template <typename ComplexTraits>
00043 class TFFT2D
00044 : public TRegularData2D<std::complex<typename ComplexTraits::ComplexPrecision> >
00045 {
00046 public:
00047
00048 typedef std::complex<typename ComplexTraits::ComplexPrecision> Complex;
00049 typedef TRegularData2D<std::complex<typename ComplexTraits::ComplexPrecision> > ComplexVector;
00050 typedef typename TRegularData2D<std::complex<typename ComplexTraits::ComplexPrecision> >::IndexType IndexType;
00051
00052 BALL_CREATE(TFFT2D)
00053
00054
00057
00058
00059 TFFT2D();
00060
00062 TFFT2D(const TFFT2D &data);
00063
00073
00074 TFFT2D(Size nX, Size nY, double stepPhysX=1., double stepPhysY=1., Vector2 origin=Vector2(0.,0.), bool inFourierSpace=false);
00075
00077 virtual ~TFFT2D();
00078
00080
00084
00086 const TFFT2D& operator = (const TFFT2D& fft_2d);
00087
00090 virtual void clear();
00091
00094 virtual void destroy();
00095
00097
00101
00104 bool operator == (const TFFT2D& fft_2d) const;
00106
00107
00108
00111 void doFFT();
00112
00115 void doiFFT();
00116
00122 bool translate(const Vector2& trans_origin);
00123
00129 bool setPhysStepWidth(double new_width_x, double new_width_y);
00130
00133 double getPhysStepWidthX() const;
00134
00137 double getPhysStepWidthY() const;
00138
00141 double getFourierStepWidthX() const;
00142
00145 double getFourierStepWidthY() const;
00146
00149 double getPhysSpaceMinX() const;
00150
00153 double getPhysSpaceMinY() const;
00154
00157 double getPhysSpaceMaxX() const;
00158
00161 double getPhysSpaceMaxY() const;
00162
00165 double getFourierSpaceMinX() const;
00166
00169 double getFourierSpaceMinY() const;
00170
00173 double getFourierSpaceMaxX() const;
00174
00177 double getFourierSpaceMaxY() const;
00178
00184 Size getMaxXIndex() const;
00185
00191 Size getMaxYIndex() const;
00192
00196 Size getNumberOfInverseTransforms() const;
00197
00200 Vector2 getGridCoordinates(Position position) const;
00201
00206 Complex getData(const Vector2& pos) const
00207 throw(Exception::OutOfGrid);
00208
00214 Complex getInterpolatedValue(const Vector2& pos) const
00215 throw(Exception::OutOfGrid);
00216
00222 void setData(const Vector2& pos, Complex val)
00223 throw(Exception::OutOfGrid);
00224
00228 Complex& operator[](const Vector2& pos)
00229 throw(Exception::OutOfGrid);
00230
00234 const Complex& operator[](const Vector2& pos) const
00235 throw(Exception::OutOfGrid);
00236
00237
00242 const Complex& operator [] (const IndexType& index) const { return TRegularData2D<Complex>::operator [](index); }
00243
00248 Complex& operator [] (const IndexType& index) { return TRegularData2D<Complex>::operator [](index); }
00249
00252 Complex& operator[](const Position& pos)
00253 throw(Exception::OutOfGrid)
00254 {
00255 return TRegularData2D<Complex>::operator [] (pos);
00256 }
00257
00260 const Complex& operator[](const Position& pos) const
00261 throw(Exception::OutOfGrid)
00262 {
00263 return TRegularData2D<Complex>::operator [] (pos);
00264 }
00265
00266
00267 void setNumberOfFFTTransforms(Size num)
00268 {
00269 numPhysToFourier_ = num;
00270 }
00271
00272
00273 void setNumberOfiFFTTransforms(Size num)
00274 {
00275 numFourierToPhys_ = num;
00276 }
00277
00282 Complex phase(const Vector2& pos) const;
00283
00287 bool isInFourierSpace() const;
00288
00289 protected:
00290 Size lengthX_, lengthY_;
00291 bool inFourierSpace_;
00292 Size numPhysToFourier_;
00293 Size numFourierToPhys_;
00294 Vector2 origin_;
00295 double stepPhysX_, stepPhysY_;
00296 double stepFourierX_, stepFourierY_;
00297 Vector2 minPhys_, maxPhys_;
00298 Vector2 minFourier_, maxFourier_;
00299
00300
00301 typename ComplexTraits::FftwPlan planForward_;
00302 typename ComplexTraits::FftwPlan planBackward_;
00303
00304
00305
00306 Size dataLength_;
00307 Complex *dataAdress_;
00308 bool planCalculated_;
00309
00310 };
00311
00314 typedef TFFT2D<BALL_FFTW_DEFAULT_TRAITS> FFT2D;
00315
00316
00319 template <typename ComplexTraits>
00320 const TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>& operator<<
00321 (TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>& to, const TFFT2D<ComplexTraits>& from);
00322
00327 template <typename ComplexTraits>
00328 const RegularData2D& operator << (RegularData2D& to, const TFFT2D<ComplexTraits>& from);
00329
00330 template <typename ComplexTraits>
00331 TFFT2D<ComplexTraits>::TFFT2D()
00332 : TRegularData2D<Complex>(),
00333 dataLength_(0),
00334 dataAdress_(0),
00335 planCalculated_(false)
00336 {
00337 }
00338
00339 template <typename ComplexTraits>
00340 bool TFFT2D<ComplexTraits>::operator == (const TFFT2D<ComplexTraits>& fft2D) const
00341 {
00342
00343
00344
00345 if (lengthX_ == fft2D.lengthX_ &&
00346 lengthY_ == fft2D.lengthY_ &&
00347 origin_ == fft2D.origin_ &&
00348 stepPhysX_ == fft2D.stepPhysX_ &&
00349 stepPhysY_ == fft2D.stepPhysY_ &&
00350 stepFourierX_ == fft2D.stepFourierX_ &&
00351 stepFourierY_ == fft2D.stepFourierY_ &&
00352 minPhys_ == fft2D.minPhys_ &&
00353 maxPhys_ == fft2D.maxPhys_ &&
00354 minFourier_ == fft2D.minFourier_ &&
00355 maxFourier_ == fft2D.maxFourier_ &&
00356 numPhysToFourier_ == fft2D.numPhysToFourier_ &&
00357 numFourierToPhys_ == fft2D.numFourierToPhys_)
00358 {
00359 Vector2 min = inFourierSpace_ ? minFourier_ : minPhys_;
00360 Vector2 max = inFourierSpace_ ? maxFourier_ : maxPhys_;
00361 double stepX = inFourierSpace_ ? stepFourierX_ : stepPhysX_;
00362 double stepY = inFourierSpace_ ? stepFourierY_ : stepPhysY_;
00363
00364 for (double posX=min.x; posX<=max.x; posX+=stepX)
00365 {
00366 for (double posY=min.y; posY<=max.y; posY+=stepY)
00367 {
00368 if (getData(Vector2(posX,posY)) != fft2D.getData(Vector2(posX,posY)))
00369 {
00370 return false;
00371 }
00372 }
00373 }
00374
00375 return true;
00376 }
00377
00378 return false;
00379 }
00380
00381 template <typename ComplexTraits>
00382 bool TFFT2D<ComplexTraits>::translate(const Vector2& trans_origin)
00383 {
00384 Position internalOriginX = (Position) Maths::rint(trans_origin.x*stepPhysX_);
00385 Position internalOriginY = (Position) Maths::rint(trans_origin.y*stepPhysY_);
00386
00387 if ((internalOriginX <= lengthX_) && (internalOriginY <= lengthY_))
00388 {
00389 origin_.x = trans_origin.x;
00390 origin_.y = trans_origin.y;
00391
00392 minPhys_ = Vector2(-origin_.x,-origin_.y);
00393 maxPhys_ = Vector2(((lengthX_-1)*stepPhysX_)-origin_.x,((lengthY_-1)*stepPhysY_)-origin_.y);
00394 minFourier_ = Vector2(-(lengthX_/2.-1)*stepFourierX_,-(lengthY_/2.-1)*stepFourierY_);
00395 maxFourier_ = Vector2((lengthX_/2.)*stepFourierX_,(lengthY_/2.)*stepFourierY_);
00396
00397 return true;
00398 }
00399 else
00400 {
00401 return false;
00402 }
00403 }
00404
00405 template <typename ComplexTraits>
00406 bool TFFT2D<ComplexTraits>::setPhysStepWidth(double new_width_x, double new_width_y)
00407 {
00408 if ((new_width_x <= 0) || (new_width_y <= 0))
00409 {
00410 return false;
00411 }
00412 else
00413 {
00414 stepPhysX_ = new_width_x;
00415 stepPhysY_ = new_width_y;
00416 stepFourierX_ = 2.*M_PI/(stepPhysX_*lengthX_);
00417 stepFourierY_ = 2.*M_PI/(stepPhysY_*lengthY_);
00418
00419 minPhys_ = Vector2(-origin_.x,-origin_.y);
00420 maxPhys_ = Vector2(((lengthX_-1)*stepPhysX_)-origin_.x,((lengthY_-1)*stepPhysY_)-origin_.y);
00421 minFourier_ = Vector2(-(lengthX_/2.-1)*stepFourierX_,-(lengthY_/2.-1)*stepFourierY_);
00422 maxFourier_ = Vector2((lengthX_/2.)*stepFourierX_,(lengthY_/2.)*stepFourierY_);
00423
00424 return true;
00425 }
00426 }
00427
00428 template <typename ComplexTraits>
00429 double TFFT2D<ComplexTraits>::getPhysStepWidthX() const
00430 {
00431 return stepPhysX_;
00432 }
00433
00434 template <typename ComplexTraits>
00435 double TFFT2D<ComplexTraits>::getPhysStepWidthY() const
00436 {
00437 return stepPhysY_;
00438 }
00439
00440 template <typename ComplexTraits>
00441 double TFFT2D<ComplexTraits>::getFourierStepWidthX() const
00442 {
00443 return stepFourierX_;
00444 }
00445
00446 template <typename ComplexTraits>
00447 double TFFT2D<ComplexTraits>::getFourierStepWidthY() const
00448 {
00449 return stepFourierY_;
00450 }
00451
00452 template <typename ComplexTraits>
00453 double TFFT2D<ComplexTraits>::getPhysSpaceMinX() const
00454 {
00455 return minPhys_.x;
00456 }
00457
00458 template <typename ComplexTraits>
00459 double TFFT2D<ComplexTraits>::getPhysSpaceMinY() const
00460 {
00461 return minPhys_.y;
00462 }
00463
00464 template <typename ComplexTraits>
00465 double TFFT2D<ComplexTraits>::getPhysSpaceMaxX() const
00466 {
00467 return maxPhys_.x;
00468 }
00469
00470 template <typename ComplexTraits>
00471 double TFFT2D<ComplexTraits>::getPhysSpaceMaxY() const
00472 {
00473 return maxPhys_.y;
00474 }
00475
00476 template <typename ComplexTraits>
00477 double TFFT2D<ComplexTraits>::getFourierSpaceMinX() const
00478 {
00479 return minFourier_.x;
00480 }
00481
00482 template <typename ComplexTraits>
00483 double TFFT2D<ComplexTraits>::getFourierSpaceMinY() const
00484 {
00485 return minFourier_.y;
00486 }
00487
00488 template <typename ComplexTraits>
00489 double TFFT2D<ComplexTraits>::getFourierSpaceMaxX() const
00490 {
00491 return maxFourier_.x;
00492 }
00493
00494 template <typename ComplexTraits>
00495 double TFFT2D<ComplexTraits>::getFourierSpaceMaxY() const
00496 {
00497 return maxFourier_.y;
00498 }
00499
00500 template <typename ComplexTraits>
00501 Size TFFT2D<ComplexTraits>::getMaxXIndex() const
00502 {
00503 return (lengthX_ - 1);
00504 }
00505
00506 template <typename ComplexTraits>
00507 Size TFFT2D<ComplexTraits>::getMaxYIndex() const
00508 {
00509 return (lengthY_ - 1);
00510 }
00511
00512 template <typename ComplexTraits>
00513 Size TFFT2D<ComplexTraits>::getNumberOfInverseTransforms() const
00514 {
00515 return numFourierToPhys_;
00516 }
00517
00518
00519 template <typename ComplexTraits>
00520 Vector2 TFFT2D<ComplexTraits>::getGridCoordinates(Position position) const
00521 {
00522 if (!inFourierSpace_)
00523 {
00524 if (position >= ComplexVector::size())
00525 {
00526 throw Exception::OutOfGrid(__FILE__, __LINE__);
00527 }
00528
00529 Vector2 r;
00530 Position x, y;
00531
00532
00533
00534 y = position % lengthY_;
00535 x = position / lengthY_;
00536
00537 r.set(-origin_.x + (float)x * stepPhysX_,
00538 -origin_.y + (float)y * stepPhysY_);
00539
00540 return r;
00541 }
00542 else
00543 {
00544 if (position >= ComplexVector::size())
00545 {
00546 throw Exception::OutOfGrid(__FILE__, __LINE__);
00547 }
00548
00549 Vector2 r;
00550 Index x, y;
00551
00552
00553 y = position % lengthY_;
00554 x = position / lengthY_;
00555
00556 if (x>=lengthX_/2.)
00557 {
00558 x-=lengthX_;
00559 }
00560
00561 if (y>=lengthY_/2.)
00562 {
00563 y-=lengthY_;
00564 }
00565
00566 r.set((float)x * stepFourierX_,
00567 (float)y * stepFourierY_);
00568
00569 return r;
00570 }
00571 }
00572
00573
00574
00575 template <typename ComplexTraits>
00576 typename TFFT2D<ComplexTraits>::Complex TFFT2D<ComplexTraits>::getData(const Vector2& pos) const
00577 throw(Exception::OutOfGrid)
00578 {
00579 Complex result;
00580 double normalization=1.;
00581
00582 if (!inFourierSpace_)
00583 {
00584 result = (*this)[pos];
00585 normalization=1./((float)pow((float)(lengthX_*lengthY_),(int)numFourierToPhys_));
00586 }
00587 else
00588 {
00589 result = (*this)[pos] * phase(pos);
00590 normalization=1./(2.*M_PI)*(stepPhysX_*stepPhysY_)/((float)pow((float)(lengthX_*lengthY_),(int)numFourierToPhys_));
00591 }
00592
00593 result *= normalization;
00594
00595 return result;
00596 }
00597
00598 template <typename ComplexTraits>
00599 typename TFFT2D<ComplexTraits>::Complex TFFT2D<ComplexTraits>::getInterpolatedValue(const Vector2& pos) const
00600 throw(Exception::OutOfGrid)
00601 {
00602 Complex result;
00603
00604 Vector2 min = inFourierSpace_ ? minFourier_ : minPhys_;
00605 Vector2 max = inFourierSpace_ ? maxFourier_ : maxPhys_;
00606 double stepX = inFourierSpace_ ? stepFourierX_ : stepPhysX_;
00607 double stepY = inFourierSpace_ ? stepFourierY_ : stepPhysY_;
00608
00609 if ( (pos.x < min.x) || (pos.y < min.y)
00610 || (pos.x > max.x) || (pos.y > max.y) )
00611 {
00612 throw Exception::OutOfGrid(__FILE__, __LINE__);
00613 }
00614
00615 Vector2 h(pos.x - min.x, pos.y - min.y);
00616 double modX = fmod((double)h.x,stepX);
00617 double modY = fmod((double)h.y,stepY);
00618
00619 if (modX==0 && modY ==0)
00620 {
00621 return getData(pos);
00622 }
00623
00624 double beforeX = floor(h.x/stepX)*stepX+ min.x;
00625 double beforeY = floor(h.y/stepY)*stepY+ min.y;
00626 double afterX = ceil(h.x/stepX)*stepX+ min.x;
00627 double afterY = ceil(h.y/stepY)*stepY+ min.y;
00628
00629 double tx = (pos.x - beforeX)/stepX;
00630 double ty = (pos.y - beforeY)/stepY;
00631
00632 result = getData(Vector2(beforeX,beforeY))*(typename ComplexTraits::ComplexPrecision)((1.-tx)*(1.-ty));
00633 result += getData(Vector2(afterX, beforeY))*(typename ComplexTraits::ComplexPrecision)( tx *(1.-ty));
00634 result += getData(Vector2(beforeX,afterY ))*(typename ComplexTraits::ComplexPrecision)((1.-tx)* ty );
00635 result += getData(Vector2(afterX, afterY ))*(typename ComplexTraits::ComplexPrecision)( tx * ty );
00636
00637 return result;
00638 }
00639
00640 template <typename ComplexTraits>
00641 void TFFT2D<ComplexTraits>::setData(const Vector2& pos, Complex val)
00642 throw(Exception::OutOfGrid)
00643 {
00644 Complex dummy;
00645
00646 if (!inFourierSpace_)
00647 {
00648 dummy = Complex(val.real()*((float)pow((float)(lengthX_*lengthY_),(int)numFourierToPhys_)),
00649 val.imag()*((float)pow((float)(lengthX_*lengthY_),(int)numFourierToPhys_)));
00650
00651 (*this)[pos]=dummy;
00652 }
00653 else
00654 {
00655 val*=phase(pos)*(typename ComplexTraits::ComplexPrecision)((2*M_PI/(stepPhysX_*stepPhysY_)))
00656 *(typename ComplexTraits::ComplexPrecision)pow((typename ComplexTraits::ComplexPrecision)(lengthX_*lengthY_),(int)numFourierToPhys_);
00657
00658 dummy = val;
00659
00660 (*this)[pos]=dummy;
00661 }
00662 }
00663
00664 template <typename ComplexTraits>
00665 typename TFFT2D<ComplexTraits>::Complex& TFFT2D<ComplexTraits>::operator[](const Vector2& pos)
00666 throw(Exception::OutOfGrid)
00667 {
00668 Index internalPos;
00669
00670 if (!inFourierSpace_)
00671 {
00672 Index i, j;
00673
00674 i = (Index) Maths::rint((pos.x+origin_.x)/stepPhysX_);
00675 j = (Index) Maths::rint((pos.y+origin_.y)/stepPhysY_);
00676
00677 internalPos = j + i*lengthY_;
00678 }
00679 else
00680 {
00681 Index i, j;
00682
00683 i = (Index) Maths::rint(pos.x/stepFourierX_);
00684 j = (Index) Maths::rint(pos.y/stepFourierY_);
00685
00686 if (i<0)
00687 {
00688 i+=lengthX_;
00689 }
00690
00691 if (j<0)
00692 {
00693 j+=lengthY_;
00694 }
00695
00696 internalPos = (j + i*lengthY_);
00697 }
00698
00699 if ((internalPos < 0) || (internalPos>=(Index) (lengthX_*lengthY_)))
00700 {
00701 throw Exception::OutOfGrid(__FILE__, __LINE__);
00702 }
00703
00704 return operator [] (internalPos);
00705 }
00706
00707 template <typename ComplexTraits>
00708 const typename TFFT2D<ComplexTraits>::Complex& TFFT2D<ComplexTraits>::operator[](const Vector2& pos) const
00709 throw(Exception::OutOfGrid)
00710 {
00711 Index internalPos;
00712
00713 if (!inFourierSpace_)
00714 {
00715 Index i, j;
00716
00717 i = (Index) Maths::rint((pos.x+origin_.x)/stepPhysX_);
00718 j = (Index) Maths::rint((pos.y+origin_.y)/stepPhysY_);
00719
00720 internalPos = j + i*lengthY_;
00721 }
00722 else
00723 {
00724 Index i, j;
00725
00726 i = (Index) Maths::rint(pos.x/stepFourierX_);
00727 j = (Index) Maths::rint(pos.y/stepFourierY_);
00728
00729 if (i<0)
00730 {
00731 i+=lengthX_;
00732 }
00733
00734 if (j<0)
00735 {
00736 j+=lengthY_;
00737 }
00738
00739 internalPos = (j + i*lengthY_);
00740 }
00741
00742 if ((internalPos < 0) || (internalPos>=(Index) (lengthX_*lengthY_)))
00743 {
00744 throw Exception::OutOfGrid(__FILE__, __LINE__);
00745 }
00746
00747 return operator [] (internalPos);
00748 }
00749
00750 template <typename ComplexTraits>
00751 typename TFFT2D<ComplexTraits>::Complex TFFT2D<ComplexTraits>::phase(const Vector2& pos) const
00752 {
00753 double phase = 2.*M_PI*( Maths::rint(pos.x/stepFourierX_)*Maths::rint(origin_.x/stepPhysX_)
00754 /lengthX_
00755 + Maths::rint(pos.y/stepFourierY_)*Maths::rint(origin_.y/stepPhysY_)
00756 /lengthY_ );
00757
00758 Complex result = Complex(cos(phase), sin(phase));
00759
00760 return result;
00761 }
00762
00763 template <typename ComplexTraits>
00764 bool TFFT2D<ComplexTraits>::isInFourierSpace() const
00765 {
00766 return inFourierSpace_;
00767 }
00768
00769 template <typename ComplexTraits>
00770 const TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>& operator <<
00771 (TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>& to, const TFFT2D<ComplexTraits>& from)
00772 {
00773
00774 if (!from.isInFourierSpace())
00775 {
00776
00777 Size lengthX = from.getMaxXIndex()+1;
00778 Size lengthY = from.getMaxYIndex()+1;
00779
00780 TRegularData2D<typename TFFT2D<ComplexTraits>::Complex> newGrid(TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>::IndexType(lengthX, lengthY),
00781 Vector2(from.getPhysSpaceMinX(), from.getPhysSpaceMinY()),
00782 Vector2(from.getPhysSpaceMaxX(), from.getPhysSpaceMaxY()));
00783
00784
00785 double normalization=1./(pow((float)(lengthX*lengthY),from.getNumberOfInverseTransforms()));
00786 typename TFFT2D<ComplexTraits>::Complex dataIn;
00787 typename TFFT2D<ComplexTraits>::Complex dataOut;
00788
00789 for (Position i = 0; i < from.size(); i++)
00790 {
00791 Position x, y;
00792
00793 y = i % lengthY;
00794 x = i / lengthY;
00795
00796 dataIn = from[i];
00797 dataOut = dataIn;
00798
00799 newGrid[x + y*lengthY] = dataOut*(typename ComplexTraits::ComplexPrecision)normalization;
00800 }
00801
00802 to = newGrid;
00803
00804 return to;
00805 }
00806 else
00807 {
00808
00809
00810
00811 Size lengthX = from.getMaxXIndex()+1;
00812 Size lengthY = from.getMaxYIndex()+1;
00813
00814
00815 float stepFourierX = from.getFourierStepWidthX();
00816 float stepFourierY = from.getFourierStepWidthY();
00817
00818
00819
00820 TRegularData2D<typename TFFT2D<ComplexTraits>::Complex> newGrid(TRegularData2D<typename TFFT2D<ComplexTraits>::Complex>::IndexType(lengthX, lengthY),
00821 Vector2(from.getFourierSpaceMinX(),
00822 from.getFourierSpaceMinY()),
00823 Vector2(from.getFourierSpaceMaxX(),
00824 from.getFourierSpaceMaxY()));
00825
00826
00827
00828 double normalization=1./(2.*M_PI)/(pow((float)(lengthX*lengthY),from.getNumberOfInverseTransforms()));
00829
00830
00831 Index x, y;
00832 Vector2 r;
00833 typename TFFT2D<ComplexTraits>::Complex dataIn;
00834 typename TFFT2D<ComplexTraits>::Complex dataOut;
00835
00836 for (Position i = 0; i < from.size(); i++)
00837 {
00838 y = i % lengthY;
00839 x = i / lengthY;
00840
00841 if (x>lengthX/2.)
00842 {
00843 x-=lengthX;
00844 }
00845
00846 if (y>lengthY/2.)
00847 {
00848 y-=lengthY;
00849 }
00850
00851 r.set((float)x * stepFourierX,
00852 (float)y * stepFourierY);
00853
00854 dataIn = from[i];
00855 dataOut = dataIn;
00856
00857 newGrid[x + y*lengthY] = dataOut*(typename ComplexTraits::ComplexPrecision)normalization*from.phase(r);
00858 }
00859
00860 to = newGrid;
00861
00862 return to;
00863 }
00864 }
00865
00866 template <typename ComplexTraits>
00867 const RegularData2D& operator << (RegularData2D& to, const TFFT2D<ComplexTraits>& from)
00868 {
00869
00870 if (!from.isInFourierSpace())
00871 {
00872
00873 Size lengthX = from.getMaxXIndex()+1;
00874 Size lengthY = from.getMaxYIndex()+1;
00875
00876 RegularData2D newGrid(RegularData2D::IndexType(lengthX, lengthY),
00877 Vector2(from.getPhysSpaceMinX(),
00878 from.getPhysSpaceMinY()),
00879 Vector2(from.getPhysSpaceMaxX(),
00880 from.getPhysSpaceMaxY()));
00881
00882
00883 double normalization = 1./(pow((float)(lengthX*lengthY),from.getNumberOfInverseTransforms()));
00884 typename TFFT2D<ComplexTraits>::Complex dataIn;
00885 typename TFFT2D<ComplexTraits>::Complex dataOut;
00886
00887 typename TFFT2D<ComplexTraits>::IndexType current_index;
00888 typename RegularData2D::IndexType regdat_index;
00889 for (current_index.x = 0; current_index.x < lengthX; current_index.x++)
00890 {
00891 for (current_index.y = 0; current_index.y < lengthY; current_index.y++)
00892 {
00893 regdat_index.x = current_index.x;
00894 regdat_index.y = current_index.y;
00895
00896 dataIn = from[current_index];
00897 dataOut = dataIn;
00898
00899 newGrid[regdat_index] = dataOut.real()*normalization;
00900 }
00901 }
00902
00903 to = newGrid;
00904
00905 return to;
00906 }
00907 else
00908 {
00909
00910
00911
00912 Size lengthX = from.getMaxXIndex()+1;
00913 Size lengthY = from.getMaxYIndex()+1;
00914
00915
00916 float stepFourierX = from.getFourierStepWidthX();
00917 float stepFourierY = from.getFourierStepWidthY();
00918
00919 RegularData2D newGrid(RegularData2D::IndexType(lengthX, lengthY), Vector2(from.getFourierSpaceMinX(), from.getFourierSpaceMinY()), Vector2(from.getFourierSpaceMaxX(), from.getFourierSpaceMaxY()));
00920
00921
00922
00923 double normalization=1./(2.*M_PI)/(pow((float)(lengthX*lengthY),from.getNumberOfInverseTransforms()));
00924
00925 Index x, y;
00926 signed int xp, yp;
00927 Vector2 r;
00928 typename TFFT2D<ComplexTraits>::Complex dataIn;
00929 typename TFFT2D<ComplexTraits>::Complex dataOut;
00930
00931 RegularData2D::IndexType current_index;
00932 for (Position i = 0; i < from.size(); i++)
00933 {
00934 y = i % lengthY;
00935 x = i / lengthY;
00936
00937 xp = x;
00938 yp = y;
00939
00940 if (xp>=lengthX/2.)
00941 {
00942 xp-=(int)lengthX;
00943 }
00944 if (yp>=lengthY/2.)
00945 {
00946 yp-=(int)lengthY;
00947 }
00948
00949 if (x>=lengthX/2.)
00950 {
00951 x-=(int)(lengthX/2.);
00952 }
00953 else
00954 {
00955 x+=(int)(lengthX/2.);
00956 }
00957
00958 if (y>=lengthY/2.)
00959 {
00960 y-=(int)(lengthY/2.);
00961 }
00962 else
00963 {
00964 y+=(int)(lengthY/2.);
00965 }
00966
00967
00968 r.set((float)xp * stepFourierX,
00969 (float)yp * stepFourierY);
00970
00971 dataIn = from[i];
00972 dataOut = dataIn;
00973
00974 current_index.x = x;
00975 current_index.y = y;
00976
00977 newGrid[current_index] = (dataOut*(typename ComplexTraits::ComplexPrecision)normalization*from.phase(r)).real();
00978 }
00979
00980 to = newGrid;
00981
00982 return to;
00983 }
00984 }
00985
00986
00987
00988 }
00989
00990 #endif // BALL_MATHS_TFFT2D_H