Math/Angle: Add sine, cosine, tangent methods
This commit is contained in:
parent
3cc70daf3e
commit
9e0b61f30d
|
|
@ -11,6 +11,7 @@
|
||||||
#include <Nazara/Math/Algorithm.hpp>
|
#include <Nazara/Math/Algorithm.hpp>
|
||||||
#include <Nazara/Math/Enums.hpp>
|
#include <Nazara/Math/Enums.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
|
@ -28,6 +29,11 @@ namespace Nz
|
||||||
Angle(const Angle&) = default;
|
Angle(const Angle&) = default;
|
||||||
~Angle() = default;
|
~Angle() = default;
|
||||||
|
|
||||||
|
T GetCos() const;
|
||||||
|
T GetSin() const;
|
||||||
|
std::pair<T, T> GetSinCos() const;
|
||||||
|
T GetTan() const;
|
||||||
|
|
||||||
Angle& MakeZero();
|
Angle& MakeZero();
|
||||||
|
|
||||||
void Normalize();
|
void Normalize();
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@ namespace Nz
|
||||||
template<>
|
template<>
|
||||||
struct AngleUtils<AngleUnit::Degree>
|
struct AngleUtils<AngleUnit::Degree>
|
||||||
{
|
{
|
||||||
|
template<typename T> static constexpr T GetEpsilon()
|
||||||
|
{
|
||||||
|
return T(1e-4);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> static constexpr T GetLimit()
|
template<typename T> static constexpr T GetLimit()
|
||||||
{
|
{
|
||||||
return 180;
|
return 180;
|
||||||
|
|
@ -55,9 +60,14 @@ namespace Nz
|
||||||
template<>
|
template<>
|
||||||
struct AngleUtils<AngleUnit::Radian>
|
struct AngleUtils<AngleUnit::Radian>
|
||||||
{
|
{
|
||||||
|
template<typename T> static constexpr T GetEpsilon()
|
||||||
|
{
|
||||||
|
return T(1e-5);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> static constexpr T GetLimit()
|
template<typename T> static constexpr T GetLimit()
|
||||||
{
|
{
|
||||||
return M_PI;
|
return T(M_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> static T FromDegrees(T degrees)
|
template<typename T> static T FromDegrees(T degrees)
|
||||||
|
|
@ -90,6 +100,14 @@ namespace Nz
|
||||||
return out << "Angle(" << value << "rad)";
|
return out << "Angle(" << value << "rad)";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Naive implementation, hopefully optimized by the compiler
|
||||||
|
template<typename T>
|
||||||
|
void SinCos(T x, T* sin, T* cos)
|
||||||
|
{
|
||||||
|
*sin = std::sin(x);
|
||||||
|
*cos = std::cos(x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*!
|
/*!
|
||||||
* \ingroup math
|
* \ingroup math
|
||||||
|
|
@ -108,6 +126,59 @@ namespace Nz
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Computes the cosine of the angle
|
||||||
|
* \return Cosine of angle
|
||||||
|
*
|
||||||
|
* \see GetSinCos
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
T Angle<Unit, T>::GetCos() const
|
||||||
|
{
|
||||||
|
return std::cos(ToRadians().angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Computes the sine of the angle
|
||||||
|
* \return Sine of angle
|
||||||
|
*
|
||||||
|
* \see GetSinCos
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
T Angle<Unit, T>::GetSin() const
|
||||||
|
{
|
||||||
|
return std::sin(ToRadians().angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Computes both sines and cosines of the angle
|
||||||
|
* \return Sine and cosine of the angle
|
||||||
|
*
|
||||||
|
* \remark This is potentially faster than calling both GetSin and GetCos separately as it can computes both values at the same time.
|
||||||
|
*
|
||||||
|
* \see GetCos, GetSin
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
std::pair<T, T> Angle<Unit, T>::GetSinCos() const
|
||||||
|
{
|
||||||
|
T sin, cos;
|
||||||
|
Detail::SinCos<T>(ToRadians().angle, &sin, &cos);
|
||||||
|
|
||||||
|
return std::make_pair(sin, cos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Computes the tangent of the angle
|
||||||
|
* \return Tangent value of the angle
|
||||||
|
*
|
||||||
|
* \see GetCos, GetSin
|
||||||
|
*/
|
||||||
|
template<AngleUnit Unit, typename T>
|
||||||
|
T Angle<Unit, T>::GetTan() const
|
||||||
|
{
|
||||||
|
return std::tan(ToRadians().angle);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Changes the angle value to zero
|
* \brief Changes the angle value to zero
|
||||||
*/
|
*/
|
||||||
|
|
@ -115,6 +186,7 @@ namespace Nz
|
||||||
Angle<Unit, T>& Angle<Unit, T>::MakeZero()
|
Angle<Unit, T>& Angle<Unit, T>::MakeZero()
|
||||||
{
|
{
|
||||||
angle = T(0);
|
angle = T(0);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -303,7 +375,7 @@ namespace Nz
|
||||||
template<AngleUnit Unit, typename T>
|
template<AngleUnit Unit, typename T>
|
||||||
bool Angle<Unit, T>::operator==(const Angle& Angle) const
|
bool Angle<Unit, T>::operator==(const Angle& Angle) const
|
||||||
{
|
{
|
||||||
return NumberEquals(angle, Angle.angle);
|
return NumberEquals(angle, Angle.angle, Detail::AngleUtils<Unit>::GetEpsilon<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -315,7 +387,7 @@ namespace Nz
|
||||||
template<AngleUnit Unit, typename T>
|
template<AngleUnit Unit, typename T>
|
||||||
bool Angle<Unit, T>::operator!=(const Angle& Angle) const
|
bool Angle<Unit, T>::operator!=(const Angle& Angle) const
|
||||||
{
|
{
|
||||||
return !NumberEquals(angle, Angle.angle);
|
return !NumberEquals(angle, Angle.angle, Detail::AngleUtils<Unit>::GetEpsilon<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,26 @@ SCENARIO("Angle", "[MATH][ANGLE]")
|
||||||
CHECK(angle.ToRadians() == expectedResult);
|
CHECK(angle.ToRadians() == expectedResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WHEN("We compute its sinus/cosinus separatly")
|
||||||
|
{
|
||||||
|
THEN("It should be equal to 1 and 0")
|
||||||
|
{
|
||||||
|
CHECK(angle.GetSin() == Approx(1.f).margin(0.0001f));
|
||||||
|
CHECK(angle.GetCos() == Approx(0.f).margin(0.0001f));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
AND_WHEN("We compute it at the same time")
|
||||||
|
{
|
||||||
|
auto sincos = angle.GetSinCos();
|
||||||
|
|
||||||
|
THEN("It should also be equal to 1 and 0")
|
||||||
|
{
|
||||||
|
CHECK(sincos.first == Approx(1.f).margin(0.0001f));
|
||||||
|
CHECK(sincos.second == Approx(0.f).margin(0.0001f));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GIVEN("A degree angle of 480deg")
|
GIVEN("A degree angle of 480deg")
|
||||||
|
|
@ -48,9 +68,9 @@ SCENARIO("Angle", "[MATH][ANGLE]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GIVEN("A degree angle of -270deg")
|
GIVEN("A degree angle of -300deg")
|
||||||
{
|
{
|
||||||
Nz::DegreeAnglef angle(-270.f);
|
Nz::DegreeAnglef angle(-300.f);
|
||||||
|
|
||||||
WHEN("We normalize it")
|
WHEN("We normalize it")
|
||||||
{
|
{
|
||||||
|
|
@ -58,7 +78,7 @@ SCENARIO("Angle", "[MATH][ANGLE]")
|
||||||
|
|
||||||
THEN("It should be equal to a normalized version of itself")
|
THEN("It should be equal to a normalized version of itself")
|
||||||
{
|
{
|
||||||
Nz::DegreeAnglef expectedResult(90.f);
|
Nz::DegreeAnglef expectedResult(60.f);
|
||||||
|
|
||||||
CHECK(angle == expectedResult);
|
CHECK(angle == expectedResult);
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +111,28 @@ SCENARIO("Angle", "[MATH][ANGLE]")
|
||||||
CHECK(angle.ToDegrees() == expectedResult);
|
CHECK(angle.ToDegrees() == expectedResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WHEN("We compute its sinus/cosinus separatly")
|
||||||
|
{
|
||||||
|
THEN("It should be equal to 0 and -1")
|
||||||
|
{
|
||||||
|
CHECK(angle.GetSin() == Approx(0.f).margin(0.0001f));
|
||||||
|
CHECK(angle.GetCos() == Approx(-1.f).margin(0.0001f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
AND_WHEN("We compute it at the same time")
|
||||||
|
{
|
||||||
|
auto sincos = angle.GetSinCos();
|
||||||
|
|
||||||
|
THEN("It should also be equal to 0 and -1")
|
||||||
|
{
|
||||||
|
CHECK(sincos.first == Approx(0.f).margin(0.0001f));
|
||||||
|
CHECK(sincos.second == Approx(-1.f).margin(0.0001f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GIVEN("A radian angle of 7pi")
|
GIVEN("A radian angle of 7pi")
|
||||||
{
|
{
|
||||||
Nz::RadianAnglef angle(float(7 * M_PI));
|
Nz::RadianAnglef angle(float(7 * M_PI));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue