63 lines
1.8 KiB
C++
63 lines
1.8 KiB
C++
/*
|
|
* 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 <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
|
|
#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 <typename GeneratorT>
|
|
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;
|
|
};
|
|
} |