mirrorview.h

Back to Concrete views

pastel/sys/view/

// Description: MirrorView class
// Detail: An adapter view to mirror a specific dimension
// Documentation: concrete_views.txt

#ifndef PASTELSYS_MIRRORVIEW_H
#define PASTELSYS_MIRRORVIEW_H

#include "pastel/sys/view/mirrorviewcursor.h"

namespace Pastel
{

    //! Mirrors the specified dimension.
    /*!
   More specifically:

   mirrorView(x_1, ..., x_k, ..., x_n) =
   view(x_1, ..., (extent(k) - 1) - x_k, ..., x_n)
   */

    template <integer N, integer MirrorIndex, typename Contained_ConstView>
    class ConstMirrorView
    {
    public:
        static constexpr int Dimension = N;

        using Element = typename Contained_ConstView::Element;
        using ConstReference = typename Contained_ConstView::ConstReference;
        typedef MirrorView_::ConstMirrorViewCursor<N, MirrorIndex,
            typename Contained_ConstView::ConstCursor> ConstCursor;

        explicit ConstMirrorView(
            const Contained_ConstView& view)
            : view_(view)
        {
        }

        const Vector<integer, N>& extent() const
        {
            return view_.extent();
        }

        ConstCursor constCursor(
            Vector<integer, N> position) const
        {
            position[MirrorIndex] = view_.extent()[MirrorIndex] - 1 - position[MirrorIndex];

            return ConstCursor(view_.constCursor(position));
        }

    protected:
        Contained_ConstView view_;
    };

    template <integer MirrorIndex, integer N, typename Input_Element, typename Input_ConstView>
    ConstView<N, Input_Element, ConstMirrorView<N, MirrorIndex, Input_ConstView> >
        constMirrorView(
        const ConstView<N, Input_Element, Input_ConstView>& view)
    {
        return wrapConstView(ConstMirrorView<N, MirrorIndex, Input_ConstView>(view.contained()));
    }

    //! Mirrors the specified dimension.
    /*!
   More specifically:

   mirrorView(x_1, ..., x_k, ..., x_n) =
   view(x_1, ..., (extent(k) - 1) - x_k, ..., x_n)
   */

    template <integer N, integer MirrorIndex, typename Contained_View>
    class MirrorView
        : public ConstMirrorView<N, MirrorIndex, Contained_View>
    {
    private:
        using Base = ConstMirrorView<N, MirrorIndex, Contained_View>;
        using Base::view_;

    public:
        //using Base::Dimension;
        using Element = typename Base::Element;
        using ConstReference = typename Base::ConstReference;
        using ConstCursor = typename Base::ConstCursor;
        using Base::width;
        using Base::height;
        using Base::constCursor;

        using Reference = typename Contained_View::Reference;
        typedef MirrorView_::MirrorViewCursor<N, MirrorIndex, typename Contained_View::Cursor>
            Cursor;

        explicit MirrorView(const Contained_View& view)
            : ConstMirrorView<N, MirrorIndex, Contained_View>(view)
        {
        }

        Cursor cursor(
            Vector<integer, N> position) const
        {
            position[MirrorIndex] = view_.extent()[MirrorIndex] - 1 - position[MirrorIndex];

            return Cursor(view_.cursor(position));
        }
    };

    template <integer MirrorIndex, integer N, typename Input_Element, typename Input_View>
    View<N, Input_Element, MirrorView<N, MirrorIndex, Input_View> >
        mirrorView(
        const View<N, Input_Element, Input_View>& view)
    {
        return wrapView(MirrorView<N, MirrorIndex, Input_View>(view.contained()));
    }

}

#endif