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 
00214       void
00215       setArray(const Array2D<Type0>& inputArray);
00216 
00217       
00233       template <class Functor>
00234       void
00235       setArray(const Array2D<Type0>& inputArray, Functor functor);
00236 
00237       
00256       void
00257       setArray(const Array2D<Type0>& inputArray,
00258                const Index2D& corner0,
00259                const Index2D& corner1);
00260 
00261 
00282       template <class Functor>
00283       void
00284       setArray(const Array2D<Type0>& inputArray,
00285                const Index2D& corner0,
00286                const Index2D& corner1,
00287                Functor functor);
00288 
00289 
00290     protected:
00291 
00292 
00309       template <class Functor>
00310       void
00311       fillCache(typename Array2D<Type0>::const_iterator inIter,
00312                 int roiRows,
00313                 int roiColumns,
00314                 int inputArrayColumns,
00315                 Functor functor);
00316 
00317 
00318       Array2D<Type1> m_cache;
00319       Index2D m_corner0;
00320     };
00321 
00322 
00323   } // namespace numeric
00324   
00325 } // namespace dlr
00326 
00327 
00328 /* =============================================================== */
00329 /* Implementation follows.                                         */
00330 /* =============================================================== */
00331 
00332 
00333 #include <dlrCommon/functional.h>
00334 
00335 
00336 namespace dlr {
00337 
00338   namespace numeric {
00339 
00340   
00341     // This constructor performs almost no work, and simply
00342     // initializes the class instance to a "zero" state.
00343     template <class Type0, class Type1>
00344     BoxIntegrator2D<Type0, Type1>::
00345     BoxIntegrator2D()
00346       : m_cache(),
00347         m_corner0(0, 0)
00348     {
00349       // Empty.
00350     }
00351 
00352 
00353     // This constructor initializes the class instance, and then
00354     // passes its arguments to member function setArray() in order
00355     // to precompute integral information.
00356     template <class Type0, class Type1>
00357     BoxIntegrator2D<Type0, Type1>::
00358     BoxIntegrator2D(const Array2D<Type0>& inputArray)
00359       : m_cache(),
00360         m_corner0(0, 0)
00361     {
00362       this->setArray(inputArray);
00363     }
00364 
00365 
00366     // This constructor works just like the single argument version
00367     // of setArray, with the exception that the pre-integration is
00368     // performed over only a rectangular sub-array.
00369     template <class Type0, class Type1>
00370     BoxIntegrator2D<Type0, Type1>::
00371     BoxIntegrator2D(const Array2D<Type0>& inputArray,
00372                     const Index2D& corner0,
00373                     const Index2D& corner1)
00374       : m_cache(),
00375         m_corner0(0, 0)
00376     {
00377       this->setArray(inputArray, corner0, corner1);
00378     }
00379 
00380 
00381     // The copy constructor does a shallow copy of its argument,
00382     // however behavior of the class should be indistinguishable
00383     // from a deep copy (operations on each of the original and copy
00384     // will not affect the other).
00385     template <class Type0, class Type1>
00386     BoxIntegrator2D<Type0, Type1>::
00387     BoxIntegrator2D(const BoxIntegrator2D& other)
00388       : m_cache(other.m_cache),
00389         m_corner0(other.m_corner0)
00390     {
00391       // Empty.
00392     }
00393 
00394 
00395     // This member function returns the integral over the
00396     // rectangular region with corner0 and corner1 at its diagonally
00397     // opposite corners.
00398     template <class Type0, class Type1>
00399     Type1
00400     BoxIntegrator2D<Type0, Type1>::
00401     getIntegral(const Index2D& corner0, const Index2D& corner1)
00402     {
00403       return (m_cache(corner1.getRow(), corner1.getColumn())
00404               - m_cache(corner1.getRow(), corner0.getColumn())
00405               - m_cache(corner0.getRow(), corner1.getColumn())
00406               + m_cache(corner0.getRow(), corner0.getColumn()));
00407     }
00408 
00409 
00410     // This member function works just like member function
00411     // getIntegral(const Index2D&, const Index2D&), with two
00412     // exceptions: it is very slightly slower; and corner indexing
00413     // is slightly more sophisticated.
00414     template <class Type0, class Type1>
00415     Type1
00416     BoxIntegrator2D<Type0, Type1>::
00417     getIntegral(const Index2D& corner0, const Index2D& corner1, bool dummy)
00418     {
00419       int row0 = corner0.getRow() - m_corner0.getRow();
00420       int row1 = corner1.getRow() - m_corner0.getRow();
00421       int column0 = corner0.getColumn() - m_corner0.getColumn();
00422       int column1 = corner1.getColumn() - m_corner0.getColumn();
00423       return (m_cache(row1, column1)
00424               - m_cache(row1, column0)
00425               - m_cache(row0, column1)
00426               + m_cache(row0, column0));
00427     }
00428 
00429 
00430     // This member function discards and previously cached integral
00431     // information, performs a double integral over the input array,
00432     // and caches the result for future use in computing
00433     // sub-integrals.
00434     template <class Type0, class Type1>
00435     void
00436     BoxIntegrator2D<Type0, Type1>::
00437     setArray(const Array2D<Type0>& inputArray)
00438     {
00439       this->setArray(inputArray, common::StaticCastFunctor<Type0, Type1>());
00440     }
00441 
00442       
00443     // This member function discards and previously cached integral
00444     // information, applies the specified functor to each element of
00445     // the input array, performs a double integral over the input
00446     // array, and caches the result for future use in computing
00447     // sub-integrals.
00448     template <class Type0, class Type1>
00449     template <class Functor>
00450     void
00451     BoxIntegrator2D<Type0, Type1>::
00452     setArray(const Array2D<Type0>& inputArray, Functor functor)
00453     {
00454       m_corner0.setValue(0, 0);
00455       this->fillCache(
00456         inputArray.begin(), inputArray.rows(), inputArray.columns(),
00457         inputArray.columns(), functor);
00458     }
00459 
00460       
00461     // This constructor works just like the single argument version
00462     // of setArray, with the exception that the pre-integration is
00463     // performed over only a rectangular sub-array.
00464     template <class Type0, class Type1>
00465     void
00466     BoxIntegrator2D<Type0, Type1>::
00467     setArray(const Array2D<Type0>& inputArray,
00468              const Index2D& corner0,
00469              const Index2D& corner1)
00470     {
00471       this->setArray(inputArray, corner0, corner1,
00472                      common::StaticCastFunctor<Type0, Type1>());
00473     }
00474 
00475     
00476     // This member function works just like the three-argument
00477     // version of setArray, with the exception that the the
00478     // specified functor is applied to each element of the array
00479     // before integration.
00480     template <class Type0, class Type1>
00481     template <class Functor>
00482     void
00483     BoxIntegrator2D<Type0, Type1>::
00484     setArray(const Array2D<Type0>& inputArray,
00485              const Index2D& corner0,
00486              const Index2D& corner1,
00487              Functor functor)
00488     {
00489       int row0 = corner0.getRow();
00490       int row1 = corner1.getRow();
00491       int column0 = corner0.getColumn();
00492       int column1 = corner1.getColumn();
00493       if(row1 < row0) {
00494         std::swap(row0, row1);
00495       }
00496       if(column1 < column0) {
00497         std::swap(column0, column1);
00498       }
00499 
00500       int roiRows = row1 - row0;
00501       int roiColumns = column1 - column0;
00502       
00503       m_corner0.setValue(row0, column0);
00504       this->fillCache(
00505         inputArray.begin() + (row0 * inputArray.columns() + column0),
00506         roiRows, roiColumns, inputArray.columns(), functor);
00507     }
00508 
00509 
00510     // This constructor works just like the single argument version
00511     // of setArray, with the exception that the pre-integration is
00512     // performed over only a rectangular sub-array.
00513     template <class Type0, class Type1>
00514     template <class Functor>
00515     void
00516     BoxIntegrator2D<Type0, Type1>::
00517     fillCache(typename Array2D<Type0>::const_iterator inIter,
00518               int roiRows,
00519               int roiColumns,
00520               int inputArrayColumns,
00521               Functor functor)
00522     {
00523       int rowIncrement = inputArrayColumns - roiColumns;
00524       m_cache.reinit(roiRows + 1, roiColumns + 1);
00525 
00526       // First row of cache represents boxes with zero height, so
00527       // values are identically zero.
00528       std::fill(m_cache.rowBegin(0), m_cache.rowEnd(0),
00529                 static_cast<Type1>(functor(0)));
00530       
00531       // Pre-integrate first row.
00532       typename Array2D<Type0>::const_iterator endIter = inIter + roiColumns;
00533       typename Array2D<Type1>::iterator outIter =
00534         m_cache.begin() + m_cache.columns();
00535       *(outIter++) = static_cast<Type1>(functor(0));
00536       while(inIter != endIter) {
00537         *outIter = *(outIter - 1) + static_cast<Type1>(functor(*inIter));
00538         ++outIter;
00539         ++inIter;
00540       }
00541 
00542       // Pre-integrate all remaining rows.
00543       typename Array2D<Type1>::iterator previousRowIter =
00544         m_cache.begin() + m_cache.columns();
00545       for(int row = 1; row < roiRows; ++row) {
00546         inIter += rowIncrement;
00547         Type1 rowSum = static_cast<Type1>(0);
00548         *(outIter++) = rowSum;
00549         ++previousRowIter;
00550         for(int column = 0; column < roiColumns; ++column) {
00551           rowSum += static_cast<Type1>(functor(*inIter));
00552           *outIter = rowSum + (*previousRowIter);
00553           ++inIter;
00554           ++outIter;
00555           ++previousRowIter;
00556         }
00557       }
00558     }
00559     
00560     
00561   } // namespace numeric
00562   
00563 } // namespace dlr
00564 
00565 #endif /* #ifndef _DLRNUMERIC_BOXINTEGRATOR2D_H_ */

Generated on Tue Jun 24 16:48:37 2008 for dlrUtilities Utility Library by  doxygen 1.5.5