diff --git a/test/vector.cpp b/test/vector.cpp index 394e48d9..688bba0f 100644 --- a/test/vector.cpp +++ b/test/vector.cpp @@ -102,6 +102,56 @@ test_euler (util::TAP::logger &tap) } +/////////////////////////////////////////////////////////////////////////////// +void +test_spherical (util::TAP::logger &tap) +{ + static constexpr struct { + util::vector3f spherical; + util::vector3f cartesian; + const char *message; + } TESTS[] = { + { { 1, 0, 0 }, { 0, 0, 1 }, "+zero", }, + { { -1, 0, 0 }, { 0, 0, -1 }, "-zero", }, + + { { 1, 1, 0 }, { 1, 0, 0 }, "90-theta", }, + { { 1, 2, 0 }, { 0, 0, -1 }, "180-theta", }, + { { 1, 3, 0 }, { -1, 0, 0 }, "270-theta", }, + + { { 1, 0, 1 }, { 0, 0, 1 }, "90-phi", }, + { { 1, 0, 2 }, { 0, 0, 1 }, "180-phi", }, + { { 1, 0, 3 }, { 0, 0, 1 }, "270-phi", }, + + { { 1, 1, 1 }, { 0, 1, 0 }, "90-theta, 90-phi" }, + { { 1, 1, 2 }, { -1, 0, 0 }, "90-theta, 180-phi" }, + { { 1, 1, 3 }, { 0, -1, 0 }, "90-theta, 270-phi" }, + }; + + for (const auto t: TESTS) { + tap.expect_eq ( + util::spherical_to_cartesian (t.spherical), + t.cartesian, + "%s, spherical-cartesian", + t.message + ); + + tap.expect_eq ( + util::cartesian_to_spherical (t.cartesian), + t.spherical, + "%s, cartesian-spherical", + t.message + ); + } + + + { + //util::vector3f s { 1, .5f, 2/3.f }; + //util::vector3f c { 0.35f, 0.61f, 0.71f }; + //tap.expect_eq + } +}; + + /////////////////////////////////////////////////////////////////////////////// int main () @@ -110,6 +160,7 @@ main () test_polar (tap); test_euler (tap); + test_spherical (tap); tap.expect (!is_normalised (util::vector3f::zeros ()), "zeros isn't normalised"); tap.expect (!is_normalised (util::vector3f::ones ()), "ones isn't normalised"); diff --git a/vector.cpp b/vector.cpp index da76eced..ea381a04 100644 --- a/vector.cpp +++ b/vector.cpp @@ -84,34 +84,6 @@ template util::vector2f util::to_euler (util::vector3f); template util::vector2d util::to_euler (util::vector3d); -//----------------------------------------------------------------------------- -template -vector<3,T> -util::spherical_to_cartesian (vector<3,T> s) -{ - return vector<3,T> { - s.x * sin (s.y) * cos (s.z), - s.x * sin (s.y) * sin (s.z), - s.x * cos (s.y), - }; -} - - -//----------------------------------------------------------------------------- -template -vector<3,T> -util::cartesian_to_spherical (vector<3,T> c) -{ - T mag = norm (c); - - return vector<3,T> { - mag, - acos (c.z / mag), - atan2 (c.y, c.x) - }; -} - - /////////////////////////////////////////////////////////////////////////////// template void diff --git a/vector.hpp b/vector.hpp index fcf5e9e4..5179e728 100644 --- a/vector.hpp +++ b/vector.hpp @@ -23,6 +23,7 @@ #include "json/fwd.hpp" #include +#include /////////////////////////////////////////////////////////////////////////////// @@ -56,8 +57,32 @@ namespace util { template vector<2,T> polar_to_cartesian (vector<2,T>); template vector<2,T> cartesian_to_polar (vector<2,T>); - template vector<3,T> spherical_to_cartesian (vector<3,T>); - template vector<3,T> cartesian_to_spherical (vector<3,T>); + // convert vector in spherical coordinates (r,theta,phi) with theta + // inclination and phi azimuth to cartesian coordinates (x,y,z) + template + constexpr vector<3,T> + spherical_to_cartesian (const vector<3,T> s) + { + return { + s.x * std::sin (s.y) * std::cos (s.z), + s.x * std::sin (s.y) * std::sin (s.z), + s.x * std::cos (s.y) + }; + } + + // convert vector in cartesian coordinates (x,y,z) to spherical + // coordinates (r,theta,phi) with theta inclination and phi azimuth. + template + constexpr vector<3,T> + cartesian_to_spherical (vector<3,T> c) + { + auto r = norm (c); + return { + r, + std::acos (c.z / r), + std::atan (c.y / c.z) + }; + } template vector<2,T> to_euler (vector<3,T>); template vector<3,T> from_euler (vector<2,T>);