2018-05-17 13:50:03 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cgv/type/standard_types.h>
|
|
|
|
#include <cgv/math/vec.h>
|
|
|
|
#include <cgv/math/fvec.h>
|
|
|
|
|
|
|
|
namespace cgv {
|
|
|
|
namespace media {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An axis aligned box, defined by to points: min and max
|
|
|
|
*/
|
|
|
|
template<typename T, cgv::type::uint32_type N>
|
|
|
|
class axis_aligned_box
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
/// internally fixed sized points and vectors are used
|
|
|
|
typedef cgv::math::fvec<T,N> fpnt_type;
|
|
|
|
typedef cgv::math::fvec<T,N> fvec_type;
|
|
|
|
/// the interface allows also to work with variable sized points
|
|
|
|
typedef cgv::math::vec<T> pnt_type;
|
|
|
|
typedef cgv::math::vec<T> vec_type;
|
|
|
|
protected:
|
|
|
|
fpnt_type minp;
|
|
|
|
fpnt_type maxp;
|
|
|
|
public:
|
|
|
|
/// standard constructor does not initialize
|
2018-05-17 14:01:02 +00:00
|
|
|
axis_aligned_box() { invalidate(); }
|
|
|
|
/// type conversion copy constructor
|
|
|
|
template <typename S>
|
|
|
|
axis_aligned_box(const axis_aligned_box<S, N>& B) :
|
|
|
|
minp(T(B.get_min_pnt()(0)), T(B.get_min_pnt()(1)), T(B.get_min_pnt()(2))),
|
|
|
|
maxp(T(B.get_max_pnt()(0)), T(B.get_max_pnt()(1)), T(B.get_max_pnt()(2))) {}
|
2018-05-17 13:50:03 +00:00
|
|
|
/// construct from min point and max point
|
|
|
|
axis_aligned_box(const fpnt_type& _minp, const fpnt_type& _maxp) : minp(_minp), maxp(_maxp) {}
|
|
|
|
/// construct from min point and max point
|
|
|
|
axis_aligned_box(const pnt_type& _minp, const pnt_type& _maxp)
|
|
|
|
{
|
|
|
|
invalidate();
|
|
|
|
unsigned i;
|
|
|
|
for (i=0; i<_minp.size(); ++i) {
|
|
|
|
if (i == N)
|
|
|
|
break;
|
|
|
|
minp(i) = _minp(i);
|
|
|
|
}
|
|
|
|
for (i=0; i<_maxp.size(); ++i) {
|
|
|
|
if (i == N)
|
|
|
|
break;
|
|
|
|
maxp(i) = _maxp(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// set to invalid min and max points
|
|
|
|
void invalidate() {
|
|
|
|
for (unsigned int c = 0; c<N; ++c) {
|
|
|
|
minp(c) = 1;
|
|
|
|
maxp(c) = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// return a const reference to corner 0
|
|
|
|
const fpnt_type& get_min_pnt() const { return minp; }
|
|
|
|
/// return a const reference to corner 7
|
|
|
|
const fpnt_type& get_max_pnt() const { return maxp; }
|
|
|
|
/// return a reference to corner 0
|
|
|
|
fpnt_type& ref_min_pnt() { return minp; }
|
|
|
|
/// return a reference to corner 7
|
|
|
|
fpnt_type& ref_max_pnt() { return maxp; }
|
|
|
|
/// return the i-th corner where the lower N bits of i are used to select between min (bit = 0) and max (bit = 1) coordinate
|
|
|
|
fpnt_type get_corner(int i) const
|
|
|
|
{
|
|
|
|
fpnt_type c = minp;
|
|
|
|
int bit = 1;
|
|
|
|
for (unsigned int dim=0; dim < N; ++dim, bit *= 2)
|
|
|
|
if (i & bit)
|
|
|
|
c(dim) = maxp(dim);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
/// return a vector with the extents in the different dimensions
|
|
|
|
fvec_type get_extent() const { return maxp-minp; }
|
|
|
|
/// return the center of the box
|
|
|
|
fpnt_type get_center() const { return minp+(T)0.5*get_extent(); }
|
|
|
|
/// check if aab is valid
|
|
|
|
bool is_valid() const { return minp[0] <= maxp[0]; }
|
|
|
|
/// check whether a point is inside the aabb
|
|
|
|
bool inside(const fpnt_type& p) const {
|
|
|
|
for (unsigned int c = 0; c<N; ++c) {
|
|
|
|
if (p(c) < minp(c)) return false;
|
|
|
|
if (p(c) >= maxp(c)) return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
/// extent box to include given point
|
|
|
|
void add_point(const fpnt_type& p) {
|
|
|
|
if (is_valid()) {
|
|
|
|
for (unsigned int c = 0; c<N; ++c) {
|
|
|
|
if (p(c) > maxp(c)) maxp(c) = p(c);
|
|
|
|
if (p(c) < minp(c)) minp(c) = p(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
minp = maxp = p;
|
|
|
|
}
|
|
|
|
/// extent box to include given point
|
|
|
|
void add_point(const pnt_type& p) {
|
|
|
|
if (is_valid()) {
|
|
|
|
for (unsigned int c = 0; p.size(); ++c) {
|
|
|
|
if (c == N)
|
|
|
|
break;
|
|
|
|
if (p(c) > maxp(c)) maxp(c) = p(c);
|
|
|
|
if (p(c) < minp(c)) minp(c) = p(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*this = axis_aligned_box<T,N>(p,p);
|
|
|
|
}
|
|
|
|
/// extent box to include given axis alinged box
|
|
|
|
void add_axis_aligned_box(const axis_aligned_box<T,N>& aab) {
|
|
|
|
if (!aab.is_valid())
|
|
|
|
return;
|
|
|
|
add_point(aab.minp);
|
|
|
|
add_point(aab.maxp);
|
|
|
|
}
|
|
|
|
/// scale the complete box with respect to the world coordinate origin
|
|
|
|
void scale(const T& f)
|
|
|
|
{
|
|
|
|
for (unsigned int c = 0; c<N; ++c) {
|
|
|
|
maxp(c) *= f;
|
|
|
|
minp(c) *= f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// return the index of the coordinte with maximum extend
|
|
|
|
unsigned get_max_extent_coord_index() const
|
|
|
|
{
|
|
|
|
fvec_type e = get_extent();
|
|
|
|
unsigned j = 0;
|
|
|
|
for (unsigned i=1; i<N; ++i)
|
|
|
|
if (e(i) > e(j))
|
|
|
|
j = i;
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|