region: add make_range for regions
introduces an object that provides iterators suitable for row-major scanning of points covering a region object. mostly a wrapper for the equivalent extent_range.
This commit is contained in:
parent
439809ca65
commit
a016e98b12
97
region.hpp
97
region.hpp
@ -11,17 +11,17 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
*
|
||||||
* Copyright 2010-2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __UTIL_REGION_HPP
|
#ifndef CRUFT_UTIL_REGION_HPP
|
||||||
#define __UTIL_REGION_HPP
|
#define CRUFT_UTIL_REGION_HPP
|
||||||
|
|
||||||
#include "extent.hpp"
|
#include "./extent.hpp"
|
||||||
#include "point.hpp"
|
#include "./point.hpp"
|
||||||
#include "vector.hpp"
|
#include "./vector.hpp"
|
||||||
#include "types/traits.hpp"
|
#include "./types/traits.hpp"
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
@ -121,6 +121,89 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
/// construct a point iterator across a given region, generating each
|
||||||
|
/// valid point in row-major sequence.
|
||||||
|
///
|
||||||
|
/// this is only defined for integral types as it's not clear how to
|
||||||
|
/// handle floats; it's _super_ unlikely anyone actually wants to visit
|
||||||
|
/// every single floating point value for a region (and if so they can
|
||||||
|
/// damn well code that monstrosity themselves).
|
||||||
|
template <
|
||||||
|
typename T,
|
||||||
|
std::size_t S,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
std::is_integral_v<T>, void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
auto
|
||||||
|
make_range (region<S,T> r)
|
||||||
|
{
|
||||||
|
using region_t = region<S,T>;
|
||||||
|
using point_t = typename region_t::point_t;
|
||||||
|
using vector_t = util::vector<S,T>;
|
||||||
|
|
||||||
|
// this range object is mostly a wrapper around the existing
|
||||||
|
// extent_range object with a constant offset. it's not going to be as
|
||||||
|
// performant, but when we discover this is an issue we can do write a
|
||||||
|
// better version of this object & iterator.
|
||||||
|
class region_range {
|
||||||
|
public:
|
||||||
|
class iterator : public std::iterator<std::forward_iterator_tag, point_t, size_t> {
|
||||||
|
public:
|
||||||
|
iterator (typename extent_range<S,T>::iterator _inner, vector_t _offset):
|
||||||
|
m_inner (_inner),
|
||||||
|
m_offset (_offset)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
|
point_t operator* (void) const { return *m_inner + m_offset; }
|
||||||
|
|
||||||
|
iterator&
|
||||||
|
operator++ (void)
|
||||||
|
{
|
||||||
|
++m_inner;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator== (const iterator &rhs) const
|
||||||
|
{
|
||||||
|
assert (m_offset == rhs.m_offset);
|
||||||
|
return m_inner == rhs.m_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator!= (const iterator &rhs) const
|
||||||
|
{ return !(*this == rhs); }
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
typename extent_range<S,T>::iterator m_inner;
|
||||||
|
vector_t m_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
region_range (region_t _r):
|
||||||
|
m_range { _r.e + T{1} },
|
||||||
|
m_offset { _r.p.template as<util::vector> () }
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
iterator begin (void) const { return { m_range.begin (), m_offset }; }
|
||||||
|
iterator end (void) const { return { m_range.end (), m_offset }; }
|
||||||
|
|
||||||
|
iterator cbegin (void) const { return begin (); }
|
||||||
|
iterator cend (void) const { return end (); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const extent_range<S,T> m_range;
|
||||||
|
const vector_t m_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return region_range { r };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T> using region2 = region<2,T>;
|
template <typename T> using region2 = region<2,T>;
|
||||||
template <typename T> using region3 = region<3,T>;
|
template <typename T> using region3 = region<3,T>;
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "point.hpp"
|
#include "point.hpp"
|
||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int
|
int
|
||||||
@ -80,6 +81,29 @@ main (int, char **)
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ensure make_region covers the expected values
|
||||||
|
{
|
||||||
|
const util::region2i REGION {
|
||||||
|
util::point2i { -1, 1 },
|
||||||
|
util::point2i { 1, 3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const util::point2i EXPECTED[] = {
|
||||||
|
{ -1, 1 }, { 0, 1 }, { 1, 1 },
|
||||||
|
{ -1, 2 }, { 0, 2 }, { 1, 2 },
|
||||||
|
{ -1, 3 }, { 0, 3 }, { 1, 3 },
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<util::point2i> values;
|
||||||
|
auto sequence = util::make_range (REGION);
|
||||||
|
std::copy (std::cbegin (sequence), std::cend (sequence), std::back_inserter (values));
|
||||||
|
|
||||||
|
bool success = values.size () == std::size (EXPECTED)
|
||||||
|
&& std::equal (std::cbegin (values), std::cend (values),
|
||||||
|
std::cbegin (EXPECTED), std::cend (EXPECTED));
|
||||||
|
tap.expect (success, "make_range(region2i)");
|
||||||
|
};
|
||||||
|
|
||||||
//CHECK (region<2,intmax_t> (0, 0, 10, 10).includes (point2d (0.4, 0.01)));
|
//CHECK (region<2,intmax_t> (0, 0, 10, 10).includes (point2d (0.4, 0.01)));
|
||||||
//CHECK (region<2,intmax_t> (0, 0, 10, 10).contains (point2d (0.4, 0.01)));
|
//CHECK (region<2,intmax_t> (0, 0, 10, 10).contains (point2d (0.4, 0.01)));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user