g/s/surface: add an 'accept' query for poisson sampling

This commit is contained in:
Danny Robson 2020-10-22 09:29:22 +10:00
parent 94d3f676c6
commit 3fffacc19c

View File

@ -30,16 +30,29 @@ namespace cruft::geom::sample {
/// best of a set of candidates. The 'best' is the point that is /// best of a set of candidates. The 'best' is the point that is
/// furthest from all selected points. /// furthest from all selected points.
/// ///
/// \tparam SamplerT A surface sampler
/// \tparam DistanceT The type of point-to-point distances
/// \tparam GeneratorT The random generator passed to the sampler
/// \tparam AcceptT A unary bool function that returns true if a sampled
/// point is permissible. The point is counted in the candidate set
/// regardless.
///
/// \return A vector of the computed points /// \return A vector of the computed points
template <typename SamplerT, typename DistanceT, typename GeneratorT> template <
typename SamplerT,
typename DistanceT,
typename GeneratorT,
typename AcceptT
>
auto auto
poisson (SamplerT const &target, poisson (
GeneratorT &&gen, SamplerT const &sampler,
DistanceT &&minimum_distance, GeneratorT &&gen,
size_t candidates_count) AcceptT &&accept,
DistanceT &&minimum_distance,
{ std::size_t candidates_count
using point_type = decltype (target.eval (gen)); ) {
using point_type = decltype (sampler.eval (gen));
using value_type = typename point_type::value_type; using value_type = typename point_type::value_type;
std::vector<point_type> selected; std::vector<point_type> selected;
@ -47,7 +60,7 @@ namespace cruft::geom::sample {
// prime the found elements list with an initial point we can // prime the found elements list with an initial point we can
// perform distance calculations on // perform distance calculations on
selected.push_back (target.eval (gen)); selected.push_back (sampler.eval (gen));
// keep trying to add one more new point // keep trying to add one more new point
while (1) { while (1) {
@ -57,10 +70,16 @@ namespace cruft::geom::sample {
std::back_inserter (candidates), std::back_inserter (candidates),
candidates_count, candidates_count,
[&] (void) { [&] (void) {
return target.eval (gen); return sampler.eval (gen);
} }
); );
// Remove points that aren't acceptable
std::erase_if (
candidates,
[&] (auto const &p) { return !accept (p); }
);
// find the point whose minimum distance to the existing // find the point whose minimum distance to the existing
// points is the greatest (while also being greater than the // points is the greatest (while also being greater than the
// required minimum distance); // required minimum distance);
@ -95,6 +114,30 @@ namespace cruft::geom::sample {
} }
/// A convenience function that forwards to poisson with unconditional
/// point acceptance.
template <
typename SamplerT,
typename DistanceT,
typename GeneratorT
>
auto
poisson (
SamplerT &&sampler,
GeneratorT &&gen,
DistanceT &&minimum_distance,
std::size_t candidates_count
) {
return poisson (
std::forward<SamplerT> (sampler),
std::forward<GeneratorT> (gen),
[] (auto&&...) { return true; },
std::forward<DistanceT> (minimum_distance),
candidates_count
);
}
/// A surface sampler specialisation for 2d extents. /// A surface sampler specialisation for 2d extents.
/// ///
/// The actual work is handed off to the volume sampler, as it's /// The actual work is handed off to the volume sampler, as it's