diff --git a/Angle16.h b/Angle16.h new file mode 100644 index 0000000..410c5f7 --- /dev/null +++ b/Angle16.h @@ -0,0 +1,21 @@ +#include "AngleUsing.h" + +#include "Angle.h" +#include + +typedef AngleUsing Angle16; + +Angle16::AngleUsing(float angle) { + if (!isfinite(angle)) { + value = 0; + return; + } + + // map float [-180..180) to integer [-32768..32767] + this->value = (signed short)((angle / 360.0F) * 65536.0F); +} + +float Angle16::ToFloat() const { + float f = ((this->value * 180) / 32768.0F); + return f; +} diff --git a/Angle8.h b/Angle8.h new file mode 100644 index 0000000..2db4d18 --- /dev/null +++ b/Angle8.h @@ -0,0 +1,22 @@ +#include "AngleUsing.h" + +#include "Angle.h" +#include + +typedef AngleUsing Angle8; + +Angle8::AngleUsing(float angle) { + if (!isfinite(angle)) { + value = 0; + return; + } + + // map float [-180..180) to integer [-128..127] + float f = angle / 360.0F; + this->value = (signed char)(f * 256.0F); +} + +float Angle8::ToFloat() const { + float f = (this->value * 180) / 128.0F; + return f; +} diff --git a/AngleUsing.cpp b/AngleUsing.cpp new file mode 100644 index 0000000..37d4bf1 --- /dev/null +++ b/AngleUsing.cpp @@ -0,0 +1,83 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0.If a copy of the MPL was not distributed with this +// file, You can obtain one at https ://mozilla.org/MPL/2.0/. + +#include "DiscreteAngle.h" + +#include "Angle.h" +#include + +// 1-byte angle + +// template <> AngleUsing::AngleUsing(unsigned char angle) { +// if (!isfinite(angle)) { +// value = 0; +// return; +// } + +// // normalize to (-180..180] +// angle = Angle::Normalize(angle); + +// // map (-180..180] to (0..255], which is equivaluent to 1..255 +// // This means that range value 0 is not used +// this->value = (unsigned char)((angle + 180.0F) / 360.0F * 255.0F); +// } + +// template <> float AngleUsing::ToFloat() const { +// float f = ((float)this->value / 255.0F) * 360.0F - 180.0F; +// return f; +// } + +// template <> AngleUsing::AngleUsing(float angle) { +// if (!isfinite(angle)) { +// value = 0; +// return; +// } + +// // normalize to (-180..180] +// angle = Angle::Normalize(angle); + +// // map (-180..180] to (0..255], which is equivaluent to 1..255 +// // This means that range value 0 is not used +// this->value = (unsigned char)((angle + 180.0F) / 360.0F * 255.0F); +// } + +// template <> float AngleUsing::ToFloat() const { +// float f = ((float)this->value / 255.0F) * 360.0F - 180.0F; +// return f; +// } + +// 2-byte angle + +template <> AngleUsing::AngleUsing(unsigned short angle) { + if (!isfinite(angle)) { + value = 0; + return; + } + + // normalize to (-180..180] + angle = Angle::Normalize(angle); + + // map (-180..180] to (0..65535] which is equivalent to 1..65535 + // This means that range value 0 is not used + this->value = (unsigned short)((angle + 180.0F) / 360.0F * 65535.0F); +} + +template <> AngleUsing::AngleUsing(float angle) { + if (!isfinite(angle)) { + value = 0; + return; + } + + // normalize to (-180..180] + angle = Angle::Normalize(angle); + + // map (-180..180] to (0..65535] which is equivalent to 1..65535 + // This means that range value 0 is not used + this->value = (unsigned short)((angle + 180.0F) / 360.0F * 65535.0F); +} + +template <> float AngleUsing::ToFloat() const { + float f = ((float)this->value / 65535.0F) * 360.0F - 180.0F; + return f; +} \ No newline at end of file diff --git a/AngleUsing.h b/AngleUsing.h new file mode 100644 index 0000000..d6eb4d0 --- /dev/null +++ b/AngleUsing.h @@ -0,0 +1,42 @@ +#ifndef DISCRETEANGLE_H +#define DISCRETEANGLE_H + +#include "Angle.h" +#include "Range.h" + +// A fixed angle between (-180..180] + +template class AngleUsing { +public: + AngleUsing(T sourceValue) { this->value = sourceValue; } + AngleUsing(float f); + float ToFloat() const; + inline T GetValue() const { return this->value; } + + AngleUsing operator+(const AngleUsing a) { + AngleUsing r = AngleUsing(this->value + a.value); + return r; + } + + inline AngleUsing operator+=(const AngleUsing a) { + return this->value + a.value; + } + + inline AngleUsing operator-(const AngleUsing a) { + return this->value - a.value; + } + + inline AngleUsing operator-() { + this->value = -this->value; + return *this; + } + + inline bool operator==(const AngleUsing a) { + return this->value == a.value; + } + + // protected: + T value; +}; + +#endif diff --git a/CMakeLists.txt b/CMakeLists.txt index ef430ee..1591739 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ else() "test/Matrix_test.cc" "test/Polar_test.cc" "test/Spherical_test.cc" + "test/DiscreteAngle_test.cc" ) target_link_libraries( VectorAlgebraTest diff --git a/DiscreteAngle.cpp b/DiscreteAngle.cpp deleted file mode 100644 index 6cff5f8..0000000 --- a/DiscreteAngle.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0.If a copy of the MPL was not distributed with this -// file, You can obtain one at https ://mozilla.org/MPL/2.0/. - -#include "DiscreteAngle.h" - -#include "Angle.h" -#include - -// 1-byte angle - -template <> AngleUsing::AngleUsing(unsigned char angle) { - if (!isfinite(angle)) { - value = 0; - return; - } - - // normalize to (-180..180] - angle = Angle::Normalize(angle); - - // map (-180..180] to (0..255], which is equivaluent to 1..255 - // This means that range value 0 is not used - this->value = (unsigned char)((angle + 180.0F) / 360.0F * 255.0F); -} - -template <> float AngleUsing::ToFloat() const { - float f = ((float)this->value / 255.0F) * 360.0F - 180.0F; - return f; -} - -// 2-byte angle - -template <> AngleUsing::AngleUsing(unsigned short angle) { - if (!isfinite(angle)) { - value = 0; - return; - } - - // normalize to (-180..180] - angle = Angle::Normalize(angle); - - // map (-180..180] to (0..65535] which is equivalent to 1..65535 - // This means that range value 0 is not used - this->value = (unsigned short)((angle + 180.0F) / 360.0F * 65535.0F); -} - -template <> float AngleUsing::ToFloat() const { - float f = ((float)this->value / 65535.0F) * 360.0F - 180.0F; - return f; -} \ No newline at end of file diff --git a/DiscreteAngle.h b/DiscreteAngle.h deleted file mode 100644 index 8f7454a..0000000 --- a/DiscreteAngle.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef DISCRETEANGLE_H -#define DISCRETEANGLE_H - -#include "Range.h" - -// A fixed angle between (-180..180] - -template class AngleUsing { -public: - AngleUsing(T sourceValue); - float ToFloat() const; - inline T GetValue() const { return this->value; } - - inline AngleUsing operator+(const AngleUsing a) { - return this->value + a.value; - } - - inline AngleUsing operator+=(const AngleUsing a &) { - return this->value + a.value; - } - - inline AngleUsing operator-(const AngleUsing a) { - return this->value - a.value; - } - - inline AngleUsing operator-() { return -this->value; } - inline bool operator==(const AngleUsing a, const AngleUsing b) { - return a.value == b.value; - } - -protected: - T value; -}; - -#endif diff --git a/test/DiscreteAngle_test.cc b/test/DiscreteAngle_test.cc new file mode 100644 index 0000000..b0d59df --- /dev/null +++ b/test/DiscreteAngle_test.cc @@ -0,0 +1,64 @@ +#if GTEST +#include + +#include +#include + +#include "Angle16.h" +#include "Angle8.h" + +#define FLOAT_INFINITY std::numeric_limits::infinity() + +TEST(Angle8, Construct) { + float angle = 0.0F; + Angle8 a = Angle8(angle); + float f = a.ToFloat(); + EXPECT_FLOAT_EQ(f, angle); + + angle = -180.0F; + a = Angle8(angle); + f = a.ToFloat(); + EXPECT_FLOAT_EQ(f, angle); +} + +TEST(Angle8, Negate) { + float angle = 0; + Angle8 a = Angle8(angle); + a = -a; + float f = a.ToFloat(); + EXPECT_FLOAT_EQ(f, angle); + + angle = 90.0F; + a = Angle8(angle); + a = -a; + f = a.ToFloat(); + EXPECT_FLOAT_EQ(f, -angle); +} + +TEST(Angle8, Add) { + Angle8 a = Angle8(0.0F); + Angle8 b = Angle8(0.0F); + Angle8 r = a + b; + EXPECT_FLOAT_EQ(r.ToFloat(), 0); +} + +TEST(Angle16, Construct) { + Angle16 a = Angle16(0.0F); + float f = a.ToFloat(); + EXPECT_FLOAT_EQ(f, 0); +} + +TEST(Angle16, Negate) { + float angle = 0; + Angle16 a = Angle16(angle); + a = -a; + float f = a.ToFloat(); + EXPECT_FLOAT_EQ(f, angle); + + angle = 90.0F; + a = Angle16(angle); + a = -a; + f = a.ToFloat(); + EXPECT_FLOAT_EQ(f, -angle); +} +#endif \ No newline at end of file