libcruft-util/extent.hpp

191 lines
5.4 KiB
C++

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
*/
#ifndef CRUFT_UTIL_EXTENT_HPP
#define CRUFT_UTIL_EXTENT_HPP
#include "coord/fwd.hpp"
#include "coord/base.hpp"
#include "vector.hpp"
#include "point.hpp"
#include <cstddef>
namespace util {
/**
* A pure n-dimensional size, without positioning
*/
template <size_t S, typename T>
struct extent : public ::util::coord::base<S,T,::util::extent<S,T>>
{
using ::util::coord::base<S,T,::util::extent<S,T>>::base;
extent () = default;
explicit extent (::util::vector<S,T>);
constexpr T
area (void) const
{
return std::accumulate (std::begin (this->data),
std::end (this->data),
T {1},
std::multiplies<T> ());
}
constexpr T
diameter (void) const
{
return static_cast<T> (
std::sqrt (
std::accumulate (std::begin (this->data),
std::end (this->data),
T {0},
[] (auto a, auto b) { return a + b * b; })
)
);
}
template <typename U = float>
constexpr
U aspect (void) const
{
return static_cast<U> (this->w) / this->h;
}
/// tests whether a point would lie within:
/// region { origin, *this }, inclusive of borders.
///
/// included for parity with util::region.
constexpr bool
inclusive (util::point<S,T> p) const
{
return all (p >= T{0} && p <= *this);
}
/// tests whether a point would like within:
/// region { origin, *this }, exclusive of the bottom-right border
/// included for parity with util::region
constexpr bool
exclusive (point<S,T> p) const
{
return all (p >= T{0} && p < *this);
}
::util::extent<S,T> expanded (::util::vector<S,T>) const;
::util::extent<S,T> expanded (T) const;
::util::extent<S,T> contracted (::util::vector<S,T>) const;
::util::extent<S,T> contracted (T) const;
bool empty (void) const;
static constexpr
::util::extent<S,T> max (void)
{
return extent<S,T> {
std::numeric_limits<T>::max ()
};
}
static constexpr
::util::extent<S,T> min (void)
{
return extent<S,T> { 0 };
}
///////////////////////////////////////////////////////////////////////
class iterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = point<S,T>;
using difference_type = size_t;
using pointer = value_type*;
using reference = value_type&;
iterator (point<S,T> _cursor, extent<S,T> _target):
m_cursor (_cursor),
m_target (_target)
{ ; }
point<S,T>& operator* () & { return m_cursor; }
const point<S,T>& operator* () const & { return m_cursor; }
iterator& operator++ (void)&
{
++m_cursor[0];
for (size_t i = 0; i < S - 1; ++i) {
if (m_cursor[i] < m_target[i])
break;
m_cursor[i] = 0;
m_cursor[i+1]++;
}
return *this;
}
bool operator!= (const iterator &rhs) const { return m_cursor != rhs.m_cursor; }
bool operator== (const iterator &rhs) const { return m_cursor == rhs.m_cursor; }
private:
point<S,T> m_cursor;
extent<S,T> m_target;
};
auto step (void) const
{
point<S,T> last {0};
last[S-1] = this->data[S-1];
return util::view {
iterator {point<S,T> {0}, *this},
iterator {last, *this}
};
}
};
///////////////////////////////////////////////////////////////////////////
// convenience typedefs
template <typename T> using extent2 = extent<2,T>;
template <typename T> using extent3 = extent<3,T>;
template <size_t S> using extentu = extent<S,unsigned>;
template <size_t S> using extenti = extent<S,int>;
template <size_t S> using extentf = extent<S,float>;
template <size_t S> using extentd = extent<S,double>;
typedef extent2<int> extent2i;
typedef extent2<unsigned> extent2u;
typedef extent2<float> extent2f;
typedef extent2<double> extent2d;
typedef extent3<unsigned> extent3u;
typedef extent3<float> extent3f;
}
#endif