arrayextender.h

Back to IndexExtender concept

pastel/sys/extender/

// Description: Array extender
// Documentation: indexextenders.txt

#ifndef PASTELSYS_ARRAYEXTENDER_H
#define PASTELSYS_ARRAYEXTENDER_H

#include "pastel/sys/array.h"
#include "pastel/sys/extender/indexextender.h"
#include "pastel/sys/view/view.h"

namespace Pastel
{

    template <integer N, typename Type>
    class ArrayExtender
    {
    public:
        ArrayExtender()
            : extender_()
            , border_()
        {
        }

        explicit ArrayExtender(
            const Type& border)
            : extender_()
            , border_(border)
        {
        }

        // Implicit conversion
        ArrayExtender(
            const ConstIndexExtenderPtr& uniformExtender,
            const Type& border = Type())
            : extender_(uniformExtender)
            , border_(border)
        {
        }

        void swap(ArrayExtender& that)
        {
            using std::swap;

            extender_.swap(that.extender_);
            swap(border_, that.border_);
        }

        void clear()
        {
            extender_.set(IndexExtenderPtr());
        }

        void clearExtender(integer index)
        {
            setExtender(index, IndexExtenderPtr());
        }

        void setExtender(integer index,
            const ConstIndexExtenderPtr& extender)
        {
            ENSURE2(index >= 0 && index < extender_.size(),
                index, extender_.size());

            extender_[index] = extender;
        }

        ConstIndexExtenderPtr extender(integer index) const
        {
            ENSURE2(index >= 0 && index < extender_.size(),
                index, extender_.size());

            return extender_[index];
        }

        void setBorder(const Type& border)
        {
            border_ = border;
        }

        const Type& border() const
        {
            return border_;
        }

        Type operator()(
            const Array<Type, N>& image,
            const Vector<integer, N>& position) const
        {
            return (*this)(constArrayView(image), position);
        }

        template <typename Image_ConstView>
        Type operator()(
            const ConstView<N, Type, Image_ConstView>& image,
            const Vector<integer, N>& position) const
        {
            const Vector<integer, N>& extent = image.extent();

            Vector<integer, N> newPosition;
            for (integer i = 0;i < N;++i)
            {
                const ConstIndexExtenderPtr& extender = extender_[i];
                if (extender.empty())
                {
                    if (position[i] < 0 || position[i] >= extent[i])
                    {
                        return border_;
                    }

                    newPosition[i] = position[i];
                }
                else
                {
                    newPosition[i] = (*extender)(position[i], extent[i]);
                }
            }

            return image(newPosition);
        }

    private:
        Tuple<ConstIndexExtenderPtr, N> extender_;
        Type border_;
    };

}

#endif