2019-08-20 15:00:26 +10:00
|
|
|
/*
|
|
|
|
* 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 2019 Danny Robson <danny@nerdcruft.net>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "fwd.hpp"
|
|
|
|
|
|
|
|
#include "../../extent.hpp"
|
|
|
|
#include "../../region.hpp"
|
|
|
|
|
|
|
|
namespace cruft::geom::sample {
|
|
|
|
template <typename T>
|
|
|
|
struct edge<cruft::extent2<T>> {
|
|
|
|
using shape_type = cruft::extent2<T>;
|
|
|
|
|
|
|
|
edge (shape_type _shape)
|
|
|
|
: m_shape (_shape)
|
|
|
|
{ ; }
|
|
|
|
|
|
|
|
template <typename GeneratorT>
|
|
|
|
point2<T>
|
|
|
|
eval (GeneratorT &&gen)
|
|
|
|
{
|
|
|
|
// Generate a point at some point along the perimeter.
|
|
|
|
//
|
|
|
|
// Unwind half the perimeter with length `w + h - 1`.
|
|
|
|
// This gives us the full length of the width, and subtract one of
|
|
|
|
// the extreme axis on the height side that is covered by the full
|
|
|
|
// width case.
|
|
|
|
//
|
|
|
|
// If we're in the first portion of the perimeter then choose if
|
|
|
|
// we're on the top/bottom randomly. And use the position as the x
|
|
|
|
// coordinate.
|
|
|
|
//
|
|
|
|
// Otherwise bump the coordinate above the baseline which was
|
|
|
|
// already covered and choose the left/right side randomly.
|
|
|
|
//
|
|
|
|
// TODO: avoid repeated calls into uniform. We can do this by
|
|
|
|
// doubling the extent we're testing and using the extra bit for
|
|
|
|
// the side test. But I'm lacking time right now.
|
|
|
|
auto const [w, h] = m_shape;
|
|
|
|
auto const len = w + h - 1;
|
|
|
|
|
|
|
|
auto pos = cruft::random::uniform (T{0}, len, gen);
|
|
|
|
|
|
|
|
if (pos <= w) {
|
|
|
|
auto const _w = pos;
|
2020-11-06 13:26:49 +11:00
|
|
|
auto const _h = cruft::random::uniform (1, gen) ? h : 0;
|
2019-08-20 15:00:26 +10:00
|
|
|
return { _w, _h };
|
|
|
|
}
|
|
|
|
|
|
|
|
pos -= w;
|
|
|
|
|
2020-11-06 13:26:49 +11:00
|
|
|
auto const _w = cruft::random::uniform (1, gen) ? w : 0;
|
2019-08-20 15:00:26 +10:00
|
|
|
auto const _h = pos;
|
|
|
|
|
|
|
|
return { _w, _h };
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
shape_type m_shape;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct edge<cruft::region2<T>> {
|
|
|
|
using shape_type = cruft::region2<T>;
|
|
|
|
|
|
|
|
edge (shape_type _shape)
|
|
|
|
: m_shape (_shape)
|
|
|
|
{ ; }
|
|
|
|
|
|
|
|
template <typename GeneratorT>
|
|
|
|
decltype(auto)
|
|
|
|
eval (GeneratorT &&gen)
|
|
|
|
{
|
|
|
|
return edge<cruft::extent2i> (m_shape.e).eval (
|
|
|
|
std::forward<GeneratorT> (gen)
|
|
|
|
) + m_shape.p.template as<vector> ();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
shape_type m_shape;
|
|
|
|
};
|
|
|
|
}
|