boxIntegrator2D.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLRNUMERIC_BOXINTEGRATOR2D_H_
00016 #define _DLRNUMERIC_BOXINTEGRATOR2D_H_
00017 
00018 #include <dlrNumeric/array2D.h>
00019 #include <dlrNumeric/index2D.h>
00020 
00021 
00022 namespace dlr {
00023 
00024   namespace numeric {
00025 
00038     template <class Type0, class Type1>
00039     class BoxIntegrator2D {
00040     public:
00041 
00046       inline
00047       BoxIntegrator2D();
00048 
00049 
00060       explicit
00061       BoxIntegrator2D(const Array2D<Type0>& inputArray);
00062 
00063 
00077       template <class Functor>
00078       explicit
00079       BoxIntegrator2D(const Array2D<Type0>& inputArray, Functor functor);
00080 
00081 
00100       BoxIntegrator2D(const Array2D<Type0>& inputArray,
00101                       const Index2D& corner0,
00102                       const Index2D& corner1);
00103 
00104 
00114       BoxIntegrator2D(const BoxIntegrator2D& other);
00115 
00116 
00166       Type1
00167       getIntegral(const Index2D& corner0, const Index2D& corner1);
00168 
00169 
00199       Type1
00200       getIntegral(const Index2D& corner0, const Index2D& corner1, bool dummy);
00201 
00202 
00220       Type1
00221       getRawIntegral(size_t row, size_t column);
00222 
00223 
00234       Type1
00235       getRawIntegral(size_t index0);
00236 
00237 
00249       void
00250       setArray(const Array2D<Type0>& inputArray);
00251 
00252       
00268       template <class Functor>
00269       void
00270       setArray(const Array2D<Type0>& inputArray, Functor functor);
00271 
00272       
00291       void
00292       setArray(const Array2D<Type0>& inputArray,
00293                const Index2D& corner0,
00294                const Index2D& corner1);
00295 
00296 
00317       template <class Functor>
00318       void
00319       setArray(const Array2D<Type0>& inputArray,
00320                const Index2D& corner0,
00321                const Index2D& corner1,
00322                Functor functor);
00323 
00324 
00325     protected:
00326 
00327 
00344       template <class Functor>
00345       void
00346       fillCache(typename Array2D<Type0>::const_iterator inIter,
00347                 int roiRows,
00348                 int roiColumns,
00349                 int inputArrayColumns,
00350                 Functor functor);
00351 
00352 
00353       Array2D<Type1> m_cache;
00354       Index2D m_corner0;
00355     };
00356 
00357 
00358   } // namespace numeric
00359   
00360 } // namespace dlr
00361 
00362 
00363 /* =============================================================== */
00364 /* Implementation follows.                                         */
00365 /* =============================================================== */
00366 
00367 
00368 #include <dlrCommon/functional.h>
00369 
00370 
00371 namespace dlr {
00372 
00373   namespace numeric {
00374 
00375   
00376     // This constructor performs almost no work, and simply
00377     // initializes the class instance to a "zero" state.
00378     template <class Type0, class Type1>
00379     BoxIntegrator2D<Type0, Type1>::
00380     BoxIntegrator2D()
00381       : m_cache(),
00382         m_corner0(0, 0)
00383     {
00384       // Empty.
00385     }
00386 
00387 
00388     // This constructor initializes the class instance, and then
00389     // passes its arguments to member function setArray() in order
00390     // to precompute integral information.
00391     template <class Type0, class Type1>
00392     BoxIntegrator2D<Type0, Type1>::
00393     BoxIntegrator2D(const Array2D<Type0>& inputArray)
00394       : m_cache(),
00395         m_corner0(0, 0)
00396     {
00397       this->setArray(inputArray);
00398     }
00399 
00400 
00401     // This constructor initializes the class instance, and then
00402     // passes its arguments to member function setArray() in order
00403     // to precompute integral information.
00404     template <class Type0, class Type1>
00405     template <class Functor>
00406     BoxIntegrator2D<Type0, Type1>::
00407     BoxIntegrator2D(const Array2D<Type0>& inputArray, Functor functor)
00408       : m_cache(),
00409         m_corner0(0, 0)
00410     {
00411       this->setArray(inputArray, functor);
00412     }
00413 
00414 
00415     // This constructor works just like the single argument version
00416     // of setArray, with the exception that the pre-integration is
00417     // performed over only a rectangular sub-array.
00418     template <class Type0, class Type1>
00419     BoxIntegrator2D<Type0, Type1>::
00420     BoxIntegrator2D(const Array2D<Type0>& inputArray,
00421                     const Index2D& corner0,
00422                     const Index2D& corner1)
00423       : m_cache(),
00424         m_corner0(0, 0)
00425     {
00426       this->setArray(inputArray, corner0, corner1);
00427     }
00428 
00429 
00430     // The copy constructor does a shallow copy of its argument,
00431     // however behavior of the class should be indistinguishable
00432     // from a deep copy (operations on each of the original and copy
00433     // will not affect the other).
00434     template <class Type0, class Type1>
00435     BoxIntegrator2D<Type0, Type1>::
00436     BoxIntegrator2D(const BoxIntegrator2D& other)
00437       : m_cache(other.m_cache),
00438         m_corner0(other.m_corner0)
00439     {
00440       // Empty.
00441     }
00442 
00443 
00444     // This member function returns the integral over the
00445     // rectangular region with corner0 and corner1 at its diagonally
00446     // opposite corners.
00447     template <class Type0, class Type1>
00448     Type1
00449     BoxIntegrator2D<Type0, Type1>::
00450     getIntegral(const Index2D& corner0, const Index2D& corner1)
00451     {
00452       return (m_cache(corner1.getRow(), corner1.getColumn())
00453               - m_cache(corner1.getRow(), corner0.getColumn())
00454               - m_cache(corner0.getRow(), corner1.getColumn())
00455               + m_cache(corner0.getRow(), corner0.getColumn()));
00456     }
00457 
00458 
00459     // This member function works just like member function
00460     // getIntegral(const Index2D&, const Index2D&), with two
00461     // exceptions: it is very slightly slower; and corner indexing
00462     // is slightly more sophisticated.
00463     template <class Type0, class Type1>
00464     Type1
00465     BoxIntegrator2D<Type0, Type1>::
00466     getIntegral(const Index2D& corner0, const Index2D& corner1, bool dummy)
00467     {
00468       int row0 = corner0.getRow() - m_corner0.getRow();
00469       int row1 = corner1.getRow() - m_corner0.getRow();
00470       int column0 = corner0.getColumn() - m_corner0.getColumn();
00471       int column1 = corner1.getColumn() - m_corner0.getColumn();
00472       return (m_cache(row1, column1)
00473               - m_cache(row1, column0)
00474               - m_cache(row0, column1)
00475               + m_cache(row0, column0));
00476     }
00477 
00478 
00479     // This member function returns the raw 2D integral from which box
00480     // integration is performed.
00481     template <class Type0, class Type1>
00482     Type1
00483     BoxIntegrator2D<Type0, Type1>::
00484     getRawIntegral(size_t row, size_t column)
00485     {
00486       return m_cache(row, column);
00487     }
00488 
00489 
00490     // This member function works just like member function
00491     // getRawIntegral(size_t, size_t), but uses raster-indexing.
00492     template <class Type0, class Type1>
00493     Type1
00494     BoxIntegrator2D<Type0, Type1>::
00495     getRawIntegral(size_t index0)
00496     {
00497       return m_cache(index0);
00498     }
00499 
00500 
00501     // This member function discards and previously cached integral
00502     // information, performs a double integral over the input array,
00503     // and caches the result for future use in computing
00504     // sub-integrals.
00505     template <class Type0, class Type1>
00506     void
00507     BoxIntegrator2D<Type0, Type1>::
00508     setArray(const Array2D<Type0>& inputArray)
00509     {
00510       this->setArray(inputArray, common::StaticCastFunctor<Type0, Type1>());
00511     }
00512 
00513       
00514     // This member function discards and previously cached integral
00515     // information, applies the specified functor to each element of
00516     // the input array, performs a double integral over the input
00517     // array, and caches the result for future use in computing
00518     // sub-integrals.
00519     template <class Type0, class Type1>
00520     template <class Functor>
00521     void
00522     BoxIntegrator2D<Type0, Type1>::
00523     setArray(const Array2D<Type0>& inputArray, Functor functor)
00524     {
00525       m_corner0.setValue(0, 0);
00526       this->fillCache(
00527         inputArray.begin(), inputArray.rows(), inputArray.columns(),
00528         inputArray.columns(), functor);
00529     }
00530 
00531       
00532     // This constructor works just like the single argument version
00533     // of setArray, with the exception that the pre-integration is
00534     // performed over only a rectangular sub-array.
00535     template <class Type0, class Type1>
00536     void
00537     BoxIntegrator2D<Type0, Type1>::
00538     setArray(const Array2D<Type0>& inputArray,
00539              const Index2D& corner0,
00540              const Index2D& corner1)
00541     {
00542       this->setArray(inputArray, corner0, corner1,
00543                      common::StaticCastFunctor<Type0, Type1>());
00544     }
00545 
00546     
00547     // This member function works just like the three-argument
00548     // version of setArray, with the exception that the the
00549     // specified functor is applied to each element of the array
00550     // before integration.
00551     template <class Type0, class Type1>
00552     template <class Functor>
00553     void
00554     BoxIntegrator2D<Type0, Type1>::
00555     setArray(const Array2D<Type0>& inputArray,
00556              const Index2D& corner0,
00557              const Index2D& corner1,
00558              Functor functor)
00559     {
00560       int row0 = corner0.getRow();
00561       int row1 = corner1.getRow();
00562       int column0 = corner0.getColumn();
00563       int column1 = corner1.getColumn();
00564       if(row1 < row0) {
00565         std::swap(row0, row1);
00566       }
00567       if(column1 < column0) {
00568         std::swap(column0, column1);
00569       }
00570 
00571       int roiRows = row1 - row0;
00572       int roiColumns = column1 - column0;
00573       
00574       m_corner0.setValue(row0, column0);
00575       this->fillCache(
00576         inputArray.begin() + (row0 * inputArray.columns() + column0),
00577         roiRows, roiColumns, inputArray.columns(), functor);
00578     }
00579 
00580 
00581     // This constructor works just like the single argument version
00582     // of setArray, with the exception that the pre-integration is
00583     // performed over only a rectangular sub-array.
00584     template <class Type0, class Type1>
00585     template <class Functor>
00586     void
00587     BoxIntegrator2D<Type0, Type1>::
00588     fillCache(typename Array2D<Type0>::const_iterator inIter,
00589               int roiRows,
00590               int roiColumns,
00591               int inputArrayColumns,
00592               Functor functor)
00593     {
00594       int rowIncrement = inputArrayColumns - roiColumns;
00595       m_cache.reinit(roiRows + 1, roiColumns + 1);
00596 
00597       // First row of cache represents boxes with zero height, so
00598       // values are identically zero.
00599       std::fill(m_cache.rowBegin(0), m_cache.rowEnd(0),
00600                 static_cast<Type1>(functor(0)));
00601       
00602       // Pre-integrate first row.
00603       typename Array2D<Type0>::const_iterator endIter = inIter + roiColumns;
00604       typename Array2D<Type1>::iterator outIter =
00605         m_cache.begin() + m_cache.columns();
00606       *(outIter++) = static_cast<Type1>(functor(0));
00607       while(inIter != endIter) {
00608         *outIter = *(outIter - 1) + static_cast<Type1>(functor(*inIter));
00609         ++outIter;
00610         ++inIter;
00611       }
00612 
00613       // Pre-integrate all remaining rows.
00614       typename Array2D<Type1>::iterator previousRowIter =
00615         m_cache.begin() + m_cache.columns();
00616       for(int row = 1; row < roiRows; ++row) {
00617         inIter += rowIncrement;
00618         Type1 rowSum = static_cast<Type1>(0);
00619         *(outIter++) = rowSum;
00620         ++previousRowIter;
00621         for(int column = 0; column < roiColumns; ++column) {
00622           rowSum += static_cast<Type1>(functor(*inIter));
00623           *outIter = rowSum + (*previousRowIter);
00624           ++inIter;
00625           ++outIter;
00626           ++previousRowIter;
00627         }
00628       }
00629     }
00630     
00631     
00632   } // namespace numeric
00633   
00634 } // namespace dlr
00635 
00636 #endif /* #ifndef _DLRNUMERIC_BOXINTEGRATOR2D_H_ */

Generated on Wed Nov 25 00:42:41 2009 for dlrUtilities Utility Library by  doxygen 1.5.8