diff --git a/Makefile.am b/Makefile.am index 0ec9976d..c93aef84 100644 --- a/Makefile.am +++ b/Makefile.am @@ -277,6 +277,7 @@ TEST_BIN = \ test/signal \ test/stringid \ test/uri \ + test/vector \ test/version diff --git a/test/vector.cpp b/test/vector.cpp new file mode 100644 index 00000000..c6ec9c92 --- /dev/null +++ b/test/vector.cpp @@ -0,0 +1,67 @@ +#include "vector.hpp" + +#include "maths.hpp" + +using util::vector; +using util::vector2f; + + +void +test_polar (void) +{ + static const struct { + util::vector2f polar; + util::vector2f cartesian; + const char *desc; + } TESTS[] { + { + { 0.f, 0.f }, + { 0.f, 0.f }, + "all zeroes" + }, + + { + { 1.f, 0.f }, + { 1.f, 0.f }, + "unit length, unrotated" + }, + + { + { 1.f, PI_f / 2.f }, + { 0.f, 1.f }, + "unit length, rotated" + }, + + { + { 1.f, 2 * PI_f }, + { 1.f, 0.f }, + "full rotation, unit length" + } + }; + + for (const auto &t: TESTS) { + // Compare the difference of cartesian representations. Don't use + // direct equality comparisons here as the numeric stability can be + // poor and we have nice whole numbers to start with. + auto in_cart = t.cartesian; + auto to_cart = util::polar_to_cartesian (t.polar); + + CHECK_LT ((in_cart - to_cart).magnitude (), 0.00001f); + + // Compare polar representations. Make sure to normalise them first. + auto in_polar = t.polar; + auto to_polar = util::cartesian_to_polar (t.cartesian); + + in_polar[1] = std::fmod (in_polar[1], 2 * PI_f); + to_polar[1] = std::fmod (to_polar[1], 2 * PI_f); + + CHECK_EQ (in_polar, to_polar); + } +} + + +int +main () +{ + test_polar (); +} diff --git a/vector.cpp b/vector.cpp index 49fb231e..5ba8657e 100644 --- a/vector.cpp +++ b/vector.cpp @@ -98,10 +98,12 @@ util::vector::normalised (void) const { return out; } -//----------------------------------------------------------------------------- + +/////////////////////////////////////////////////////////////////////////////// template util::vector<2,T> -util::polar_to_cartesian (util::vector<2,T> v) { +util::polar_to_cartesian (util::vector<2,T> v) +{ return util::vector<2,T> { v[0] * std::cos (v[1]), v[0] * std::sin (v[1]) @@ -111,6 +113,18 @@ util::polar_to_cartesian (util::vector<2,T> v) { //----------------------------------------------------------------------------- template +util::vector<2,T> +util::cartesian_to_polar (util::vector<2,T> v) +{ + return util::vector<2,T> { + std::hypot (v.x, v.y), + std::atan2 (v.y, v.x) + }; +} + + +/////////////////////////////////////////////////////////////////////////////// +template util::vector<3,T> util::cross (const util::vector<3,T> &a, const util::vector<3,T> &b) @@ -236,6 +250,7 @@ INSTANTIATE(double) //----------------------------------------------------------------------------- namespace util { template vector<2,float> polar_to_cartesian (util::vector<2,float>); + template vector<2,float> cartesian_to_polar (util::vector<2,float>); template <> vector<1,float> random (void) { util::vector<1,float> out; randomise (out.data); return out; } template <> vector<2,float> random (void) { util::vector<2,float> out; randomise (out.data); return out; } diff --git a/vector.hpp b/vector.hpp index ce36af7b..1fa01caa 100644 --- a/vector.hpp +++ b/vector.hpp @@ -57,6 +57,7 @@ namespace util { // free vector operators template vector<2,T> polar_to_cartesian (vector<2,T>); + template vector<2,T> cartesian_to_polar (vector<2,T>); template vector<3,T> cross (const vector<3,T>&, const vector<3,T>&); template vector<3,T> spherical_to_cartesian (const vector<3,T>&);