reconstruct_nearest.hpp

Back to Reconstruction

pastel/gfx/reconstruction/

#ifndef PASTELGFX_RECONSTRUCT_NEAREST_HPP
#define PASTELGFX_RECONSTRUCT_NEAREST_HPP

#include "pastel/gfx/reconstruct_nearest.h"

#include "pastel/geometry/pointkdtree/pointkdtree.h"
#include "pastel/geometry/overlap/overlaps_alignedbox_point.h"

#include "pastel/sys/vector/vector_tools.h"
#include "pastel/sys/view/view_visit.h"
#include "pastel/sys/output.h"

namespace Pastel
{

    namespace ReconstructNearest_
    {

        template <typename Real, integer N, typename Data>
        class DataPoint
        {
        public:
            using Data_ = Data;

            DataPoint()
                : position_()
                , data_()
            {
            }

            DataPoint(
                const Vector<Real, N>& position,
                const Data& data)
                : position_(position)
                , data_(data)
            {
            }

            Vector<Real, N> position_;
            Data data_;
        };

        template <
            typename Real_, integer N_, typename Data>
        class DataPolicy
        {
        public:
            using Real = Real_;
            static constexpr integer N = N_;
            using Point = DataPoint<Real, N, Data>;

            explicit DataPolicy(
                integer dimension)
                : dimension_(dimension)
            {
                ENSURE(N == Dynamic || 
                    dimension == N);
            }

            integer n() const
            {
                return (N != Dynamic) ? N : dimension_;
            }

            const Real& operator(
                const Point& point, integer index) const
            {
                return point.position_[index];
            }

        private:
            integer dimension_;
        };

        template <typename Tree>
        class ReconstructFunctor
        {
        public:
            using Locator = typename Tree::Locator;
            using Real = typename Locator::Real;
            static constexpr integer N = Locator::N;

            explicit ReconstructFunctor(
                const Tree& kdTree,
                integer kNearest,
                integer maxRelativeError)
                : kdtree_(kdTree)
                , kNearest_(kNearest)
                , maxRelativeError_(maxRelativeError)
            {
            }

            using Data = typename Locator::Point;

            void operator()(
                const Vector<integer, N>& position,
                typename Data::Data_& data) const
            {
                typedef typename Tree::Point_ConstIterator
                    ConstIterator;

                std::vector<ConstIterator> nearestSet;
                auto report = [&](
                    Real distance, ConstIterator point)
                {
                    nearestSet.push_back(point);
                };

                searchNearest(
                    kdtree_, 
                    evaluate(Vector<Real, N>(position) + 0.5), 
                    report)
                    .kNearest(kNearest_)
                    .maxRelativeError(maxRelativeError_);

                data = nearestSet.back()->point().data_;
            }

        private:
            const Tree& kdtree_;
            integer kNearest_;
            Real maxRelativeError_;
        };
    }

    template <typename Real, integer N, typename Data, typename Output_View>
    void reconstructNearest(
        const std::vector<Vector<Real, N> >& positionList,
        const std::vector<Data>& dataList,
        const AlignedBox<Real, N>& region,
        const View<N, Data, Output_View>& view,
        integer kNearest,
        const NoDeduction<Real>& maxRelativeError)
    {
        integer n = region.n();
        integer points = positionList.size();

        ENSURE_OP(kNearest, >, 0);
        ENSURE2(points == dataList.size(), points, dataList.size());

        using DataPoint = ReconstructNearest_::DataPoint<Real, N, Data>;
        using DataPolicy = ReconstructNearest_::DataPolicy<Real, N, Data>;

        DataPolicy locator(n);

        using Tree = PointKdTree<PointKdTree_Settings<DataPolicy>>

        Tree kdTree(locator);

        Vector<Real, N> scaling =
            inverse(region.extent()) * Vector<Real, N>(view.extent());

        std::vector<DataPoint> dataPointList;
        for (integer i = 0;i < points;++i)
        {
            if (overlaps(region, positionList[i]))
            {
                dataPointList.push_back(
                    DataPoint((positionList[i] - region.min()) * scaling, dataList[i]));
            }
        }

        kdTree.insertSet(dataPointList);
        kdTree.refine(SlidingMidpoint2_SplitRule());

        ReconstructNearest_::ReconstructFunctor<Tree>
            reconstructFunctor(kdTree, kNearest, maxRelativeError);

        visitPosition(
            view, reconstructFunctor);
    }

    template <typename Real, integer N, typename Data, typename Output_View>
    void reconstructNearest(
        const std::vector<Vector<Real, N> >& positionList,
        const std::vector<Data>& dataList,
        const AlignedBox<Real, N>& region,
        const View<N, Data, Output_View>& view,
        integer kNearest)
    {
        Pastel::reconstructNearest(
            positionList, dataList,
            region, view, kNearest, 0);
    }

    template <typename Real, integer N, typename Data, typename Output_View>
    void reconstructNearest(
        const std::vector<Vector<Real, N> >& positionList,
        const std::vector<Data>& dataList,
        const AlignedBox<Real, N>& region,
        const View<N, Data, Output_View>& view)
    {
        Pastel::reconstructNearest(
            positionList, dataList,
            region, view, 1, 0);
    }

}

#endif