/* * 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 2020, Danny Robson */ #pragma once #include #include "../../extent.hpp" #include "../../region.hpp" #include "../../random.hpp" namespace cruft::geom::sample { /// Given a desired subregion shape, and a possible field of locations, /// select a random location for surface placement. /// /// Valid placements allow for rotations, but are exclusive of far edges /// for integer types. /// /// The largest axis of the shape must not be larger than the smallest /// axis of the placement field otherwise the chosen region may fall /// outside the field. class subregion { public: subregion (cruft::extent2i _shape, cruft::extent2i _field) : m_shape (_shape) , m_field (_field) { CHECK (all (m_shape <= m_field)); } // Choose placements by looking at each axis in turn. // // We support rotations by randomising the axis ordering for the shape // but not the field. template cruft::region2i operator() (GeneratorT &&gen) { int axes[] = { 0, 1 }; std::shuffle (std::begin (axes), std::end (axes), gen); cruft::region2i res; for (int i = 0; i < std::ssize (axes); ++i) { res.e[i] = m_shape[axes[i]]; res.p[i] = cruft::random::uniform (m_field[i] - res.e[i]); } return res; } private: cruft::extent2i m_shape; cruft::extent2i m_field; }; }