diff --git a/src/polymesh/impl/impl_ranges.hh b/src/polymesh/impl/impl_ranges.hh index 4d5ecd33b93750ff98d3f095991646220cea85d8..52d0cb075392d3770a558d20bc53d8ae2dcc627d 100644 --- a/src/polymesh/impl/impl_ranges.hh +++ b/src/polymesh/impl/impl_ranges.hh @@ -328,6 +328,25 @@ auto smart_range<this_t, ElementT>::aabb(FuncT&& f) const -> polymesh::minmax_t< return r; } +template <class this_t, class ElementT> +template <class Generator, class FuncT> +auto smart_range<this_t, ElementT>::random(Generator& g, FuncT&& f) const -> tmp::decayed_result_type_of<FuncT, ElementT> +{ + auto it = static_cast<this_t const*>(this)->begin(); + POLYMESH_ASSERT(it.is_valid() && "requires non-empty range"); + auto v = f(*it); + double cnt = 2; + ++it; + while (it.is_valid()) + { + if (double(g()) * cnt < double(g.max())) + v = f(*it); + ++it; + cnt += 1; + } + return v; +} + template <class this_t, class ElementT> template <class FuncT> auto smart_range<this_t, ElementT>::minmax(FuncT&& f) const -> polymesh::minmax_t<tmp::decayed_result_type_of<FuncT, ElementT>> diff --git a/src/polymesh/ranges.hh b/src/polymesh/ranges.hh index 7ef23663285179374d0902a0645264ea784f5339..5e86a0eb7dd360ccecc4d70f54f706d79529f1b1 100644 --- a/src/polymesh/ranges.hh +++ b/src/polymesh/ranges.hh @@ -161,6 +161,11 @@ struct smart_range template <class PredT> auto filter(PredT&& p) -> filtered_range<ElementT, this_t&, PredT>; + /// returns a uniformly random sampled element from this range + /// complexity is O(n) (but does not allocate) + template <class Generator, class FuncT = tmp::identity> + auto random(Generator& g, FuncT&& f = {}) const -> tmp::decayed_result_type_of<FuncT, ElementT>; + // TODO: (requires new ranges) // - filter (or where?) // - map @@ -233,6 +238,7 @@ struct smart_collection : smart_range<smart_collection<mesh_ptr, tag, iterator>, end_iterator end() const { return {}; } /// returns a handle chosen uniformly at random + /// Complexity is usually O(1) /// NOTE: when only valid handles are allowed, this will use rejection sampling /// and thus get very slow if a lot of data is invalid template <class Generator>