diff --git a/Makefile.am b/Makefile.am index c93aef84..b3b5fc2f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -244,6 +244,7 @@ AM_LDFLAGS += $(BOOST_LDFLAGS) $(BOOST_FILESYSTEM_LIB) $(BOOST_SYSTEM_LIB) AM_CXXFLAGS += -I$(top_srcdir) TEST_BIN = \ + test/aabb \ test/backtrace \ test/bezier \ test/bitwise \ diff --git a/aabb.cpp b/aabb.cpp index 7da23dc3..d88d0f02 100644 --- a/aabb.cpp +++ b/aabb.cpp @@ -74,13 +74,58 @@ AABB::closest (point q) const } +/////////////////////////////////////////////////////////////////////////////// +template +AABB& +AABB::expand (util::vector mag) +{ + p0 -= mag / T{2}; + p1 += mag / T{2}; + + return *this; +} + + //----------------------------------------------------------------------------- template AABB& +AABB::expand (T t) +{ + return expand (vector {t}); +} + + +//----------------------------------------------------------------------------- +template +AABB +AABB::expanded (vector mag) +{ + auto ret = *this; + ret.expand (mag); + return ret; +} + + +//----------------------------------------------------------------------------- +template +AABB +AABB::expanded (T t) +{ + return expanded (vector {t}); +} + + +/////////////////////////////////////////////////////////////////////////////// +template +AABB& AABB::contract (util::vector mag) { - p0 -= mag / T{2}; - p1 += mag / T{2}; + // Avoid contracting magnitudes larger than our extent + auto diff = p1 - p0; + auto delta = min (diff, mag); + + p0 += delta / T{2}; + p1 -= delta / T{2}; return *this; } diff --git a/aabb.hpp b/aabb.hpp index 9f27d0ec..87c949d1 100644 --- a/aabb.hpp +++ b/aabb.hpp @@ -39,6 +39,11 @@ namespace util { point closest (point) const; + AABB& expand (util::vector); + AABB& expand (T); + AABB expanded (util::vector); + AABB expanded (T); + AABB& contract (util::vector); AABB& contract (T); AABB contracted (util::vector) const; diff --git a/test/aabb.cpp b/test/aabb.cpp new file mode 100644 index 00000000..e8daff86 --- /dev/null +++ b/test/aabb.cpp @@ -0,0 +1,51 @@ +#include "aabb.hpp" + +int +main (int, char**) +{ + { + // Test contraction + util::AABB2f box { + { 2, 2 }, + { 8, 8 } + }; + + box.contract (2.f); + + CHECK_EQ (box.p0.x, 3); + CHECK_EQ (box.p0.y, 3); + CHECK_EQ (box.p1.x, 7); + CHECK_EQ (box.p1.y, 7); + } + + { + // Test expansion + util::AABB2f box { + { 2, 2 }, + { 8, 8 } + }; + + box.expand (2.f); + + CHECK_EQ (box.p0.x, 1); + CHECK_EQ (box.p0.y, 1); + CHECK_EQ (box.p1.x, 9); + CHECK_EQ (box.p1.y, 9); + } + + + { + // Ensure we don't wrap-around on unsigned position types when contracting + util::AABB2f small { + { 0, 0 }, + { 1, 1 } + }; + + small.contract (10); + + CHECK_EQ (small.p0.x, 0.5f); + CHECK_EQ (small.p0.y, 0.5f); + CHECK_EQ (small.p1.x, 0.5f); + CHECK_EQ (small.p1.y, 0.5f); + } +}