From d5e5b42889f75585c971d1be02df7a403a8ff1db Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Wed, 22 Oct 2025 20:26:13 -0500 Subject: [PATCH 1/2] Test specific values in sin and cos functions --- src/pstack/geo/functions.hpp | 1 + src/pstack/geo/test/functions_ut.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/pstack/geo/functions.hpp b/src/pstack/geo/functions.hpp index 8d621d4..96ded6f 100644 --- a/src/pstack/geo/functions.hpp +++ b/src/pstack/geo/functions.hpp @@ -11,6 +11,7 @@ namespace pstack::geo { static_assert(sizeof(double) == sizeof(std::uint64_t)); using std::numbers::pi; +using std::numbers::sqrt2; constexpr double sin(double x) { while (x > pi) { diff --git a/src/pstack/geo/test/functions_ut.cpp b/src/pstack/geo/test/functions_ut.cpp index e9a6997..47e106d 100644 --- a/src/pstack/geo/test/functions_ut.cpp +++ b/src/pstack/geo/test/functions_ut.cpp @@ -16,16 +16,44 @@ TEST_CASE("pi", "[functions]") { STATIC_CHECK(pi == std::numbers::pi); } +TEST_CASE("sqrt2", "[functions]") { + STATIC_CHECK(sqrt2 == std::numbers::sqrt2); +} + TEST_CASE("sin", "[functions]") { const auto num = g.generate(); CHECK_THAT(sin(num), WithinAbs(std::sin(num), epsilon)); } +TEST_CASE("sin specific values", "[functions]") { + CHECK_THAT(sin(0), WithinAbs(0, epsilon)); + CHECK_THAT(sin(pi / 4), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(sin(pi / 2), WithinAbs(1, epsilon)); + CHECK_THAT(sin(3 * pi / 4), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(sin(pi), WithinAbs(0, epsilon)); + CHECK_THAT(sin(5 * pi / 4), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(sin(3 * pi / 2), WithinAbs(-1, epsilon)); + CHECK_THAT(sin(7 * pi / 4), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(sin(2 * pi), WithinAbs(0, epsilon)); +} + TEST_CASE("cos", "[functions]") { const auto num = g.generate(); CHECK_THAT(cos(num), WithinAbs(std::cos(num), epsilon)); } +TEST_CASE("cos specific values", "[functions]") { + CHECK_THAT(cos(0), WithinAbs(1, epsilon)); + CHECK_THAT(cos(pi / 4), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(cos(pi / 2), WithinAbs(0, epsilon)); + CHECK_THAT(cos(3 * pi / 4), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(cos(pi), WithinAbs(-1, epsilon)); + CHECK_THAT(cos(5 * pi / 4), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(cos(3 * pi / 2), WithinAbs(0, epsilon)); + CHECK_THAT(cos(7 * pi / 4), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(cos(2 * pi), WithinAbs(1, epsilon)); +} + TEST_CASE("ceil fractional", "[functions]") { const auto num = g.generate(); if (num > 0) { From 225227dd85df1e1696562a75c87dfc6784c6b166 Mon Sep 17 00:00:00 2001 From: Braden Ganetsky Date: Wed, 22 Oct 2025 20:26:14 -0500 Subject: [PATCH 2/2] Create strong types for degrees and radians, to fix the error in defining the rotations --- src/pstack/calc/rotations.cpp | 14 +++--- src/pstack/calc/rotations.hpp | 46 +++++++++---------- src/pstack/calc/stacker.cpp | 6 +-- src/pstack/geo/functions.hpp | 24 +++++++++- src/pstack/geo/matrix3.hpp | 8 ++-- src/pstack/geo/matrix4.hpp | 6 +-- src/pstack/geo/test/functions_ut.cpp | 68 +++++++++++++++++++--------- src/pstack/geo/test/matrix3_ut.cpp | 8 ++-- src/pstack/geo/test/matrix4_ut.cpp | 6 +-- src/pstack/gui/transformation.hpp | 2 +- 10 files changed, 117 insertions(+), 71 deletions(-) diff --git a/src/pstack/calc/rotations.cpp b/src/pstack/calc/rotations.cpp index 10b2386..daecc23 100644 --- a/src/pstack/calc/rotations.cpp +++ b/src/pstack/calc/rotations.cpp @@ -6,16 +6,18 @@ namespace pstack::calc { const std::array, 32> arbitrary_rotations = [] { std::array, 32> out; out[0] = geo::eye3; - out[1] = geo::rot3({ 1, 1, 1 }, 120); - out[2] = geo::rot3({ 1, 1, 1 }, 240); - out[3] = geo::rot3({ 1, 0, 0 }, 180); - out[4] = geo::rot3({ 0, 1, 0 }, 180); - out[5] = geo::rot3({ 0, 0, 1 }, 180); + out[1] = geo::rot3({ 1, 1, 1 }, geo::degrees{120}); + out[2] = geo::rot3({ 1, 1, 1 }, geo::degrees{240}); + out[3] = geo::rot3({ 1, 0, 0 }, geo::degrees{180}); + out[4] = geo::rot3({ 0, 1, 0 }, geo::degrees{180}); + out[5] = geo::rot3({ 0, 0, 1 }, geo::degrees{180}); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution dis(0, 2 * geo::pi); for (std::size_t i = 6; i != 32; ++i) { - out[i] = geo::rot3_z(dis(gen)) * geo::rot3_y(dis(gen)) * geo::rot3_x(dis(gen)); + out[i] = geo::rot3_z(geo::radians{dis(gen)}) + * geo::rot3_y(geo::radians{dis(gen)}) + * geo::rot3_x(geo::radians{dis(gen)}); } return out; }(); diff --git a/src/pstack/calc/rotations.hpp b/src/pstack/calc/rotations.hpp index 77b89f2..ac78b0a 100644 --- a/src/pstack/calc/rotations.hpp +++ b/src/pstack/calc/rotations.hpp @@ -13,29 +13,29 @@ inline constexpr std::array no_rotations = { inline constexpr std::array cubic_rotations = { geo::eye3, - geo::rot3({ 1, 0, 0 }, 90), - geo::rot3({ 1, 0, 0 }, 180), - geo::rot3({ 1, 0, 0 }, 270), - geo::rot3({ 0, 1, 0 }, 90), - geo::rot3({ 0, 1, 0 }, 180), - geo::rot3({ 0, 1, 0 }, 270), - geo::rot3({ 0, 0, 1 }, 90), - geo::rot3({ 0, 0, 1 }, 180), - geo::rot3({ 0, 0, 1 }, 270), - geo::rot3({ 1, 1, 0 }, 180), - geo::rot3({ 1, -1, 0 }, 180), - geo::rot3({ 0, 1, 1 }, 180), - geo::rot3({ 0, -1, 1 }, 180), - geo::rot3({ 1, 0, 1 }, 180), - geo::rot3({ 1, 0, -1 }, 180), - geo::rot3({ 1, 1, 1 }, 120), - geo::rot3({ 1, 1, 1 }, 240), - geo::rot3({ -1, 1, 1 }, 120), - geo::rot3({ -1, 1, 1 }, 240), - geo::rot3({ 1, -1, 1 }, 120), - geo::rot3({ 1, -1, 1 }, 240), - geo::rot3({ 1, 1, -1 }, 120), - geo::rot3({ 1, 1, -1 }, 240), + geo::rot3({ 1, 0, 0 }, geo::degrees{90}), + geo::rot3({ 1, 0, 0 }, geo::degrees{180}), + geo::rot3({ 1, 0, 0 }, geo::degrees{270}), + geo::rot3({ 0, 1, 0 }, geo::degrees{90}), + geo::rot3({ 0, 1, 0 }, geo::degrees{180}), + geo::rot3({ 0, 1, 0 }, geo::degrees{270}), + geo::rot3({ 0, 0, 1 }, geo::degrees{90}), + geo::rot3({ 0, 0, 1 }, geo::degrees{180}), + geo::rot3({ 0, 0, 1 }, geo::degrees{270}), + geo::rot3({ 1, 1, 0 }, geo::degrees{180}), + geo::rot3({ 1, -1, 0 }, geo::degrees{180}), + geo::rot3({ 0, 1, 1 }, geo::degrees{180}), + geo::rot3({ 0, -1, 1 }, geo::degrees{180}), + geo::rot3({ 1, 0, 1 }, geo::degrees{180}), + geo::rot3({ 1, 0, -1 }, geo::degrees{180}), + geo::rot3({ 1, 1, 1 }, geo::degrees{120}), + geo::rot3({ 1, 1, 1 }, geo::degrees{240}), + geo::rot3({ -1, 1, 1 }, geo::degrees{120}), + geo::rot3({ -1, 1, 1 }, geo::degrees{240}), + geo::rot3({ 1, -1, 1 }, geo::degrees{120}), + geo::rot3({ 1, -1, 1 }, geo::degrees{240}), + geo::rot3({ 1, 1, -1 }, geo::degrees{120}), + geo::rot3({ 1, 1, -1 }, geo::degrees{240}), }; extern const std::array, 32> arbitrary_rotations; diff --git a/src/pstack/calc/stacker.cpp b/src/pstack/calc/stacker.cpp index 669d29c..471f3be 100644 --- a/src/pstack/calc/stacker.cpp +++ b/src/pstack/calc/stacker.cpp @@ -158,8 +158,8 @@ std::optional stack_impl(const stack_parameters& params, const std static constexpr std::size_t sections = 20; static constexpr double angle_diff = 2 * geo::pi / sections; - static constexpr geo::matrix3 rot_x = geo::rot3_x(angle_diff); - static constexpr geo::matrix3 rot_y = geo::rot3_y(angle_diff); + static constexpr geo::matrix3 rot_x = geo::rot3_x(geo::radians{angle_diff}); + static constexpr geo::matrix3 rot_y = geo::rot3_y(geo::radians{angle_diff}); int min_box_volume = std::numeric_limits::max(); double best_x = 0; @@ -179,7 +179,7 @@ std::optional stack_impl(const stack_parameters& params, const std } } - base_rotation = geo::rot3_y(best_y) * geo::rot3_x(best_x); + base_rotation = geo::rot3_y(geo::radians{best_y}) * geo::rot3_x(geo::radians{best_x}); } // Set up array of parts diff --git a/src/pstack/geo/functions.hpp b/src/pstack/geo/functions.hpp index 96ded6f..42e3eb7 100644 --- a/src/pstack/geo/functions.hpp +++ b/src/pstack/geo/functions.hpp @@ -2,6 +2,7 @@ #define PSTACK_GEO_FUNCTIONS_HPP #include +#include #include #include #include @@ -13,7 +14,25 @@ static_assert(sizeof(double) == sizeof(std::uint64_t)); using std::numbers::pi; using std::numbers::sqrt2; -constexpr double sin(double x) { +struct radians; +struct degrees; + +struct radians { + explicit radians(double val) : value(val) {} + radians(degrees d); + double value; +}; +struct degrees { + explicit degrees(double val) : value(val) {} + degrees(radians r); + double value; +}; + +inline radians::radians(degrees d) : value(d.value * (pi / 180)) {} +inline degrees::degrees(radians r) : value(r.value * (180 / pi)) {} + +constexpr double sin(radians r) { + double x = r.value; while (x > pi) { x -= 2 * pi; } @@ -44,7 +63,8 @@ constexpr double sin(double x) { return result * sign; } -constexpr double cos(double x) { +constexpr double cos(radians r) { + double x = r.value; while (x > pi) { x -= 2 * pi; } diff --git a/src/pstack/geo/matrix3.hpp b/src/pstack/geo/matrix3.hpp index 38683f2..3a7dec9 100644 --- a/src/pstack/geo/matrix3.hpp +++ b/src/pstack/geo/matrix3.hpp @@ -65,7 +65,7 @@ constexpr matrix3 operator*(const std::type_identity_t& lhs, const matrix3 } template -constexpr matrix3 rot3(const vector3& axis, const std::type_identity_t theta) { +constexpr matrix3 rot3(const vector3& axis, const radians theta) { const T c = static_cast(cos(theta)); const T s = static_cast(sin(theta)); const auto n = normalize(axis); @@ -77,7 +77,7 @@ constexpr matrix3 rot3(const vector3& axis, const std::type_identity_t } template -constexpr matrix3 rot3_x(const T theta) { +constexpr matrix3 rot3_x(const radians theta) { const T c = static_cast(cos(theta)); const T s = static_cast(sin(theta)); return { 1, 0, 0, @@ -86,7 +86,7 @@ constexpr matrix3 rot3_x(const T theta) { } template -constexpr matrix3 rot3_y(const T theta) { +constexpr matrix3 rot3_y(const radians theta) { const T c = static_cast(cos(theta)); const T s = static_cast(sin(theta)); return { c, 0, s, @@ -95,7 +95,7 @@ constexpr matrix3 rot3_y(const T theta) { } template -constexpr matrix3 rot3_z(const T theta) { +constexpr matrix3 rot3_z(const radians theta) { const T c = static_cast(cos(theta)); const T s = static_cast(sin(theta)); return { c, -s, 0, diff --git a/src/pstack/geo/matrix4.hpp b/src/pstack/geo/matrix4.hpp index e59a089..793be9b 100644 --- a/src/pstack/geo/matrix4.hpp +++ b/src/pstack/geo/matrix4.hpp @@ -46,7 +46,7 @@ inline constexpr matrix4 eye4 = { 1, 0, 0, 0, 0, 0, 0, 1 }; template -constexpr matrix4 rot4_x(const T theta) { +constexpr matrix4 rot4_x(const radians theta) { const T c = static_cast(cos(theta)); const T s = static_cast(sin(theta)); return { 1, 0, 0, 0, @@ -56,7 +56,7 @@ constexpr matrix4 rot4_x(const T theta) { } template -constexpr matrix4 rot4_y(const T theta) { +constexpr matrix4 rot4_y(const radians theta) { const T c = static_cast(cos(theta)); const T s = static_cast(sin(theta)); return { c, 0, s, 0, @@ -66,7 +66,7 @@ constexpr matrix4 rot4_y(const T theta) { } template -constexpr matrix4 rot4_z(const T theta) { +constexpr matrix4 rot4_z(const radians theta) { const T c = static_cast(cos(theta)); const T s = static_cast(sin(theta)); return { c, -s, 0, 0, diff --git a/src/pstack/geo/test/functions_ut.cpp b/src/pstack/geo/test/functions_ut.cpp index 47e106d..29e6c10 100644 --- a/src/pstack/geo/test/functions_ut.cpp +++ b/src/pstack/geo/test/functions_ut.cpp @@ -22,36 +22,60 @@ TEST_CASE("sqrt2", "[functions]") { TEST_CASE("sin", "[functions]") { const auto num = g.generate(); - CHECK_THAT(sin(num), WithinAbs(std::sin(num), epsilon)); + CHECK_THAT(sin(radians{num}), WithinAbs(std::sin(num), epsilon)); } -TEST_CASE("sin specific values", "[functions]") { - CHECK_THAT(sin(0), WithinAbs(0, epsilon)); - CHECK_THAT(sin(pi / 4), WithinAbs(sqrt2 / 2, epsilon)); - CHECK_THAT(sin(pi / 2), WithinAbs(1, epsilon)); - CHECK_THAT(sin(3 * pi / 4), WithinAbs(sqrt2 / 2, epsilon)); - CHECK_THAT(sin(pi), WithinAbs(0, epsilon)); - CHECK_THAT(sin(5 * pi / 4), WithinAbs(-sqrt2 / 2, epsilon)); - CHECK_THAT(sin(3 * pi / 2), WithinAbs(-1, epsilon)); - CHECK_THAT(sin(7 * pi / 4), WithinAbs(-sqrt2 / 2, epsilon)); - CHECK_THAT(sin(2 * pi), WithinAbs(0, epsilon)); +TEST_CASE("sin specific radian values", "[functions]") { + CHECK_THAT(sin(radians{0}), WithinAbs(0, epsilon)); + CHECK_THAT(sin(radians{pi / 4}), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(sin(radians{pi / 2}), WithinAbs(1, epsilon)); + CHECK_THAT(sin(radians{3 * pi / 4}), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(sin(radians{pi}), WithinAbs(0, epsilon)); + CHECK_THAT(sin(radians{5 * pi / 4}), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(sin(radians{3 * pi / 2}), WithinAbs(-1, epsilon)); + CHECK_THAT(sin(radians{7 * pi / 4}), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(sin(radians{2 * pi}), WithinAbs(0, epsilon)); +} + +TEST_CASE("sin specific degree values", "[functions]") { + CHECK_THAT(sin(degrees{0}), WithinAbs(0, epsilon)); + CHECK_THAT(sin(degrees{45}), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(sin(degrees{90}), WithinAbs(1, epsilon)); + CHECK_THAT(sin(degrees{135}), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(sin(degrees{180}), WithinAbs(0, epsilon)); + CHECK_THAT(sin(degrees{225}), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(sin(degrees{270}), WithinAbs(-1, epsilon)); + CHECK_THAT(sin(degrees{315}), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(sin(degrees{360}), WithinAbs(0, epsilon)); } TEST_CASE("cos", "[functions]") { const auto num = g.generate(); - CHECK_THAT(cos(num), WithinAbs(std::cos(num), epsilon)); + CHECK_THAT(cos(radians{num}), WithinAbs(std::cos(num), epsilon)); +} + +TEST_CASE("cos specific radian values", "[functions]") { + CHECK_THAT(cos(radians{0}), WithinAbs(1, epsilon)); + CHECK_THAT(cos(radians{pi / 4}), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(cos(radians{pi / 2}), WithinAbs(0, epsilon)); + CHECK_THAT(cos(radians{3 * pi / 4}), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(cos(radians{pi}), WithinAbs(-1, epsilon)); + CHECK_THAT(cos(radians{5 * pi / 4}), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(cos(radians{3 * pi / 2}), WithinAbs(0, epsilon)); + CHECK_THAT(cos(radians{7 * pi / 4}), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(cos(radians{2 * pi}), WithinAbs(1, epsilon)); } -TEST_CASE("cos specific values", "[functions]") { - CHECK_THAT(cos(0), WithinAbs(1, epsilon)); - CHECK_THAT(cos(pi / 4), WithinAbs(sqrt2 / 2, epsilon)); - CHECK_THAT(cos(pi / 2), WithinAbs(0, epsilon)); - CHECK_THAT(cos(3 * pi / 4), WithinAbs(-sqrt2 / 2, epsilon)); - CHECK_THAT(cos(pi), WithinAbs(-1, epsilon)); - CHECK_THAT(cos(5 * pi / 4), WithinAbs(-sqrt2 / 2, epsilon)); - CHECK_THAT(cos(3 * pi / 2), WithinAbs(0, epsilon)); - CHECK_THAT(cos(7 * pi / 4), WithinAbs(sqrt2 / 2, epsilon)); - CHECK_THAT(cos(2 * pi), WithinAbs(1, epsilon)); +TEST_CASE("cos specific degree values", "[functions]") { + CHECK_THAT(cos(degrees{0}), WithinAbs(1, epsilon)); + CHECK_THAT(cos(degrees{45}), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(cos(degrees{90}), WithinAbs(0, epsilon)); + CHECK_THAT(cos(degrees{135}), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(cos(degrees{180}), WithinAbs(-1, epsilon)); + CHECK_THAT(cos(degrees{225}), WithinAbs(-sqrt2 / 2, epsilon)); + CHECK_THAT(cos(degrees{270}), WithinAbs(0, epsilon)); + CHECK_THAT(cos(degrees{315}), WithinAbs(sqrt2 / 2, epsilon)); + CHECK_THAT(cos(degrees{360}), WithinAbs(1, epsilon)); } TEST_CASE("ceil fractional", "[functions]") { diff --git a/src/pstack/geo/test/matrix3_ut.cpp b/src/pstack/geo/test/matrix3_ut.cpp index 9c3124a..ffe6046 100644 --- a/src/pstack/geo/test/matrix3_ut.cpp +++ b/src/pstack/geo/test/matrix3_ut.cpp @@ -148,7 +148,7 @@ TEMPLATE_TEST_CASE("rot3()", "[matrix3]", const auto [axis, theta] = g.generate, T>(); const auto c = std::cos(theta); const auto s = std::sin(theta); - const matrix3 actual = rot3(axis, theta); + const matrix3 actual = rot3(axis, geo::radians{theta}); const auto n = normalize(axis); const matrix3 K = { 0, -n.z, n.y, n.z, 0, -n.x, @@ -172,7 +172,7 @@ TEMPLATE_TEST_CASE("rot3_x()", "[matrix3]", const auto theta = g.generate(); const auto c = std::cos(theta); const auto s = std::sin(theta); - const matrix3 actual = rot3_x(theta); + const matrix3 actual = rot3_x(geo::radians{theta}); CHECK(actual.xx == 1); CHECK(actual.xy == 0); CHECK(actual.xz == 0); @@ -191,7 +191,7 @@ TEMPLATE_TEST_CASE("rot3_y()", "[matrix3]", const auto theta = g.generate(); const auto c = std::cos(theta); const auto s = std::sin(theta); - const matrix3 actual = rot3_y(theta); + const matrix3 actual = rot3_y(geo::radians{theta}); CHECK_THAT(actual.xx, WithinAbs(c, epsilon)); CHECK(actual.xy == 0); CHECK_THAT(actual.xz, WithinAbs(s, epsilon)); @@ -210,7 +210,7 @@ TEMPLATE_TEST_CASE("rot3_z()", "[matrix3]", const auto theta = g.generate(); const auto c = std::cos(theta); const auto s = std::sin(theta); - const matrix3 actual = rot3_z(theta); + const matrix3 actual = rot3_z(geo::radians{theta}); CHECK_THAT(actual.xx, WithinAbs(c, epsilon)); CHECK_THAT(actual.xy, WithinAbs(-s, epsilon)); CHECK(actual.xz == 0); diff --git a/src/pstack/geo/test/matrix4_ut.cpp b/src/pstack/geo/test/matrix4_ut.cpp index 90eab7f..eee8e1f 100644 --- a/src/pstack/geo/test/matrix4_ut.cpp +++ b/src/pstack/geo/test/matrix4_ut.cpp @@ -117,7 +117,7 @@ TEMPLATE_TEST_CASE("rot4_x()", "[matrix4]", const auto theta = g.generate(); const auto c = std::cos(theta); const auto s = std::sin(theta); - const matrix4 actual = rot4_x(theta); + const matrix4 actual = rot4_x(geo::radians{theta}); CHECK(actual.xx == 1); CHECK(actual.xy == 0); CHECK(actual.xz == 0); @@ -143,7 +143,7 @@ TEMPLATE_TEST_CASE("rot4_y()", "[matrix4]", const auto theta = g.generate(); const auto c = std::cos(theta); const auto s = std::sin(theta); - const matrix4 actual = rot4_y(theta); + const matrix4 actual = rot4_y(geo::radians{theta}); CHECK_THAT(actual.xx, WithinAbs(c, epsilon)); CHECK(actual.xy == 0); CHECK_THAT(actual.xz, WithinAbs(s, epsilon)); @@ -169,7 +169,7 @@ TEMPLATE_TEST_CASE("rot4_z()", "[matrix4]", const auto theta = g.generate(); const auto c = std::cos(theta); const auto s = std::sin(theta); - const matrix4 actual = rot4_z(theta); + const matrix4 actual = rot4_z(geo::radians{theta}); CHECK_THAT(actual.xx, WithinAbs(c, epsilon)); CHECK_THAT(actual.xy, WithinAbs(-s, epsilon)); CHECK(actual.xz == 0); diff --git a/src/pstack/gui/transformation.hpp b/src/pstack/gui/transformation.hpp index db78a56..87f8c2c 100644 --- a/src/pstack/gui/transformation.hpp +++ b/src/pstack/gui/transformation.hpp @@ -18,7 +18,7 @@ class transformation { } void rotate_by(float rx, float ry) { - _orientation = geo::rot4_y(ry) * geo::rot4_x(rx) * _orientation; + _orientation = geo::rot4_y(geo::radians{ry}) * geo::rot4_x(geo::radians{rx}) * _orientation; _recalculate(); } void scale_mesh(float factor) {