/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2015-2018 Danny Robson */ #pragma once #include "../../coord/fwd.hpp" #include "../../extent.hpp" #include "../../random.hpp" #include "../ops.hpp" #include #include /////////////////////////////////////////////////////////////////////////////// namespace cruft::geom::sample { /////////////////////////////////////////////////////////////////////// /// A convenience function that calls sample::fn to select a random /// point in a provided shape. /// /// This function is useful because we can perform use partial /// specialisation if we pass the functionality off to a well known /// class. template < typename ShapeT, typename GeneratorT // random generator > auto eval (ShapeT const &shape, GeneratorT &&gen) { volume query (shape); return query.eval (std::forward (gen)); } /// A function object that selects a uniformly random point inside a /// shape using a provided random generator. The point will lie /// within the shape, inclusive of boundaries. /// /// This should be specialised for anything complex, but will work /// (with a varying performance hit) for anything that provides /// bounds` and `intersects`. template class volume { public: using shape_type = ShapeT; explicit volume (shape_type&&) = delete; explicit volume (shape_type const &target): m_target (target) { ; } /// Returns a point which lies within the supplied shape, inclusive /// of borders. /// template auto eval (GeneratorT &&g) const { auto b = bounds (m_target); while (true) { auto p = ::cruft::geom::sample::eval (b, g); if (intersects (m_target, p)) return p; } } private: ShapeT const &m_target; }; /////////////////////////////////////////////////////////////////////// /// A specialisation of the volume sampler for extents. template class volume> { public: using shape_type = extent; explicit volume (shape_type&&) = delete; explicit volume (shape_type const &target): m_target (target) { ; } template auto eval (GeneratorT &&gen) const noexcept { cruft::point p; for (size_t i = 0; i < S; ++i) p[i] = random::uniform (T{0}, m_target[i], gen); return p; } private: shape_type const &m_target; }; }