count_nearest.h

Back to Nearest set

pastel/geometry/

// Description: Nearest neighbors searching in a kd-tree
// Documentation: nearestset.txt

#ifndef PASTELGEOMETRY_COUNT_NEAREST_H
#define PASTELGEOMETRY_COUNT_NEAREST_H

// Template concepts

#include "pastel/sys/indicator/indicator_concept.h"
#include "pastel/sys/output/output_concept.h"
#include "pastel/sys/point/point_concept.h"
#include "pastel/math/norm/norm_concept.h"
#include "pastel/geometry/nearestset/nearestset_concept.h"
#include "pastel/geometry/search_nearby.h"

// Template defaults

#include "pastel/math/norm/euclidean_norm.h"
#include "pastel/sys/indicator/all_indicator.h"
#include "pastel/sys/output/null_output.h"

namespace Pastel
{

    //! Finds all points contained in an open norm-ball.
    /*!
   nearestSet (NearestSet):
   The nearest-set in which to search neighbors in.

   searchPoint (Point):
   The point for which to search a neighbor for.

   returns (integer):
   The number of accepted neighbors under distance 
   maxDistance2.

   Optional arguments
   ------------------

   accept (Indicator(PointId)):
   An indicator which decides whether to accept a point 
   as a neighbor or not.
   Default: allIndicator()

   maxDistance2 (Distance):
   The distance after which points are not considered neighbors
   anymore. Can be set to (Real)Infinity(). 
   Default: norm((Real)Infinity())

   report (Output(Real, PointId)):
   An output to which the found neighbors 
   are reported to. The reporting is done in the 
   form report(distance, point). 
   Default: nullOutput()

   norm (Norm):
   The norm used to measure distance.
   */
    template <
        NearestSet_Concept NearestSet,
        Point_Concept Search_Point,
        typename... ArgumentSet
    >
    integer countNearest(
        const NearestSet& nearestSet,
        const Search_Point& searchPoint,
        ArgumentSet&&... argumentSet)
    {
        using std::begin;

        using PointId = PointSet_PointId<NearestSet>;
        using Real = Point_Real<Search_Point>;

        auto&& report = 
            PASTEL_ARG_C(report, nullOutput(), Trivial_Concept);

        auto&& accept = 
            PASTEL_ARG_C1(accept, allIndicator(), Indicator_Concept, PointId);

        auto&& norm = 
            PASTEL_ARG_C(norm, Euclidean_Norm<Real>(), Norm_Concept);

        using Distance = decltype(norm());

        Distance maxDistance2 = 
            PASTEL_ARG_C(maxDistance2, norm((Real)Infinity()), Distance_Concept);

        if (~maxDistance2 == 0)
        {
            // There is nothing to search for.
            // Note that we consider the search-ball open.
            return 0;
        }

        integer count = 0;
        auto reportCandidate = [&](
            const Distance& distance2,
            const auto& pointId)
        {
            ++count;
            report(distance2, pointId);
            return Distance((Real)Infinity());
        };

        searchNearby(
            nearestSet,
            searchPoint,
            PASTEL_TAG(accept), accept,
            PASTEL_TAG(report), reportCandidate,
            PASTEL_TAG(norm), norm,
            PASTEL_TAG(maxDistance2), maxDistance2);

        return count;
    }

}

#endif